import asyncio import os import sys import signal import sqlite3 # Ensure project root is on sys.path for module resolution CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) if CURRENT_DIR not in sys.path: sys.path.insert(0, CURRENT_DIR) from helper_bot.main import start_bot from helper_bot.utils.base_dependency_factory import get_global_instance from helper_bot.utils.auto_unban_scheduler import get_auto_unban_scheduler from logs.custom_logger import logger async def main(): """Основная функция запуска""" bdf = get_global_instance() # Создаем бота для автоматического разбана from aiogram import Bot from aiogram.client.default import DefaultBotProperties auto_unban_bot = Bot( token=bdf.settings['Telegram']['bot_token'], default=DefaultBotProperties(parse_mode='HTML'), timeout=30.0 ) # Инициализируем планировщик автоматического разбана auto_unban_scheduler = get_auto_unban_scheduler() auto_unban_scheduler.set_bot(auto_unban_bot) auto_unban_scheduler.start_scheduler() # Метрики запускаются в main.py через server_prometheus.py # Здесь не нужно дублировать функциональность # Флаг для корректного завершения shutdown_event = asyncio.Event() def signal_handler(signum, frame): """Обработчик сигналов для корректного завершения""" logger.info(f"Получен сигнал {signum}, завершаем работу...") shutdown_event.set() # Регистрируем обработчики сигналов signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) # Запускаем бота (метрики запускаются внутри start_bot) bot_task = asyncio.create_task(start_bot(bdf)) main_bot = None try: # Ждем сигнала завершения await shutdown_event.wait() logger.info("Начинаем корректное завершение...") except KeyboardInterrupt: logger.info("Получен сигнал завершения...") finally: logger.info("Останавливаем планировщик автоматического разбана...") auto_unban_scheduler.stop_scheduler() # Останавливаем планировщик метрик try: from helper_bot.utils.metrics_scheduler import stop_metrics_scheduler stop_metrics_scheduler() logger.info("Планировщик метрик остановлен") except Exception as e: logger.error(f"Ошибка при остановке планировщика метрик: {e}") # Метрики останавливаются в main.py logger.info("Останавливаем задачи...") # Отменяем задачу бота bot_task.cancel() # Ждем завершения задачи бота и получаем результат main bot try: results = await asyncio.gather(bot_task, return_exceptions=True) # Результат - это main bot if results[0] and not isinstance(results[0], Exception): main_bot = results[0] except Exception as e: logger.error(f"Ошибка при остановке задач: {e}") # Закрываем сессию основного бота (если она еще не закрыта) if main_bot and hasattr(main_bot, 'session') and not main_bot.session.closed: try: await main_bot.session.close() logger.info("Сессия основного бота корректно закрыта") except Exception as e: logger.error(f"Ошибка при закрытии сессии основного бота: {e}") # Закрываем сессию бота для автоматического разбана if not auto_unban_bot.session.closed: try: await auto_unban_bot.session.close() logger.info("Сессия бота автоматического разбана корректно закрыта") except Exception as e: logger.error(f"Ошибка при закрытии сессии бота автоматического разбана: {e}") # Даем время на завершение всех aiohttp соединений await asyncio.sleep(0.2) logger.info("Бот корректно остановлен") def init_db(): db_path = '/app/database/tg-bot-database.db' schema_path = '/app/database/schema.sql' if not os.path.exists(db_path): print("Initializing database...") with open(schema_path, 'r') as f: schema = f.read() with sqlite3.connect(db_path) as conn: conn.executescript(schema) print("Database initialized successfully") if __name__ == '__main__': try: init_db() asyncio.run(main()) except AttributeError: # Fallback for Python 3.6-3.7 loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) finally: # Закрываем все pending tasks pending = asyncio.all_tasks(loop) for task in pending: task.cancel() # Ждем завершения всех задач if pending: loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True)) loop.close()