"""Точка входа бота: python -m bot""" from __future__ import annotations import asyncio import logging from bot.bot_factory import create_bot, create_dispatcher from bot.commands_menu import ensure_commands from bot.services.heartbeat import run_heartbeat from bot.services.notifications import run_notifications from bot.services.runtime import uptime_seconds from common import __version__ from common.analytics import EventType, close_analytics, init_analytics, record from common.analytics.partitions import ensure_partitions, run_partitions from common.config import get_settings from common.db.pool import close_pool, init_pool from common.logging_config import setup_logging logger = logging.getLogger(__name__) async def main() -> None: setup_logging(logging.INFO) settings = get_settings() logger.info("Запуск DispelEvilBot v%s (APP_ENV=%s)", __version__, settings.app_env) await init_pool() await init_analytics() try: await ensure_partitions(settings) except Exception: logger.warning("Не удалось создать партиции аналитики", exc_info=True) record(EventType.BOT_START, payload={"app_env": settings.app_env}) bot = create_bot() dp = create_dispatcher() # Сверяем меню команд при каждом старте (Telegram разрешает только ASCII-имена). await ensure_commands(bot) notifications_task = asyncio.create_task(run_notifications(bot)) heartbeat_task = asyncio.create_task(run_heartbeat(bot)) partitions_task = asyncio.create_task(run_partitions(settings)) try: await bot.delete_webhook(drop_pending_updates=True) await dp.start_polling(bot, allowed_updates=dp.resolve_used_update_types()) finally: notifications_task.cancel() heartbeat_task.cancel() partitions_task.cancel() await asyncio.gather( notifications_task, heartbeat_task, partitions_task, return_exceptions=True, ) record(EventType.BOT_STOP, payload={"app_env": settings.app_env, "uptime_seconds": uptime_seconds()}) await close_analytics() await close_pool() await bot.session.close() if __name__ == "__main__": try: asyncio.run(main()) except (KeyboardInterrupt, SystemExit): logger.info("Бот остановлен")