import asyncio import logging from contextlib import suppress from zoneinfo import ZoneInfo from telegram.ext import Application from .config import REMINDER_POLL_SECONDS from .storage import AssistantStorage from .time_utils import format_local_dt, utc_now logger = logging.getLogger(__name__) async def reminder_loop(application: Application) -> None: storage: AssistantStorage = application.bot_data["storage"] tz: ZoneInfo = application.bot_data["timezone"] while True: try: due_reminders = storage.due_reminders(utc_now()) for reminder in due_reminders: await application.bot.send_message( chat_id=reminder["chat_id"], text=( f"Напоминание #{reminder['id']} " f"({format_local_dt(reminder['remind_at'], tz)}):\n" f"{reminder['text']}" ), ) storage.mark_reminder_sent(int(reminder["id"])) except asyncio.CancelledError: raise except Exception: logger.exception("Reminder loop failed") await asyncio.sleep(REMINDER_POLL_SECONDS) async def post_init(application: Application) -> None: application.bot_data["reminder_task"] = asyncio.create_task( reminder_loop(application), name="reminder-loop", ) async def post_shutdown(application: Application) -> None: task = application.bot_data.pop("reminder_task", None) if task is None: return task.cancel() with suppress(asyncio.CancelledError): await task