尝试加入权限内容。

This commit is contained in:
liuwei
2025-03-18 14:51:37 +08:00
parent bcca2dab28
commit adfa3505a5
3 changed files with 33 additions and 112 deletions

View File

@@ -1,6 +1,7 @@
import os import os
import toml import toml
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
import logging
from enum import Enum from enum import Enum
from typing import Dict, Any, List, Optional from typing import Dict, Any, List, Optional
@@ -61,6 +62,8 @@ class PluginInterface(ABC):
self._status = PluginStatus.UNLOADED self._status = PluginStatus.UNLOADED
self._config = {} self._config = {}
self._plugin_path = "" self._plugin_path = ""
# 初始化日志记录器
self.LOG = logging.getLogger(f"Plugin.{self.name}")
def load_config(self) -> bool: def load_config(self) -> bool:
""" """

View File

@@ -1,14 +1,14 @@
import os
import time
import requests
import json import json
from typing import Dict, Any, Tuple, Optional, List from typing import Dict, Any, Tuple, Optional, List
import requests
from message_storage.message_to_db import MessageStorage 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.compress_chat_data import compress_chat_data
from message_summary.markdown_to_image import convert_md_str_to_image 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): class MessageSummaryPlugin(MessagePluginInterface):
@@ -41,6 +41,7 @@ class MessageSummaryPlugin(MessagePluginInterface):
def initialize(self, context: Dict[str, Any]) -> bool: def initialize(self, context: Dict[str, Any]) -> bool:
"""初始化插件""" """初始化插件"""
try: try:
# 从插件配置中获取API密钥和URL # 从插件配置中获取API密钥和URL
api_config = self._config.get("api", {}) api_config = self._config.get("api", {})
self._api_key = api_config.get("api_key", "app-McGLzBhBjeBCSEi7n83MtuTo") self._api_key = api_config.get("api_key", "app-McGLzBhBjeBCSEi7n83MtuTo")
@@ -49,22 +50,25 @@ class MessageSummaryPlugin(MessagePluginInterface):
self.all_contacts = context["all_contacts"] self.all_contacts = context["all_contacts"]
self.message_storage = MessageStorage() self.message_storage = MessageStorage()
print(f"初始化 {self.name} 插件成功") self.LOG.info(f"初始化 {self.name} 插件成功")
return True return True
except Exception as e: 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 return False
def start(self) -> bool: def start(self) -> bool:
"""启动插件""" """启动插件"""
self.status = PluginStatus.RUNNING self.status = PluginStatus.RUNNING
print(f"{self.name} 插件已启动") self.LOG.info(f"{self.name} 插件已启动")
return True return True
def stop(self) -> bool: def stop(self) -> bool:
"""停止插件""" """停止插件"""
self.status = PluginStatus.STOPPED self.status = PluginStatus.STOPPED
print(f"{self.name} 插件已停止") self.LOG.info(f"{self.name} 插件已停止")
return True return True
def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]: def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
@@ -87,10 +91,11 @@ class MessageSummaryPlugin(MessagePluginInterface):
if wcf: if wcf:
wcf.send_text("只支持群聊消息总结", message.get("sender")) wcf.send_text("只支持群聊消息总结", message.get("sender"))
return True, None 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) chat_content = self.message_storage.get_messages(group_id, self.all_contacts)
if len(chat_content) < 100: if len(chat_content) < 100:
return False, None return False, None
@@ -109,27 +114,18 @@ class MessageSummaryPlugin(MessagePluginInterface):
return True, None return True, None
except Exception as e: except Exception as e:
print(f"处理消息总结命令失败: {e}") self.LOG.error(f"处理消息总结命令失败: {e}")
return False, None return False, None
def _generate_summary(self, chat_content: str, group_id: str) -> Tuple[str, Optional[str]]: def _generate_summary(self, chat_content: str, group_id: str) -> Tuple[str, Optional[str]]:
"""生成总结""" """生成总结"""
"""
使用Dify API生成群聊消息总结
Args:
content: 需要总结的群聊消息内容
Returns:
生成的总结内容和图片路径
"""
# Dify API配置 # Dify API配置
content_compress = chat_content content_compress = chat_content
try: try:
content_compress = compress_chat_data(chat_content) 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: except Exception as e:
print(f"压缩内容失败:{e}") self.LOG.error(f"压缩内容失败:{e}")
# 准备请求数据 # 准备请求数据
data = { data = {
@@ -154,8 +150,8 @@ class MessageSummaryPlugin(MessagePluginInterface):
# 解析响应 # 解析响应
response_data = response.json() response_data = response.json()
print(f"Dify API响应状态码: {response.status_code}") self.LOG.info(f"Dify API响应状态码: {response.status_code}")
print(f"响应数据: {json.dumps(response_data, ensure_ascii=False, indent=2)}") self.LOG.debug(f"响应数据: {json.dumps(response_data, ensure_ascii=False, indent=2)}")
# 提取回答内容 # 提取回答内容
answer = response_data.get("answer", "") answer = response_data.get("answer", "")
@@ -175,18 +171,18 @@ class MessageSummaryPlugin(MessagePluginInterface):
try: try:
spath = convert_md_str_to_image(answer, "output.png") spath = convert_md_str_to_image(answer, "output.png")
except Exception as e: except Exception as e:
print(f"生成image失败:{e}") self.LOG.error(f"生成image失败:{e}")
# 返回文本内容和图片路径 # 返回文本内容和图片路径
return answer, spath return answer, spath
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
print(f"请求Dify API时出错: {e}") self.LOG.error(f"请求Dify API时出错: {e}")
return f"生成总结时出错: {str(e)}", None return f"生成总结时出错: {str(e)}", None
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
print(f"解析Dify API响应时出错: {e}") self.LOG.error(f"解析Dify API响应时出错: {e}")
return "解析API响应时出错", None return "解析API响应时出错", None
except Exception as e: except Exception as e:
print(f"处理总结时出现未知错误: {e}") self.LOG.error(f"处理总结时出现未知错误: {e}")
return f"生成总结时出现未知错误: {str(e)}", None return f"生成总结时出现未知错误: {str(e)}", None

View File

@@ -24,7 +24,6 @@ from wcferry import Wcf, WxMsg
from base.func_bard import BardAssistant from base.func_bard import BardAssistant
from base.func_chatglm import ChatGLM from base.func_chatglm import ChatGLM
from base.func_chatgpt import ChatGPT from base.func_chatgpt import ChatGPT
from base.func_chengyu import cy
from base.func_news import News from base.func_news import News
from base.func_tigerbot import TigerBot from base.func_tigerbot import TigerBot
from base.func_xinghuo_web import XinghuoWeb from base.func_xinghuo_web import XinghuoWeb
@@ -95,6 +94,8 @@ class Robot(Job):
self.groups = {} # 存储按group_id分组的消息列表每个group_id最多保留10条消息 self.groups = {} # 存储按group_id分组的消息列表每个group_id最多保留10条消息
GroupBotManager.load_local_cache() GroupBotManager.load_local_cache()
# 权限模块加载
self.gbm = GroupBotManager()
# 初始化插件系统 # 初始化插件系统
self.LOG.info("开始初始化插件系统...") self.LOG.info("开始初始化插件系统...")
self.plugin_registry = PluginRegistry() self.plugin_registry = PluginRegistry()
@@ -123,8 +124,6 @@ class Robot(Job):
# 消息存档模块初始化,自动完成入库动作 # 消息存档模块初始化,自动完成入库动作
self.message_storage = MessageStorage() self.message_storage = MessageStorage()
# 权限模块加载
self.gbm = GroupBotManager()
# 群成员变更模块加载 # 群成员变更模块加载
self.gmc = GroupMemberChange(wcf, self.redis_pool) self.gmc = GroupMemberChange(wcf, self.redis_pool)
# 点歌模块加载 # 点歌模块加载
@@ -203,33 +202,6 @@ class Robot(Job):
""" """
return self.toChitchat(msg) 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: def toChitchat(self, msg: WxMsg) -> bool:
"""闲聊,接入 ChatGPT """闲聊,接入 ChatGPT
""" """
@@ -344,18 +316,6 @@ class Robot(Job):
except Exception as e: except Exception as e:
self.LOG.error(f"archive_message error: {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: try:
if msg.content.startswith("/"): if msg.content.startswith("/"):
@@ -589,40 +549,6 @@ class Robot(Job):
except Exception as e: except Exception as e:
self.LOG.error(f"send_group_file_message:{feature.description} error{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: def process_plugin_message(self, msg: WxMsg) -> bool:
"""使用插件处理消息""" """使用插件处理消息"""
# 获取所有消息处理插件 # 获取所有消息处理插件
@@ -644,7 +570,8 @@ class Robot(Job):
"is_at": msg.is_at(self.wxid), "is_at": msg.is_at(self.wxid),
"timestamp": time.time(), "timestamp": time.time(),
"wcf": self.wcf, # 提供wcf对象让插件可以直接发送消息 "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: try:
# 每天下载10组图然后发一个帖子PDF # 每天下载10组图然后发一个帖子PDF
meitu_dowload_pub_pic() meitu_dowload_pub_pic()
# meitu_dowload_heisi_pic()
except Exception as e: except Exception as e:
self.LOG.error(f"xiu_ren_download_task error{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") pub_path = generate_pdf_from_images("xiuren")
self.wcf.send_file(pub_path, "45317011307@chatroom") 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: except Exception as e:
self.LOG.error(f"xiu_ren_pdf_send error{e}") self.LOG.error(f"xiu_ren_pdf_send error{e}")