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