""" Wechat-Bot 主入口 启动企业微信 WebSocket 长连接,接收消息后转发给远程 Agent。 """ import asyncio import logging import sys from config import Config from bot.wecom_bot import create_bot_client from bot.agent_client import close_http_client # 配置日志 logging.basicConfig( level=getattr(logging, Config.LOG_LEVEL, logging.INFO), format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) logger = logging.getLogger(__name__) async def run_bot(): """启动企业微信机器人 WebSocket 客户端""" # 创建机器人客户端并注册事件处理器 ws_client = create_bot_client() logger.info("正在连接企业微信...") # 用 Event 等待认证完成 authenticated = asyncio.Event() @ws_client.on("authenticated") def _on_authenticated(): logger.info("企业微信认证成功,机器人已上线") authenticated.set() @ws_client.on("error") def _on_error(err): logger.error("SDK 错误: %s", err) try: await ws_client.connect() # 等待认证结果(最多 30 秒) try: await asyncio.wait_for(authenticated.wait(), timeout=30) except asyncio.TimeoutError: logger.error("认证超时(30秒),请检查 BOT_ID 和 BOT_SECRET 是否正确") return # 认证成功,保持事件循环运行以持续接收消息 logger.info("正在监听消息...") await asyncio.Future() # 永远挂起,直到事件循环被取消 except asyncio.CancelledError: logger.info("任务被取消") except Exception as e: logger.error("企业微信连接异常: %s", e) finally: await close_http_client() logger.info("机器人已停止") def main(): """主函数""" # 校验配置 missing = Config.validate() if missing: logger.error("缺少必要配置项: %s", ", ".join(missing)) logger.error("请复制 .env.example 为 .env 并填写配置") sys.exit(1) logger.info("=" * 50) logger.info(" Wechat-Bot 启动中") logger.info(" Agent 地址: %s", Config.AGENT_BASE_URL) logger.info(" 日志级别: %s", Config.LOG_LEVEL) logger.info("=" * 50) try: asyncio.run(run_bot()) except KeyboardInterrupt: logger.info("收到中断信号,正在停止...") logger.info("Wechat-Bot 已退出") if __name__ == "__main__": main()