""" 消息发送钩子工具 用于自动记录机器人发送的消息到 MessageLogger """ from loguru import logger async def log_bot_message(to_wxid: str, content: str, msg_type: str = "text", media_url: str = ""): """ 记录机器人发送的消息到 MessageLogger Args: to_wxid: 接收者微信ID content: 消息内容 msg_type: 消息类型 (text/image/video/file等) media_url: 媒体文件URL (可选) """ try: logger.info(f"message_hook: 开始记录机器人消息") # 动态导入避免循环依赖 from plugins.MessageLogger.main import MessageLogger logger.info(f"message_hook: MessageLogger 导入成功") # 获取 MessageLogger 实例 message_logger = MessageLogger.get_instance() logger.info(f"message_hook: MessageLogger 实例: {message_logger}") if message_logger: logger.info(f"message_hook: 调用 save_bot_message") await message_logger.save_bot_message(to_wxid, content, msg_type, media_url) logger.info(f"message_hook: save_bot_message 调用完成") else: logger.warning("MessageLogger 实例未找到,跳过消息记录") # 同步写入 AIChat 群聊 history(避免其他插件的机器人回复缺失,导致上下文混乱/工具误触) try: if to_wxid and to_wxid.endswith("@chatroom"): from utils.plugin_manager import PluginManager aichat = PluginManager().plugins.get("AIChat") store = getattr(aichat, "store", None) if aichat else None aichat_config = getattr(aichat, "config", None) if aichat else None if store and aichat_config and aichat_config.get("history", {}).get("sync_bot_messages", False): bot_nickname = "机器人" bot_wxid = "" try: import tomllib with open("main_config.toml", "rb") as f: main_config = tomllib.load(f) bot_nickname = main_config.get("Bot", {}).get("nickname") or bot_nickname bot_wxid = main_config.get("Bot", {}).get("wxid") or "" except Exception: pass sync_content = content if msg_type == "image": sync_content = "[图片]" elif msg_type == "video": sync_content = "[视频]" elif msg_type == "file": sync_content = "[文件]" await store.add_group_message( to_wxid, bot_nickname, sync_content, role="assistant", sender_wxid=bot_wxid or None, ) except Exception as e: logger.debug(f"message_hook: 同步 AIChat 群聊 history 失败: {e}") except Exception as e: logger.error(f"记录机器人消息失败: {e}") import traceback logger.error(f"详细错误: {traceback.format_exc()}") def create_message_hook(original_method): """ 创建消息发送钩子装饰器 Args: original_method: 原始的发送消息方法 Returns: 包装后的方法 """ async def wrapper(self, to_wxid: str, content: str, *args, **kwargs): # 调用原始方法 result = await original_method(self, to_wxid, content, *args, **kwargs) # 记录消息 await log_bot_message(to_wxid, content, "text") return result return wrapper def create_file_message_hook(original_method, msg_type: str): """ 创建文件消息发送钩子装饰器 Args: original_method: 原始的发送文件方法 msg_type: 消息类型 Returns: 包装后的方法 """ async def wrapper(self, to_wxid: str, file_path: str, *args, **kwargs): # 调用原始方法 result = await original_method(self, to_wxid, file_path, *args, **kwargs) # 记录消息 import os filename = os.path.basename(file_path) await log_bot_message(to_wxid, f"[{msg_type}] {filename}", msg_type, file_path) return result return wrapper