From 6f6a5b565ca9d5679fa3298443a45ca1c25d6e25 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Wed, 9 Jul 2025 11:19:32 +0800 Subject: [PATCH] fix: active message cannot handle forward type message properly in aiocqhttp adapter --- .../aiocqhttp/aiocqhttp_message_event.py | 107 +++++++++++------- .../aiocqhttp/aiocqhttp_platform_adapter.py | 29 ++--- 2 files changed, 83 insertions(+), 53 deletions(-) diff --git a/astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py b/astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py index b5539b7eb..69aa497e1 100644 --- a/astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +++ b/astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py @@ -1,7 +1,7 @@ import asyncio import re from typing import AsyncGenerator, Dict, List -from aiocqhttp import CQHttp +from aiocqhttp import CQHttp, Event from astrbot.api.event import AstrMessageEvent, MessageChain from astrbot.api.message_components import ( Image, @@ -58,50 +58,79 @@ class AiocqhttpMessageEvent(AstrMessageEvent): ret.append(d) return ret - async def send(self, message: MessageChain): + @classmethod + async def send_message( + cls, + bot: CQHttp, + message_chain: MessageChain, + event: Event | None = None, + is_group: bool = False, + session_id: str = None, + ): + """发送消息""" + + async def _send( + event: Event, is_group: bool, session_id: str, messages: list[dict] + ): + if event: + await bot.send(event=event, message=messages) + elif is_group: + await bot.send_group_msg(group_id=session_id, message=messages) + else: + await bot.send_private_msg(user_id=session_id, message=messages) + # 转发消息、文件消息不能和普通消息混在一起发送 send_one_by_one = any( - isinstance(seg, (Node, Nodes, File)) for seg in message.chain + isinstance(seg, (Node, Nodes, File)) for seg in message_chain.chain ) - if send_one_by_one: - for seg in message.chain: - if isinstance(seg, (Node, Nodes)): - # 合并转发消息 - - if isinstance(seg, Node): - nodes = Nodes([seg]) - seg = nodes - - payload = await seg.to_dict() - - if self.get_group_id(): - payload["group_id"] = self.get_group_id() - await self.bot.call_action("send_group_forward_msg", **payload) - else: - payload["user_id"] = self.get_sender_id() - await self.bot.call_action( - "send_private_forward_msg", **payload - ) - elif isinstance(seg, File): - d = await AiocqhttpMessageEvent._from_segment_to_dict(seg) - await self.bot.send( - self.message_obj.raw_message, - [d], - ) - else: - await self.bot.send( - self.message_obj.raw_message, - await AiocqhttpMessageEvent._parse_onebot_json( - MessageChain([seg]) - ), - ) - await asyncio.sleep(0.5) - else: - ret = await AiocqhttpMessageEvent._parse_onebot_json(message) + if not send_one_by_one: + ret = await cls._parse_onebot_json(message_chain) if not ret: return - await self.bot.send(self.message_obj.raw_message, ret) + await _send(event, is_group, session_id, ret) + return + for seg in message_chain.chain: + if isinstance(seg, (Node, Nodes)): + # 合并转发消息 + if isinstance(seg, Node): + nodes = Nodes([seg]) + seg = nodes + payload = await seg.to_dict() + + if is_group: + payload["group_id"] = session_id + await bot.call_action("send_group_forward_msg", **payload) + else: + payload["user_id"] = session_id + await bot.call_action("send_private_forward_msg", **payload) + elif isinstance(seg, File): + d = await cls._from_segment_to_dict(seg) + await _send(event, is_group, session_id, [d]) + else: + messages = await cls._parse_onebot_json(MessageChain([seg])) + if not messages: + continue + await _send(event, is_group, session_id, messages) + await asyncio.sleep(0.5) + + async def send(self, message: MessageChain): + """发送消息""" + event = self.message_obj.raw_message + assert isinstance(event, Event), "Event must be an instance of aiocqhttp.Event" + is_group = False + if self.get_group_id(): + is_group = True + session_id = self.get_group_id() + else: + session_id = self.get_sender_id() + await self.send_message( + bot=self.bot, + message_chain=message, + event=event, + is_group=is_group, + session_id=session_id, + ) await super().send(message) async def send_streaming( diff --git a/astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py b/astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py index 02e655af7..1991bf393 100644 --- a/astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +++ b/astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py @@ -83,19 +83,18 @@ class AiocqhttpAdapter(Platform): async def send_by_session( self, session: MessageSesion, message_chain: MessageChain ): - ret = await AiocqhttpMessageEvent._parse_onebot_json(message_chain) - match session.message_type.value: - case MessageType.GROUP_MESSAGE.value: - if "_" in session.session_id: - # 独立会话 - _, group_id = session.session_id.split("_") - await self.bot.send_group_msg(group_id=group_id, message=ret) - else: - await self.bot.send_group_msg( - group_id=session.session_id, message=ret - ) - case MessageType.FRIEND_MESSAGE.value: - await self.bot.send_private_msg(user_id=session.session_id, message=ret) + is_group = session.message_type == MessageType.GROUP_MESSAGE + if is_group: + session_id = session.session_id.split("_")[-1] + else: + session_id = session.session_id + await AiocqhttpMessageEvent.send_message( + bot=self.bot, + message_chain=message_chain, + event=None, # 这里不需要 event,因为是通过 session 发送的 + is_group=is_group, + session_id=session_id, + ) await super().send_by_session(session, message_chain) async def convert_message(self, event: Event) -> AstrBotMessage: @@ -307,7 +306,9 @@ class AiocqhttpAdapter(Platform): user_id=int(m["data"]["qq"]), ) if at_info: - nickname = at_info.get("nick", "") or at_info.get("nickname", "") + nickname = at_info.get("nick", "") or at_info.get( + "nickname", "" + ) is_at_self = str(m["data"]["qq"]) in {abm.self_id, "all"} abm.message.append(