"""Main entry point for the reminder bot.""" import asyncio import signal import sys from aiogram import Bot, Dispatcher from bot.config import get_config from bot.logging_config import setup_logging, get_logger from bot.db.base import init_db, create_tables, close_db from bot.core.bot import create_bot, create_dispatcher from bot.core.scheduler import create_scheduler, start_scheduler, stop_scheduler # Global instances bot: Bot = None dp: Dispatcher = None async def on_startup() -> None: """Execute actions on bot startup.""" logger = get_logger(__name__) logger.info("Starting reminder bot...") # Load config config = get_config() # Initialize database init_db(config.db_url) await create_tables() logger.info("Bot startup completed") async def on_shutdown() -> None: """Execute actions on bot shutdown.""" logger = get_logger(__name__) logger.info("Shutting down reminder bot...") # Stop scheduler stop_scheduler() # Close database await close_db() # Close bot session if bot: await bot.session.close() logger.info("Bot shutdown completed") async def main() -> None: """Main function to run the bot.""" global bot, dp # Load configuration config = get_config() # Setup logging setup_logging(config.log_level) logger = get_logger(__name__) try: # Execute startup await on_startup() # Create bot and dispatcher bot = create_bot(config.bot_token) dp = create_dispatcher() # Create and start scheduler scheduler = create_scheduler(bot) start_scheduler() # Start polling logger.info("Starting polling...") await dp.start_polling( bot, skip_updates=config.polling_skip_updates, ) except KeyboardInterrupt: logger.info("Received keyboard interrupt") except Exception as e: logger.error(f"Fatal error: {e}", exc_info=True) raise finally: await on_shutdown() def handle_signal(signum, frame): """Handle termination signals.""" logger = get_logger(__name__) logger.info(f"Received signal {signum}") sys.exit(0) if __name__ == "__main__": # Setup signal handlers for graceful shutdown signal.signal(signal.SIGINT, handle_signal) signal.signal(signal.SIGTERM, handle_signal) # Run the bot try: asyncio.run(main()) except (KeyboardInterrupt, SystemExit): pass