diff --git a/bot.py b/bot.py index 3737279d..20299644 100644 --- a/bot.py +++ b/bot.py @@ -2,10 +2,13 @@ import asyncio import hashlib import os import sys + +# import shutil from pathlib import Path import time import platform import traceback +import signal from dotenv import load_dotenv from src.common.logger_manager import get_logger @@ -14,7 +17,8 @@ from src.common.crash_logger import install_crash_handler from src.main import MainSystem from rich.traceback import install -from src.manager.async_task_manager import async_task_manager +from asyncio import CancelledError +# from src.manager.async_task_manager import async_task_manager install(extra_lines=3) @@ -34,15 +38,19 @@ driver = None app = None loop = None -# shutdown_requested = False # 新增全局变量 +shutdown_requested = False # 新增全局变量 async def request_shutdown() -> bool: """请求关闭程序""" + global shutdown_requested + if shutdown_requested: + return True + shutdown_requested = True try: if loop and not loop.is_closed(): try: - loop.run_until_complete(graceful_shutdown()) + await graceful_shutdown() except Exception as ge: # 捕捉优雅关闭时可能发生的错误 logger.error(f"优雅关闭时发生错误: {ge}") return False @@ -65,6 +73,38 @@ def easter_egg(): print(rainbow_text) +# def init_config(): +# # 初次启动检测 +# if not os.path.exists("config/bot_config.toml"): +# logger.warning("检测到bot_config.toml不存在,正在从模板复制") + +# # 检查config目录是否存在 +# if not os.path.exists("config"): +# os.makedirs("config") +# logger.info("创建config目录") + +# shutil.copy("template/bot_config_template.toml", "config/bot_config.toml") +# logger.info("复制完成,请修改config/bot_config.toml和.env中的配置后重新启动") +# if not os.path.exists("config/lpmm_config.toml"): +# logger.warning("检测到lpmm_config.toml不存在,正在从模板复制") + +# # 检查config目录是否存在 +# if not os.path.exists("config"): +# os.makedirs("config") +# logger.info("创建config目录") + +# shutil.copy("template/lpmm_config_template.toml", "config/lpmm_config.toml") +# logger.info("复制完成,请修改config/lpmm_config.toml和.env中的配置后重新启动") + + +# def init_env(): +# # 检测.env文件是否存在 +# if not os.path.exists(".env"): +# logger.error("检测到.env文件不存在") +# shutil.copy("template/template.env", "./.env") +# logger.info("已从template/template.env复制创建.env,请修改配置后重新启动") + + def load_env(): # 直接加载生产环境变量配置 if os.path.exists(".env"): @@ -109,10 +149,7 @@ def scan_provider(env_config: dict): async def graceful_shutdown(): try: logger.info("正在优雅关闭麦麦...") - - # 停止所有异步任务 - await async_task_manager.stop_and_wait_all_tasks() - + # await async_task_manager.stop_and_wait_all_tasks() tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()] for task in tasks: task.cancel() @@ -208,9 +245,9 @@ def raw_main(): check_eula() print("检查EULA和隐私条款完成") - easter_egg() - + # init_config() + # init_env() load_env() env_config = {key: os.getenv(key) for key in os.environ} @@ -220,6 +257,11 @@ def raw_main(): return MainSystem() +def signal_handler(sig, frame): + """信号处理函数,捕获SIGINT和SIGTERM信号""" + loop.create_task(request_shutdown()) + + if __name__ == "__main__": exit_code = 0 # 用于记录程序最终的退出状态 try: @@ -230,18 +272,22 @@ if __name__ == "__main__": loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) + # 新增:设置信号处理 + if platform.system().lower() != "windows": + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + try: # 执行初始化和任务调度 loop.run_until_complete(main_system.initialize()) loop.run_until_complete(main_system.schedule_tasks()) + loop.run_forever() except KeyboardInterrupt: - # loop.run_until_complete(global_api.stop()) logger.warning("收到中断信号,正在优雅关闭...") - if loop and not loop.is_closed(): - try: - loop.run_until_complete(graceful_shutdown()) - except Exception as ge: # 捕捉优雅关闭时可能发生的错误 - logger.error(f"优雅关闭时发生错误: {ge}") + try: + loop.run_until_complete(request_shutdown()) + except CancelledError as e: + logger.error(f"优雅关闭时发生错误: {e}") # 新增:检测外部请求关闭 # except Exception as e: # 将主异常捕获移到外层 try...except