From 7f7fc1296eafc1f7e8677f2e06bd8875819ef833 Mon Sep 17 00:00:00 2001 From: h Date: Mon, 19 Oct 2026 03:21:57 +0000 Subject: [PATCH] feat(watcher): watched bots report capture uptime like the userbot --- backend/src/watcher/registry.py | 6 ++++++ backend/src/watcher/runner.py | 18 +++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/backend/src/watcher/registry.py b/backend/src/watcher/registry.py index 49befa8..56cac1a 100644 --- a/backend/src/watcher/registry.py +++ b/backend/src/watcher/registry.py @@ -113,6 +113,12 @@ class BotRegistry: def running(self) -> list[int]: return list(self._running) + @property + def connected_accounts(self) -> list[int]: + return [ + bot.account_id for bot in self._running.values() if bot.client.is_connected + ] + async def sync(self) -> None: async with self._lock: await self._adopt_dropped_in() diff --git a/backend/src/watcher/runner.py b/backend/src/watcher/runner.py index 63bb3ac..b17ddca 100644 --- a/backend/src/watcher/runner.py +++ b/backend/src/watcher/runner.py @@ -6,6 +6,7 @@ import asyncpg import uvloop from dependencies.container import container +from userbot.modules.uptime import repository as uptime from utils.listen import Listener from utils.logging import logger, setup_logging from utils.read.bots import BOTS_CHANGED_CHANNEL @@ -16,6 +17,7 @@ from watcher.registry import BotRegistry setup_logging() RETRY_INTERVAL = 300 +UPTIME_INTERVAL = 60 async def _retry_loop(registry: BotRegistry) -> None: @@ -27,6 +29,14 @@ async def _retry_loop(registry: BotRegistry) -> None: logger.exception("[red]Bot sync failed[/]") +async def _keep_uptime(registry: BotRegistry, pool: asyncpg.Pool) -> None: + while True: + for account_id in registry.connected_accounts: + with contextlib.suppress(Exception): + await uptime.heartbeat(pool, account_id) + await asyncio.sleep(UPTIME_INTERVAL) + + def _change_listener(registry: BotRegistry, tasks: set[asyncio.Task]) -> Listener: def on_change(_payload: str) -> None: task = asyncio.create_task(registry.sync()) @@ -58,6 +68,7 @@ async def runner() -> None: stop = asyncio.Event() asyncio.get_running_loop().add_signal_handler(signal.SIGTERM, stop.set) retry = asyncio.create_task(_retry_loop(registry)) + beat = asyncio.create_task(_keep_uptime(registry, pool)) try: await registry.sync() if not registry.running: @@ -66,9 +77,10 @@ async def runner() -> None: logger.info("[green]Bot watcher running.[/]") await stop.wait() finally: - retry.cancel() - with contextlib.suppress(asyncio.CancelledError): - await retry + for task in (retry, beat): + task.cancel() + with contextlib.suppress(asyncio.CancelledError): + await task await listener.stop() await registry.close() await container.close()