尝试加入权限内容。
This commit is contained in:
@@ -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:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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:
|
||||||
|
if hasattr(self, 'LOG'):
|
||||||
|
self.LOG.error(f"初始化 {self.name} 插件失败: {e}")
|
||||||
|
else:
|
||||||
print(f"初始化 {self.name} 插件失败: {e}")
|
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
|
||||||
|
|||||||
86
robot.py
86
robot.py
@@ -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}")
|
||||||
|
|||||||
Reference in New Issue
Block a user