Skip to content

Commit 28a178a

Browse files
authored
Merge pull request #2067 from AstrBotDevs/refactor-aiocqhttp-send-message
Fix: active message cannot handle forward type message properly in aiocqhttp adapter
2 parents af258c5 + 88f1300 commit 28a178a

File tree

2 files changed

+89
-53
lines changed

2 files changed

+89
-53
lines changed

astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import asyncio
22
import re
33
from typing import AsyncGenerator, Dict, List
4-
from aiocqhttp import CQHttp
4+
from aiocqhttp import CQHttp, Event
55
from astrbot.api.event import AstrMessageEvent, MessageChain
66
from astrbot.api.message_components import (
77
Image,
@@ -58,50 +58,85 @@ async def _parse_onebot_json(message_chain: MessageChain):
5858
ret.append(d)
5959
return ret
6060

61-
async def send(self, message: MessageChain):
61+
@classmethod
62+
async def _dispatch_send(
63+
cls,
64+
bot: CQHttp,
65+
event: Event | None,
66+
is_group: bool,
67+
session_id: str,
68+
messages: list[dict],
69+
):
70+
if event:
71+
await bot.send(event=event, message=messages)
72+
elif is_group:
73+
await bot.send_group_msg(group_id=session_id, message=messages)
74+
else:
75+
await bot.send_private_msg(user_id=session_id, message=messages)
76+
77+
@classmethod
78+
async def send_message(
79+
cls,
80+
bot: CQHttp,
81+
message_chain: MessageChain,
82+
event: Event | None = None,
83+
is_group: bool = False,
84+
session_id: str = None,
85+
):
86+
"""发送消息"""
87+
6288
# 转发消息、文件消息不能和普通消息混在一起发送
6389
send_one_by_one = any(
64-
isinstance(seg, (Node, Nodes, File)) for seg in message.chain
90+
isinstance(seg, (Node, Nodes, File)) for seg in message_chain.chain
6591
)
66-
if send_one_by_one:
67-
for seg in message.chain:
68-
if isinstance(seg, (Node, Nodes)):
69-
# 合并转发消息
70-
71-
if isinstance(seg, Node):
72-
nodes = Nodes([seg])
73-
seg = nodes
74-
75-
payload = await seg.to_dict()
76-
77-
if self.get_group_id():
78-
payload["group_id"] = self.get_group_id()
79-
await self.bot.call_action("send_group_forward_msg", **payload)
80-
else:
81-
payload["user_id"] = self.get_sender_id()
82-
await self.bot.call_action(
83-
"send_private_forward_msg", **payload
84-
)
85-
elif isinstance(seg, File):
86-
d = await AiocqhttpMessageEvent._from_segment_to_dict(seg)
87-
await self.bot.send(
88-
self.message_obj.raw_message,
89-
[d],
90-
)
91-
else:
92-
await self.bot.send(
93-
self.message_obj.raw_message,
94-
await AiocqhttpMessageEvent._parse_onebot_json(
95-
MessageChain([seg])
96-
),
97-
)
98-
await asyncio.sleep(0.5)
99-
else:
100-
ret = await AiocqhttpMessageEvent._parse_onebot_json(message)
92+
if not send_one_by_one:
93+
ret = await cls._parse_onebot_json(message_chain)
10194
if not ret:
10295
return
103-
await self.bot.send(self.message_obj.raw_message, ret)
96+
await cls._dispatch_send(bot, event, is_group, session_id, ret)
97+
return
98+
for seg in message_chain.chain:
99+
if isinstance(seg, (Node, Nodes)):
100+
# 合并转发消息
101+
if isinstance(seg, Node):
102+
nodes = Nodes([seg])
103+
seg = nodes
104+
105+
payload = await seg.to_dict()
106+
107+
if is_group:
108+
payload["group_id"] = session_id
109+
await bot.call_action("send_group_forward_msg", **payload)
110+
else:
111+
payload["user_id"] = session_id
112+
await bot.call_action("send_private_forward_msg", **payload)
113+
elif isinstance(seg, File):
114+
d = await cls._from_segment_to_dict(seg)
115+
await cls._dispatch_send(bot, event, is_group, session_id, [d])
116+
else:
117+
messages = await cls._parse_onebot_json(MessageChain([seg]))
118+
if not messages:
119+
continue
120+
await cls._dispatch_send(bot, event, is_group, session_id, messages)
121+
await asyncio.sleep(0.5)
104122

123+
async def send(self, message: MessageChain):
124+
"""发送消息"""
125+
event = self.message_obj.raw_message
126+
assert isinstance(event, Event), "Event must be an instance of aiocqhttp.Event"
127+
is_group = False
128+
if self.get_group_id():
129+
is_group = True
130+
session_id = self.get_group_id()
131+
else:
132+
session_id = self.get_sender_id()
133+
await self.send_message(
134+
bot=self.bot,
135+
message_chain=message,
136+
event=event,
137+
is_group=is_group,
138+
session_id=session_id,
139+
)
105140
await super().send(message)
106141

107142
async def send_streaming(

astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,18 @@ def on_websocket_connection(_):
8383
async def send_by_session(
8484
self, session: MessageSesion, message_chain: MessageChain
8585
):
86-
ret = await AiocqhttpMessageEvent._parse_onebot_json(message_chain)
87-
match session.message_type.value:
88-
case MessageType.GROUP_MESSAGE.value:
89-
if "_" in session.session_id:
90-
# 独立会话
91-
_, group_id = session.session_id.split("_")
92-
await self.bot.send_group_msg(group_id=group_id, message=ret)
93-
else:
94-
await self.bot.send_group_msg(
95-
group_id=session.session_id, message=ret
96-
)
97-
case MessageType.FRIEND_MESSAGE.value:
98-
await self.bot.send_private_msg(user_id=session.session_id, message=ret)
86+
is_group = session.message_type == MessageType.GROUP_MESSAGE
87+
if is_group:
88+
session_id = session.session_id.split("_")[-1]
89+
else:
90+
session_id = session.session_id
91+
await AiocqhttpMessageEvent.send_message(
92+
bot=self.bot,
93+
message_chain=message_chain,
94+
event=None, # 这里不需要 event,因为是通过 session 发送的
95+
is_group=is_group,
96+
session_id=session_id,
97+
)
9998
await super().send_by_session(session, message_chain)
10099

101100
async def convert_message(self, event: Event) -> AstrBotMessage:
@@ -307,7 +306,9 @@ async def _convert_handle_message_event(
307306
user_id=int(m["data"]["qq"]),
308307
)
309308
if at_info:
310-
nickname = at_info.get("nick", "") or at_info.get("nickname", "")
309+
nickname = at_info.get("nick", "") or at_info.get(
310+
"nickname", ""
311+
)
311312
is_at_self = str(m["data"]["qq"]) in {abm.self_id, "all"}
312313

313314
abm.message.append(

0 commit comments

Comments
 (0)