@@ -20,16 +20,6 @@ class RobotMenuPlugin(MessagePluginInterface):
|
||||
# 功能权限常量
|
||||
FEATURE_KEY = "ROBOT_MENU"
|
||||
FEATURE_DESCRIPTION = "📋 功能菜单 [菜单 - 显示功能菜单 | 菜单 状态 - 显示功能状态]"
|
||||
AT_QUERY_KEYWORDS = (
|
||||
"功能清单",
|
||||
"功能菜单",
|
||||
"功能列表",
|
||||
"菜单",
|
||||
"怎么用",
|
||||
"如何用",
|
||||
"帮助",
|
||||
"help",
|
||||
)
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
@@ -102,56 +92,9 @@ class RobotMenuPlugin(MessagePluginInterface):
|
||||
return False
|
||||
|
||||
content = str(message.get("content", "")).strip()
|
||||
command = content.split(" ")[0] if content else ""
|
||||
roomid = str(message.get("roomid", "") or "")
|
||||
is_at = bool(message.get("is_at", False))
|
||||
command = content.split(" ")[0]
|
||||
|
||||
# 指令入口
|
||||
if command in self._commands:
|
||||
return True
|
||||
|
||||
# @语义入口:只在群聊 + @机器人 + 明确菜单意图时触发
|
||||
if roomid and is_at and self._is_at_menu_query(content):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _normalize_text(content: str) -> str:
|
||||
text = str(content or "").lower().strip()
|
||||
text = re.sub(r"\s+", "", text)
|
||||
return text
|
||||
|
||||
def _is_at_menu_query(self, content: str) -> bool:
|
||||
text = self._normalize_text(content)
|
||||
if not text:
|
||||
return False
|
||||
return any(self._normalize_text(keyword) in text for keyword in self.AT_QUERY_KEYWORDS)
|
||||
|
||||
@staticmethod
|
||||
def _extract_usage_from_description(description: str) -> str:
|
||||
"""
|
||||
从 Feature.description 中提取 [ ... ] 内的触发方式
|
||||
例如: '📋 功能菜单 [菜单 - 显示功能菜单]' -> '菜单'
|
||||
"""
|
||||
desc = str(description or "")
|
||||
match = re.search(r"\[(.*?)\]", desc)
|
||||
if not match:
|
||||
return "请发送“菜单”查看"
|
||||
inner = match.group(1).strip()
|
||||
# 取第一段触发方式,避免太长
|
||||
first = inner.split("|")[0].strip()
|
||||
if "-" in first:
|
||||
first = first.split("-", 1)[0].strip()
|
||||
return first or "请发送“菜单”查看"
|
||||
|
||||
@staticmethod
|
||||
def _extract_brief_from_description(description: str) -> str:
|
||||
desc = str(description or "")
|
||||
# 去掉开头 emoji 和 [..] 指令块,只保留一句用途
|
||||
desc = re.sub(r"^[^\u4e00-\u9fa5A-Za-z0-9]+", "", desc)
|
||||
desc = re.sub(r"\[.*?\]", "", desc).strip()
|
||||
return desc or "暂无说明"
|
||||
return command in self._commands
|
||||
|
||||
def display_menu_status(self, group_id: str) -> str:
|
||||
"""显示所有功能列表及其在指定群组中的当前状态,带emoji"""
|
||||
@@ -163,64 +106,43 @@ class RobotMenuPlugin(MessagePluginInterface):
|
||||
menu.append(f"{status_emoji} {status_str}-{feature.value}-{feature.description}")
|
||||
return "\n".join(menu)
|
||||
|
||||
def _get_enabled_feature_items(self, group_id: str) -> List[Dict[str, str]]:
|
||||
"""获取本群已启用且可对用户展示的功能条目"""
|
||||
items: List[Dict[str, str]] = []
|
||||
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 items
|
||||
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:
|
||||
items.append({
|
||||
enabled_features.append({
|
||||
"id": feature.value,
|
||||
"name": feature.name,
|
||||
"description": feature.description
|
||||
})
|
||||
return items
|
||||
|
||||
def get_enabled_features(self, group_id: str) -> str:
|
||||
"""兼容旧接口:返回简化文本菜单"""
|
||||
enabled_features = self._get_enabled_feature_items(group_id)
|
||||
if group_id not in GroupBotManager.local_cache["group_list"]:
|
||||
return "该群未启用机器人功能"
|
||||
# 如果没有启用任何带指令的功能
|
||||
if not enabled_features:
|
||||
return "该群未启用任何带指令的功能"
|
||||
result = "群功能菜单:\n"
|
||||
|
||||
# 构建格式化的字符串
|
||||
result = f"不支持@交互,请通过指令触发\n 群功能菜单:\n"
|
||||
for feature in enabled_features:
|
||||
usage = self._extract_usage_from_description(feature["description"])
|
||||
brief = self._extract_brief_from_description(feature["description"])
|
||||
result += f"{feature['id']}. {feature['name']} | 触发:{usage} | {brief}\n"
|
||||
return result.strip()
|
||||
result += f"{feature['id']}.{feature['description']}\n"
|
||||
|
||||
def build_user_friendly_menu(self, group_id: str) -> str:
|
||||
"""构建给普通群成员看的直观功能菜单"""
|
||||
if group_id not in GroupBotManager.local_cache["group_list"]:
|
||||
return "当前群未开通机器人功能,请联系管理员开启。"
|
||||
|
||||
enabled_features = self._get_enabled_feature_items(group_id)
|
||||
if not enabled_features:
|
||||
return "当前群暂无可用功能。"
|
||||
|
||||
lines = [
|
||||
"本群已开通功能:",
|
||||
"直接复制“触发”里的命令发送即可。",
|
||||
"",
|
||||
]
|
||||
for idx, feature in enumerate(enabled_features, start=1):
|
||||
usage = self._extract_usage_from_description(feature["description"])
|
||||
brief = self._extract_brief_from_description(feature["description"])
|
||||
lines.append(f"{idx}. {feature['name']}")
|
||||
lines.append(f"触发:{usage}")
|
||||
lines.append(f"说明:{brief}")
|
||||
lines.append("")
|
||||
|
||||
lines.append("快捷入口:")
|
||||
lines.append("发送“菜单”可再次查看;发送“菜单 状态”可看全部开关状态。")
|
||||
return "\n".join(lines).strip()
|
||||
return result
|
||||
|
||||
def get_group_list(self) -> str:
|
||||
"""返回所有启用了群机器人的群组清单"""
|
||||
@@ -249,7 +171,6 @@ class RobotMenuPlugin(MessagePluginInterface):
|
||||
self.LOG.debug(f"插件执行: {self.name}:{content}")
|
||||
sender = message.get("sender")
|
||||
roomid = message.get("roomid", "")
|
||||
is_at = bool(message.get("is_at", False))
|
||||
command = content.split(" ")[0]
|
||||
gbm: GroupBotManager = message.get("gbm")
|
||||
bot: WechatAPIClient = message.get("bot")
|
||||
@@ -266,24 +187,15 @@ class RobotMenuPlugin(MessagePluginInterface):
|
||||
return False, "没有权限"
|
||||
|
||||
target = roomid if roomid else sender
|
||||
is_at_menu_query = roomid and is_at and self._is_at_menu_query(content)
|
||||
|
||||
# @语义菜单入口:用户@机器人直接问“功能清单/怎么用”
|
||||
if is_at_menu_query and command not in self._commands:
|
||||
menu_text = self.build_user_friendly_menu(roomid)
|
||||
client_msg_id, create_time, new_msg_id = await bot.send_text_message(target, menu_text, sender)
|
||||
revoke.add_message_to_revoke(target, client_msg_id, create_time, new_msg_id, 120)
|
||||
return True, "at菜单问答"
|
||||
|
||||
# 检查命令格式
|
||||
parts = content.split()
|
||||
if len(parts) == 1:
|
||||
# 显示功能菜单
|
||||
group_for_menu = roomid if roomid else sender
|
||||
menu_text = self.build_user_friendly_menu(group_for_menu)
|
||||
menu_text = self.get_enabled_features(roomid if roomid else sender)
|
||||
|
||||
client_msg_id, create_time, new_msg_id = await bot.send_text_message(target, menu_text, sender)
|
||||
revoke.add_message_to_revoke(target, client_msg_id, create_time, new_msg_id, 120)
|
||||
revoke.add_message_to_revoke(target, client_msg_id, create_time, new_msg_id, 90)
|
||||
return True, "显示功能菜单"
|
||||
|
||||
# 提取命令名
|
||||
|
||||
Reference in New Issue
Block a user