优化代码,删除无效代码

This commit is contained in:
liuwei
2025-05-19 17:58:49 +08:00
parent 28f02b58e0
commit fb752c084e
23 changed files with 83 additions and 503 deletions

View File

@@ -1,11 +0,0 @@
@echo off
cd /d F:\python\WeChatRobot
echo [INFO] Pulling latest code...
git pull
echo [INFO] Installing Python dependencies...
pip install -r requirements.txt
echo [INFO] Starting application...
start python F:\python\WeChatRobot\main.py -c 8

View File

@@ -1,84 +0,0 @@
logging:
version: 1
disable_existing_loggers: False
formatters:
simple:
format: "%(asctime)s %(message)s"
datefmt: "%Y-%m-%d %H:%M:%S"
error:
format: "%(asctime)s %(name)s %(levelname)s %(filename)s::%(funcName)s[%(lineno)d]:%(message)s"
handlers:
console:
class: logging.StreamHandler
level: INFO
formatter: simple
stream: ext://sys.stdout
info_file_handler:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: simple
filename: wx_info.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8
error_file_handler:
class: logging.handlers.RotatingFileHandler
level: ERROR
formatter: error
filename: wx_error.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8
root:
level: INFO
handlers: [console, info_file_handler, error_file_handler]
groups:
enable: [] # 允许响应的群 roomId大概长这样2xxxxxxxxx3@chatroom
news:
receivers: [] # 定时新闻接收人roomid 或者 wxid
report_reminder:
receivers: [] # 定时日报周报月报提醒roomid 或者 wxid
chatgpt: # -----chatgpt配置这行不填-----
key: # 填写你 ChatGPT 的 key
api: https://api.openai.com/v1 # 如果你不知道这是干嘛的,就不要改
model: gpt-3.5-turbo
proxy: # 如果你在国内你可能需要魔法大概长这样http://域名或者IP地址:端口号
prompt: 你是智能聊天机器人,你叫 wcferry # 根据需要对角色进行设定
chatglm: # -----chatglm配置这行不填-----
key: sk-012345678901234567890123456789012345678901234567 # 这个应该不用动
api: http://localhost:8000/v1 # 根据自己的chatglm地址修改
proxy: # 如果你在国内你可能需要魔法大概长这样http://域名或者IP地址:端口号
prompt: 你是智能聊天机器人,你叫小薇 # 根据需要对角色进行设定
file_path: F:/Pictures/temp #设定生成图片和代码使用的文件夹路径
tigerbot: # -----tigerbot配置这行不填-----
key: # key
model: # tigerbot-7b-sft
xinghuo_web: # -----讯飞星火web模式api配置这行不填 抓取方式详见文档https://www.bilibili.com/read/cv27066577-----
cookie: # cookie
fd: # fd
GtToken: # GtToken
prompt: 你是智能聊天机器人,你叫 wcferry。请用这个角色回答我的问题 # 根据需要对角色进行设定
bard: # -----bard配置这行不填-----
api_key: # api-key 创建地址https://ai.google.dev/pricing?hl=en创建后复制过来即可
model_name: gemini-pro # 新模型上线后可以选择模型
proxy: http://127.0.0.1:7890 # 如果你在国内你可能需要魔法大概长这样http://域名或者IP地址:端口号
# 提示词尽可能用英文bard对中文提示词的效果不是很理想下方提示词为英语老师的示例请按实际需要修改,默认设置的提示词为谷歌创造的AI大语言模型
# I want you to act as a spoken English teacher and improver. I will speak to you in English and you will reply to me in English to practice my spoken English. I want you to keep your reply neat, limiting the reply to 100 words. I want you to strictly correct my grammar mistakes, typos, and factual errors. I want you to ask me a question in your reply. Now let's start practicing, you could ask me a question first. Remember, I want you to strictly correct my grammar mistakes, typos, and factual errors.
prompt: You am a large language model, trained by Google.
zhipu: # -----zhipu配置这行不填-----
api_key: #api key
model: # 模型类型

View File

@@ -1,110 +0,0 @@
# -*- coding: utf-8 -*-
from loguru import logger
import os.path
import random
import time
from typing import Any, Tuple, Coroutine
from utils.wechat.contact_manager import ContactManager
from wechat_ipad import WechatAPIClient
class MessageUtil:
"""
消息发送工具类,封装了发送文本和文件的方法
"""
# 修改 MessageUtil 类的初始化方法,接受联系人管理器而不是联系人字典
def __init__(self, client: WechatAPIClient = None):
self.client = client
self.contact_manager = ContactManager.get_instance()
self.LOG = logger
def send_text(self, msg: str, receiver: str, at_list: str = "") -> None:
"""
发送文本消息
:param msg: 消息字符串
:param receiver: 接收人wxid或者群id
:param at_list: 要@的wxid, @所有人的wxid为notify@all
"""
# 风控处理,随机延迟发送,解决群消息高频发送导致的微信风险
time.sleep(random.uniform(0.3, 1.0))
ats = ""
if at_list:
if at_list == "notify@all": # @所有人
ats = " @所有人"
# {msg}{ats} 表示要发送的消息内容后面紧跟@,例如 北京天气情况为xxx @张三
if ats == "":
self.LOG.info(f"To {receiver}: {msg}")
self.client.send_text_message(receiver, msg, "")
else:
self.LOG.info(f"To {receiver}: {ats}\r{msg}")
self.client.send_at_message(receiver, msg, at_list.split(","))
def send_file(self, file_path: str, receiver: str) -> str:
"""
发送文件消息
:param file_path: 文件路径
:param receiver: 接收人wxid或者群id
"""
# 风控处理,随机延迟发送,解决群消息高频发送导致的微信风险
time.sleep(random.uniform(0.5, 1.5))
self.LOG.info(f"Sending file to {receiver}: {file_path}")
(path, filename) = os.path.split(file_path)
self.LOG.info(f"Sending file to {path}: {filename}")
return self.client.post_file(self.app_id, receiver, file_path, filename)
def send_image(self, image_path: str, receiver: str) -> Coroutine[Any, Any, tuple[int, int, int]]:
"""
发送文件消息
:param image_path: 文件路径
:param receiver: 接收人wxid或者群id
"""
# 风控处理,随机延迟发送,解决群消息高频发送导致的微信风险
time.sleep(random.uniform(0.5, 1.5))
self.LOG.info(f"Sending file to {receiver}: {image_path}")
return self.client.send_image_message(receiver, image_path)
def send_rich_text(self, name: str, account: str, title: str, digest: str, url: str, thumburl: str,
receiver: str) -> int:
"""
发送富文本消息
卡片样式:
|-------------------------------------|
|title, 最长两行 |
|(长标题, 标题短的话这行没有) |
|digest, 最多三行,会占位 |--------|
|digest, 最多三行,会占位 |thumburl|
|digest, 最多三行,会占位 |--------|
|(account logo) name |
|-------------------------------------|
:param name: 左下显示的名字
:param account: 填公众号 id 可以显示对应的头像gh_ 开头的)
:param title: 标题,最多两行
:param digest: 摘要,三行
:param url: 点击后跳转的链接
:param thumburl: 缩略图的链接
:param receiver: 接收人, wxid 或者 roomid
:return: 0 为成功,其他失败
"""
# 风控处理,随机延迟发送,解决群消息高频发送导致的微信风险
time.sleep(random.uniform(0.5, 1.5))
self.LOG.info(f"Sending rich text to {receiver}: {title}")
return self.client.send_link_message(self.app_id, receiver, title, digest, url, thumburl)
def invite_member(self, group_id, sender):
return self.client.invite_chatroom_member(sender, group_id)
def get_chatroom_members(self, group_id) -> dict:
data = self.client.get_chatroom_member_list(self.app_id, group_id)
members = {member["wxid"]: member["nickName"] for member in data["data"]["memberList"]}
return members

View File

@@ -2,12 +2,12 @@ import os
import random
from typing import Dict, Any, List, Optional, Tuple
from message_util import MessageUtil
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
from utils.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
from utils.decorator.points_decorator import plugin_points_cost
from wechat_ipad import WechatAPIClient
class BeautyLegPlugin(MessagePluginInterface):
@@ -41,7 +41,7 @@ class BeautyLegPlugin(MessagePluginInterface):
super().__init__()
# 修改图片目录路径指向 resource/beauty_leg
self.image_folder = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
"resource", "beauty_leg")
"resource", "beauty_leg")
def initialize(self, context: Dict[str, Any]) -> bool:
"""初始化插件"""
@@ -49,7 +49,6 @@ class BeautyLegPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util: MessageUtil = context.get("message_util")
self.gbm = context.get("gbm")
self._commands = self._config.get("Beautyleg", {}).get("command", ["美腿", "腿来"])
@@ -88,13 +87,14 @@ class BeautyLegPlugin(MessagePluginInterface):
@plugin_stats_decorator(plugin_name="美腿图片")
@plugin_points_cost(2, "美腿图片消耗积分", Feature.BEAUTY_LEG)
def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
async def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""处理消息"""
content = str(message.get("content", "")).strip()
self.LOG.debug(f"插件执行: {self.name}{content}")
sender = message.get("sender")
roomid = message.get("roomid", "")
gbm: GroupBotManager = message.get("gbm")
bot: WechatAPIClient = message.get("bot")
# 检查权限
if roomid and gbm.get_group_permission(roomid, Feature.BEAUTY_LEG) == PermissionStatus.DISABLED:
@@ -104,14 +104,13 @@ class BeautyLegPlugin(MessagePluginInterface):
# 获取随机图片
random_file_path = self._get_random_file_from_dir(self.image_folder)
if not random_file_path:
self.message_util.send_text(f"\n❌未找到美腿图片资源",
(roomid if roomid else sender), sender)
await bot.send_text_message((roomid if roomid else sender), f"\n❌未找到美腿图片资源")
return True, "未找到图片资源"
# 发送图片
random_file_path = os.path.abspath(random_file_path)
self.LOG.info(f"BeautyLeg.random_file_path: {random_file_path}")
result = self.message_util.send_file(random_file_path, (roomid if roomid else sender))
result = await bot.send_image_message((roomid if roomid else sender), random_file_path)
self.LOG.info(f"发送图片结果: {result}")
return True, "发送成功"

View File

@@ -1,4 +1,3 @@
import logging
import os
import requests
import json
@@ -6,9 +5,6 @@ import time
import re # 添加re模块导入
from typing import Dict, Any, List, Optional, Tuple
from loguru import logger
from message_util import MessageUtil
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
@@ -65,7 +61,6 @@ class DifyPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util: MessageUtil = context.get("message_util")
self.gbm = context.get("gbm")
# 从配置中获取参数
@@ -140,8 +135,6 @@ class DifyPlugin(MessagePluginInterface):
await bot.send_at_message(roomid, "请在@我的同时提供问题内容", [sender])
return False, "没有提供问题内容"
# self.message_util.send_text_msg("⏳AI 正在加油,请稍候… 😊", roomid, sender)
try:
# 调用Dify API获取回复
response = self._chat_with_dify((roomid if roomid else sender), sender, query)
@@ -153,7 +146,7 @@ class DifyPlugin(MessagePluginInterface):
# 判断是否为本地文件路径
if os.path.isfile(response):
# 如果是文件路径,使用发送文件方法
self.message_util.send_file(response, roomid)
await bot.send_image_message(roomid, response)
else:
# 如果是普通文本,使用发送文本方法
await bot.send_at_message((roomid if roomid else sender), response, [sender])
@@ -184,7 +177,11 @@ class DifyPlugin(MessagePluginInterface):
if roomid and gbm.get_group_permission(roomid, Feature.AI_CAPABILITY) == PermissionStatus.DISABLED:
return False, "没有权限"
# self.message_util.send_text_msg("⏳AI 正在加油,请稍候… 😊", (roomid if roomid else sender),sender if roomid else "")
client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender),
"⏳AI 正在加油,请稍候… 😊",
sender if roomid else "")
revoke.add_message_to_revoke(roomid, client_msg_id, create_time, new_msg_id, 3)
# 获取查询内容
query = parts[1].strip()

View File

@@ -7,11 +7,11 @@ from typing import Dict, Any, List, Optional, Tuple
from loguru import logger
from message_util import MessageUtil
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
from utils.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
from wechat_ipad import WechatAPIClient
class DouyinParserError(Exception):
@@ -62,7 +62,6 @@ class DouyinParserPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util: MessageUtil = context.get("message_util")
self.gbm = context.get("gbm")
# 从配置中获取参数
@@ -104,6 +103,7 @@ class DouyinParserPlugin(MessagePluginInterface):
roomid = message.get("roomid", "")
gbm: GroupBotManager = message.get("gbm")
bot: WechatAPIClient = message.get("bot")
# 检查权限
if roomid and gbm.get_group_permission(roomid, Feature.DOUYIN_PARSER) == PermissionStatus.DISABLED:
return False, "没有权限"
@@ -136,7 +136,7 @@ class DouyinParserPlugin(MessagePluginInterface):
# 下载并发送文件
mp4_path = self._download_stream(video_url, os.path.join(self.download_dir, "douyin.mp4"))
if mp4_path:
self.message_util.send_file(mp4_path, (roomid if roomid else sender))
bot.send_video_message((roomid if roomid else sender),mp4_path)
return True, "发送视频文件成功"
else:
print(f"❌下载视频失败")

View File

@@ -4,7 +4,6 @@ from typing import Dict, Any, List, Optional, Tuple
from loguru import logger
from message_util import MessageUtil
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
@@ -54,7 +53,6 @@ class GameTaskPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util: MessageUtil = context.get("message_util")
# 初始化配置
self._commands = self._config.get("GameTask", {}).get("command",
@@ -117,7 +115,7 @@ class GameTaskPlugin(MessagePluginInterface):
gbm: GroupBotManager = message.get("gbm")
all_contacts = message.get("all_contacts", {})
self.bot = message.get("bot")
self.bot: WechatAPIClient = message.get("bot")
self.LOG.debug(f"插件执行: {self.name}{content}")
# 检查权限
@@ -147,8 +145,8 @@ class GameTaskPlugin(MessagePluginInterface):
await self._handle_list_uncompleted_tasks(sender, roomid)
return True, "列举未完成任务成功"
else:
self.message_util.send_text(f"❌未知命令!\n{self.command_format}",
(roomid if roomid else sender), sender)
await self.bot.send_at_message((roomid if roomid else sender), f"❌未知命令!\n{self.command_format}",
[sender])
return False, "未知命令"
except Exception as e:
@@ -420,10 +418,10 @@ class GameTaskPlugin(MessagePluginInterface):
for i, row in enumerate(ranks, 1):
rank_text += f"🐓 {i}. {row['player_name']}: {row['points']}\n"
self.message_util.send_text(
rank_text,
await self.bot.send_at_message(
(roomid if roomid else sender),
sender
rank_text,
[sender]
)
except Exception as e:
self.LOG.error(f"显示排行榜出错: {e}")

View File

@@ -3,7 +3,6 @@ import threading
import time # 添加这一行
from typing import Dict, Any, List, Optional, Tuple
from message_util import MessageUtil
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
@@ -56,7 +55,6 @@ class GlobalNewsPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util: MessageUtil = context.get("message_util")
self._commands = self._config.get("GlobalNews", {}).get("command",
["全球新闻", "国际新闻", "环球新闻", "政经新闻"])

View File

@@ -3,12 +3,9 @@ from typing import Dict, Any, List, Optional, Tuple
import xml.etree.ElementTree as ET
import dacite
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
from message_util import MessageUtil # 导入消息工具类
from wechat_ipad import WechatAPIClient
@@ -50,9 +47,6 @@ class GroupMemberChangePlugin(MessagePluginInterface):
"""初始化插件"""
self.LOG.info(f"正在初始化 {self.name} 插件...")
# 创建消息工具实例message_util
self.message_util: MessageUtil = context.get("message_util")
self.LOG.info(f"{self.name} 插件初始化完成")
return True

View File

@@ -1,12 +1,12 @@
from typing import Dict, Any, List, Optional, Tuple
from message_util import MessageUtil
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
from utils.wechat.contact_manager import ContactManager
from db.connection import DBConnectionManager
from db.group_virtual_redis import GroupVirtualRedisDB
from wechat_ipad import WechatAPIClient
from wechat_ipad.models.message import WxMessage
@@ -42,6 +42,7 @@ class GroupVirtualPlugin(MessagePluginInterface):
self.data = None
self.message_cache = set() # 用于防止消息循环转发
self.group_virtual_redis = None
self.bot: WechatAPIClient = None
def initialize(self, context: Dict[str, Any]) -> bool:
"""初始化插件"""
@@ -49,7 +50,6 @@ class GroupVirtualPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util: MessageUtil = context.get("message_util")
# 初始化配置
self.enable = self._config.get("GroupVirtual", {}).get("enable", True)
@@ -96,6 +96,8 @@ class GroupVirtualPlugin(MessagePluginInterface):
roomid = message.get("roomid", "")
sender = message.get("sender", "")
full_wx_msg: WxMessage = message.get("full_wx_msg")
self.bot: WechatAPIClient = message.get("bot")
# 检查是否是机器人自己发送的消息
if full_wx_msg.from_self():
return False, "不转发自己的消息"
@@ -154,7 +156,7 @@ class GroupVirtualPlugin(MessagePluginInterface):
# 转发到其他群
for group in chat_group["groups"]:
if group["id"] != roomid: # 不转发回源群
self.message_util.send_text(forward_content, group["id"])
self.bot.send_text_message(group["id"], forward_content)
# 图片消息 暂时不支持。
# elif msg_type == 3:

View File

@@ -152,7 +152,6 @@ class JDTokenPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util = context.get("message_util")
# 从TOML配置文件加载配置
self._commands = self._config.get("JD_Token", {}).get("command", ["设置京东"])

View File

@@ -1,7 +0,0 @@
# 从当前包的main模块导入MusicPlugin类
from .main import MessageRecallPlugin
# 提供get_plugin函数返回插件实例
def get_plugin():
"""获取插件实例"""
return MessageRecallPlugin()

View File

@@ -1,4 +0,0 @@
[MessageRecall]
enable = false
command = ["#撤回"]
command-format = "#撤回 3"

View File

@@ -1,142 +0,0 @@
from loguru import logger
from typing import Dict, Any, List, Tuple, Optional
from message_util import MessageUtil
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
from utils.robot_cmd.robot_command import GroupBotManager
class MessageRecallPlugin(MessagePluginInterface):
"""消息撤回功能插件"""
@property
def name(self) -> str:
return "消息撤回"
@property
def version(self) -> str:
return "1.0.0"
@property
def description(self) -> str:
return "允许管理员撤回机器人在群聊中发送的消息"
@property
def author(self) -> str:
return "Trae AI"
@property
def command_prefix(self) -> Optional[str]:
return "" # 不需要前缀,直接匹配命令
@property
def commands(self) -> List[str]:
return self._commands
def __init__(self):
super().__init__()
def initialize(self, context: Dict[str, Any]) -> bool:
"""初始化插件"""
self.LOG = logger
self.LOG.info(f"正在初始化 {self.name} 插件...")
self.event_system = context.get("event_system")
self.message_util: MessageUtil = context.get("message_util")
# 从配置中获取命令和启用状态
self._commands = self._config.get("MessageRecall", {}).get("command", ["撤回"])
# 希望加入撤回最近3条的功能,将最近的3条发言撤回,加上群信息
self.command_format = self._config.get("MessageRecall", {}).get("command-format", "撤回 3")
self.enable = self._config.get("MessageRecall", {}).get("enable", True)
self.LOG.info(f"[{self.name}] 插件初始化完成,指令:{self._commands}")
return True
def start(self) -> bool:
"""启动插件"""
self.LOG.info(f"[{self.name}] 插件已启动")
self.status = PluginStatus.RUNNING
return True
def stop(self) -> bool:
"""停止插件"""
self.LOG.info(f"[{self.name}] 插件已停止")
self.status = PluginStatus.STOPPED
return True
def can_process(self, message: Dict[str, Any]) -> bool:
"""检查是否可以处理该消息"""
if not self.enable:
return False
content = str(message.get("content", "")).strip()
# 检查是否是撤回命令
for cmd in self._commands:
if content.startswith(cmd):
return True
return False
@plugin_stats_decorator(plugin_name="消息撤回")
def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""处理消息"""
content = str(message.get("content", "")).strip()
self.LOG.debug(f"插件执行: {self.name}{content}")
sender = message.get("sender")
roomid = message.get("roomid", "")
# 检查是否是管理员
admin_list = GroupBotManager.get_admin_list()
self.LOG.info(f"admin_list={admin_list}")
# if sender not in admin_list:
# self.message_util.send_text("⚠️ 权限不足,只有管理员才能撤回消息",
# (roomid if roomid else sender), sender)
# return True, "权限不足"
# 解析命令获取消息ID
parts = content.split(" ", 1)
if len(parts) < 2:
self.message_util.send_text(f"❌命令格式错误!\n{self.command_format}",
(roomid if roomid else sender), sender)
return True, "命令格式错误"
#
# try:
# # 从数据库里面提取可以处理的消息and StrTalker ={roomid}
# sql = (f"SELECT * FROM MSG where IsSender=1 and CreateTime > (strftime('%s', 'now') - 120) "
# f"limit {parts[1]}")
# data = self.message_util.query_sql('MSG0.db', sql)
# self.LOG.info(f"SQL:{sql}\n 查询到可撤回数据: {data}")
# if not data:
# self.message_util.send_text("❌ 没有可撤回的消息", (roomid if roomid else sender), sender)
# return True, "没有可撤回的消息"
# for item in data:
# if item["MsgSvrID"]:
# # 调用撤回消息API
# result = self.message_util.revoke_msg(item["MsgSvrID"])
# if result:
# self.message_util.send_text("✅ 消息撤回成功", (roomid if roomid else sender), sender)
# return True, "撤回成功"
# else:
# self.message_util.send_text("❌ 消息撤回失败可能是消息ID无效或已超过撤回时间限制2分钟",
# (roomid if roomid else sender), sender)
# return True, "撤回失败"
#
# except Exception as e:
# self.LOG.error(f"撤回消息出错: {e}")
# self.message_util.send_text(f"❌ 撤回消息出错: {str(e)}", (roomid if roomid else sender), sender)
# return True, f"处理出错: {e}"
def get_help(self) -> str:
"""获取插件帮助信息"""
return """消息撤回插件:
功能:允许管理员撤回机器人在群聊中发送的消息
用法:#撤回 3
说明:
1. 只有管理员可以使用此功能
2. 消息ID需要从日志或其他方式获取
3. 微信限制只能撤回2分钟内的消息"""

View File

@@ -47,7 +47,6 @@ class MusicPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util = context.get("message_util")
self._commands = self._config.get("Music", {}).get("command", ["点歌", "音乐"])
self.command_format = self._config.get("Music", {}).get("command-format", "点歌 歌曲名")

View File

@@ -7,6 +7,7 @@ from plugin_common.plugin_interface import PluginStatus
from plugin_common.plugin_registry import PluginRegistry
from plugin_common.plugin_manager import PluginManager
from utils.robot_cmd.robot_command import GroupBotManager
from wechat_ipad import WechatAPIClient
class PluginManagerPlugin(MessagePluginInterface):
@@ -36,20 +37,9 @@ class PluginManagerPlugin(MessagePluginInterface):
def commands(self) -> List[str]:
return self._commands
def start(self) -> bool:
"""启动插件"""
self.LOG.info(f"[{self.name}] 插件已启动")
self.status = PluginStatus.RUNNING
return True
def stop(self) -> bool:
"""停止插件"""
self.LOG.info(f"[{self.name}] 插件已停止")
self.status = PluginStatus.STOPPED
return True
def __init__(self):
super().__init__()
self.bot: WechatAPIClient = None
def initialize(self, context: Dict[str, Any]) -> bool:
"""初始化插件"""
@@ -58,7 +48,6 @@ class PluginManagerPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util = context.get("message_util")
self._commands = self._config.get("PluginManager", {}).get("command", ["插件", "plugin", "插件管理"])
self.command_format = self._config.get("PluginManager", {}).get("command-format", "插件 列表")
@@ -67,8 +56,6 @@ class PluginManagerPlugin(MessagePluginInterface):
self.LOG.info(f"[{self.name}] 插件初始化完成,指令:{self._commands}")
return True
# ... start 和 stop 方法保持不变 ...
def can_process(self, message: Dict[str, Any]) -> bool:
"""检查是否可以处理该消息"""
if not self.enable:
@@ -79,7 +66,7 @@ class PluginManagerPlugin(MessagePluginInterface):
return command in self._commands
def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
async def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""处理消息"""
content = str(message.get("content", "")).strip()
self.LOG.debug(f"插件执行: {self.name}{content}")
@@ -88,18 +75,25 @@ class PluginManagerPlugin(MessagePluginInterface):
roomid = message.get("roomid", "")
gbm = message.get("gbm")
target = roomid if roomid else sender
self.bot: WechatAPIClient = message.get("bot")
if not self.bot:
self.LOG.error("WechatAPIClient 未初始化")
return False, "Bot 未初始化"
# 检查命令格式
parts = content.split(" ")
if len(parts) == 1:
self.message_util.send_text(f"❌命令格式错误!\n{self.command_format}", target, sender)
await self.bot.send_at_message(target, f"❌命令格式错误!\n{self.command_format}", [sender])
return True, "命令格式错误"
# 只有使用的时候才全局获取对象。防止在预加载的时候跟主线程冲突
self.plugin_registry = PluginRegistry()
self.plugin_manager = PluginManager().get_instance()
# 检查权限 (只允许管理员操作)
if not self._is_admin(sender, gbm):
self.message_util.send_text(f"❌权限不足,只有管理员可以管理插件", target, sender)
await self.bot.send_at_message(target, f"❌权限不足,只有管理员可以管理插件", [sender])
return True, "权限不足"
# 解析子命令
@@ -114,23 +108,22 @@ class PluginManagerPlugin(MessagePluginInterface):
"禁用": lambda s, r: self._operate_plugin(plugin_name, s, r, self._disable_plugin),
"重载": lambda s, r: self._operate_plugin(plugin_name, s, r, self._reload_plugin),
"卸载": lambda s, r: self._operate_plugin(plugin_name, s, r, self._unload_plugin),
# 修改这一行,使用 lambda 函数而不是直接调用
"加载": lambda s, r: self._load_plugin(plugin_name, s, r),
"信息": lambda s, r: self._operate_plugin(plugin_name, s, r, self._plugin_info)
}
handler = command_handlers.get(sub_command)
if handler and (sub_command == "列表" or plugin_name):
return handler(sender, roomid)
return await handler(sender, roomid)
else:
self.message_util.send_text(f"❌未知命令或缺少参数!\n{self.command_format}", target, sender)
await self.bot.send_at_message(target, f"❌未知命令或缺少参数!\n{self.command_format}", [sender])
return True, "未知命令"
except Exception as e:
import traceback
error_trace = traceback.format_exc()
self.LOG.error(f"处理插件管理请求出错: {e}\n{error_trace}")
self.message_util.send_text(f"❌操作失败: {str(e)}", target, sender)
await self.bot.send_at_message(target, f"❌操作失败: {str(e)}", [sender])
return True, f"处理出错: {e}"
def _is_admin(self, user_id: str, gbm: GroupBotManager) -> bool:
@@ -138,7 +131,7 @@ class PluginManagerPlugin(MessagePluginInterface):
admin_list = gbm.get_admin_list() if gbm else []
return user_id in admin_list
def _list_plugins(self, wcf, sender: str, roomid: str) -> Tuple[bool, str]:
async def _list_plugins(self, sender: str, roomid: str) -> Tuple[bool, str]:
"""列出所有插件"""
plugins = self.plugin_registry.get_all_plugins().values()
target = roomid if roomid else sender
@@ -147,15 +140,14 @@ class PluginManagerPlugin(MessagePluginInterface):
message = "📋 插件列表:\n"
for plugin in plugins:
status = "✅ 已启用" if plugin.status == PluginStatus.RUNNING else "❌ 已禁用"
# 获取插件模块名
module_name = plugin.__class__.__module__.split('.')[-2]
message += f"{status}-{plugin.name} [模块: {module_name}]\n"
self.message_util.send_text(message, target, sender)
await self.bot.send_at_message(target, message, [sender])
return True, "列出插件成功"
def _operate_plugin(self, plugin_name: str, sender: str, roomid: str,
operation_func) -> Tuple[bool, str]:
async def _operate_plugin(self, plugin_name: str, sender: str, roomid: str,
operation_func) -> Tuple[bool, str]:
"""通用插件操作函数"""
target = roomid if roomid else sender
@@ -163,170 +155,147 @@ class PluginManagerPlugin(MessagePluginInterface):
display_name, plugin = self.plugin_manager.find_plugin_by_name(plugin_name)
if not display_name:
self.message_util.send_text(f"❌未找到插件 {plugin_name},请检查名称是否正确", target, sender)
await self.bot.send_at_message(target, f"❌未找到插件 {plugin_name},请检查名称是否正确", [sender])
return True, f"未找到插件 {plugin_name}"
# 不允许操作自身(对于某些操作)
if display_name == self.name and operation_func in [self._unload_plugin, self._disable_plugin]:
self.message_util.send_text(f"⚠️不能对插件管理插件自身执行此操作", target, sender)
await self.bot.send_at_message(target, f"⚠️不能对插件管理插件自身执行此操作", [sender])
return True, "不能对插件管理插件自身执行此操作"
# 执行具体操作
return operation_func(display_name, sender, roomid)
return await operation_func(display_name, sender, roomid)
def _enable_plugin(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
async def _enable_plugin(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
"""启用插件"""
target = roomid if roomid else sender
plugin = self.plugin_registry.get_plugin(plugin_name)
if not plugin:
self.message_util.send_text(f"❌插件 {plugin_name} 不存在", target, sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 不存在", [sender])
return True, f"插件 {plugin_name} 不存在"
if plugin.status == PluginStatus.RUNNING:
self.message_util.send_text(f"⚠️插件 {plugin_name} 已经处于启用状态", target, sender)
await self.bot.send_at_message(target, f"⚠️插件 {plugin_name} 已经处于启用状态", [sender])
return True, f"插件 {plugin_name} 已经处于启用状态"
# 获取插件的模块名
module_name = plugin.__class__.__module__.split('.')[-2]
# 启动插件
if self.plugin_manager.start_plugin(module_name):
self.message_util.send_text(f"✅插件 {plugin_name} 启用成功", target, sender)
await self.bot.send_at_message(target, f"✅插件 {plugin_name} 启用成功", [sender])
return True, f"插件 {plugin_name} 启用成功"
else:
self.message_util.send_text(f"❌插件 {plugin_name} 启用失败", target, sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 启用失败", [sender])
return False, f"插件 {plugin_name} 启用失败"
def _disable_plugin(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
async def _disable_plugin(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
"""禁用插件"""
target = roomid if roomid else sender
plugin = self.plugin_registry.get_plugin(plugin_name)
if not plugin:
self.message_util.send_text(f"❌插件 {plugin_name} 不存在", target, sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 不存在", [sender])
return True, f"插件 {plugin_name} 不存在"
if plugin.status != PluginStatus.RUNNING:
self.message_util.send_text(f"⚠️插件 {plugin_name} 已经处于禁用状态", target, sender)
await self.bot.send_at_message(target, f"⚠️插件 {plugin_name} 已经处于禁用状态", [sender])
return True, f"插件 {plugin_name} 已经处于禁用状态"
# 获取插件的模块名
module_name = plugin.__class__.__module__.split('.')[-2]
# 停止插件
if self.plugin_manager.stop_plugin(module_name):
self.message_util.send_text(f"✅插件 {plugin_name} 禁用成功", target, sender)
await self.bot.send_at_message(target, f"✅插件 {plugin_name} 禁用成功", [sender])
return True, f"插件 {plugin_name} 禁用成功"
else:
self.message_util.send_text(f"❌插件 {plugin_name} 禁用失败", target, sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 禁用失败", [sender])
return False, f"插件 {plugin_name} 禁用失败"
def _reload_plugin(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
async def _reload_plugin(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
"""重载插件"""
target = roomid if roomid else sender
plugin = self.plugin_registry.get_plugin(plugin_name)
if not plugin:
self.message_util.send_text(f"❌插件 {plugin_name} 不存在", target, sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 不存在", [sender])
return True, f"插件 {plugin_name} 不存在"
# 记录原插件状态
was_running = plugin.status == PluginStatus.RUNNING
# 获取插件的模块名
module_name = plugin.__class__.__module__.split('.')[-2]
# 重载插件
reloaded_plugin = self.plugin_manager.reload_plugin(module_name)
if reloaded_plugin:
self.message_util.send_text(f"✅插件 {plugin_name} 重载成功", target, sender)
await self.bot.send_at_message(target, f"✅插件 {plugin_name} 重载成功", [sender])
return True, f"插件 {plugin_name} 重载成功"
else:
self.message_util.send_text(f"❌插件 {plugin_name} 重载失败", target, sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 重载失败", [sender])
return False, f"插件 {plugin_name} 重载失败"
def _unload_plugin(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
async def _unload_plugin(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
"""卸载插件"""
target = roomid if roomid else sender
plugin = self.plugin_registry.get_plugin(plugin_name)
if not plugin:
self.message_util.send_text(f"❌插件 {plugin_name} 不存在", target, sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 不存在", [sender])
return True, f"插件 {plugin_name} 不存在"
# 获取插件的模块名
module_name = plugin.__class__.__module__.split('.')[-2]
# 卸载插件
if self.plugin_manager.unload_plugin(module_name):
self.message_util.send_text(f"✅插件 {plugin_name} 卸载成功", target, sender)
await self.bot.send_at_message(target, f"✅插件 {plugin_name} 卸载成功", [sender])
return True, f"插件 {plugin_name} 卸载成功"
else:
self.message_util.send_text(f"❌插件 {plugin_name} 卸载失败", target, sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 卸载失败", [sender])
return False, f"插件 {plugin_name} 卸载失败"
def _load_plugin(self, plugin_name: str, sender: str, roomid: str, silent: bool = False) -> Tuple[bool, str]:
async def _load_plugin(self, plugin_name: str, sender: str, roomid: str, silent: bool = False) -> Tuple[bool, str]:
"""加载插件"""
# 对于加载操作,我们直接使用目录名作为模块名
# 检查插件目录是否存在
plugin_dir = os.path.join("plugins", plugin_name)
target = roomid if roomid else sender
if not os.path.exists(plugin_dir):
if not silent:
self.message_util.send_text(f"❌插件目录 {plugin_dir} 不存在",
(roomid if roomid else sender), sender)
await self.bot.send_at_message(target, f"❌插件目录 {plugin_dir} 不存在", [sender])
return False, f"插件目录 {plugin_dir} 不存在"
# 检查插件是否已加载 - 遍历所有插件查找模块名匹配的
for existing_plugin in self.plugin_registry.get_all_plugins().values():
existing_module_name = existing_plugin.__class__.__module__.split('.')[-2]
if existing_module_name == plugin_name:
if not silent:
self.message_util.send_text(f"⚠️插件 {existing_plugin.name} (模块名: {plugin_name}) 已经加载",
(roomid if roomid else sender), sender)
await self.bot.send_at_message(target, f"⚠️插件 {existing_plugin.name} (模块名: {plugin_name}) 已经加载", [sender])
return True, f"插件 {existing_plugin.name} 已经加载"
try:
# 使用插件管理器加载插件
plugin = self.plugin_manager.load_plugin(plugin_name)
if plugin:
if not silent:
self.message_util.send_text(f"✅插件 {plugin.name} 加载成功",
(roomid if roomid else sender), sender)
await self.bot.send_at_message(target, f"✅插件 {plugin.name} 加载成功", [sender])
return True, f"插件 {plugin.name} 加载成功"
else:
if not silent:
self.message_util.send_text(f"❌插件 {plugin_name} 加载失败",
(roomid if roomid else sender), sender)
await self.bot.send_at_message(target, f"❌插件 {plugin_name} 加载失败", [sender])
return False, f"插件 {plugin_name} 加载失败"
except Exception as e:
self.LOG.error(f"加载插件 {plugin_name} 出错: {e}")
if not silent:
self.message_util.send_text(f"❌加载插件出错: {str(e)}",
(roomid if roomid else sender), sender)
await self.bot.send_at_message(target, f"❌加载插件出错: {str(e)}", [sender])
return False, f"加载插件出错: {e}"
def _plugin_info(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
async def _plugin_info(self, plugin_name: str, sender: str, roomid: str) -> Tuple[bool, str]:
"""查看插件详情"""
# 查找匹配的插件名称
target = roomid if roomid else sender
display_name, plugin = self.plugin_manager.find_plugin_by_name(plugin_name)
if not display_name:
self.message_util.send_text(f"❌未找到插件 {plugin_name},请检查名称是否正确",
(roomid if roomid else sender), sender)
await self.bot.send_at_message(target, f"❌未找到插件 {plugin_name},请检查名称是否正确", [sender])
return True, f"未找到插件 {plugin_name}"
plugin = self.plugin_registry.get_plugin(display_name)
if not plugin:
self.message_util.send_text(f"❌插件 {display_name} 不存在",
(roomid if roomid else sender), sender)
await self.bot.send_at_message(target, f"❌插件 {display_name} 不存在", [sender])
return True, f"插件 {display_name} 不存在"
# 获取插件模块名
module_name = plugin.__class__.__module__.split('.')[-2]
# 构建插件详情消息
status_text = "✅ 已启用" if plugin.status == PluginStatus.RUNNING else "❌ 已禁用"
message = f"""
📦 插件详情:{plugin.name}
@@ -338,5 +307,5 @@ class PluginManagerPlugin(MessagePluginInterface):
🔑 命令:{', '.join(plugin.commands) if hasattr(plugin, 'commands') else ''}
"""
self.message_util.send_text(message, (roomid if roomid else sender), sender)
return True, "查看插件详情成功"
await self.bot.send_at_message(target, message, [sender])
return True, "查看插件详情成功"

View File

@@ -5,8 +5,7 @@ from typing import Dict, Any, List, Optional, Tuple
import xml.etree.ElementTree as ET
from db.connection import DBConnectionManager
from db.points_db import PointsDBOperator, PointSource
from message_util import MessageUtil
from db.points_db import PointsDBOperator
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator

View File

@@ -49,7 +49,6 @@ class SystemUpdaterPlugin(MessagePluginInterface):
self.LOG.info(f"正在初始化 {self.name} 插件...")
# 保存上下文对象
self.message_util = context.get("message_util")
self.config = self._config
# 从配置中获取命令和其他设置

View File

@@ -54,8 +54,6 @@ class VideoPlugin(MessagePluginInterface):
self.LOG.info(f"正在初始化 {self.name} 插件...")
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util = context.get("message_util")
self.gbm = context.get("gbm")
self._commands = self._config.get("Video", {}).get("command", ["黑丝视频", "黑丝", "来个黑丝", "搞个黑丝"])

View File

@@ -3,7 +3,6 @@ import os
import requests
from typing import Dict, Any, List, Optional, Tuple
from message_util import MessageUtil
from plugin_common.message_plugin_interface import MessagePluginInterface
from plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
@@ -50,7 +49,6 @@ class VideoManPlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util: MessageUtil = context.get("message_util")
self.gbm = context.get("gbm")
self._commands = self._config.get("VideoMan", {}).get("command", ["猛男", "肌肉", "帅哥"])

View File

@@ -47,10 +47,6 @@ class WeatherPlugin(MessagePluginInterface):
self.LOG = logger
self.LOG.info(f"正在初始化 {self.name} 插件...")
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util = context.get("message_util")
# 从TOML配置文件加载配置
self._commands = self._config.get("Weather", {}).get("command", ["天气"])
self.command_format = self._config.get("Weather", {}).get("command-format", """⚙️获取天气:

View File

@@ -53,8 +53,7 @@ class XiurenImagePlugin(MessagePluginInterface):
# 保存上下文对象
self.event_system = context.get("event_system")
self.message_util = context.get("message_util")
self._commands = self._config.get("XiurenImage", {}).get("command", ["图来", "秀人"])
self.command_format = self._config.get("XiurenImage", {}).get("command-format", "图来")
self.enable = self._config.get("XiurenImage", {}).get("enable", True)

View File

@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
import re
import time
import asyncio
import threading
@@ -23,7 +22,6 @@ from utils.revoke.message_auto_revoke import MessageAutoRevoke
from utils.robot_cmd.robot_command import GroupBotManager, Feature, PermissionStatus
from db.connection import DBConnectionManager
from message_util import MessageUtil
from db.contacts_db import ContactsDBOperator
from utils.wechat.contact_manager import ContactManager
from utils.wechat.message_to_db import MessageStorage
@@ -81,15 +79,13 @@ class Robot(Job):
self.event_system = EventSystem()
self.plugin_modules = {} # 存储已加载的插件模块
self.plugins = {} # 存储已加载的插件实例
self.message_util = None
# 设置插件系统上下文
self.system_context = {
"config": config,
"event_system": self.event_system,
"plugin_registry": self.plugin_registry,
"db_pool": self.db_pool,
"redis_pool": self.redis_pool,
"message_util": self.message_util
"redis_pool": self.redis_pool
}
self.plugin_manager = PluginManager(plugin_dir=getattr(self.config, "plugin_dir", "plugins"))
@@ -185,8 +181,6 @@ class Robot(Job):
self.message_storage = MessageStorage(self.ipad_bot)
# 初始化消息工具类 - 使用联系人管理器
self.message_util = MessageUtil(self.ipad_bot)
# 先接受堆积消息
self.LOG.info("处理堆积消息中")