From 601bce884745fffb97e3ba7ed48d681cbfb6d8c7 Mon Sep 17 00:00:00 2001 From: zhilv Date: Sat, 2 May 2026 19:58:47 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(command):=20=E5=9B=9E=E5=A4=8D?= =?UTF-8?q?=E6=97=B6=E5=BC=95=E7=94=A8=E5=8E=9F=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 event.reply() 替代手动调用 send_group/private_text - 自动引用触发命令的原消息,回复带引用效果 - 群聊默认 @发送者,可通过 at_sender=false 关闭 --- handlers/command.py | 52 ++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/handlers/command.py b/handlers/command.py index 53ddf9c..4ac5437 100644 --- a/handlers/command.py +++ b/handlers/command.py @@ -35,16 +35,18 @@ async def send_command_callback(data: dict, event, api, logger) -> None: 回调服务器返回格式: { - "reply": "回复文本", // 纯文本回复 + "reply": "回复文本", // 纯文本回复(引用原消息) "messages": [ // 批量回复(可选,优先于 reply) {"type": "text", "msg": "..."}, {"type": "image", "url": "..."}, {"type": "file", "url": "..."}, {"type": "video", "url": "..."} - ] + ], + "at_sender": true // 是否 @发送者(默认 true,仅群聊) } 所有字段均为可选,无回复内容时返回空 JSON 即可。 + 回复会引用触发命令的原消息。 """ if not COMMAND_CALLBACK_URL: logger.warning("COMMAND_CALLBACK_URL 未配置,跳过命令回调") @@ -81,13 +83,12 @@ async def send_command_callback(data: dict, event, api, logger) -> None: async def _handle_reply(result: dict, event, api, logger) -> None: - """处理回调响应,自动回复到原消息来源。""" - group_id = result.get("group_id") or (getattr(event.data, "group_id", None)) - user_id = result.get("user_id") or event.data.user_id + """处理回调响应,引用原消息自动回复。""" + at_sender = result.get("at_sender", True) messages = result.get("messages") reply = result.get("reply") - # 批量回复(使用 post_group_msg / post_private_msg 组合消息段) + # 批量回复:引用 + 批量消息段 if messages and isinstance(messages, list): text_parts: list[str] = [] image_url: str | None = None @@ -106,38 +107,27 @@ async def _handle_reply(result: dict, event, api, logger) -> None: file_msgs.append(msg) text = "\n".join(text_parts) if text_parts else None + group_id = getattr(event.data, "group_id", None) try: - if group_id: - if text or image_url or video_url: - await api.qq.post_group_msg( - group_id=group_id, text=text, image=image_url, video=video_url, - ) - for fm in file_msgs: - url = fm.get("url", "") - await api.qq.send_group_file( - group_id=group_id, file=url, name=url.split("/")[-1], - ) - else: - if text or image_url or video_url: - await api.qq.post_private_msg( - user_id=user_id, text=text, image=image_url, video=video_url, - ) - for fm in file_msgs: - url = fm.get("url", "") - await api.qq.send_private_file( - user_id=user_id, file=url, name=url.split("/")[-1], - ) + # 组合消息用 event.reply 引用原消息 + if text or image_url or video_url: + await event.reply(text=text, image=image_url, video=video_url, at_sender=at_sender) + # 文件单独发(file 是独占段) + for fm in file_msgs: + url = fm.get("url", "") + filename = url.split("/")[-1] + if group_id: + await api.qq.send_group_file(group_id=group_id, file=url, name=filename) + else: + await api.qq.send_private_file(user_id=event.data.user_id, file=url, name=filename) except Exception as exc: logger.error("命令回复失败: %s", exc) return - # 纯文本回复 + # 纯文本回复:引用原消息 if reply and isinstance(reply, str): try: - if group_id: - await api.qq.send_group_text(group_id=group_id, text=reply) - else: - await api.qq.send_private_text(user_id=user_id, text=reply) + await event.reply(text=reply, at_sender=at_sender) except Exception as exc: logger.error("命令回复失败: %s", exc)