2020-02-19 15:31:39 +00:00
|
|
|
""" PagerMaid initialization. """
|
|
|
|
|
2021-11-10 05:14:04 +00:00
|
|
|
import asyncio
|
2021-07-16 09:03:11 +00:00
|
|
|
from concurrent.futures import CancelledError
|
2021-04-03 15:24:07 +00:00
|
|
|
|
2021-07-17 17:25:54 +00:00
|
|
|
# Analytics
|
2021-07-16 09:03:11 +00:00
|
|
|
import sentry_sdk
|
2021-04-03 15:24:07 +00:00
|
|
|
from sentry_sdk.integrations.redis import RedisIntegration
|
2021-07-16 09:03:11 +00:00
|
|
|
|
2021-06-19 14:09:46 +00:00
|
|
|
python36 = True
|
|
|
|
try:
|
|
|
|
from asyncio.exceptions import CancelledError as CancelError
|
2021-07-16 09:03:11 +00:00
|
|
|
|
2021-06-19 14:09:46 +00:00
|
|
|
python36 = False
|
|
|
|
except:
|
|
|
|
pass
|
2021-04-03 15:24:07 +00:00
|
|
|
from subprocess import run, PIPE
|
2021-09-04 08:28:38 +00:00
|
|
|
from datetime import datetime
|
2021-04-03 15:24:07 +00:00
|
|
|
from time import time
|
2021-09-15 13:24:56 +00:00
|
|
|
from os import getcwd, makedirs, environ, remove
|
2020-02-19 15:31:39 +00:00
|
|
|
from os.path import exists
|
|
|
|
from sys import version_info, platform
|
2021-04-12 16:25:32 +00:00
|
|
|
from yaml import load, FullLoader, safe_load
|
2021-06-15 04:31:05 +00:00
|
|
|
from json import load as load_json
|
2020-02-19 15:31:39 +00:00
|
|
|
from shutil import copyfile
|
|
|
|
from redis import StrictRedis
|
2021-03-03 17:08:02 +00:00
|
|
|
from logging import getLogger, INFO, DEBUG, ERROR, StreamHandler, basicConfig
|
2021-08-18 08:41:22 +00:00
|
|
|
from distutils.util import strtobool
|
2020-02-19 15:31:39 +00:00
|
|
|
from coloredlogs import ColoredFormatter
|
2020-08-08 16:31:48 +00:00
|
|
|
from telethon import TelegramClient
|
2021-09-03 11:03:34 +00:00
|
|
|
from telethon.sessions import StringSession
|
2021-08-18 08:41:22 +00:00
|
|
|
|
|
|
|
# Errors
|
2021-06-19 07:25:31 +00:00
|
|
|
from telethon.errors.rpcerrorlist import MessageNotModifiedError, MessageIdInvalidError, ChannelPrivateError, \
|
2021-07-16 09:03:11 +00:00
|
|
|
ChatSendMediaForbiddenError, YouBlockedUserError, FloodWaitError, ChatWriteForbiddenError, \
|
2021-09-03 11:03:34 +00:00
|
|
|
AuthKeyDuplicatedError, ChatSendStickersForbiddenError, SlowModeWaitError, MessageEditTimeExpiredError, \
|
2021-09-15 13:24:56 +00:00
|
|
|
PeerIdInvalidError, AuthKeyUnregisteredError, UserBannedInChannelError, UserDeactivatedBanError, PeerFloodError
|
2021-06-19 07:25:31 +00:00
|
|
|
from telethon.errors.common import AlreadyInConversationError
|
|
|
|
from requests.exceptions import ChunkedEncodingError
|
2021-06-19 13:18:55 +00:00
|
|
|
from requests.exceptions import ConnectionError as ConnectedError
|
2021-06-14 10:24:23 +00:00
|
|
|
from sqlite3 import OperationalError
|
2021-06-19 07:25:31 +00:00
|
|
|
from http.client import RemoteDisconnected
|
|
|
|
from urllib.error import URLError
|
|
|
|
from concurrent.futures._base import TimeoutError
|
2021-08-27 11:33:45 +00:00
|
|
|
from redis.exceptions import ResponseError
|
2021-06-14 10:24:23 +00:00
|
|
|
|
2020-02-19 15:31:39 +00:00
|
|
|
persistent_vars = {}
|
|
|
|
module_dir = __path__[0]
|
|
|
|
working_dir = getcwd()
|
|
|
|
config = None
|
|
|
|
help_messages = {}
|
2021-01-23 12:48:38 +00:00
|
|
|
logs = getLogger(__name__)
|
|
|
|
logging_format = "%(levelname)s [%(asctime)s] [%(name)s] %(message)s"
|
|
|
|
logging_handler = StreamHandler()
|
|
|
|
logging_handler.setFormatter(ColoredFormatter(logging_format))
|
2021-03-03 17:03:48 +00:00
|
|
|
root_logger = getLogger()
|
2021-03-03 17:08:02 +00:00
|
|
|
root_logger.setLevel(ERROR)
|
2021-03-03 17:03:48 +00:00
|
|
|
root_logger.addHandler(logging_handler)
|
2021-01-23 12:48:38 +00:00
|
|
|
basicConfig(level=INFO)
|
|
|
|
logs.setLevel(INFO)
|
2020-02-19 15:31:39 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
config = load(open(r"config.yml"), Loader=FullLoader)
|
|
|
|
except FileNotFoundError:
|
2021-04-12 16:25:32 +00:00
|
|
|
logs.fatal("The configuration file does not exist, and a new configuration file is being generated.")
|
2020-02-19 15:31:39 +00:00
|
|
|
copyfile(f"{module_dir}/assets/config.gen.yml", "config.yml")
|
|
|
|
exit(1)
|
|
|
|
|
2021-04-12 16:25:32 +00:00
|
|
|
# i18n
|
|
|
|
lang_dict: dict = {}
|
|
|
|
|
|
|
|
try:
|
|
|
|
with open(f"languages/built-in/{config['application_language']}.yml", "r", encoding="utf-8") as f:
|
|
|
|
lang_dict = safe_load(f)
|
|
|
|
except Exception as e:
|
|
|
|
print("Reading language YAML file failed")
|
|
|
|
print(e)
|
|
|
|
exit(1)
|
2021-08-21 09:59:40 +00:00
|
|
|
# Customization
|
|
|
|
try:
|
|
|
|
with open(f"languages/custom.yml", "r", encoding="utf-8") as f:
|
|
|
|
lang_temp = safe_load(f)
|
|
|
|
for key, value in lang_temp.items():
|
|
|
|
lang_dict[key] = value
|
|
|
|
except FileNotFoundError:
|
|
|
|
pass
|
|
|
|
except Exception as e:
|
|
|
|
logs.fatal("Reading custom YAML file failed")
|
2021-04-12 16:25:32 +00:00
|
|
|
|
2021-06-15 04:31:05 +00:00
|
|
|
# alias
|
|
|
|
alias_dict: dict = {}
|
|
|
|
|
|
|
|
if exists("data/alias.json"):
|
|
|
|
try:
|
|
|
|
with open("data/alias.json", encoding="utf-8") as f:
|
|
|
|
alias_dict = load_json(f)
|
|
|
|
except Exception as e:
|
|
|
|
print("Reading alias file failed")
|
|
|
|
print(e)
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
|
2021-04-12 16:25:32 +00:00
|
|
|
def lang(text: str) -> str:
|
|
|
|
""" i18n """
|
|
|
|
result = lang_dict.get(text, text)
|
|
|
|
return result
|
2020-02-19 15:31:39 +00:00
|
|
|
|
2021-06-15 04:31:05 +00:00
|
|
|
|
2021-07-19 03:27:02 +00:00
|
|
|
analytics = None
|
2021-07-18 07:52:11 +00:00
|
|
|
try:
|
2021-07-19 03:27:02 +00:00
|
|
|
allow_analytics = strtobool(config['allow_analytic'])
|
2021-07-18 07:52:11 +00:00
|
|
|
except KeyError:
|
|
|
|
allow_analytics = True
|
|
|
|
except ValueError:
|
|
|
|
allow_analytics = True
|
|
|
|
if allow_analytics:
|
2021-07-19 03:27:02 +00:00
|
|
|
import analytics
|
2021-08-21 09:59:40 +00:00
|
|
|
|
2021-07-19 03:27:02 +00:00
|
|
|
analytics.write_key = 'EI5EyxFl8huwAvv932Au7XoRSdZ63wC4'
|
|
|
|
analytics = analytics
|
2021-01-23 12:48:38 +00:00
|
|
|
if strtobool(config['debug']):
|
|
|
|
logs.setLevel(DEBUG)
|
|
|
|
else:
|
|
|
|
logs.setLevel(INFO)
|
|
|
|
|
2020-02-19 15:31:39 +00:00
|
|
|
if platform == "linux" or platform == "linux2" or platform == "darwin" or platform == "freebsd7" \
|
|
|
|
or platform == "freebsd8" or platform == "freebsdN" or platform == "openbsd6":
|
|
|
|
logs.info(
|
2021-04-12 16:25:32 +00:00
|
|
|
lang('platform') + platform + lang('platform_load')
|
2020-02-19 15:31:39 +00:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
logs.error(
|
2021-04-12 16:25:32 +00:00
|
|
|
f"{lang('error_prefix')} {lang('platform')}" + platform + lang('platform_unsupported')
|
2020-02-19 15:31:39 +00:00
|
|
|
)
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
if version_info[0] < 3 or version_info[1] < 6:
|
|
|
|
logs.error(
|
2021-04-12 16:25:32 +00:00
|
|
|
f"{lang('error_prefix')} {lang('python')}"
|
2020-02-19 15:31:39 +00:00
|
|
|
)
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
if not exists(f"{getcwd()}/data"):
|
|
|
|
makedirs(f"{getcwd()}/data")
|
|
|
|
|
|
|
|
api_key = config['api_key']
|
|
|
|
api_hash = config['api_hash']
|
2021-09-03 11:03:34 +00:00
|
|
|
session_string = "pagermaid"
|
|
|
|
# environ
|
|
|
|
if environ.get('api_key'):
|
|
|
|
api_key = environ.get('api_key')
|
|
|
|
if environ.get('api_hash'):
|
|
|
|
api_hash = environ.get('api_hash')
|
|
|
|
if environ.get('session'):
|
|
|
|
string_session = environ.get('session')
|
|
|
|
session_string = StringSession(string_session)
|
|
|
|
# api type
|
|
|
|
try:
|
|
|
|
api_key = int(api_key)
|
|
|
|
except ValueError:
|
|
|
|
logs.info(
|
|
|
|
lang('config_error')
|
|
|
|
)
|
|
|
|
exit(1)
|
|
|
|
except:
|
|
|
|
pass
|
2020-08-08 13:28:59 +00:00
|
|
|
try:
|
|
|
|
proxy_addr = config['proxy_addr'].strip()
|
|
|
|
proxy_port = config['proxy_port'].strip()
|
2021-06-19 13:53:03 +00:00
|
|
|
http_addr = config['http_addr'].strip()
|
|
|
|
http_port = config['http_port'].strip()
|
2020-08-08 13:28:59 +00:00
|
|
|
mtp_addr = config['mtp_addr'].strip()
|
|
|
|
mtp_port = config['mtp_port'].strip()
|
|
|
|
mtp_secret = config['mtp_secret'].strip()
|
2021-07-11 06:08:29 +00:00
|
|
|
except KeyError:
|
2020-08-08 13:28:59 +00:00
|
|
|
proxy_addr = ''
|
|
|
|
proxy_port = ''
|
2021-06-19 13:53:03 +00:00
|
|
|
http_addr = ''
|
|
|
|
http_port = ''
|
2020-08-08 13:28:59 +00:00
|
|
|
mtp_addr = ''
|
|
|
|
mtp_port = ''
|
|
|
|
mtp_secret = ''
|
2020-02-19 15:31:39 +00:00
|
|
|
try:
|
|
|
|
redis_host = config['redis']['host']
|
|
|
|
except KeyError:
|
|
|
|
redis_host = 'localhost'
|
|
|
|
try:
|
|
|
|
redis_port = config['redis']['port']
|
|
|
|
except KeyError:
|
|
|
|
redis_port = 6379
|
|
|
|
try:
|
|
|
|
redis_db = config['redis']['db']
|
|
|
|
except KeyError:
|
|
|
|
redis_db = 14
|
2021-07-11 06:08:29 +00:00
|
|
|
try:
|
|
|
|
if strtobool(config['ipv6']):
|
|
|
|
use_ipv6 = True
|
|
|
|
else:
|
|
|
|
use_ipv6 = False
|
|
|
|
except KeyError:
|
|
|
|
use_ipv6 = False
|
2020-02-19 15:31:39 +00:00
|
|
|
if api_key is None or api_hash is None:
|
|
|
|
logs.info(
|
2021-04-12 16:25:32 +00:00
|
|
|
lang('config_error')
|
2020-02-19 15:31:39 +00:00
|
|
|
)
|
|
|
|
exit(1)
|
|
|
|
|
2021-08-27 07:27:49 +00:00
|
|
|
# 开始检查代理配置
|
|
|
|
proxies = {}
|
2020-08-08 13:17:46 +00:00
|
|
|
if not proxy_addr == '' and not proxy_port == '':
|
2020-08-08 16:31:48 +00:00
|
|
|
try:
|
2021-06-19 13:53:03 +00:00
|
|
|
import python_socks
|
|
|
|
|
2021-08-27 07:27:49 +00:00
|
|
|
proxies = {
|
|
|
|
"http": f"socks5://{proxy_addr}:{proxy_port}",
|
|
|
|
"https": f"socks5://{proxy_addr}:{proxy_port}"
|
|
|
|
}
|
2021-09-03 11:03:34 +00:00
|
|
|
bot = TelegramClient(session_string, api_key, api_hash,
|
2021-07-11 06:08:29 +00:00
|
|
|
auto_reconnect=True,
|
|
|
|
proxy=(python_socks.ProxyType.SOCKS5, proxy_addr, int(proxy_port)),
|
|
|
|
use_ipv6=use_ipv6)
|
2020-08-08 16:31:48 +00:00
|
|
|
except:
|
2021-08-27 07:27:49 +00:00
|
|
|
proxies = {}
|
2021-09-03 11:03:34 +00:00
|
|
|
bot = TelegramClient(session_string, api_key, api_hash,
|
2021-07-11 06:08:29 +00:00
|
|
|
auto_reconnect=True,
|
|
|
|
use_ipv6=use_ipv6)
|
2021-06-19 13:53:03 +00:00
|
|
|
elif not http_addr == '' and not http_port == '':
|
|
|
|
try:
|
|
|
|
import python_socks
|
|
|
|
|
2021-08-27 07:27:49 +00:00
|
|
|
proxies = {
|
|
|
|
"http": f"http://{http_addr}:{http_port}",
|
|
|
|
"https": f"http://{http_addr}:{http_port}"
|
|
|
|
}
|
2021-09-03 11:03:34 +00:00
|
|
|
bot = TelegramClient(session_string, api_key, api_hash,
|
2021-07-11 06:08:29 +00:00
|
|
|
auto_reconnect=True,
|
|
|
|
proxy=(python_socks.ProxyType.HTTP, http_addr, int(http_port)),
|
|
|
|
use_ipv6=use_ipv6)
|
2021-06-19 13:53:03 +00:00
|
|
|
except:
|
2021-09-03 11:03:34 +00:00
|
|
|
bot = TelegramClient(session_string, api_key, api_hash,
|
2021-07-11 06:08:29 +00:00
|
|
|
auto_reconnect=True,
|
|
|
|
use_ipv6=use_ipv6)
|
2020-08-08 13:17:46 +00:00
|
|
|
elif not mtp_addr == '' and not mtp_port == '' and not mtp_secret == '':
|
2020-08-08 16:31:48 +00:00
|
|
|
from telethon import connection
|
2021-06-15 04:31:05 +00:00
|
|
|
|
2021-09-03 11:03:34 +00:00
|
|
|
bot = TelegramClient(session_string, api_key, api_hash,
|
2021-07-11 06:08:29 +00:00
|
|
|
auto_reconnect=True,
|
2020-08-08 13:17:46 +00:00
|
|
|
connection=connection.ConnectionTcpMTProxyRandomizedIntermediate,
|
2021-07-11 06:08:29 +00:00
|
|
|
proxy=(mtp_addr, int(mtp_port), mtp_secret),
|
|
|
|
use_ipv6=use_ipv6)
|
2020-08-08 13:17:46 +00:00
|
|
|
else:
|
2021-09-03 11:03:34 +00:00
|
|
|
bot = TelegramClient(session_string, api_key, api_hash, auto_reconnect=True, use_ipv6=use_ipv6)
|
2021-07-17 17:25:54 +00:00
|
|
|
user_id = 0
|
2021-10-03 16:42:16 +00:00
|
|
|
user_bot = False
|
2020-02-19 15:31:39 +00:00
|
|
|
redis = StrictRedis(host=redis_host, port=redis_port, db=redis_db)
|
|
|
|
|
2021-04-03 15:24:07 +00:00
|
|
|
|
|
|
|
async def save_id():
|
2021-10-03 16:42:16 +00:00
|
|
|
global user_id, user_bot
|
2021-04-03 15:24:07 +00:00
|
|
|
me = await bot.get_me()
|
2021-07-17 17:25:54 +00:00
|
|
|
user_id = me.id
|
2021-10-03 16:42:16 +00:00
|
|
|
user_bot = me.bot
|
2021-04-04 05:03:57 +00:00
|
|
|
if me.username is not None:
|
2021-10-03 16:42:16 +00:00
|
|
|
sentry_sdk.set_user({"id": user_id, "name": me.first_name, "username": me.username, "ip_address": "{{auto}}",
|
|
|
|
"bot": f"{user_bot}"})
|
2021-07-18 07:52:11 +00:00
|
|
|
if allow_analytics:
|
2021-07-19 03:27:02 +00:00
|
|
|
analytics.identify(user_id, {
|
|
|
|
'name': me.first_name,
|
2021-10-03 16:42:16 +00:00
|
|
|
'username': me.username,
|
|
|
|
'bot': f"{user_bot}"
|
2021-07-19 03:27:02 +00:00
|
|
|
})
|
2021-04-04 05:03:57 +00:00
|
|
|
else:
|
2021-10-03 16:42:16 +00:00
|
|
|
sentry_sdk.set_user({"id": user_id, "name": me.first_name, "ip_address": "{{auto}}",
|
|
|
|
"bot": f"{user_bot}"})
|
2021-07-18 07:52:11 +00:00
|
|
|
if allow_analytics:
|
2021-07-19 03:27:02 +00:00
|
|
|
analytics.identify(user_id, {
|
2021-10-03 16:42:16 +00:00
|
|
|
'name': me.first_name,
|
|
|
|
'bot': f"{user_bot}"
|
2021-07-19 03:27:02 +00:00
|
|
|
})
|
2021-10-03 16:42:16 +00:00
|
|
|
if user_bot:
|
|
|
|
user_bot = me.username
|
2021-07-17 17:25:54 +00:00
|
|
|
logs.info(f"{lang('save_id')} {me.first_name}({user_id})")
|
2021-04-03 15:24:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
with bot:
|
2021-11-10 05:14:04 +00:00
|
|
|
asyncio.ensure_future(save_id())
|
2021-04-03 15:24:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
def before_send(event, hint):
|
|
|
|
global report_time
|
2021-04-04 03:04:11 +00:00
|
|
|
exc_info = hint.get("exc_info")
|
2021-10-03 16:42:16 +00:00
|
|
|
if exc_info and isinstance(exc_info[1], (ConnectionError, CancelledError, MessageNotModifiedError,
|
|
|
|
MessageIdInvalidError, OperationalError, ChannelPrivateError,
|
|
|
|
BufferError, RemoteDisconnected, ChatSendMediaForbiddenError,
|
|
|
|
TypeError, URLError, YouBlockedUserError, FloodWaitError,
|
|
|
|
ChunkedEncodingError, TimeoutError, UnicodeEncodeError,
|
|
|
|
ChatWriteForbiddenError, ChatSendStickersForbiddenError,
|
|
|
|
AlreadyInConversationError, ConnectedError, KeyboardInterrupt,
|
|
|
|
OSError, AuthKeyDuplicatedError, ResponseError, SlowModeWaitError,
|
|
|
|
PeerFloodError, MessageEditTimeExpiredError, PeerIdInvalidError,
|
|
|
|
AuthKeyUnregisteredError, UserBannedInChannelError)):
|
2021-09-15 13:24:56 +00:00
|
|
|
return
|
|
|
|
elif exc_info and isinstance(exc_info[1], UserDeactivatedBanError):
|
|
|
|
# The user has been deleted/deactivated
|
|
|
|
try:
|
|
|
|
remove('pagermaid.session')
|
|
|
|
except Exception as exc:
|
|
|
|
print(exc)
|
|
|
|
exit(1)
|
2021-06-19 14:09:46 +00:00
|
|
|
if not python36:
|
|
|
|
if exc_info and isinstance(exc_info[1], CancelError):
|
2021-09-03 11:03:34 +00:00
|
|
|
return
|
2021-04-03 15:24:07 +00:00
|
|
|
if time() <= report_time + 30:
|
|
|
|
report_time = time()
|
2021-09-03 11:03:34 +00:00
|
|
|
return
|
2021-04-03 15:24:07 +00:00
|
|
|
else:
|
|
|
|
report_time = time()
|
|
|
|
return event
|
|
|
|
|
|
|
|
|
|
|
|
report_time = time()
|
2021-09-04 08:28:38 +00:00
|
|
|
start_time = datetime.utcnow()
|
2021-04-04 03:04:11 +00:00
|
|
|
git_hash = run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode()
|
2021-04-03 15:24:07 +00:00
|
|
|
sentry_sdk.init(
|
2021-09-15 13:24:56 +00:00
|
|
|
"https://ae2b937dba4a4f948f13ae1c902b30a3@o416616.ingest.sentry.io/5312335",
|
2021-04-03 15:24:07 +00:00
|
|
|
traces_sample_rate=1.0,
|
|
|
|
release=git_hash,
|
|
|
|
before_send=before_send,
|
|
|
|
environment="production",
|
|
|
|
integrations=[RedisIntegration()]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2020-02-19 15:31:39 +00:00
|
|
|
def redis_status():
|
|
|
|
try:
|
|
|
|
redis.ping()
|
|
|
|
return True
|
|
|
|
except BaseException:
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
async def log(message):
|
|
|
|
logs.info(
|
|
|
|
message.replace('`', '\"')
|
|
|
|
)
|
|
|
|
if not strtobool(config['log']):
|
|
|
|
return
|
2021-10-16 13:54:45 +00:00
|
|
|
try:
|
|
|
|
await bot.send_message(
|
|
|
|
int(config['log_chatid']),
|
|
|
|
message
|
|
|
|
)
|
|
|
|
except ValueError:
|
|
|
|
pass
|