import asyncio import logging import signal import os from dotenv import load_dotenv from telegram import Update from telegram.ext import Application, CommandHandler, CallbackQueryHandler from bot import database, handlers from bot import background_tasks # Enable logging logging.basicConfig( format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO ) # Quieten down the HTTPX logger, which is very verbose logging.getLogger("httpx").setLevel(logging.WARNING) logger = logging.getLogger(__name__) # A global event to signal shutdown shutdown_event = asyncio.Event() def signal_handler(sig, frame): """Gracefully handle shutdown signals.""" logger.info("Shutdown signal received. Shutting down gracefully...") shutdown_event.set() async def main() -> None: """Start the bot and wait for a shutdown signal.""" load_dotenv() TOKEN = os.getenv("TELEGRAM_TOKEN") if not TOKEN or TOKEN == "YOUR_TELEGRAM_BOT_TOKEN_HERE": logger.error("TELEGRAM_TOKEN is not set! Please edit your .env file.") return await database.create_tables() application = Application.builder().token(TOKEN).build() application.add_handler(CommandHandler("start", handlers.start)) application.add_handler(CommandHandler("map", handlers.export_map)) application.add_handler(CommandHandler("spawns", handlers.spawn_stats)) application.add_handler(CallbackQueryHandler(handlers.button_handler)) async with application: await application.start() await application.updater.start_polling(allowed_updates=Update.ALL_TYPES) logger.info("Bot is running and polling for updates...") # Start the spawn manager from bot import spawn_manager await spawn_manager.start_spawn_manager() # Start the background tasks logger.info("Starting background tasks...") decay_task = asyncio.create_task(background_tasks.decay_dropped_items(shutdown_event)) stamina_task = asyncio.create_task(background_tasks.regenerate_stamina(shutdown_event)) combat_timer_task = asyncio.create_task(background_tasks.check_combat_timers(shutdown_event)) corpse_decay_task = asyncio.create_task(background_tasks.decay_corpses(shutdown_event)) status_effects_task = asyncio.create_task(background_tasks.process_status_effects(shutdown_event)) logger.info("✅ All background tasks started") await shutdown_event.wait() await application.updater.stop() await application.stop() # Ensure the background tasks are also cancelled on shutdown logger.info("Stopping background tasks...") decay_task.cancel() stamina_task.cancel() combat_timer_task.cancel() corpse_decay_task.cancel() status_effects_task.cancel() logger.info("Bot has been shut down.") if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) try: asyncio.run(main()) except (KeyboardInterrupt, SystemExit): logger.info("Main function interrupted.")