PagerMaid-Modify/pagermaid/__init__.py

334 lines
10 KiB
Python

""" PagerMaid initialization. """
from concurrent.futures import CancelledError
# Analytics
import sentry_sdk
from sentry_sdk.integrations.redis import RedisIntegration
python36 = True
try:
from asyncio.exceptions import CancelledError as CancelError
python36 = False
except:
pass
from subprocess import run, PIPE
from time import time
from os import getcwd, makedirs
from os.path import exists
from sys import version_info, platform
from yaml import load, FullLoader, safe_load
from json import load as load_json
from shutil import copyfile
from redis import StrictRedis
from logging import getLogger, INFO, DEBUG, ERROR, StreamHandler, basicConfig
from distutils.util import strtobool
from coloredlogs import ColoredFormatter
from telethon import TelegramClient
# Errors
from telethon.errors.rpcerrorlist import MessageNotModifiedError, MessageIdInvalidError, ChannelPrivateError, \
ChatSendMediaForbiddenError, YouBlockedUserError, FloodWaitError, ChatWriteForbiddenError, \
AuthKeyDuplicatedError
from telethon.errors.common import AlreadyInConversationError
from requests.exceptions import ChunkedEncodingError
from requests.exceptions import ConnectionError as ConnectedError
from sqlite3 import OperationalError
from http.client import RemoteDisconnected
from urllib.error import URLError
from concurrent.futures._base import TimeoutError
persistent_vars = {}
module_dir = __path__[0]
working_dir = getcwd()
config = None
help_messages = {}
logs = getLogger(__name__)
logging_format = "%(levelname)s [%(asctime)s] [%(name)s] %(message)s"
logging_handler = StreamHandler()
logging_handler.setFormatter(ColoredFormatter(logging_format))
root_logger = getLogger()
root_logger.setLevel(ERROR)
root_logger.addHandler(logging_handler)
basicConfig(level=INFO)
logs.setLevel(INFO)
try:
config = load(open(r"config.yml"), Loader=FullLoader)
except FileNotFoundError:
logs.fatal("The configuration file does not exist, and a new configuration file is being generated.")
copyfile(f"{module_dir}/assets/config.gen.yml", "config.yml")
exit(1)
# 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)
# 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")
# 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)
def lang(text: str) -> str:
""" i18n """
result = lang_dict.get(text, text)
return result
analytics = None
try:
allow_analytics = strtobool(config['allow_analytic'])
except KeyError:
allow_analytics = True
except ValueError:
allow_analytics = True
if allow_analytics:
import analytics
analytics.write_key = 'EI5EyxFl8huwAvv932Au7XoRSdZ63wC4'
analytics = analytics
if strtobool(config['debug']):
logs.setLevel(DEBUG)
else:
logs.setLevel(INFO)
if platform == "linux" or platform == "linux2" or platform == "darwin" or platform == "freebsd7" \
or platform == "freebsd8" or platform == "freebsdN" or platform == "openbsd6":
logs.info(
lang('platform') + platform + lang('platform_load')
)
else:
logs.error(
f"{lang('error_prefix')} {lang('platform')}" + platform + lang('platform_unsupported')
)
exit(1)
if version_info[0] < 3 or version_info[1] < 6:
logs.error(
f"{lang('error_prefix')} {lang('python')}"
)
exit(1)
if not exists(f"{getcwd()}/data"):
makedirs(f"{getcwd()}/data")
api_key = config['api_key']
api_hash = config['api_hash']
try:
proxy_addr = config['proxy_addr'].strip()
proxy_port = config['proxy_port'].strip()
http_addr = config['http_addr'].strip()
http_port = config['http_port'].strip()
mtp_addr = config['mtp_addr'].strip()
mtp_port = config['mtp_port'].strip()
mtp_secret = config['mtp_secret'].strip()
except KeyError:
proxy_addr = ''
proxy_port = ''
http_addr = ''
http_port = ''
mtp_addr = ''
mtp_port = ''
mtp_secret = ''
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
try:
if strtobool(config['ipv6']):
use_ipv6 = True
else:
use_ipv6 = False
except KeyError:
use_ipv6 = False
if api_key is None or api_hash is None:
logs.info(
lang('config_error')
)
exit(1)
if not proxy_addr == '' and not proxy_port == '':
try:
import python_socks
bot = TelegramClient("pagermaid", api_key, api_hash,
auto_reconnect=True,
proxy=(python_socks.ProxyType.SOCKS5, proxy_addr, int(proxy_port)),
use_ipv6=use_ipv6)
except:
bot = TelegramClient("pagermaid", api_key, api_hash,
auto_reconnect=True,
use_ipv6=use_ipv6)
elif not http_addr == '' and not http_port == '':
try:
import python_socks
bot = TelegramClient("pagermaid", api_key, api_hash,
auto_reconnect=True,
proxy=(python_socks.ProxyType.HTTP, http_addr, int(http_port)),
use_ipv6=use_ipv6)
except:
bot = TelegramClient("pagermaid", api_key, api_hash,
auto_reconnect=True,
use_ipv6=use_ipv6)
elif not mtp_addr == '' and not mtp_port == '' and not mtp_secret == '':
from telethon import connection
bot = TelegramClient("pagermaid", api_key, api_hash,
auto_reconnect=True,
connection=connection.ConnectionTcpMTProxyRandomizedIntermediate,
proxy=(mtp_addr, int(mtp_port), mtp_secret),
use_ipv6=use_ipv6)
else:
bot = TelegramClient("pagermaid", api_key, api_hash, auto_reconnect=True, use_ipv6=use_ipv6)
user_id = 0
redis = StrictRedis(host=redis_host, port=redis_port, db=redis_db)
async def save_id():
global user_id
me = await bot.get_me()
user_id = me.id
if me.username is not None:
sentry_sdk.set_user({"id": user_id, "name": me.first_name, "username": me.username, "ip_address": "{{auto}}"})
if allow_analytics:
analytics.identify(user_id, {
'name': me.first_name,
'username': me.username
})
else:
sentry_sdk.set_user({"id": user_id, "name": me.first_name, "ip_address": "{{auto}}"})
if allow_analytics:
analytics.identify(user_id, {
'name': me.first_name
})
logs.info(f"{lang('save_id')} {me.first_name}({user_id})")
with bot:
bot.loop.run_until_complete(save_id())
def before_send(event, hint):
global report_time
exc_info = hint.get("exc_info")
if exc_info and isinstance(exc_info[1], ConnectionError):
return None
elif exc_info and isinstance(exc_info[1], CancelledError):
return None
elif exc_info and isinstance(exc_info[1], MessageNotModifiedError):
return None
elif exc_info and isinstance(exc_info[1], MessageIdInvalidError):
return None
elif exc_info and isinstance(exc_info[1], OperationalError):
return None
elif exc_info and isinstance(exc_info[1], ChannelPrivateError):
return None
elif exc_info and isinstance(exc_info[1], BufferError):
return None
elif exc_info and isinstance(exc_info[1], RemoteDisconnected):
return None
elif exc_info and isinstance(exc_info[1], ChatSendMediaForbiddenError):
return None
elif exc_info and isinstance(exc_info[1], TypeError):
return None
elif exc_info and isinstance(exc_info[1], URLError):
return None
elif exc_info and isinstance(exc_info[1], YouBlockedUserError):
return None
elif exc_info and isinstance(exc_info[1], FloodWaitError):
return None
elif exc_info and isinstance(exc_info[1], ChunkedEncodingError):
return None
elif exc_info and isinstance(exc_info[1], TimeoutError):
return None
elif exc_info and isinstance(exc_info[1], UnicodeEncodeError):
return None
elif exc_info and isinstance(exc_info[1], ChatWriteForbiddenError):
return None
elif exc_info and isinstance(exc_info[1], AlreadyInConversationError):
return None
elif exc_info and isinstance(exc_info[1], ConnectedError):
return None
elif exc_info and isinstance(exc_info[1], KeyboardInterrupt):
return None
elif exc_info and isinstance(exc_info[1], OSError):
return None
elif exc_info and isinstance(exc_info[1], AuthKeyDuplicatedError):
return None
if not python36:
if exc_info and isinstance(exc_info[1], CancelError):
return None
if time() <= report_time + 30:
report_time = time()
return None
else:
report_time = time()
return event
report_time = time()
git_hash = run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode()
sentry_sdk.init(
"https://a0e1ef3c67ca48f4b1ecfc5538528ef3@o416616.ingest.sentry.io/5312335",
traces_sample_rate=1.0,
release=git_hash,
before_send=before_send,
environment="production",
integrations=[RedisIntegration()]
)
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
await bot.send_message(
int(config['log_chatid']),
message
)