RSS-to-Telegram-Bot/src/env.py

265 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
from typing import Optional
from .compat import Final
import asyncio
import os
import sys
import logging
import re
import argparse
from telethon import TelegramClient
from telethon.tl.types import User, InputPeerUser
from python_socks import parse_proxy_url
from dotenv import load_dotenv
from pathlib import Path
from .version import __version__
logging.basicConfig(level=logging.INFO)
# ----- utils -----
def __bool_parser(var: Optional[str], default_value: bool = False) -> bool:
if not var:
return default_value
if var.isdecimal() or var.lstrip('-').isdecimal():
return int(var) > 0
var = var.upper()
if var in ('FALSE', 'NONE', 'NULL', 'NO', 'NOT', 'DISABLE', 'DISABLED', 'INACTIVE', 'DEACTIVATED', 'OFF'):
return False
if var in ('TRUE', 'YES', 'OK', 'ENABLE', 'ENABLED', 'ACTIVE', 'ACTIVATED', 'ON'):
return True
return default_value
def __list_parser(var: Optional[str]) -> list[str]:
if not var:
return []
var_t = re.split(r'[\s,;]+', var.strip())
return var_t
# ----- determine the environment -----
__arg_parser = argparse.ArgumentParser(
description='RSS to Telegram Bot, a Telegram RSS bot that cares about your reading experience.')
__arg_parser.add_argument('-c', '--config', metavar='/path/to/config/folder', type=str, nargs=1,
help='path to the config folder')
cli_args = __arg_parser.parse_args()
cli_entry = sys.argv[0] # expect `-m` or `/path/to/telegramRSSbot.py`
custom_config_path = cli_args.config[0] if cli_args.config else None
is_self_run_as_a_whole_package = cli_entry.endswith('telegramRSSbot.py')
user_home = os.path.expanduser('~')
self_path = os.path.dirname(__file__)
self_module_name = os.path.basename(self_path)
if custom_config_path:
config_folder_path = os.path.normpath(os.path.abspath(custom_config_path))
elif is_self_run_as_a_whole_package:
config_folder_path = os.path.normpath(os.path.join(self_path, '..', 'config'))
else:
config_folder_path = os.path.join(user_home, '.rsstt')
Path(config_folder_path).mkdir(parents=True, exist_ok=True)
logging.info(f'Config folder: {config_folder_path}')
# ----- load .env -----
dot_env_paths = (os.path.join(config_folder_path, '.env'),
os.path.join(os.path.abspath('.'), '.env'))
if is_self_run_as_a_whole_package:
dot_env_paths = (os.path.normpath(os.path.join(self_path, '..', '.env')),) + dot_env_paths
for dot_env_path in sorted(set(dot_env_paths), key=dot_env_paths.index):
if os.path.isfile(dot_env_path):
load_dotenv(dot_env_path, override=True)
logging.info(f'Found .env file at "{dot_env_path}", loaded')
# ----- get version -----
if is_self_run_as_a_whole_package:
# noinspection PyBroadException
try:
with open(os.path.normpath(os.path.join(self_path, '..', '.version')), 'r') as v:
_version = v.read().strip()
except Exception:
_version = 'dirty'
if _version == 'dirty':
from subprocess import Popen, PIPE, DEVNULL
# noinspection PyBroadException
try:
with Popen(['git', 'describe', '--tags'], shell=False, stdout=PIPE, stderr=DEVNULL, bufsize=-1) as __:
__.wait(3)
_version = __.stdout.read().decode().strip()
with Popen(['git', 'branch', '--show-current'], shell=False, stdout=PIPE, stderr=DEVNULL, bufsize=-1) as __:
__.wait(3)
__ = __.stdout.read().decode().strip()
if __:
_version += f'@{__}'
except Exception:
_version = 'dirty'
if not _version or _version == '@':
_version = 'dirty'
else:
_version = 'dirty'
if not re.match(r'v?\d+\.\d+(\.\d+)?', _version):
_version = 'v' + (__version__ + '-' + _version if not _version == 'dirty' else __version__)
VERSION: Final = _version
del _version
# ----- basic config -----
SAMPLE_APIS: Final = {
# https://github.com/DrKLO/Telegram/blob/master/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java
4: '014b35b6184100b085b0d0572f9b5103',
# https://github.com/TelegramMessenger/Telegram-iOS/blob/master/build-system/verify.sh
8: '7245de8e747a0d6fbe11f7cc14fcc0bb',
# https://github.com/overtake/TelegramSwift/blob/master/Telegram-Mac/Config.swift
9: '3975f648bb682ee889f35483bc618d1c',
# https://github.com/vysheng/tg/blob/master/loop.h
2899: '36722c72256a24c1225de00eb6a1ca74',
# https://github.com/telegramdesktop/tdesktop/blob/dev/docs/api_credentials.md
17349: '344583e45741c457fe1862106095a5eb',
# https://github.com/tdlib/td/blob/master/example/uwp/app/MainPage.xaml.cs
94575: 'a3406de8d171bb422bb6ddf3bbd800e2',
# https://github.com/morethanwords/tweb/blob/master/t.py
1025907: '452b0359b988148995f22ff0f4229750'
}
API_ID: Final = int(os.environ['API_ID']) if os.environ.get('API_ID') else None
API_HASH: Final = os.environ.get('API_HASH')
TOKEN: Final = os.environ.get('TOKEN')
try:
_chatid = os.environ.get('CHATID')
_chatid = int(_chatid) if isinstance(_chatid, str) and _chatid.lstrip('-').isdecimal() else _chatid
_manager = os.environ.get('MANAGER') or _chatid
MANAGER: Final = int(_manager) if isinstance(_manager, str) and _manager.lstrip('-').isdecimal() else _manager
del _chatid
del _manager
if not all((TOKEN, MANAGER)):
logging.critical('"TOKEN" OR "MANAGER" NOT SET! PLEASE CHECK YOUR SETTINGS!')
exit(1)
except Exception as e:
logging.critical('INVALID "MANAGER"! PLEASE CHECK YOUR SETTINGS!', exc_info=e)
exit(1)
TELEGRAPH_TOKEN: Final = __list_parser(os.environ.get('TELEGRAPH_TOKEN'))
MULTIUSER: Final = __bool_parser(os.environ.get('MULTIUSER'), default_value=True)
CRON_SECOND: Final = int(os.environ.get('CRON_SECOND') or 0) % 60
# ----- proxy config -----
DEFAULT_PROXY: Final = os.environ.get('SOCKS_PROXY') or os.environ.get('socks_proxy') \
or os.environ.get('HTTP_PROXY') or os.environ.get('http_proxy') \
or os.environ.get('HTTPS_PROXY') or os.environ.get('https_proxy')
TELEGRAM_PROXY: Final = os.environ.get('T_PROXY') or DEFAULT_PROXY
if TELEGRAM_PROXY:
_parsed = parse_proxy_url(TELEGRAM_PROXY.replace('socks5h', 'socks5'))
TELEGRAM_PROXY_DICT: Final = {
'proxy_type': _parsed[0],
'addr': _parsed[1],
'port': _parsed[2],
'username': _parsed[3],
'password': _parsed[4],
'rdns': True
}
TELEGRAPH_PROXY_DICT: Final = {
'proxy_type': _parsed[0],
'host': _parsed[1],
'port': _parsed[2],
'username': _parsed[3],
'password': _parsed[4],
'rdns': True
}
del _parsed
else:
TELEGRAM_PROXY_DICT: Final = None
TELEGRAPH_PROXY_DICT: Final = None
R_PROXY: Final = os.environ.get('R_PROXY') or DEFAULT_PROXY
if R_PROXY:
REQUESTS_PROXIES: Final = {
'all': R_PROXY
}
else:
REQUESTS_PROXIES: Final = {}
PROXY_BYPASS_PRIVATE: Final = __bool_parser(os.environ.get('PROXY_BYPASS_PRIVATE'))
PROXY_BYPASS_DOMAINS: Final = __list_parser(os.environ.get('PROXY_BYPASS_DOMAINS'))
USER_AGENT: Final = os.environ.get('USER_AGENT') or f'RSStT/{__version__} RSS Reader'
IPV6_PRIOR: Final = __bool_parser(os.environ.get('IPV6_PRIOR'))
# ----- img relay server config -----
_img_relay_server = os.environ.get('IMG_RELAY_SERVER') or 'https://rsstt-img-relay.rongrong.workers.dev/'
IMG_RELAY_SERVER: Final = ('https://' if not _img_relay_server.startswith('http') else '') \
+ _img_relay_server \
+ ('' if _img_relay_server.endswith(('/', '=')) else '/')
del _img_relay_server
# ----- images.weserv.nl config -----
_images_weserv_nl = os.environ.get('IMAGES_WESERV_NL') or 'https://images.weserv.nl/'
IMAGES_WESERV_NL: Final = ('https://' if not _images_weserv_nl.startswith('http') else '') \
+ _images_weserv_nl \
+ ('' if _images_weserv_nl.endswith('/') else '/')
del _images_weserv_nl
# ----- db config -----
_database_url = os.environ.get('DATABASE_URL') or f'sqlite://{config_folder_path}/db.sqlite3?journal_mode=OFF'
DATABASE_URL: Final = (_database_url.replace('postgresql', 'postgres', 1) if _database_url.startswith('postgresql')
else _database_url)
del _database_url
# ----- misc config -----
DEBUG: Final = __bool_parser(os.environ.get('DEBUG'))
TABLE_TO_IMAGE: Final = __bool_parser(os.environ.get('TABLE_TO_IMAGE'))
# ----- environment config -----
RAILWAY_STATIC_URL: Final = os.environ.get('RAILWAY_STATIC_URL')
PORT: Final = int(os.environ.get('PORT', 0)) or (8080 if RAILWAY_STATIC_URL else None)
# !!!!! DEPRECATED WARNING !!!!!
if os.environ.get('DELAY'):
logging.warning('Env var "DELAY" is DEPRECATED and of no use!\n'
'To avoid this warning, remove this env var.')
if os.environ.get('CHATID'):
logging.warning('Env var "CHATID" is DEPRECATED!\n'
'To avoid this warning, remove this env var.')
if any((os.environ.get('REDISHOST'), os.environ.get('REDISUSER'), os.environ.get('REDISPASSWORD'),
os.environ.get('REDISPORT'), os.environ.get('REDIS_NUM'),)):
logging.warning('Redis DB is DEPRECATED!\n'
'ALL SUBS IN THE OLD DB WILL NOT BE MIGRATED. '
'IF YOU NEED TO BACKUP YOUR SUBS, DOWNGRADE AND USE "/export" COMMAND TO BACKUP.\n\n'
'Please remove these env vars (if exist):\n'
'REDISHOST\n'
'REDISUSER\n'
'REDISPASSWORD\n'
'REDISPORT\n'
'REDIS_NUM')
if is_self_run_as_a_whole_package and os.path.exists(os.path.join(config_folder_path, 'rss.db')):
os.rename(os.path.join(config_folder_path, 'rss.db'), os.path.join(config_folder_path, 'rss.db.bak'))
logging.warning('Sqlite DB "rss.db" with old schema is DEPRECATED and renamed to "rss.db.bak" automatically!\n'
'ALL SUBS IN THE OLD DB WILL NOT BE MIGRATED. '
'IF YOU NEED TO BACKUP YOUR SUBS, DOWNGRADE AND USE "/export" COMMAND TO BACKUP.')
# ----- shared var -----
bot: Optional[TelegramClient] = None # placeholder
bot_id: Optional[int] = None # placeholder
bot_peer: Optional[User] = None # placeholder
bot_input_peer: Optional[InputPeerUser] = None # placeholder
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)