Skip to content

Commit 7f94bce

Browse files
authored
feat(qqofficial): split message chain by media and update sending logic (#8376)
* feat(qqofficial): split message chain by media and update sending logic * Delete tests/test_qqofficial_adapter.py
1 parent 85f9c4d commit 7f94bce

2 files changed

Lines changed: 65 additions & 5 deletions

File tree

astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,62 @@ def _extract_response_message_id(ret) -> str | None:
183183
ret_id = getattr(ret, "id", None)
184184
return str(ret_id) if ret_id is not None else None
185185

186+
@staticmethod
187+
def _split_message_chain_by_media(message: MessageChain) -> list[MessageChain]:
188+
chunks: list[MessageChain] = []
189+
current_chain = []
190+
current_has_media = False
191+
192+
for component in message.chain:
193+
is_media = isinstance(component, Image | Record | Video | File)
194+
if is_media and current_has_media:
195+
chunks.append(
196+
MessageChain(
197+
chain=current_chain,
198+
use_t2i_=message.use_t2i_,
199+
type=message.type,
200+
)
201+
)
202+
current_chain = []
203+
current_has_media = False
204+
205+
current_chain.append(component)
206+
current_has_media = current_has_media or is_media
207+
208+
if current_chain or not message.chain:
209+
chunks.append(
210+
MessageChain(
211+
chain=current_chain,
212+
use_t2i_=message.use_t2i_,
213+
type=message.type,
214+
)
215+
)
216+
217+
return chunks
218+
186219
async def _post_send(self, stream: dict | None = None):
187220
if not self.send_buffer:
188221
return None
189222

223+
message_chains = self._split_message_chain_by_media(self.send_buffer)
224+
stream_for_chain = stream if len(message_chains) == 1 else None
225+
226+
ret = None
227+
for message_chain in message_chains:
228+
ret = await self._post_send_one(message_chain, stream_for_chain)
229+
230+
self.send_buffer = None
231+
232+
return ret
233+
234+
async def _post_send_one(
235+
self,
236+
message_to_send: MessageChain,
237+
stream: dict | None = None,
238+
):
239+
if not message_to_send:
240+
return None
241+
190242
source = self.message_obj.raw_message
191243

192244
if not isinstance(
@@ -207,10 +259,12 @@ async def _post_send(self, stream: dict | None = None):
207259
video_file_source,
208260
file_source,
209261
file_name,
210-
) = await QQOfficialMessageEvent._parse_to_qqofficial(self.send_buffer)
262+
) = await QQOfficialMessageEvent._parse_to_qqofficial(message_to_send)
211263

212264
# C2C 流式仅用于文本分片,富媒体时降级为普通发送,避免平台侧流式校验报错。
213-
if stream and (image_base64 or record_file_path):
265+
if stream and (
266+
image_base64 or record_file_path or video_file_source or file_source
267+
):
214268
logger.debug("[QQOfficial] 检测到富媒体,降级为非流式发送。")
215269
stream = None
216270

@@ -416,9 +470,7 @@ async def _post_send(self, stream: dict | None = None):
416470
case _:
417471
pass
418472

419-
await super().send(self.send_buffer)
420-
421-
self.send_buffer = None
473+
await super().send(message_to_send)
422474

423475
return ret
424476

astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,14 @@ async def _send_by_session_common(
203203
session: MessageSesion,
204204
message_chain: MessageChain,
205205
) -> None:
206+
message_chains = QQOfficialMessageEvent._split_message_chain_by_media(
207+
message_chain
208+
)
209+
if len(message_chains) > 1:
210+
for split_message_chain in message_chains:
211+
await self._send_by_session_common(session, split_message_chain)
212+
return
213+
206214
(
207215
plain_text,
208216
image_base64,

0 commit comments

Comments
 (0)