55import os
66import random
77import time
8+ import uuid
9+ from pathlib import Path
810from types import SimpleNamespace
911from typing import Any , cast
1012
2426)
2527from astrbot .core .message .components import BaseMessageComponent
2628from astrbot .core .platform .astr_message_event import MessageSesion
29+ from astrbot .core .utils .astrbot_path import get_astrbot_temp_path
30+ from astrbot .core .utils .io import download_file
2731
2832from ...register import register_platform_adapter
2933from .qqofficial_message_event import QQOfficialMessageEvent
@@ -42,7 +46,7 @@ def set_platform(self, platform: QQOfficialPlatformAdapter) -> None:
4246 async def on_group_at_message_create (
4347 self , message : botpy .message .GroupMessage
4448 ) -> None :
45- abm = QQOfficialPlatformAdapter ._parse_from_qqofficial (
49+ abm = await QQOfficialPlatformAdapter ._parse_from_qqofficial (
4650 message ,
4751 MessageType .GROUP_MESSAGE ,
4852 )
@@ -53,7 +57,7 @@ async def on_group_at_message_create(
5357
5458 # 收到频道消息
5559 async def on_at_message_create (self , message : botpy .message .Message ) -> None :
56- abm = QQOfficialPlatformAdapter ._parse_from_qqofficial (
60+ abm = await QQOfficialPlatformAdapter ._parse_from_qqofficial (
5761 message ,
5862 MessageType .GROUP_MESSAGE ,
5963 )
@@ -66,7 +70,7 @@ async def on_at_message_create(self, message: botpy.message.Message) -> None:
6670 async def on_direct_message_create (
6771 self , message : botpy .message .DirectMessage
6872 ) -> None :
69- abm = QQOfficialPlatformAdapter ._parse_from_qqofficial (
73+ abm = await QQOfficialPlatformAdapter ._parse_from_qqofficial (
7074 message ,
7175 MessageType .FRIEND_MESSAGE ,
7276 )
@@ -76,7 +80,7 @@ async def on_direct_message_create(
7680
7781 # 收到 C2C 消息
7882 async def on_c2c_message_create (self , message : botpy .message .C2CMessage ) -> None :
79- abm = QQOfficialPlatformAdapter ._parse_from_qqofficial (
83+ abm = await QQOfficialPlatformAdapter ._parse_from_qqofficial (
8084 message ,
8185 MessageType .FRIEND_MESSAGE ,
8286 )
@@ -336,7 +340,22 @@ def _normalize_attachment_url(url: str | None) -> str:
336340 return f"https://{ url } "
337341
338342 @staticmethod
339- def _append_attachments (
343+ async def _prepare_audio_attachment (
344+ url : str ,
345+ filename : str ,
346+ ) -> Record :
347+ temp_dir = Path (get_astrbot_temp_path ())
348+ temp_dir .mkdir (parents = True , exist_ok = True )
349+
350+ ext = Path (filename ).suffix .lower ()
351+ source_ext = ext or ".audio"
352+ source_path = temp_dir / f"qqofficial_{ uuid .uuid4 ().hex } { source_ext } "
353+ await download_file (url , str (source_path ))
354+
355+ return Record (file = str (source_path ), url = str (source_path ))
356+
357+ @staticmethod
358+ async def _append_attachments (
340359 msg : list [BaseMessageComponent ],
341360 attachments : list | None ,
342361 ) -> None :
@@ -363,7 +382,7 @@ def _append_attachments(
363382 or getattr (attachment , "name" , None )
364383 or "attachment" ,
365384 )
366- ext = os . path . splitext (filename )[ 1 ] .lower ()
385+ ext = Path (filename ). suffix .lower ()
367386 image_exts = {".jpg" , ".jpeg" , ".png" , ".gif" , ".webp" , ".bmp" }
368387 audio_exts = {
369388 ".mp3" ,
@@ -381,8 +400,21 @@ def _append_attachments(
381400 ".webm" ,
382401 }
383402
384- if content_type .startswith ("audio" ) or ext in audio_exts :
385- msg .append (Record .fromURL (url ))
403+ if content_type .startswith ("voice" ) or ext in audio_exts :
404+ try :
405+ msg .append (
406+ await QQOfficialPlatformAdapter ._prepare_audio_attachment (
407+ url ,
408+ filename ,
409+ )
410+ )
411+ except Exception as e :
412+ logger .warning (
413+ "[QQOfficial] Failed to prepare audio attachment %s: %s" ,
414+ url ,
415+ e ,
416+ )
417+ msg .append (Record .fromURL (url ))
386418 elif content_type .startswith ("video" ) or ext in video_exts :
387419 msg .append (Video .fromURL (url ))
388420 elif content_type .startswith ("image" ) or ext in image_exts :
@@ -432,13 +464,13 @@ def replace_face(match):
432464 return re .sub (r"<faceType=\d+[^>]*>" , replace_face , content )
433465
434466 @staticmethod
435- def _parse_from_qqofficial (
467+ async def _parse_from_qqofficial (
436468 message : botpy .message .Message
437469 | botpy .message .GroupMessage
438470 | botpy .message .DirectMessage
439471 | botpy .message .C2CMessage ,
440472 message_type : MessageType ,
441- ):
473+ ) -> AstrBotMessage :
442474 abm = AstrBotMessage ()
443475 abm .type = message_type
444476 abm .timestamp = int (time .time ())
@@ -463,7 +495,9 @@ def _parse_from_qqofficial(
463495 abm .self_id = "unknown_selfid"
464496 msg .append (At (qq = "qq_official" ))
465497 msg .append (Plain (abm .message_str ))
466- QQOfficialPlatformAdapter ._append_attachments (msg , message .attachments )
498+ await QQOfficialPlatformAdapter ._append_attachments (
499+ msg , message .attachments
500+ )
467501 abm .message = msg
468502
469503 elif isinstance (message , botpy .message .Message ) or isinstance (
@@ -482,7 +516,9 @@ def _parse_from_qqofficial(
482516 ).strip ()
483517 )
484518
485- QQOfficialPlatformAdapter ._append_attachments (msg , message .attachments )
519+ await QQOfficialPlatformAdapter ._append_attachments (
520+ msg , message .attachments
521+ )
486522 abm .message = msg
487523 abm .message_str = plain_content
488524 abm .sender = MessageMember (
0 commit comments