diff --git a/plugin_common/plugin_interface.py b/plugin_common/plugin_interface.py index 13f3fb8..37835cc 100644 --- a/plugin_common/plugin_interface.py +++ b/plugin_common/plugin_interface.py @@ -1,6 +1,7 @@ import os import toml from abc import ABC, abstractmethod +import logging from enum import Enum from typing import Dict, Any, List, Optional @@ -61,6 +62,8 @@ class PluginInterface(ABC): self._status = PluginStatus.UNLOADED self._config = {} self._plugin_path = "" + # 初始化日志记录器 + self.LOG = logging.getLogger(f"Plugin.{self.name}") def load_config(self) -> bool: """ diff --git a/plugins/message_summary/main.py b/plugins/message_summary/main.py index 14d8674..af5ca3e 100644 --- a/plugins/message_summary/main.py +++ b/plugins/message_summary/main.py @@ -1,14 +1,14 @@ -import os -import time -import requests import json from typing import Dict, Any, Tuple, Optional, List +import requests + from message_storage.message_to_db import MessageStorage -from plugin_common.plugin_interface import PluginStatus -from plugin_common.message_plugin_interface import MessagePluginInterface from message_summary.compress_chat_data import compress_chat_data from message_summary.markdown_to_image import convert_md_str_to_image +from plugin_common.message_plugin_interface import MessagePluginInterface +from plugin_common.plugin_interface import PluginStatus +from robot_cmd.robot_command import GroupBotManager, Feature, PermissionStatus class MessageSummaryPlugin(MessagePluginInterface): @@ -41,6 +41,7 @@ class MessageSummaryPlugin(MessagePluginInterface): def initialize(self, context: Dict[str, Any]) -> bool: """初始化插件""" try: + # 从插件配置中获取API密钥和URL api_config = self._config.get("api", {}) self._api_key = api_config.get("api_key", "app-McGLzBhBjeBCSEi7n83MtuTo") @@ -49,22 +50,25 @@ class MessageSummaryPlugin(MessagePluginInterface): self.all_contacts = context["all_contacts"] self.message_storage = MessageStorage() - print(f"初始化 {self.name} 插件成功") + self.LOG.info(f"初始化 {self.name} 插件成功") return True except Exception as e: - print(f"初始化 {self.name} 插件失败: {e}") + if hasattr(self, 'LOG'): + self.LOG.error(f"初始化 {self.name} 插件失败: {e}") + else: + print(f"初始化 {self.name} 插件失败: {e}") return False def start(self) -> bool: """启动插件""" self.status = PluginStatus.RUNNING - print(f"{self.name} 插件已启动") + self.LOG.info(f"{self.name} 插件已启动") return True def stop(self) -> bool: """停止插件""" self.status = PluginStatus.STOPPED - print(f"{self.name} 插件已停止") + self.LOG.info(f"{self.name} 插件已停止") return True def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]: @@ -87,10 +91,11 @@ class MessageSummaryPlugin(MessagePluginInterface): if wcf: wcf.send_text("只支持群聊消息总结", message.get("sender")) return True, None - + # 权限判断 + gbm: GroupBotManager = message.get("gbm") + if gbm and gbm.get_group_permission(group_id, Feature.AI_CAPABILITY) == PermissionStatus.DISABLED: + return True, None # 从消息历史中获取群聊记录 - # 这里需要根据实际情况从系统上下文或数据库中获取群聊记录 - # 为简化示例,这里假设从消息中提取 chat_content = self.message_storage.get_messages(group_id, self.all_contacts) if len(chat_content) < 100: return False, None @@ -109,27 +114,18 @@ class MessageSummaryPlugin(MessagePluginInterface): return True, None except Exception as e: - print(f"处理消息总结命令失败: {e}") + self.LOG.error(f"处理消息总结命令失败: {e}") return False, None def _generate_summary(self, chat_content: str, group_id: str) -> Tuple[str, Optional[str]]: """生成总结""" - """ - 使用Dify API生成群聊消息总结 - - Args: - content: 需要总结的群聊消息内容 - - Returns: - 生成的总结内容和图片路径 - """ # Dify API配置 content_compress = chat_content try: content_compress = compress_chat_data(chat_content) - print(f"压缩内容成功:{len(content_compress)}--{len(chat_content)}") + self.LOG.info(f"压缩内容成功:{len(content_compress)}--{len(chat_content)}") except Exception as e: - print(f"压缩内容失败:{e}") + self.LOG.error(f"压缩内容失败:{e}") # 准备请求数据 data = { @@ -154,8 +150,8 @@ class MessageSummaryPlugin(MessagePluginInterface): # 解析响应 response_data = response.json() - print(f"Dify API响应状态码: {response.status_code}") - print(f"响应数据: {json.dumps(response_data, ensure_ascii=False, indent=2)}") + self.LOG.info(f"Dify API响应状态码: {response.status_code}") + self.LOG.debug(f"响应数据: {json.dumps(response_data, ensure_ascii=False, indent=2)}") # 提取回答内容 answer = response_data.get("answer", "") @@ -175,18 +171,18 @@ class MessageSummaryPlugin(MessagePluginInterface): try: spath = convert_md_str_to_image(answer, "output.png") except Exception as e: - print(f"生成image失败:{e}") + self.LOG.error(f"生成image失败:{e}") # 返回文本内容和图片路径 return answer, spath except requests.exceptions.RequestException as e: - print(f"请求Dify API时出错: {e}") + self.LOG.error(f"请求Dify API时出错: {e}") return f"生成总结时出错: {str(e)}", None except json.JSONDecodeError as e: - print(f"解析Dify API响应时出错: {e}") + self.LOG.error(f"解析Dify API响应时出错: {e}") return "解析API响应时出错", None except Exception as e: - print(f"处理总结时出现未知错误: {e}") + self.LOG.error(f"处理总结时出现未知错误: {e}") return f"生成总结时出现未知错误: {str(e)}", None diff --git a/robot.py b/robot.py index b2e6f1a..1454c92 100644 --- a/robot.py +++ b/robot.py @@ -24,7 +24,6 @@ from wcferry import Wcf, WxMsg from base.func_bard import BardAssistant from base.func_chatglm import ChatGLM from base.func_chatgpt import ChatGPT -from base.func_chengyu import cy from base.func_news import News from base.func_tigerbot import TigerBot from base.func_xinghuo_web import XinghuoWeb @@ -95,6 +94,8 @@ class Robot(Job): self.groups = {} # 存储按group_id分组的消息列表,每个group_id最多保留10条消息 GroupBotManager.load_local_cache() + # 权限模块加载 + self.gbm = GroupBotManager() # 初始化插件系统 self.LOG.info("开始初始化插件系统...") self.plugin_registry = PluginRegistry() @@ -123,8 +124,6 @@ class Robot(Job): # 消息存档模块初始化,自动完成入库动作 self.message_storage = MessageStorage() - # 权限模块加载 - self.gbm = GroupBotManager() # 群成员变更模块加载 self.gmc = GroupMemberChange(wcf, self.redis_pool) # 点歌模块加载 @@ -203,33 +202,6 @@ class Robot(Job): """ return self.toChitchat(msg) - def toChengyu(self, msg: WxMsg) -> bool: - """ - 处理成语查询/接龙消息 - :param msg: 微信消息结构 - :return: 处理状态,`True` 成功,`False` 失败 - """ - status = False - texts = re.findall(r"^([#|?|?])(.*)$", msg.content) - # [('#', '天天向上')] - if texts: - flag = texts[0][0] - text = texts[0][1] - if flag == "#": # 接龙 - if cy.isChengyu(text): - rsp = cy.getNext(text) - if rsp: - self.send_text_msg(rsp, msg.roomid) - status = True - elif flag in ["?", "?"]: # 查词 - if cy.isChengyu(text): - rsp = cy.getMeaning(text) - if rsp: - self.send_text_msg(rsp, msg.roomid) - status = True - - return status - def toChitchat(self, msg: WxMsg) -> bool: """闲聊,接入 ChatGPT """ @@ -344,18 +316,6 @@ class Robot(Job): except Exception as e: self.LOG.error(f"archive_message error: {e}") - # 记录在群里发的最新消息,可以通过撤回指令撤回 - try: - if msg.from_self(): - self.revoke_receive_message(msg) - rsp = self.gbm.handle_command(msg.roomid, msg.content) - # 不在群里发送,防止被骚扰 - if rsp is not None: - self.send_text_msg(rsp, msg.sender) - return - except Exception as e: - self.LOG.error(f"revoke_receive_message error: {e}") - # 兼容不@ 直接/触发指令,回答问题。 try: if msg.content.startswith("/"): @@ -589,40 +549,6 @@ class Robot(Job): except Exception as e: self.LOG.error(f"send_group_file_message:{feature.description} error:{e}") - # 自动撤回功能块 - def revoke_receive_message(self, msg: WxMsg): - try: - group_id = msg.roomid - # 如果该group_id没有记录过,初始化一个列表 - if group_id not in self.groups: - self.groups[group_id] = [] - - # 将消息ID添加到对应group_id的消息列表中,最多保留10条消息 - if len(self.groups[group_id]) >= 10: - self.groups[group_id].pop(0) # 超过10条时,移除最早的消息 - - self.groups[group_id].append(msg.id) - self.LOG.info(f"Message revoke received for group {group_id}: {msg.id}") - except Exception as e: - self.LOG.error(f"Revoke_receive_message error:{e}") - - def revoke_messages(self, group_id): - try: - # 如果没有该group_id,直接返回 - if group_id not in self.groups: - self.LOG.debug(f"No messages found for group {group_id}.") - return - - # 按照逆序撤回该组的消息 - for msg_id in reversed(self.groups[group_id]): - self.wcf.revoke_msg(msg_id) # 假设调用撤回方法 - self.LOG.info(f"Message {msg_id} recalled from group {group_id}.") - self.groups[group_id].remove(msg_id) # 撤回后移除该消息ID - self.LOG.debug(f"Message {msg_id} removed from group {group_id}.") - - except Exception as e: - self.LOG.error(f"revoke_messages error:{e}") - def process_plugin_message(self, msg: WxMsg) -> bool: """使用插件处理消息""" # 获取所有消息处理插件 @@ -644,7 +570,8 @@ class Robot(Job): "is_at": msg.is_at(self.wxid), "timestamp": time.time(), "wcf": self.wcf, # 提供wcf对象,让插件可以直接发送消息 - "message_util": self.message_util # 提供消息工具类 + "message_util": self.message_util, # 提供消息工具类 + "gbm": self.gbm # 每次从程序变量中取,保证最新 } # 检查插件是否可以处理该消息 @@ -752,8 +679,6 @@ class Robot(Job): try: # 每天下载10组图,然后发一个帖子PDF meitu_dowload_pub_pic() - # meitu_dowload_heisi_pic() - except Exception as e: self.LOG.error(f"xiu_ren_download_task error:{e}") @@ -762,8 +687,5 @@ class Robot(Job): pub_path = generate_pdf_from_images("xiuren") self.wcf.send_file(pub_path, "45317011307@chatroom") - # heisi_path = generate_pdf_from_images("xiuren/heisi") - # self.wcf.send_file(heisi_path, "45317011307@chatroom") - except Exception as e: self.LOG.error(f"xiu_ren_pdf_send error:{e}")