import logging import os import threading import time import random import string import subprocess import requests import aria2p import qbittorrentapi as qba import telegram.ext as tg from dotenv import load_dotenv from pyrogram import Client from telegraph import Telegraph import psycopg2 from psycopg2 import Error import socket import faulthandler faulthandler.enable() socket.setdefaulttimeout(600) botStartTime = time.time() if os.path.exists('log.txt'): with open('log.txt', 'r+') as f: f.truncate(0) logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[logging.FileHandler('log.txt'), logging.StreamHandler()], level=logging.INFO) LOGGER = logging.getLogger(__name__) CONFIG_FILE_URL = os.environ.get('CONFIG_FILE_URL', None) if CONFIG_FILE_URL is not None: res = requests.get(CONFIG_FILE_URL) if res.status_code == 200: with open('config.env', 'wb+') as f: f.write(res.content) f.close() else: logging.error(res.status_code) load_dotenv('config.env') SERVER_PORT = os.environ.get('SERVER_PORT', None) PORT = os.environ.get('PORT', SERVER_PORT) web = subprocess.Popen([f"gunicorn wserver:start_server --bind 0.0.0.0:{PORT} --worker-class aiohttp.GunicornWebWorker"], shell=True) time.sleep(1) alive = subprocess.Popen(["python3", "alive.py"]) subprocess.run(["mkdir", "-p", "qBittorrent/config"]) subprocess.run(["cp", "qBittorrent.conf", "qBittorrent/config/qBittorrent.conf"]) subprocess.run(["qbittorrent-nox", "-d", "--profile=."]) Interval = [] DRIVES_NAMES = [] DRIVES_IDS = [] INDEX_URLS = [] def getConfig(name: str): return os.environ[name] def mktable(): try: conn = psycopg2.connect(DB_URI) cur = conn.cursor() sql = "CREATE TABLE users (uid bigint, sudo boolean DEFAULT FALSE);" cur.execute(sql) conn.commit() logging.info("Table Created!") except Error as e: logging.error(e) exit(1) try: if bool(getConfig('_____REMOVE_THIS_LINE_____')): logging.error('The README.md file there to be read! Exiting now!') exit() except KeyError: pass aria2 = aria2p.API( aria2p.Client( host="http://localhost", port=6800, secret="", ) ) def get_client() -> qba.TorrentsAPIMixIn: qb_client = qba.Client(host="localhost", port=8090, username="admin", password="adminadmin") try: qb_client.auth_log_in() #qb_client.application.set_preferences({"disk_cache":64, "incomplete_files_ext":True, "max_connec":3000, "max_connec_per_torrent":300, "async_io_threads":8, "preallocate_all":True, "upnp":True, "dl_limit":-1, "up_limit":-1, "dht":True, "pex":True, "lsd":True, "encryption":0, "queueing_enabled":True, "max_active_downloads":15, "max_active_torrents":50, "dont_count_slow_torrents":True, "bittorrent_protocol":0, "recheck_completed_torrents":True, "enable_multi_connections_from_same_ip":True, "slow_torrent_dl_rate_threshold":100,"slow_torrent_inactive_timer":600}) return qb_client except qba.LoginFailed as e: logging.error(str(e)) return None DOWNLOAD_DIR = None BOT_TOKEN = None download_dict_lock = threading.Lock() status_reply_dict_lock = threading.Lock() # Key: update.effective_chat.id # Value: telegram.Message status_reply_dict = {} # Key: update.message.message_id # Value: An object of Status download_dict = {} # Stores list of users and chats the bot is authorized to use in AUTHORIZED_CHATS = set() SUDO_USERS = set() AS_DOC_USERS = set() AS_MEDIA_USERS = set() if os.path.exists('authorized_chats.txt'): with open('authorized_chats.txt', 'r+') as f: lines = f.readlines() for line in lines: AUTHORIZED_CHATS.add(int(line.split()[0])) if os.path.exists('sudo_users.txt'): with open('sudo_users.txt', 'r+') as f: lines = f.readlines() for line in lines: SUDO_USERS.add(int(line.split()[0])) try: achats = getConfig('AUTHORIZED_CHATS') achats = achats.split(" ") for chats in achats: AUTHORIZED_CHATS.add(int(chats)) except: pass try: schats = getConfig('SUDO_USERS') schats = schats.split(" ") for chats in schats: SUDO_USERS.add(int(chats)) except: pass try: BOT_TOKEN = getConfig('BOT_TOKEN') parent_id = getConfig('GDRIVE_FOLDER_ID') DOWNLOAD_DIR = getConfig('DOWNLOAD_DIR') if not DOWNLOAD_DIR.endswith("/"): DOWNLOAD_DIR = DOWNLOAD_DIR + '/' DOWNLOAD_STATUS_UPDATE_INTERVAL = int(getConfig('DOWNLOAD_STATUS_UPDATE_INTERVAL')) OWNER_ID = int(getConfig('OWNER_ID')) AUTO_DELETE_MESSAGE_DURATION = int(getConfig('AUTO_DELETE_MESSAGE_DURATION')) TELEGRAM_API = getConfig('TELEGRAM_API') TELEGRAM_HASH = getConfig('TELEGRAM_HASH') GITHUB_USER_NAME = getConfig('GITHUB_USER_NAME') GITHUB_TOKEN = getConfig('GITHUB_TOKEN') GITHUB_DUMPER_REPO_NAME = getConfig('GITHUB_DUMPER_REPO_NAME') GITHUB_DUMMY_REPO_NAME = getConfig('GITHUB_DUMMY_REPO_NAME') TELEGRAM_CHANNEL_NAME = getConfig('TELEGRAM_CHANNEL_NAME') DUMPER_REPO_WORKFLOW_URL = getConfig('DUMPER_REPO_WORKFLOW_URL') GITHUB_ORG_NAME = getConfig('GITHUB_ORG_NAME') GITHUB_USER_EMAIL = getConfig('GITHUB_USER_EMAIL') except KeyError as e: LOGGER.error("One or more env variables missing! Exiting now") exit(1) try: DB_URI = getConfig('DATABASE_URL') if len(DB_URI) == 0: raise KeyError except KeyError: DB_URI = None if DB_URI is not None: try: conn = psycopg2.connect(DB_URI) cur = conn.cursor() sql = "SELECT * from users;" cur.execute(sql) rows = cur.fetchall() #returns a list ==> (uid, sudo) for row in rows: AUTHORIZED_CHATS.add(row[0]) if row[1]: SUDO_USERS.add(row[0]) except Error as e: if 'relation "users" does not exist' in str(e): mktable() else: LOGGER.error(e) exit(1) finally: cur.close() conn.close() LOGGER.info("Generating USER_SESSION_STRING") app = Client('Slam', api_id=int(TELEGRAM_API), api_hash=TELEGRAM_HASH, bot_token=BOT_TOKEN) # Generate Telegraph Token sname = ''.join(random.SystemRandom().choices(string.ascii_letters, k=8)) LOGGER.info("Generating TELEGRAPH_TOKEN using '" + sname + "' name") telegraph = Telegraph() telegraph.create_account(short_name=sname) telegraph_token = telegraph.get_access_token() try: TG_SPLIT_SIZE = getConfig('TG_SPLIT_SIZE') if len(TG_SPLIT_SIZE) == 0 or int(TG_SPLIT_SIZE) > 2097152000: raise KeyError else: TG_SPLIT_SIZE = int(TG_SPLIT_SIZE) except KeyError: TG_SPLIT_SIZE = 2097152000 try: STATUS_LIMIT = getConfig('STATUS_LIMIT') if len(STATUS_LIMIT) == 0: raise KeyError else: STATUS_LIMIT = int(STATUS_LIMIT) except KeyError: STATUS_LIMIT = None try: MEGA_API_KEY = getConfig('MEGA_API_KEY') except KeyError: logging.warning('MEGA API KEY not provided!') MEGA_API_KEY = None try: MEGA_EMAIL_ID = getConfig('MEGA_EMAIL_ID') MEGA_PASSWORD = getConfig('MEGA_PASSWORD') if len(MEGA_EMAIL_ID) == 0 or len(MEGA_PASSWORD) == 0: raise KeyError except KeyError: logging.warning('MEGA Credentials not provided!') MEGA_EMAIL_ID = None MEGA_PASSWORD = None try: UPTOBOX_TOKEN = getConfig('UPTOBOX_TOKEN') except KeyError: logging.warning('UPTOBOX_TOKEN not provided!') UPTOBOX_TOKEN = None try: INDEX_URL = getConfig('INDEX_URL') if len(INDEX_URL) == 0: INDEX_URL = None INDEX_URLS.append(None) else: INDEX_URLS.append(INDEX_URL) except KeyError: INDEX_URL = None INDEX_URLS.append(None) try: TORRENT_DIRECT_LIMIT = getConfig('TORRENT_DIRECT_LIMIT') if len(TORRENT_DIRECT_LIMIT) == 0: TORRENT_DIRECT_LIMIT = None except KeyError: TORRENT_DIRECT_LIMIT = None try: CLONE_LIMIT = getConfig('CLONE_LIMIT') if len(CLONE_LIMIT) == 0: CLONE_LIMIT = None except KeyError: CLONE_LIMIT = None try: MEGA_LIMIT = getConfig('MEGA_LIMIT') if len(MEGA_LIMIT) == 0: MEGA_LIMIT = None except KeyError: MEGA_LIMIT = None try: TAR_UNZIP_LIMIT = getConfig('TAR_UNZIP_LIMIT') if len(TAR_UNZIP_LIMIT) == 0: TAR_UNZIP_LIMIT = None except KeyError: TAR_UNZIP_LIMIT = None try: BUTTON_FOUR_NAME = getConfig('BUTTON_FOUR_NAME') BUTTON_FOUR_URL = getConfig('BUTTON_FOUR_URL') if len(BUTTON_FOUR_NAME) == 0 or len(BUTTON_FOUR_URL) == 0: raise KeyError except KeyError: BUTTON_FOUR_NAME = None BUTTON_FOUR_URL = None try: BUTTON_FIVE_NAME = getConfig('BUTTON_FIVE_NAME') BUTTON_FIVE_URL = getConfig('BUTTON_FIVE_URL') if len(BUTTON_FIVE_NAME) == 0 or len(BUTTON_FIVE_URL) == 0: raise KeyError except KeyError: BUTTON_FIVE_NAME = None BUTTON_FIVE_URL = None try: BUTTON_SIX_NAME = getConfig('BUTTON_SIX_NAME') BUTTON_SIX_URL = getConfig('BUTTON_SIX_URL') if len(BUTTON_SIX_NAME) == 0 or len(BUTTON_SIX_URL) == 0: raise KeyError except KeyError: BUTTON_SIX_NAME = None BUTTON_SIX_URL = None try: STOP_DUPLICATE = getConfig('STOP_DUPLICATE') STOP_DUPLICATE = STOP_DUPLICATE.lower() == 'true' except KeyError: STOP_DUPLICATE = False try: VIEW_LINK = getConfig('VIEW_LINK') VIEW_LINK = VIEW_LINK.lower() == 'true' except KeyError: VIEW_LINK = False try: IS_TEAM_DRIVE = getConfig('IS_TEAM_DRIVE') IS_TEAM_DRIVE = IS_TEAM_DRIVE.lower() == 'true' except KeyError: IS_TEAM_DRIVE = False try: USE_SERVICE_ACCOUNTS = getConfig('USE_SERVICE_ACCOUNTS') USE_SERVICE_ACCOUNTS = USE_SERVICE_ACCOUNTS.lower() == 'true' except KeyError: USE_SERVICE_ACCOUNTS = False try: BLOCK_MEGA_FOLDER = getConfig('BLOCK_MEGA_FOLDER') BLOCK_MEGA_FOLDER = BLOCK_MEGA_FOLDER.lower() == 'true' except KeyError: BLOCK_MEGA_FOLDER = False try: BLOCK_MEGA_LINKS = getConfig('BLOCK_MEGA_LINKS') BLOCK_MEGA_LINKS = BLOCK_MEGA_LINKS.lower() == 'true' except KeyError: BLOCK_MEGA_LINKS = False try: SHORTENER = getConfig('SHORTENER') SHORTENER_API = getConfig('SHORTENER_API') if len(SHORTENER) == 0 or len(SHORTENER_API) == 0: raise KeyError except KeyError: SHORTENER = None SHORTENER_API = None try: IGNORE_PENDING_REQUESTS = getConfig("IGNORE_PENDING_REQUESTS") IGNORE_PENDING_REQUESTS = IGNORE_PENDING_REQUESTS.lower() == 'true' except KeyError: IGNORE_PENDING_REQUESTS = False try: BASE_URL = getConfig('BASE_URL_OF_BOT') if len(BASE_URL) == 0: raise KeyError except KeyError: logging.warning('BASE_URL_OF_BOT not provided!') BASE_URL = None try: IS_VPS = getConfig('IS_VPS') IS_VPS = IS_VPS.lower() == 'true' except KeyError: IS_VPS = False try: AS_DOCUMENT = getConfig('AS_DOCUMENT') AS_DOCUMENT = AS_DOCUMENT.lower() == 'true' except KeyError: AS_DOCUMENT = False try: RECURSIVE_SEARCH = getConfig('RECURSIVE_SEARCH') RECURSIVE_SEARCH = RECURSIVE_SEARCH.lower() == 'true' except KeyError: RECURSIVE_SEARCH = False try: TOKEN_PICKLE_URL = getConfig('TOKEN_PICKLE_URL') if len(TOKEN_PICKLE_URL) == 0: TOKEN_PICKLE_URL = None else: res = requests.get(TOKEN_PICKLE_URL) if res.status_code == 200: with open('token.pickle', 'wb+') as f: f.write(res.content) f.close() else: logging.error(res.status_code) raise KeyError except KeyError: pass try: ACCOUNTS_ZIP_URL = getConfig('ACCOUNTS_ZIP_URL') if len(ACCOUNTS_ZIP_URL) == 0: ACCOUNTS_ZIP_URL = None else: res = requests.get(ACCOUNTS_ZIP_URL) if res.status_code == 200: with open('accounts.zip', 'wb+') as f: f.write(res.content) f.close() else: logging.error(res.status_code) raise KeyError subprocess.run(["unzip", "-q", "-o", "accounts.zip"]) os.remove("accounts.zip") except KeyError: pass try: MULTI_SEARCH_URL = getConfig('MULTI_SEARCH_URL') if len(MULTI_SEARCH_URL) == 0: MULTI_SEARCH_URL = None else: res = requests.get(MULTI_SEARCH_URL) if res.status_code == 200: with open('drive_folder', 'wb+') as f: f.write(res.content) f.close() else: logging.error(res.status_code) raise KeyError except KeyError: pass DRIVES_NAMES.append("Main") DRIVES_IDS.append(parent_id) if os.path.exists('drive_folder'): with open('drive_folder', 'r+') as f: lines = f.readlines() for line in lines: try: temp = line.strip().split() DRIVES_IDS.append(temp[1]) DRIVES_NAMES.append(temp[0].replace("_", " ")) except: pass try: INDEX_URLS.append(temp[2]) except IndexError as e: INDEX_URLS.append(None) updater = tg.Updater(token=BOT_TOKEN) bot = updater.bot dispatcher = updater.dispatcher