From 80cbb902a71d0bb2a25a1595cf0f4fd67c59373b Mon Sep 17 00:00:00 2001 From: Hirusha Himath Date: Mon, 9 Mar 2026 21:22:47 +0530 Subject: [PATCH 1/8] perf: Optimize database with __slots__ for performance performance = tomfoolery with bit of bullshitting --- megadl/helpers/database.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/megadl/helpers/database.py b/megadl/helpers/database.py index 0874b2a3..f37d4aa4 100644 --- a/megadl/helpers/database.py +++ b/megadl/helpers/database.py @@ -9,6 +9,13 @@ class CypherDB: + # use slots for faster var lookups + # usually this isnt needed, like at all + # i cant justify myself for adding this either + # but wait maybe i can? + # i use find_one_and_update in .add(...) maximum efficiency so i guess its not that conflicting + __slots__ = ("mongoc", "coll_users") + def __init__(self) -> None: self.mongoc = AsyncMongoClient(getenv("MONGO_URI")) self.coll_users = self.mongoc["mega_nz"]["users"] From 7caecf52c780d03fc1180a92b21ada3c78ed9653 Mon Sep 17 00:00:00 2001 From: Hirusha Himath Date: Mon, 9 Mar 2026 21:26:31 +0530 Subject: [PATCH 2/8] perf: Optimize ddl with __slots__ for performance performance = tomfoolery with bit of bullshitting --- megadl/lib/ddl.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/megadl/lib/ddl.py b/megadl/lib/ddl.py index eb96ad67..c712a1df 100644 --- a/megadl/lib/ddl.py +++ b/megadl/lib/ddl.py @@ -53,6 +53,9 @@ class Downloader: _session = None _lock = asyncio.Lock() + # again same comment as the one you'd find in helpers/database.py -> CypherDB + __slots__ = ("tg_client",) # dont remove "," its there for a reason + def __init__(self, client) -> None: self.tg_client = client From 973e824b4f79f27781303fb5071cee604ffc0570 Mon Sep 17 00:00:00 2001 From: Hirusha Himath Date: Mon, 9 Mar 2026 21:40:20 +0530 Subject: [PATCH 3/8] perf: move tuple check out the loop and remove extra yielding --- megadl/lib/ddl.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/megadl/lib/ddl.py b/megadl/lib/ddl.py index c712a1df..af67d16d 100644 --- a/megadl/lib/ddl.py +++ b/megadl/lib/ddl.py @@ -177,21 +177,20 @@ async def from_ddl( total = resp.content_length curr = 0 st = time() + # for update throttling last_up = 0 up_interval = 2 + can_progress = None not in (chat_id, msg_id, self.tg_client, total) async with async_open(wpath, mode="wb") as file: async for chunk in resp.content.iter_chunked(_chunksize): - # yield before write - await asyncio.sleep(0) - # write chunk await file.write(chunk) curr += len(chunk) # Make sure everything is present before calling track_progress now = time() - if None not in (chat_id, msg_id, self.tg_client, total) and (now - last_up >= up_interval): + if can_progress and (now - last_up >= up_interval): await track_progress( curr, total, From 9ac67c73f694fc2855ff6a2a6cb2aab2a0d70c7d Mon Sep 17 00:00:00 2001 From: Hirusha Himath Date: Mon, 9 Mar 2026 21:42:07 +0530 Subject: [PATCH 4/8] chore: readme updates in lib --- megadl/lib/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/megadl/lib/README.md b/megadl/lib/README.md index b53168c1..20e77c00 100644 --- a/megadl/lib/README.md +++ b/megadl/lib/README.md @@ -4,4 +4,5 @@ Helper libraries for Mega.nz-Bot # Extensions - [`megatools`](megatools.py) - Wrapper for megatools cli with extended features -- [`ddl`](ddl.py) - Downloader for direct download links and gdrive \ No newline at end of file +- [`ddl`](ddl.py) - Downloader for direct download links and ~gdrive~ +- [`splitter`](splitter.py) - Optimized async file splitter for resource-constrained environments From 36afc5965310d7c8c87c2e20873f5ca5e007b54e Mon Sep 17 00:00:00 2001 From: Hirusha Himath Date: Mon, 9 Mar 2026 21:48:55 +0530 Subject: [PATCH 5/8] fix: catch asyncio task cancel error --- megadl/helpers/cypher.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/megadl/helpers/cypher.py b/megadl/helpers/cypher.py index a1d739e3..f3274580 100644 --- a/megadl/helpers/cypher.py +++ b/megadl/helpers/cypher.py @@ -176,7 +176,10 @@ async def cy_run(client: Client, msg: Message | CallbackQuery): await _frwded.reply( f"**#UPLOAD_LOG** \n\n**From:** `{uid}` \n**Get history:** `/info {uid}`" ) - + + # admin function handling + # if you are modifying this code: Never have a function name start with "admin_" prefix + # unless its indended to be used by one if _func_name.startswith("admin") or _func_name in self.req_db_fn: if not self.database: await self.cyeor( @@ -311,6 +314,9 @@ async def full_cleanup(self, path: str = None, user_id: int = None): # not mandatory. would've been better to yield before calling this but thats just more work to do if path: fs_cleanup(path) + # no need for anything else + except asyncio.CancelledError:: + pass except Exception as e: logging.debug(f"Cleanup error: {e}") From 806f848ab6a25723ba4bdd2c405cc5ea0149c237 Mon Sep 17 00:00:00 2001 From: Hirusha Himath Date: Mon, 9 Mar 2026 21:53:00 +0530 Subject: [PATCH 6/8] fix: pass file deleting to thread using asyncio.to_thread this wouldnt really matter for normal files but this supports large directories too so.... --- megadl/helpers/cypher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/megadl/helpers/cypher.py b/megadl/helpers/cypher.py index f3274580..66aae35c 100644 --- a/megadl/helpers/cypher.py +++ b/megadl/helpers/cypher.py @@ -313,7 +313,7 @@ async def full_cleanup(self, path: str = None, user_id: int = None): # when run_checks gets triggered by the same user # not mandatory. would've been better to yield before calling this but thats just more work to do if path: - fs_cleanup(path) + await asyncio.to_thread(fs_cleanup,path) # no need for anything else except asyncio.CancelledError:: pass From 441735b8dfe2bed4906bd8f5d0e9259e702d9721 Mon Sep 17 00:00:00 2001 From: Hirusha Himath Date: Mon, 9 Mar 2026 22:10:35 +0530 Subject: [PATCH 7/8] perf: remove unnecessary f strings and redundant calculations in track_progress function --- megadl/helpers/pyros.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/megadl/helpers/pyros.py b/megadl/helpers/pyros.py index 6559f0be..2f656dbb 100644 --- a/megadl/helpers/pyros.py +++ b/megadl/helpers/pyros.py @@ -25,16 +25,11 @@ async def track_progress( elapsed_time = human_time(elapsed_time) estimated_total_time = human_time(estimated_total_time) - progress = "[{0}{1}] \n**Process**: {2}%\n".format( - "█" * floor(percentage / 5), - "░" * (20 - floor(percentage / 5)), - round(percentage, 2), - ) + filled = floor(percentage / 5) + progress = f"[{'█'*filled}{'░'*(20-filled)}]\n**Process**: {round(percentage,2)}%\n" - tmp = f"{progress}{human_bytes(current)} of {human_bytes(total)}\n**Speed:** {human_bytes(speed)}/s\n**ETA:** {estimated_total_time if estimated_total_time != '' else '0 s'}\n" + pmsg = f"{progress}{human_bytes(current)} of {human_bytes(total)}\n**Speed:** {human_bytes(speed)}/s\n**ETA:** {estimated_total_time if estimated_total_time != '' else '0 s'}\n\n\n**Powered by @NexaBotsUpdates**" try: - await client.edit_message_text( - chat_id, msg_id, f"{tmp}\n\n**Powered by @NexaBotsUpdates**", **kwargs - ) + await client.edit_message_text(chat_id, msg_id, pmsg, **kwargs) except: pass From 5371f127f1d27d58a9fba275c33cd529e1c2d12f Mon Sep 17 00:00:00 2001 From: Hirusha Himath Date: Mon, 9 Mar 2026 22:20:06 +0530 Subject: [PATCH 8/8] chore: publish docker builds manually otherwise it exhaust the quota i have --- .github/workflows/docker-publish.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 10e89f29..bdd7b8c5 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -2,9 +2,6 @@ name: Build and Publish Docker Image "on": - push: - branches: - - main workflow_dispatch: jobs: