Path: blob/master/bot/modules/bot_settings.py
1624 views
from aiofiles import open as aiopen1from aiofiles.os import remove, rename, path as aiopath2from aioshutil import rmtree3from asyncio import (4create_subprocess_exec,5create_subprocess_shell,6sleep,7gather,8)9from functools import partial10from io import BytesIO11from os import getcwd12from pyrogram.filters import create13from pyrogram.handlers import MessageHandler14from time import time1516from .. import (17LOGGER,18drives_ids,19drives_names,20index_urls,21intervals,22aria2_options,23task_dict,24qbit_options,25sabnzbd_client,26nzb_options,27jd_listener_lock,28excluded_extensions,29included_extensions,30auth_chats,31sudo_users,32)33from ..helper.ext_utils.bot_utils import (34SetInterval,35new_task,36)37from ..core.config_manager import Config38from ..core.telegram_manager import TgClient39from ..core.torrent_manager import TorrentManager40from ..core.startup import update_qb_options, update_nzb_options, update_variables41from ..helper.ext_utils.db_handler import database42from ..core.jdownloader_booter import jdownloader43from ..helper.ext_utils.task_manager import start_from_queued44from ..helper.mirror_leech_utils.rclone_utils.serve import rclone_serve_booter45from ..helper.telegram_helper.button_build import ButtonMaker46from ..helper.telegram_helper.message_utils import (47send_message,48send_file,49edit_message,50update_status_message,51delete_message,52)53from .rss import add_job54from .search import initiate_search_tools5556start = 057state = "view"58handler_dict = {}59DEFAULT_VALUES = {60"LEECH_SPLIT_SIZE": TgClient.MAX_SPLIT_SIZE,61"RSS_DELAY": 600,62"STATUS_UPDATE_INTERVAL": 15,63"SEARCH_LIMIT": 0,64"UPSTREAM_BRANCH": "master",65"DEFAULT_UPLOAD": "rc",66}676869async def get_buttons(key=None, edit_type=None):70buttons = ButtonMaker()71if key is None:72buttons.data_button("Config Variables", "botset var")73buttons.data_button("Private Files", "botset private")74buttons.data_button("Qbit Settings", "botset qbit")75buttons.data_button("Aria2c Settings", "botset aria")76buttons.data_button("Sabnzbd Settings", "botset nzb")77buttons.data_button("JDownloader Sync", "botset syncjd")78buttons.data_button("Close", "botset close")79msg = "Bot Settings:"80elif edit_type is not None:81if edit_type == "botvar":82msg = ""83buttons.data_button("Back", "botset var")84if key not in ["TELEGRAM_HASH", "TELEGRAM_API", "OWNER_ID", "BOT_TOKEN"]:85buttons.data_button("Default", f"botset resetvar {key}")86buttons.data_button("Close", "botset close")87if key in [88"CMD_SUFFIX",89"OWNER_ID",90"USER_SESSION_STRING",91"TELEGRAM_HASH",92"TELEGRAM_API",93"BOT_TOKEN",94"TG_PROXY",95]:96msg += "Restart required for this edit to take effect! You will not see the changes in bot vars, the edit will be in database only!\n\n"97msg += f"Send a valid value for {key}. Current value is '{Config.get(key)}'. Timeout: 60 sec"98elif edit_type == "ariavar":99buttons.data_button("Back", "botset aria")100if key != "newkey":101buttons.data_button("Empty String", f"botset emptyaria {key}")102buttons.data_button("Close", "botset close")103msg = (104"Send a key with value. Example: https-proxy-user:value. Timeout: 60 sec"105if key == "newkey"106else f"Send a valid value for {key}. Current value is '{aria2_options[key]}'. Timeout: 60 sec"107)108elif edit_type == "qbitvar":109buttons.data_button("Back", "botset qbit")110buttons.data_button("Empty String", f"botset emptyqbit {key}")111buttons.data_button("Close", "botset close")112msg = f"Send a valid value for {key}. Current value is '{qbit_options[key]}'. Timeout: 60 sec"113elif edit_type == "nzbvar":114buttons.data_button("Back", "botset nzb")115buttons.data_button("Default", f"botset resetnzb {key}")116buttons.data_button("Empty String", f"botset emptynzb {key}")117buttons.data_button("Close", "botset close")118msg = f"Send a valid value for {key}. Current value is '{nzb_options[key]}'.\nIf the value is list then separate them by space or ,\nExample: .exe,info or .exe .info\nTimeout: 60 sec"119elif edit_type.startswith("nzbsevar"):120index = 0 if key == "newser" else int(edit_type.replace("nzbsevar", ""))121if key == "newser":122buttons.data_button("Back", "botset nzbserver")123msg = "Send one server as dictionary {}, like in config.py without []. Timeout: 60 sec"124else:125buttons.data_button("Empty", f"botset emptyserkey {index} {key}")126buttons.data_button("Back", f"botset nzbser{index}")127msg = f"Send a valid value for {key} in server {Config.USENET_SERVERS[index]['name']}. Current value is {Config.USENET_SERVERS[index][key]}. Timeout: 60 sec"128buttons.data_button("Close", "botset close")129elif key == "var":130conf_dict = Config.get_all()131for k in list(conf_dict.keys())[start : 10 + start]:132if k in ["DATABASE_URL", "DATABASE_NAME"] and state != "view":133continue134buttons.data_button(k, f"botset botvar {k}")135if state == "view":136buttons.data_button("Edit", "botset edit var")137else:138buttons.data_button("View", "botset view var")139buttons.data_button("Back", "botset back")140buttons.data_button("Close", "botset close")141for x in range(0, len(conf_dict), 10):142buttons.data_button(143f"{int(x / 10)}", f"botset start var {x}", position="footer"144)145msg = f"Config Variables | Page: {int(start / 10)} | State: {state}"146elif key == "private":147buttons.data_button("Back", "botset back")148buttons.data_button("Close", "botset close")149msg = """Send private file: config.py, token.pickle, rclone.conf, accounts.zip, list_drives.txt, cookies.txt, .netrc or any other private file!150To delete private file send only the file name as text message.151Note: Changing .netrc will not take effect for aria2c until restart.152Timeout: 60 sec"""153elif key == "aria":154for k in list(aria2_options.keys())[start : 10 + start]:155if k not in ["checksum", "index-out", "out", "pause", "select-file"]:156buttons.data_button(k, f"botset ariavar {k}")157if state == "view":158buttons.data_button("Edit", "botset edit aria")159else:160buttons.data_button("View", "botset view aria")161buttons.data_button("Add new key", "botset ariavar newkey")162buttons.data_button("Back", "botset back")163buttons.data_button("Close", "botset close")164for x in range(0, len(aria2_options), 10):165buttons.data_button(166f"{int(x / 10)}", f"botset start aria {x}", position="footer"167)168msg = f"Aria2c Options | Page: {int(start / 10)} | State: {state}"169elif key == "qbit":170for k in list(qbit_options.keys())[start : 10 + start]:171buttons.data_button(k, f"botset qbitvar {k}")172if state == "view":173buttons.data_button("Edit", "botset edit qbit")174else:175buttons.data_button("View", "botset view qbit")176buttons.data_button("Sync Qbittorrent", "botset syncqbit")177buttons.data_button("Back", "botset back")178buttons.data_button("Close", "botset close")179for x in range(0, len(qbit_options), 10):180buttons.data_button(181f"{int(x / 10)}", f"botset start qbit {x}", position="footer"182)183msg = f"Qbittorrent Options | Page: {int(start / 10)} | State: {state}"184elif key == "nzb":185for k in list(nzb_options.keys())[start : 10 + start]:186buttons.data_button(k, f"botset nzbvar {k}")187if state == "view":188buttons.data_button("Edit", "botset edit nzb")189else:190buttons.data_button("View", "botset view nzb")191buttons.data_button("Servers", "botset nzbserver")192buttons.data_button("Sync Sabnzbd", "botset syncnzb")193buttons.data_button("Back", "botset back")194buttons.data_button("Close", "botset close")195for x in range(0, len(nzb_options), 10):196buttons.data_button(197f"{int(x / 10)}", f"botset start nzb {x}", position="footer"198)199msg = f"Sabnzbd Options | Page: {int(start / 10)} | State: {state}"200elif key == "nzbserver":201if len(Config.USENET_SERVERS) > 0:202for index, k in enumerate(Config.USENET_SERVERS[start : 10 + start]):203buttons.data_button(k["name"], f"botset nzbser{index}")204buttons.data_button("Add New", "botset nzbsevar newser")205buttons.data_button("Back", "botset nzb")206buttons.data_button("Close", "botset close")207if len(Config.USENET_SERVERS) > 10:208for x in range(0, len(Config.USENET_SERVERS), 10):209buttons.data_button(210f"{int(x / 10)}", f"botset start nzbser {x}", position="footer"211)212msg = f"Usenet Servers | Page: {int(start / 10)} | State: {state}"213elif key.startswith("nzbser"):214index = int(key.replace("nzbser", ""))215for k in list(Config.USENET_SERVERS[index].keys())[start : 10 + start]:216buttons.data_button(k, f"botset nzbsevar{index} {k}")217if state == "view":218buttons.data_button("Edit", f"botset edit {key}")219else:220buttons.data_button("View", f"botset view {key}")221buttons.data_button("Remove Server", f"botset remser {index}")222buttons.data_button("Back", "botset nzbserver")223buttons.data_button("Close", "botset close")224if len(Config.USENET_SERVERS[index].keys()) > 10:225for x in range(0, len(Config.USENET_SERVERS[index]), 10):226buttons.data_button(227f"{int(x / 10)}", f"botset start {key} {x}", position="footer"228)229msg = f"Server Keys | Page: {int(start / 10)} | State: {state}"230231button = buttons.build_menu(1) if key is None else buttons.build_menu(2)232return msg, button233234235async def update_buttons(message, key=None, edit_type=None):236msg, button = await get_buttons(key, edit_type)237await edit_message(message, msg, button)238239240@new_task241async def edit_variable(_, message, pre_message, key):242handler_dict[message.chat.id] = False243value = str(message.text)244if value.lower() == "true":245value = True246elif value.lower() == "false":247value = False248if key == "INCOMPLETE_TASK_NOTIFIER" and Config.DATABASE_URL:249await database.trunc_table("tasks")250elif key == "STATUS_UPDATE_INTERVAL":251value = int(value)252if len(task_dict) != 0 and (st := intervals["status"]):253for cid, intvl in list(st.items()):254intvl.cancel()255intervals["status"][cid] = SetInterval(256value, update_status_message, cid257)258elif key == "TORRENT_TIMEOUT":259await TorrentManager.change_aria2_option("bt-stop-timeout", value)260value = int(value)261elif key == "LEECH_SPLIT_SIZE":262value = min(int(value), TgClient.MAX_SPLIT_SIZE)263elif key == "BASE_URL_PORT":264value = int(value)265if Config.BASE_URL:266await (await create_subprocess_exec("pkill", "-9", "-f", "gunicorn")).wait()267await create_subprocess_shell(268f"gunicorn -k uvicorn.workers.UvicornWorker -w 1 web.wserver:app --bind 0.0.0.0:{value}"269)270elif key == "EXCLUDED_EXTENSIONS":271fx = value.split()272excluded_extensions.clear()273excluded_extensions.extend(["aria2", "!qB"])274for x in fx:275x = x.lstrip(".")276excluded_extensions.append(x.strip().lower())277elif key == "INCLUDED_EXTENSIONS":278fx = value.split()279included_extensions.clear()280for x in fx:281x = x.lstrip(".")282included_extensions.append(x.strip().lower())283elif key == "GDRIVE_ID":284if drives_names and drives_names[0] == "Main":285drives_ids[0] = value286else:287drives_ids.insert(0, value)288elif key == "INDEX_URL":289if drives_names and drives_names[0] == "Main":290index_urls[0] = value291else:292index_urls.insert(0, value)293elif key == "AUTHORIZED_CHATS":294aid = value.split()295auth_chats.clear()296for id_ in aid:297chat_id, *thread_ids = id_.split("|")298chat_id = int(chat_id.strip())299if thread_ids:300thread_ids = list(map(lambda x: int(x.strip()), thread_ids))301auth_chats[chat_id] = thread_ids302else:303auth_chats[chat_id] = []304elif key == "SUDO_USERS":305sudo_users.clear()306aid = value.split()307for id_ in aid:308sudo_users.append(int(id_.strip()))309elif value.isdigit():310value = int(value)311elif value.startswith("[") and value.endswith("]"):312value = eval(value)313elif value.startswith("{") and value.endswith("}"):314value = eval(value)315Config.set(key, value)316await update_buttons(pre_message, "var")317await delete_message(message)318await database.update_config({key: value})319if key in ["SEARCH_PLUGINS", "SEARCH_API_LINK"]:320await initiate_search_tools()321elif key in ["QUEUE_ALL", "QUEUE_DOWNLOAD", "QUEUE_UPLOAD"]:322await start_from_queued()323elif key in [324"RCLONE_SERVE_URL",325"RCLONE_SERVE_PORT",326"RCLONE_SERVE_USER",327"RCLONE_SERVE_PASS",328]:329await rclone_serve_booter()330elif key in ["JD_EMAIL", "JD_PASS"]:331await jdownloader.boot()332elif key == "RSS_DELAY":333add_job()334elif key == "USET_SERVERS":335for s in value:336await sabnzbd_client.set_special_config("servers", s)337338339@new_task340async def edit_aria(_, message, pre_message, key):341handler_dict[message.chat.id] = False342value = str(message.text)343if key == "newkey":344key, value = [x.strip() for x in value.split(":", 1)]345elif value.lower() == "true":346value = "true"347elif value.lower() == "false":348value = "false"349await TorrentManager.change_aria2_option(key, value)350await update_buttons(pre_message, "aria")351await delete_message(message)352await database.update_aria2(key, value)353354355@new_task356async def edit_qbit(_, message, pre_message, key):357handler_dict[message.chat.id] = False358value = str(message.text)359if value.lower() == "true":360value = True361elif value.lower() == "false":362value = False363elif key == "max_ratio":364value = float(value)365elif value.isdigit():366value = int(value)367await TorrentManager.qbittorrent.app.set_preferences({key: value})368qbit_options[key] = value369await update_buttons(pre_message, "qbit")370await delete_message(message)371await database.update_qbittorrent(key, value)372373374@new_task375async def edit_nzb(_, message, pre_message, key):376handler_dict[message.chat.id] = False377value = str(message.text)378if value.isdigit():379value = int(value)380elif value.startswith("[") and value.endswith("]"):381try:382value = ",".join(eval(value))383except Exception as e:384LOGGER.error(e)385await update_buttons(pre_message, "nzb")386return387res = await sabnzbd_client.set_config("misc", key, value)388nzb_options[key] = res["config"]["misc"][key]389await update_buttons(pre_message, "nzb")390await delete_message(message)391await database.update_nzb_config()392393394@new_task395async def edit_nzb_server(_, message, pre_message, key, index=0):396handler_dict[message.chat.id] = False397value = str(message.text)398if key == "newser":399if value.startswith("{") and value.endswith("}"):400try:401value = eval(value)402except:403await send_message(message, "Invalid dict format!")404await update_buttons(pre_message, "nzbserver")405return406res = await sabnzbd_client.add_server(value)407if not res["config"]["servers"][0]["host"]:408await send_message(message, "Invalid server!")409await update_buttons(pre_message, "nzbserver")410return411Config.USENET_SERVERS.append(value)412await update_buttons(pre_message, "nzbserver")413else:414await send_message(message, "Invalid dict format!")415await update_buttons(pre_message, "nzbserver")416return417else:418if value.isdigit():419value = int(value)420res = await sabnzbd_client.add_server(421{"name": Config.USENET_SERVERS[index]["name"], key: value}422)423if res["config"]["servers"][0][key] == "":424await send_message(message, "Invalid value")425return426Config.USENET_SERVERS[index][key] = value427await update_buttons(pre_message, f"nzbser{index}")428await delete_message(message)429await database.update_config({"USENET_SERVERS": Config.USENET_SERVERS})430431432async def sync_jdownloader():433async with jd_listener_lock:434if not Config.DATABASE_URL or not jdownloader.is_connected:435return436await jdownloader.device.system.exit_jd()437if await aiopath.exists("cfg.zip"):438await remove("cfg.zip")439await (440await create_subprocess_exec("7z", "a", "cfg.zip", "/JDownloader/cfg")441).wait()442await database.update_private_file("cfg.zip")443444445@new_task446async def update_private_file(_, message, pre_message):447handler_dict[message.chat.id] = False448if not message.media and (file_name := str(message.text)):449if await aiopath.isfile(file_name) and file_name != "config.py":450await remove(file_name)451if file_name == "accounts.zip":452if await aiopath.exists("accounts"):453await rmtree("accounts", ignore_errors=True)454if await aiopath.exists("rclone_sa"):455await rmtree("rclone_sa", ignore_errors=True)456Config.USE_SERVICE_ACCOUNTS = False457await database.update_config({"USE_SERVICE_ACCOUNTS": False})458elif file_name in {".netrc", "netrc"}:459await (await create_subprocess_exec("touch", ".netrc")).wait()460await (await create_subprocess_exec("chmod", "600", ".netrc")).wait()461await (await create_subprocess_exec("cp", ".netrc", "/root/.netrc")).wait()462await delete_message(message)463elif doc := message.document:464file_name = doc.file_name465fpath = f"{getcwd()}/{file_name}"466if await aiopath.exists(fpath):467await remove(fpath)468await message.download(file_name=fpath)469if file_name == "accounts.zip":470if await aiopath.exists("accounts"):471await rmtree("accounts", ignore_errors=True)472if await aiopath.exists("rclone_sa"):473await rmtree("rclone_sa", ignore_errors=True)474await (475await create_subprocess_exec(476"7z", "x", "-o.", "-aoa", "accounts.zip", "accounts/*.json"477)478).wait()479await (480await create_subprocess_exec("chmod", "-R", "777", "accounts")481).wait()482elif file_name == "list_drives.txt":483drives_ids.clear()484drives_names.clear()485index_urls.clear()486if Config.GDRIVE_ID:487drives_names.append("Main")488drives_ids.append(Config.GDRIVE_ID)489index_urls.append(Config.INDEX_URL)490async with aiopen("list_drives.txt", "r+") as f:491lines = await f.readlines()492for line in lines:493temp = line.strip().split()494drives_ids.append(temp[1])495drives_names.append(temp[0].replace("_", " "))496if len(temp) > 2:497index_urls.append(temp[2])498else:499index_urls.append("")500elif file_name in [".netrc", "netrc"]:501if file_name == "netrc":502await rename("netrc", ".netrc")503file_name = ".netrc"504await (await create_subprocess_exec("chmod", "600", ".netrc")).wait()505await (await create_subprocess_exec("cp", ".netrc", "/root/.netrc")).wait()506elif file_name == "config.py":507await load_config()508if "@github.com" in Config.UPSTREAM_REPO:509buttons = ButtonMaker()510msg = "Push to UPSTREAM_REPO ?"511buttons.data_button("Yes!", f"botset push {file_name}")512buttons.data_button("No", "botset close")513await send_message(message, msg, buttons.build_menu(2))514else:515await delete_message(message)516if file_name == "rclone.conf":517await rclone_serve_booter()518await update_buttons(pre_message)519await database.update_private_file(file_name)520521522async def event_handler(client, query, pfunc, rfunc, document=False):523chat_id = query.message.chat.id524handler_dict[chat_id] = True525start_time = time()526527async def event_filter(_, __, event):528user = event.from_user or event.sender_chat529return bool(530user.id == query.from_user.id531and event.chat.id == chat_id532and (event.text or event.document and document)533)534535handler = client.add_handler(536MessageHandler(pfunc, filters=create(event_filter)), group=-1537)538while handler_dict[chat_id]:539await sleep(0.5)540if time() - start_time > 60:541handler_dict[chat_id] = False542await rfunc()543client.remove_handler(*handler)544545546@new_task547async def edit_bot_settings(client, query):548data = query.data.split()549message = query.message550handler_dict[message.chat.id] = False551if data[1] == "close":552await query.answer()553await delete_message(message.reply_to_message)554await delete_message(message)555elif data[1] == "back":556await query.answer()557globals()["start"] = 0558await update_buttons(message, None)559elif data[1] == "syncjd":560if not Config.JD_EMAIL or not Config.JD_PASS:561await query.answer(562"No Email or Password provided!",563show_alert=True,564)565return566await query.answer(567"Synchronization Started. JDownloader will get restarted. It takes up to 10 sec!",568show_alert=True,569)570await sync_jdownloader()571elif data[1] in ["var", "aria", "qbit", "nzb", "nzbserver"] or data[1].startswith(572"nzbser"573):574if data[1] == "nzbserver":575globals()["start"] = 0576await query.answer()577await update_buttons(message, data[1])578elif data[1] == "resetvar":579await query.answer()580expected_type = type(getattr(Config, data[2]))581if expected_type == bool:582value = False583elif expected_type == int:584value = 0585elif expected_type == str:586value = ""587elif expected_type == list:588value = []589elif expected_type == dict:590value = {}591if data[2] in DEFAULT_VALUES:592value = DEFAULT_VALUES[data[2]]593if (594data[2] == "STATUS_UPDATE_INTERVAL"595and len(task_dict) != 0596and (st := intervals["status"])597):598for key, intvl in list(st.items()):599intvl.cancel()600intervals["status"][key] = SetInterval(601value, update_status_message, key602)603elif data[2] == "EXCLUDED_EXTENSIONS":604excluded_extensions.clear()605excluded_extensions.extend(["aria2", "!qB"])606elif data[2] == "INCLUDED_EXTENSIONS":607included_extensions.clear()608elif data[2] == "TORRENT_TIMEOUT":609await TorrentManager.change_aria2_option("bt-stop-timeout", "0")610await database.update_aria2("bt-stop-timeout", "0")611elif data[2] == "BASE_URL":612await (await create_subprocess_exec("pkill", "-9", "-f", "gunicorn")).wait()613elif data[2] == "BASE_URL_PORT":614value = 80615if Config.BASE_URL:616await (617await create_subprocess_exec("pkill", "-9", "-f", "gunicorn")618).wait()619await create_subprocess_shell(620f"gunicorn -k uvicorn.workers.UvicornWorker -w 1 web.wserver:app --bind 0.0.0.0:{value}"621)622elif data[2] == "GDRIVE_ID":623if drives_names and drives_names[0] == "Main":624drives_names.pop(0)625drives_ids.pop(0)626index_urls.pop(0)627elif data[2] == "INDEX_URL":628if drives_names and drives_names[0] == "Main":629index_urls[0] = ""630elif data[2] == "INCOMPLETE_TASK_NOTIFIER":631await database.trunc_table("tasks")632elif data[2] in ["JD_EMAIL", "JD_PASS"]:633await create_subprocess_exec("pkill", "-9", "-f", "java")634elif data[2] == "USENET_SERVERS":635for s in Config.USENET_SERVERS:636await sabnzbd_client.delete_config("servers", s["name"])637elif data[2] == "AUTHORIZED_CHATS":638auth_chats.clear()639elif data[2] == "SUDO_USERS":640sudo_users.clear()641Config.set(data[2], value)642await update_buttons(message, "var")643if data[2] == "DATABASE_URL":644await database.disconnect()645await database.update_config({data[2]: value})646if data[2] in ["SEARCH_PLUGINS", "SEARCH_API_LINK"]:647await initiate_search_tools()648elif data[2] in ["QUEUE_ALL", "QUEUE_DOWNLOAD", "QUEUE_UPLOAD"]:649await start_from_queued()650elif data[2] in [651"RCLONE_SERVE_URL",652"RCLONE_SERVE_PORT",653"RCLONE_SERVE_USER",654"RCLONE_SERVE_PASS",655]:656await rclone_serve_booter()657elif data[1] == "resetnzb":658await query.answer()659res = await sabnzbd_client.set_config_default(data[2])660nzb_options[data[2]] = res["config"]["misc"][data[2]]661await update_buttons(message, "nzb")662await database.update_nzb_config()663elif data[1] == "syncnzb":664await query.answer(665"Synchronization Started. It takes up to 2 sec!", show_alert=True666)667nzb_options.clear()668await update_nzb_options()669await database.update_nzb_config()670elif data[1] == "syncqbit":671await query.answer(672"Synchronization Started. It takes up to 2 sec!", show_alert=True673)674qbit_options.clear()675await update_qb_options()676await database.save_qbit_settings()677elif data[1] == "emptyaria":678await query.answer()679aria2_options[data[2]] = ""680await update_buttons(message, "aria")681await TorrentManager.change_aria2_option(data[2], "")682await database.update_aria2(data[2], "")683elif data[1] == "emptyqbit":684await query.answer()685await TorrentManager.qbittorrent.app.set_preferences({data[2]: value})686qbit_options[data[2]] = ""687await update_buttons(message, "qbit")688await database.update_qbittorrent(data[2], "")689elif data[1] == "emptynzb":690await query.answer()691res = await sabnzbd_client.set_config("misc", data[2], "")692nzb_options[data[2]] = res["config"]["misc"][data[2]]693await update_buttons(message, "nzb")694await database.update_nzb_config()695elif data[1] == "remser":696index = int(data[2])697await sabnzbd_client.delete_config(698"servers", Config.USENET_SERVERS[index]["name"]699)700del Config.USENET_SERVERS[index]701await update_buttons(message, "nzbserver")702await database.update_config({"USENET_SERVERS": Config.USENET_SERVERS})703elif data[1] == "private":704await query.answer()705await update_buttons(message, data[1])706pfunc = partial(update_private_file, pre_message=message)707rfunc = partial(update_buttons, message)708await event_handler(client, query, pfunc, rfunc, True)709elif data[1] == "botvar" and state == "edit":710await query.answer()711await update_buttons(message, data[2], data[1])712pfunc = partial(edit_variable, pre_message=message, key=data[2])713rfunc = partial(update_buttons, message, "var")714await event_handler(client, query, pfunc, rfunc)715elif data[1] == "botvar" and state == "view":716value = f"{Config.get(data[2])}"717if len(value) > 200:718await query.answer()719with BytesIO(str.encode(value)) as out_file:720out_file.name = f"{data[2]}.txt"721await send_file(message, out_file)722return723elif value == "":724value = None725await query.answer(f"{value}", show_alert=True)726elif data[1] == "ariavar" and (state == "edit" or data[2] == "newkey"):727await query.answer()728await update_buttons(message, data[2], data[1])729pfunc = partial(edit_aria, pre_message=message, key=data[2])730rfunc = partial(update_buttons, message, "aria")731await event_handler(client, query, pfunc, rfunc)732elif data[1] == "ariavar" and state == "view":733value = f"{aria2_options[data[2]]}"734if len(value) > 200:735await query.answer()736with BytesIO(str.encode(value)) as out_file:737out_file.name = f"{data[2]}.txt"738await send_file(message, out_file)739return740elif value == "":741value = None742await query.answer(f"{value}", show_alert=True)743elif data[1] == "qbitvar" and state == "edit":744await query.answer()745await update_buttons(message, data[2], data[1])746pfunc = partial(edit_qbit, pre_message=message, key=data[2])747rfunc = partial(update_buttons, message, "qbit")748await event_handler(client, query, pfunc, rfunc)749elif data[1] == "qbitvar" and state == "view":750value = f"{qbit_options[data[2]]}"751if len(value) > 200:752await query.answer()753with BytesIO(str.encode(value)) as out_file:754out_file.name = f"{data[2]}.txt"755await send_file(message, out_file)756return757elif value == "":758value = None759await query.answer(f"{value}", show_alert=True)760elif data[1] == "nzbvar" and state == "edit":761await query.answer()762await update_buttons(message, data[2], data[1])763pfunc = partial(edit_nzb, pre_message=message, key=data[2])764rfunc = partial(update_buttons, message, "nzb")765await event_handler(client, query, pfunc, rfunc)766elif data[1] == "nzbvar" and state == "view":767value = f"{nzb_options[data[2]]}"768if len(value) > 200:769await query.answer()770with BytesIO(str.encode(value)) as out_file:771out_file.name = f"{data[2]}.txt"772await send_file(message, out_file)773return774elif value == "":775value = None776await query.answer(f"{value}", show_alert=True)777elif data[1] == "emptyserkey":778await query.answer()779await update_buttons(message, f"nzbser{data[2]}")780index = int(data[2])781res = await sabnzbd_client.add_server(782{"name": Config.USENET_SERVERS[index]["name"], data[3]: ""}783)784Config.USENET_SERVERS[index][data[3]] = res["config"]["servers"][0][data[3]]785await database.update_config({"USENET_SERVERS": Config.USENET_SERVERS})786elif data[1].startswith("nzbsevar") and (state == "edit" or data[2] == "newser"):787index = 0 if data[2] == "newser" else int(data[1].replace("nzbsevar", ""))788await query.answer()789await update_buttons(message, data[2], data[1])790pfunc = partial(edit_nzb_server, pre_message=message, key=data[2], index=index)791rfunc = partial(792update_buttons,793message,794f"nzbser{index}" if data[2] != "newser" else "nzbserver",795)796await event_handler(client, query, pfunc, rfunc)797elif data[1].startswith("nzbsevar") and state == "view":798index = int(data[1].replace("nzbsevar", ""))799value = f"{Config.USENET_SERVERS[index][data[2]]}"800if len(value) > 200:801await query.answer()802with BytesIO(str.encode(value)) as out_file:803out_file.name = f"{data[2]}.txt"804await send_file(message, out_file)805return806elif value == "":807value = None808await query.answer(f"{value}", show_alert=True)809elif data[1] == "edit":810await query.answer()811globals()["state"] = "edit"812await update_buttons(message, data[2])813elif data[1] == "view":814await query.answer()815globals()["state"] = "view"816await update_buttons(message, data[2])817elif data[1] == "start":818await query.answer()819if start != int(data[3]):820globals()["start"] = int(data[3])821await update_buttons(message, data[2])822elif data[1] == "push":823await query.answer()824filename = data[2].rsplit(".zip", 1)[0]825if await aiopath.exists(filename):826await (827await create_subprocess_shell(828f"git add -f {filename} \829&& git commit -sm botsettings -q \830&& git push origin {Config.UPSTREAM_BRANCH} -qf"831)832).wait()833else:834await (835await create_subprocess_shell(836f"git rm -r --cached {filename} \837&& git commit -sm botsettings -q \838&& git push origin {Config.UPSTREAM_BRANCH} -qf"839)840).wait()841await delete_message(message.reply_to_message)842await delete_message(message)843844845@new_task846async def send_bot_settings(_, message):847handler_dict[message.chat.id] = False848msg, button = await get_buttons()849globals()["start"] = 0850await send_message(message, msg, button)851852853async def load_config():854Config.load()855drives_ids.clear()856drives_names.clear()857index_urls.clear()858await update_variables()859860if not await aiopath.exists("accounts"):861Config.USE_SERVICE_ACCOUNTS = False862863if len(task_dict) != 0 and (st := intervals["status"]):864for key, intvl in list(st.items()):865intvl.cancel()866intervals["status"][key] = SetInterval(867Config.STATUS_UPDATE_INTERVAL, update_status_message, key868)869870if Config.TORRENT_TIMEOUT:871await TorrentManager.change_aria2_option(872"bt-stop-timeout", f"{Config.TORRENT_TIMEOUT}"873)874await database.update_aria2("bt-stop-timeout", f"{Config.TORRENT_TIMEOUT}")875876if not Config.INCOMPLETE_TASK_NOTIFIER:877await database.trunc_table("tasks")878879await (await create_subprocess_exec("pkill", "-9", "-f", "gunicorn")).wait()880if Config.BASE_URL:881await create_subprocess_shell(882f"gunicorn -k uvicorn.workers.UvicornWorker -w 1 web.wserver:app --bind 0.0.0.0:{Config.BASE_URL_PORT}"883)884885if Config.DATABASE_URL:886await database.connect()887config_dict = Config.get_all()888await database.update_config(config_dict)889else:890await database.disconnect()891await gather(initiate_search_tools(), start_from_queued(), rclone_serve_booter())892add_job()893894895