From db29ebfeae3ff3fb90e6b7954b6e3dcbe8d653c9 Mon Sep 17 00:00:00 2001 From: tt-P607 <68868379+tt-P607@users.noreply.github.com> Date: Mon, 22 Sep 2025 22:52:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(poke):=20=E4=BC=98=E5=8C=96=E6=88=B3?= =?UTF-8?q?=E4=B8=80=E6=88=B3=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BC=98=E5=85=88?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=20user=5Fid=20=E5=AE=9A=E4=BD=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前的戳一戳功能仅依赖 `user_name` 来查找用户,这在某些情况下可能导致识别不准确或失败。 本次更新对计划执行器 (`PlanExecutor`) 进行了增强,使其在处理 `poke_user` 动作时,能直接从目标消息中提取 `user_id`。`PokeAction` 插件现在会优先使用这个更可靠的 `user_id`。如果 `user_id` 不存在,则回退到使用 `user_name` 作为备用方案。 这显著提高了戳一戳功能的准确性和稳定性。 --- src/chat/planner_actions/plan_executor.py | 26 +++++++++++++++- src/plugins/built_in/poke_plugin/plugin.py | 35 +++++++++++++--------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/chat/planner_actions/plan_executor.py b/src/chat/planner_actions/plan_executor.py index f6d70de60..9c266b0ec 100644 --- a/src/chat/planner_actions/plan_executor.py +++ b/src/chat/planner_actions/plan_executor.py @@ -4,6 +4,7 @@ PlanExecutor: 接收 Plan 对象并执行其中的所有动作。 """ import asyncio +import re import time from typing import Dict, List @@ -216,12 +217,35 @@ class PlanExecutor: try: logger.info(f"执行其他动作: {action_info.action_type} (原因: {action_info.reasoning})") + action_data = action_info.action_data or {} + + # 针对 poke_user 动作,特殊处理 + if action_info.action_type == "poke_user": + target_message = action_info.action_message + if target_message: + # 优先直接获取 user_id,这才是最可靠的信息 + user_id = target_message.get("user_id") + if user_id: + action_data["user_id"] = user_id + logger.info(f"检测到戳一戳动作,目标用户ID: {user_id}") + else: + # 如果没有 user_id,再尝试用 user_nickname 作为备用方案 + user_name = target_message.get("user_nickname") + if user_name: + action_data["user_name"] = user_name + logger.info(f"检测到戳一戳动作,目标用户: {user_name}") + else: + logger.warning("无法从戳一戳消息中获取用户ID或昵称。") + + # 传递原始消息ID以支持引用 + action_data["target_message_id"] = target_message.get("message_id") + # 构建动作参数 action_params = { "chat_id": plan.chat_id, "target_message": action_info.action_message, "reasoning": action_info.reasoning, - "action_data": action_info.action_data or {}, + "action_data": action_data, } # 通过动作管理器执行动作 diff --git a/src/plugins/built_in/poke_plugin/plugin.py b/src/plugins/built_in/poke_plugin/plugin.py index 13cf33ca0..a37c45dd1 100644 --- a/src/plugins/built_in/poke_plugin/plugin.py +++ b/src/plugins/built_in/poke_plugin/plugin.py @@ -30,7 +30,8 @@ class PokeAction(BaseAction): # === 功能描述(必须填写)=== action_parameters = { - "user_name": "需要戳一戳的用户的名字", + "user_name": "需要戳一戳的用户的名字 (可选)", + "user_id": "需要戳一戳的用户的ID (可选,优先级更高)", "times": "需要戳一戳的次数 (默认为 1)", } action_require = ["当需要戳某个用户时使用", "当你想提醒特定用户时使用"] @@ -46,32 +47,38 @@ class PokeAction(BaseAction): async def execute(self) -> Tuple[bool, str]: """执行戳一戳的动作""" + user_id = self.action_data.get("user_id") user_name = self.action_data.get("user_name") + try: times = int(self.action_data.get("times", 1)) except (ValueError, TypeError): times = 1 - if not user_name: - logger.warning("戳一戳动作缺少 'user_name' 参数。") - return False, "缺少 'user_name' 参数" - - user_info = await get_person_info_manager().get_person_info_by_name(user_name) - if not user_info or not user_info.get("user_id"): - logger.info(f"找不到名为 '{user_name}' 的用户。") - return False, f"找不到名为 '{user_name}' 的用户" - - user_id = user_info.get("user_id") + # 优先使用 user_id + if not user_id: + if not user_name: + logger.warning("戳一戳动作缺少 'user_id' 或 'user_name' 参数。") + return False, "缺少用户标识参数" + + # 备用方案:通过 user_name 查找 + user_info = await get_person_info_manager().get_person_info_by_name(user_name) + if not user_info or not user_info.get("user_id"): + logger.info(f"找不到名为 '{user_name}' 的用户。") + return False, f"找不到名为 '{user_name}' 的用户" + user_id = user_info.get("user_id") + + display_name = user_name or user_id for i in range(times): - logger.info(f"正在向 {user_name} ({user_id}) 发送第 {i + 1}/{times} 次戳一戳...") + logger.info(f"正在向 {display_name} ({user_id}) 发送第 {i + 1}/{times} 次戳一戳...") await self.send_command( - "SEND_POKE", args={"qq_id": user_id}, display_message=f"戳了戳 {user_name} ({i + 1}/{times})" + "SEND_POKE", args={"qq_id": user_id}, display_message=f"戳了戳 {display_name} ({i + 1}/{times})" ) # 添加一个小的延迟,以避免发送过快 await asyncio.sleep(0.5) - success_message = f"已向 {user_name} 发送 {times} 次戳一戳。" + success_message = f"已向 {display_name} 发送 {times} 次戳一戳。" await self.store_action_info( action_build_into_prompt=True, action_prompt_display=success_message, action_done=True )