新增功能菜单。

This commit is contained in:
liuwei
2025-06-06 17:46:10 +08:00
parent 6b1f01da4b
commit 85c08727c2
5 changed files with 216 additions and 56 deletions

View File

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

View File

@@ -0,0 +1,8 @@
[RobotMenu]
enable = true
command = ["菜单", "功能菜单"]
command-format = """
📝功能菜单指令:
菜单 - 显示功能菜单
菜单 状态 - 显示功能状态
"""

172
plugins/robot_menu/main.py Normal file
View File

@@ -0,0 +1,172 @@
import base64
from loguru import logger
from typing import Dict, Any, List, Optional, Tuple
from base.plugin_common.message_plugin_interface import MessagePluginInterface
from base.plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
from utils.revoke.message_auto_revoke import MessageAutoRevoke
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 RobotMenuPlugin(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._commands = self._config.get("RobotMenu", {}).get("command", ["菜单", "功能"])
self.command_format = self._config.get("RobotMenu", {}).get("command-format", "菜单 功能名")
self.enable = self._config.get("RobotMenu", {}).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()
command = content.split(" ")[0]
return command in self._commands
def display_menu_status(self, group_id: str) -> str:
"""显示所有功能列表及其在指定群组中的当前状态带emoji"""
menu = []
for feature in Feature:
status = GroupBotManager.get_group_permission(group_id, feature)
status_emoji = "" if status == PermissionStatus.ENABLED else ""
status_str = "启用" if status == PermissionStatus.ENABLED else "关闭"
menu.append(f"{status_emoji} {status_str}-{feature.value}-{feature.description}")
return "\n".join(menu)
def get_enabled_features(self, group_id: str) -> str:
"""获取某个群已启用的功能列表及其描述,并返回格式化的字符串
只返回描述中包含指令(方括号[])的功能
Args:
group_id: 群ID
Returns:
str: 格式化的已启用功能列表字符串
"""
enabled_features = []
# 检查群是否在列表中
if group_id not in GroupBotManager.local_cache["group_list"]:
return "该群未启用机器人功能"
# 遍历所有功能,检查哪些已启用且包含指令
for feature in Feature:
status = GroupBotManager.get_group_permission(group_id, feature)
# 只添加已启用且描述中包含方括号的功能
if status == PermissionStatus.ENABLED and "[" in feature.description and "]" in feature.description:
enabled_features.append({
"id": feature.value,
"name": feature.name,
"description": feature.description
})
# 如果没有启用任何带指令的功能
if not enabled_features:
return "该群未启用任何带指令的功能"
# 构建格式化的字符串
result = f"不支持@交互,请通过指令触发\n 群功能菜单:\n"
for feature in enabled_features:
result += f"{feature['id']}.{feature['description']}\n"
return result
def get_group_list(self) -> str:
"""返回所有启用了群机器人的群组清单"""
group_list = list(GroupBotManager.local_cache["group_list"])
if not group_list:
return "当前没有启用机器人的群组"
return "\n".join(group_list)
@plugin_stats_decorator(plugin_name="功能菜单")
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}")
command = content.split(" ")[0]
sender = message.get("sender")
roomid = message.get("roomid", "")
bot: WechatAPIClient = message.get("bot")
revoke: MessageAutoRevoke = message.get("revoke")
# 检查命令格式
if len(content.split(" ")) == 1:
# 显示功能菜单
menu_text = self.get_enabled_features(roomid if roomid else sender)
client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender),
menu_text, sender)
revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 30)
return True, "显示功能菜单"
# 提取命令名
cmd_name = content[len(command):].strip()
try:
# 处理特殊命令
if cmd_name.upper() == "状态":
# 显示所有功能状态
status_text = self.display_menu_status(roomid if roomid else sender)
client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender),
status_text, sender)
revoke.add_message_to_revoke((roomid if roomid else sender), client_msg_id, create_time, new_msg_id, 30)
return True, "显示功能状态"
except Exception as e:
self.LOG.error(f"处理功能请求出错: {e}")
return False, f"处理出错: {e}"

View File

@@ -0,0 +1,28 @@
import requests
import urllib.parse
prompt = "创作一幅超照片级的亚洲美女单人自拍肖像仿若用高端智能手机如iPhone 16 Pro或同等设备拍摄。她具有[光泽柔顺的黑色波浪长发、杏仁状深棕色眼睛带细致虹膜纹理、光滑瓷白皮肤带微妙自然瑕疵、自信迷人的微笑]。自拍在[时尚的城市屋顶夜景灯光]中拍摄。她穿着[修身丝质连衣裙带微妙领口]散发优雅且微妙的性感气质。构图模仿自然自拍角度面部略微偏离中心持相机角度自然讨巧姿势优雅放松凸显魅力。皮肤、头发和眼睛的纹理超现实包含细致细节如单根发丝、微小皮肤毛孔和眼中真实反射。光线自然动态带有柔和阴影和高光模仿现实世界条件如黄金时段阳光或室内环境光突出她的特征。表情自信迷人带有随性、栩栩如生的氛围。背景清晰但自然模糊浅景深效果f/1.8光圈)。完全避免油画感、艺术化风格、笔触、卡通化元素,不要呈现文字或任何数字瑕疵。输出为高分辨率,超详细,与真实高分辨率照片无异。"
params = {
"width": 1080,
"height": 1920,
"seed": 44,
"model": "flux",
"nologo": "true", # Optional
# "transparent": "true", # Optional - generates transparent background (gptimage model only)
# "referrer": "MyPythonApp" # Optional
}
encoded_prompt = urllib.parse.quote(prompt)
url = f"https://image.pollinations.ai/prompt/{encoded_prompt}"
try:
response = requests.get(url, params=params, timeout=300) # Increased timeout for image generation
response.raise_for_status() # Raise an exception for bad status codes
with open('generated_image.jpg', 'wb') as f:
f.write(response.content)
print("Image saved as generated_image.jpg")
except requests.exceptions.RequestException as e:
print(f"Error fetching image: {e}")
# Consider checking response.text for error messages from the API
# if response is not None: print(response.text)

View File

@@ -155,18 +155,10 @@ class GroupBotManager:
@staticmethod
def handle_command(group_id, command_str):
"""统一处理群功能指令"""
# print(f"PermissionStatus handle_command command_str: {command_str}")
# print(f"PermissionStatus robot_menu command_str: {command_str}")
# 命令解析
command_parts = command_str.strip().split("-")
# 如果是MENU指令返回功能列表
if command_str.strip().upper() == "菜单":
return f"群ID{group_id} \n {GroupBotManager.get_enabled_features(group_id)}"
# 如果是MENU-STATUS指令返回功能列表及其状态
if command_str.strip().upper() == "菜单状态":
return f"群ID{group_id} \n {GroupBotManager.display_menu_status(group_id)}"
# 如果是GROUP_LIST指令返回 group:list 清单
if command_str.strip().upper() == "群列表":
return GroupBotManager.get_group_list()
@@ -239,53 +231,6 @@ class GroupBotManager:
permissions[feature] = status if status else PermissionStatus.DISABLED # 默认为禁用状态
return permissions
@staticmethod
def display_menu():
"""显示所有功能列表及其当前状态"""
menu = []
for feature in Feature:
menu.append(f"{feature.value}. {feature.description}")
return "\n".join(menu)
@staticmethod
def get_enabled_features(group_id):
"""获取某个群已启用的功能列表及其描述,并返回格式化的字符串
只返回描述中包含指令(方括号[])的功能
Args:
group_id: 群ID
Returns:
str: 格式化的已启用功能列表字符串
"""
enabled_features = []
# 检查群是否在列表中
if group_id not in GroupBotManager.local_cache["group_list"]:
return "该群未启用机器人功能"
# 遍历所有功能,检查哪些已启用且包含指令
for feature in Feature:
status = GroupBotManager.get_group_permission(group_id, feature)
# 只添加已启用且描述中包含方括号的功能
if status == PermissionStatus.ENABLED and "[" in feature.description and "]" in feature.description:
enabled_features.append({
"id": feature.value,
"name": feature.name,
"description": feature.description
})
# 如果没有启用任何带指令的功能
if not enabled_features:
return "该群未启用任何带指令的功能"
# 构建格式化的字符串
result = f"不支持@交互,请通过指令触发\n 群功能菜单:\n"
for feature in enabled_features:
result += f"{feature['id']}.{feature['description']}\n"
return result
@staticmethod
def get_group_list():
"""返回所有启用了群机器人的群组清单,格式为集合"""