Path: blob/master/bot/helper/ext_utils/status_utils.py
1630 views
from html import escape1from psutil import virtual_memory, cpu_percent, disk_usage2from time import time3from asyncio import iscoroutinefunction, gather45from ... import task_dict, task_dict_lock, bot_start_time, status_dict, DOWNLOAD_DIR6from ...core.config_manager import Config7from ..telegram_helper.button_build import ButtonMaker8from ..telegram_helper.bot_commands import BotCommands910SIZE_UNITS = ["B", "KB", "MB", "GB", "TB", "PB"]111213class MirrorStatus:14STATUS_UPLOAD = "Upload"15STATUS_DOWNLOAD = "Download"16STATUS_CLONE = "Clone"17STATUS_QUEUEDL = "QueueDl"18STATUS_QUEUEUP = "QueueUp"19STATUS_PAUSED = "Pause"20STATUS_ARCHIVE = "Archive"21STATUS_EXTRACT = "Extract"22STATUS_SPLIT = "Split"23STATUS_CHECK = "CheckUp"24STATUS_SEED = "Seed"25STATUS_SAMVID = "SamVid"26STATUS_CONVERT = "Convert"27STATUS_FFMPEG = "FFmpeg"282930STATUSES = {31"ALL": "All",32"DL": MirrorStatus.STATUS_DOWNLOAD,33"UP": MirrorStatus.STATUS_UPLOAD,34"QD": MirrorStatus.STATUS_QUEUEDL,35"QU": MirrorStatus.STATUS_QUEUEUP,36"AR": MirrorStatus.STATUS_ARCHIVE,37"EX": MirrorStatus.STATUS_EXTRACT,38"SD": MirrorStatus.STATUS_SEED,39"CL": MirrorStatus.STATUS_CLONE,40"CM": MirrorStatus.STATUS_CONVERT,41"SP": MirrorStatus.STATUS_SPLIT,42"SV": MirrorStatus.STATUS_SAMVID,43"FF": MirrorStatus.STATUS_FFMPEG,44"PA": MirrorStatus.STATUS_PAUSED,45"CK": MirrorStatus.STATUS_CHECK,46}474849async def get_task_by_gid(gid: str):50async with task_dict_lock:51for tk in task_dict.values():52if hasattr(tk, "seeding"):53await tk.update()54if tk.gid() == gid:55return tk56return None575859async def get_specific_tasks(status, user_id):60if status == "All":61if user_id:62return [tk for tk in task_dict.values() if tk.listener.user_id == user_id]63else:64return list(task_dict.values())65tasks_to_check = (66[tk for tk in task_dict.values() if tk.listener.user_id == user_id]67if user_id68else list(task_dict.values())69)70coro_tasks = []71coro_tasks.extend(tk for tk in tasks_to_check if iscoroutinefunction(tk.status))72coro_statuses = await gather(*[tk.status() for tk in coro_tasks])73result = []74coro_index = 075for tk in tasks_to_check:76if tk in coro_tasks:77st = coro_statuses[coro_index]78coro_index += 179else:80st = tk.status()81if (st == status) or (82status == MirrorStatus.STATUS_DOWNLOAD and st not in STATUSES.values()83):84result.append(tk)85return result868788async def get_all_tasks(req_status: str, user_id):89async with task_dict_lock:90return await get_specific_tasks(req_status, user_id)919293def get_readable_file_size(size_in_bytes):94if not size_in_bytes:95return "0B"9697index = 098while size_in_bytes >= 1024 and index < len(SIZE_UNITS) - 1:99size_in_bytes /= 1024100index += 1101102return f"{size_in_bytes:.2f}{SIZE_UNITS[index]}"103104105def get_readable_time(seconds: int):106periods = [("d", 86400), ("h", 3600), ("m", 60), ("s", 1)]107result = ""108for period_name, period_seconds in periods:109if seconds >= period_seconds:110period_value, seconds = divmod(seconds, period_seconds)111result += f"{int(period_value)}{period_name}"112return result113114115def time_to_seconds(time_duration):116try:117parts = time_duration.split(":")118if len(parts) == 3:119hours, minutes, seconds = map(float, parts)120elif len(parts) == 2:121hours = 0122minutes, seconds = map(float, parts)123elif len(parts) == 1:124hours = 0125minutes = 0126seconds = float(parts[0])127else:128return 0129return hours * 3600 + minutes * 60 + seconds130except:131return 0132133134def speed_string_to_bytes(size_text: str):135size = 0136size_text = size_text.lower()137if "k" in size_text:138size += float(size_text.split("k")[0]) * 1024139elif "m" in size_text:140size += float(size_text.split("m")[0]) * 1048576141elif "g" in size_text:142size += float(size_text.split("g")[0]) * 1073741824143elif "t" in size_text:144size += float(size_text.split("t")[0]) * 1099511627776145elif "b" in size_text:146size += float(size_text.split("b")[0])147return size148149150def get_progress_bar_string(pct):151pct = float(pct.strip("%"))152p = min(max(pct, 0), 100)153cFull = int(p // 8)154p_str = "■" * cFull155p_str += "□" * (12 - cFull)156return f"[{p_str}]"157158159async def get_readable_message(sid, is_user, page_no=1, status="All", page_step=1):160msg = ""161button = None162163tasks = await get_specific_tasks(status, sid if is_user else None)164165STATUS_LIMIT = Config.STATUS_LIMIT166tasks_no = len(tasks)167pages = (max(tasks_no, 1) + STATUS_LIMIT - 1) // STATUS_LIMIT168if page_no > pages:169page_no = (page_no - 1) % pages + 1170status_dict[sid]["page_no"] = page_no171elif page_no < 1:172page_no = pages - (abs(page_no) % pages)173status_dict[sid]["page_no"] = page_no174start_position = (page_no - 1) * STATUS_LIMIT175176for index, task in enumerate(177tasks[start_position : STATUS_LIMIT + start_position], start=1178):179if status != "All":180tstatus = status181elif iscoroutinefunction(task.status):182tstatus = await task.status()183else:184tstatus = task.status()185if task.listener.is_super_chat:186msg += f"<b>{index + start_position}.<a href='{task.listener.message.link}'>{tstatus}</a>: </b>"187else:188msg += f"<b>{index + start_position}.{tstatus}: </b>"189msg += f"<code>{escape(f'{task.name()}')}</code>"190if task.listener.subname:191msg += f"\n<i>{task.listener.subname}</i>"192if (193tstatus not in [MirrorStatus.STATUS_SEED, MirrorStatus.STATUS_QUEUEUP]194and task.listener.progress195):196progress = task.progress()197msg += f"\n{get_progress_bar_string(progress)} {progress}"198if task.listener.subname:199subsize = f"/{get_readable_file_size(task.listener.subsize)}"200ac = len(task.listener.files_to_proceed)201count = f"{task.listener.proceed_count}/{ac or '?'}"202else:203subsize = ""204count = ""205msg += f"\n<b>Processed:</b> {task.processed_bytes()}{subsize}"206if count:207msg += f"\n<b>Count:</b> {count}"208msg += f"\n<b>Size:</b> {task.size()}"209msg += f"\n<b>Speed:</b> {task.speed()}"210msg += f"\n<b>ETA:</b> {task.eta()}"211if (212tstatus == MirrorStatus.STATUS_DOWNLOAD213and task.listener.is_torrent214or task.listener.is_qbit215):216try:217msg += f"\n<b>Seeders:</b> {task.seeders_num()} | <b>Leechers:</b> {task.leechers_num()}"218except:219pass220elif tstatus == MirrorStatus.STATUS_SEED:221msg += f"\n<b>Size: </b>{task.size()}"222msg += f"\n<b>Speed: </b>{task.seed_speed()}"223msg += f"\n<b>Uploaded: </b>{task.uploaded_bytes()}"224msg += f"\n<b>Ratio: </b>{task.ratio()}"225msg += f" | <b>Time: </b>{task.seeding_time()}"226else:227msg += f"\n<b>Size: </b>{task.size()}"228msg += f"\n<code>/{BotCommands.CancelTaskCommand[1]} {task.gid()}</code>\n\n"229230if len(msg) == 0:231if status == "All":232return None, None233else:234msg = f"No Active {status} Tasks!\n\n"235buttons = ButtonMaker()236if not is_user:237buttons.data_button("📜", f"status {sid} ov", position="header")238if len(tasks) > STATUS_LIMIT:239msg += f"<b>Page:</b> {page_no}/{pages} | <b>Tasks:</b> {tasks_no} | <b>Step:</b> {page_step}\n"240buttons.data_button("<<", f"status {sid} pre", position="header")241buttons.data_button(">>", f"status {sid} nex", position="header")242if tasks_no > 30:243for i in [1, 2, 4, 6, 8, 10, 15]:244buttons.data_button(i, f"status {sid} ps {i}", position="footer")245if status != "All" or tasks_no > 20:246for label, status_value in list(STATUSES.items()):247if status_value != status:248buttons.data_button(label, f"status {sid} st {status_value}")249buttons.data_button("♻️", f"status {sid} ref", position="header")250button = buttons.build_menu(8)251msg += f"<b>CPU:</b> {cpu_percent()}% | <b>FREE:</b> {get_readable_file_size(disk_usage(DOWNLOAD_DIR).free)}"252msg += f"\n<b>RAM:</b> {virtual_memory().percent}% | <b>UPTIME:</b> {get_readable_time(time() - bot_start_time)}"253return msg, button254255256