1818
1919from astrbot .api import logger
2020from astrbot .api .event import AstrMessageEvent , MessageChain
21- from astrbot .api .message_components import Image , Plain , Record
21+ from astrbot .api .message_components import File , Image , Plain , Record , Video
2222from astrbot .api .platform import AstrBotMessage , PlatformMetadata
2323from astrbot .core .utils .astrbot_path import get_astrbot_temp_path
2424from astrbot .core .utils .io import download_image_by_url , file_to_base64
@@ -47,6 +47,10 @@ def _patch_qq_botpy_formdata() -> None:
4747
4848class QQOfficialMessageEvent (AstrMessageEvent ):
4949 MARKDOWN_NOT_ALLOWED_ERROR = "不允许发送原生 markdown"
50+ IMAGE_FILE_TYPE = 1
51+ VIDEO_FILE_TYPE = 2
52+ VOICE_FILE_TYPE = 3
53+ FILE_FILE_TYPE = 4
5054
5155 def __init__ (
5256 self ,
@@ -126,13 +130,18 @@ async def _post_send(self, stream: dict | None = None):
126130 image_base64 ,
127131 image_path ,
128132 record_file_path ,
133+ video_file_source ,
134+ file_source ,
135+ file_name ,
129136 ) = await QQOfficialMessageEvent ._parse_to_qqofficial (self .send_buffer )
130137
131138 if (
132139 not plain_text
133140 and not image_base64
134141 and not image_path
135142 and not record_file_path
143+ and not video_file_source
144+ and not file_source
136145 ):
137146 return None
138147
@@ -157,23 +166,47 @@ async def _post_send(self, stream: dict | None = None):
157166 if image_base64 :
158167 media = await self .upload_group_and_c2c_image (
159168 image_base64 ,
160- 1 ,
169+ self . IMAGE_FILE_TYPE ,
161170 group_openid = source .group_openid ,
162171 )
163172 payload ["media" ] = media
164173 payload ["msg_type" ] = 7
165174 payload .pop ("markdown" , None )
166175 payload ["content" ] = plain_text or None
167176 if record_file_path : # group record msg
168- media = await self .upload_group_and_c2c_record (
177+ media = await self .upload_group_and_c2c_media (
169178 record_file_path ,
170- 3 ,
179+ self . VOICE_FILE_TYPE ,
171180 group_openid = source .group_openid ,
172181 )
173- payload ["media" ] = media
174- payload ["msg_type" ] = 7
175- payload .pop ("markdown" , None )
176- payload ["content" ] = plain_text or None
182+ if media :
183+ payload ["media" ] = media
184+ payload ["msg_type" ] = 7
185+ payload .pop ("markdown" , None )
186+ payload ["content" ] = plain_text or None
187+ if video_file_source :
188+ media = await self .upload_group_and_c2c_media (
189+ video_file_source ,
190+ self .VIDEO_FILE_TYPE ,
191+ group_openid = source .group_openid ,
192+ )
193+ if media :
194+ payload ["media" ] = media
195+ payload ["msg_type" ] = 7
196+ payload .pop ("markdown" , None )
197+ payload ["content" ] = plain_text or None
198+ if file_source :
199+ media = await self .upload_group_and_c2c_media (
200+ file_source ,
201+ self .FILE_FILE_TYPE ,
202+ file_name = file_name ,
203+ group_openid = source .group_openid ,
204+ )
205+ if media :
206+ payload ["media" ] = media
207+ payload ["msg_type" ] = 7
208+ payload .pop ("markdown" , None )
209+ payload ["content" ] = plain_text or None
177210 ret = await self ._send_with_markdown_fallback (
178211 send_func = lambda retry_payload : self .bot .api .post_group_message (
179212 group_openid = source .group_openid , # type: ignore
@@ -187,23 +220,47 @@ async def _post_send(self, stream: dict | None = None):
187220 if image_base64 :
188221 media = await self .upload_group_and_c2c_image (
189222 image_base64 ,
190- 1 ,
223+ self . IMAGE_FILE_TYPE ,
191224 openid = source .author .user_openid ,
192225 )
193226 payload ["media" ] = media
194227 payload ["msg_type" ] = 7
195228 payload .pop ("markdown" , None )
196229 payload ["content" ] = plain_text or None
197230 if record_file_path : # c2c record
198- media = await self .upload_group_and_c2c_record (
231+ media = await self .upload_group_and_c2c_media (
199232 record_file_path ,
200- 3 ,
233+ self . VOICE_FILE_TYPE ,
201234 openid = source .author .user_openid ,
202235 )
203- payload ["media" ] = media
204- payload ["msg_type" ] = 7
205- payload .pop ("markdown" , None )
206- payload ["content" ] = plain_text or None
236+ if media :
237+ payload ["media" ] = media
238+ payload ["msg_type" ] = 7
239+ payload .pop ("markdown" , None )
240+ payload ["content" ] = plain_text or None
241+ if video_file_source :
242+ media = await self .upload_group_and_c2c_media (
243+ video_file_source ,
244+ self .VIDEO_FILE_TYPE ,
245+ openid = source .author .user_openid ,
246+ )
247+ if media :
248+ payload ["media" ] = media
249+ payload ["msg_type" ] = 7
250+ payload .pop ("markdown" , None )
251+ payload ["content" ] = plain_text or None
252+ if file_source :
253+ media = await self .upload_group_and_c2c_media (
254+ file_source ,
255+ self .FILE_FILE_TYPE ,
256+ file_name = file_name ,
257+ openid = source .author .user_openid ,
258+ )
259+ if media :
260+ payload ["media" ] = media
261+ payload ["msg_type" ] = 7
262+ payload .pop ("markdown" , None )
263+ payload ["content" ] = plain_text or None
207264 if stream :
208265 ret = await self ._send_with_markdown_fallback (
209266 send_func = lambda retry_payload : self .post_c2c_message (
@@ -327,16 +384,19 @@ async def upload_group_and_c2c_image(
327384 ttl = result .get ("ttl" , 0 ),
328385 )
329386
330- async def upload_group_and_c2c_record (
387+ async def upload_group_and_c2c_media (
331388 self ,
332389 file_source : str ,
333390 file_type : int ,
334391 srv_send_msg : bool = False ,
392+ file_name : str | None = None ,
335393 ** kwargs ,
336394 ) -> Media | None :
337395 """上传媒体文件"""
338396 # 构建基础payload
339397 payload = {"file_type" : file_type , "srv_send_msg" : srv_send_msg }
398+ if file_name :
399+ payload ["file_name" ] = file_name
340400
341401 # 处理文件数据
342402 if os .path .exists (file_source ):
@@ -416,6 +476,9 @@ async def _parse_to_qqofficial(message: MessageChain):
416476 image_base64 = None # only one img supported
417477 image_file_path = None
418478 record_file_path = None
479+ video_file_source = None
480+ file_source = None
481+ file_name = None
419482 for i in message .chain :
420483 if isinstance (i , Plain ):
421484 plain_text += i .text
@@ -454,6 +517,30 @@ async def _parse_to_qqofficial(message: MessageChain):
454517 except Exception as e :
455518 logger .error (f"处理语音时出错: { e } " )
456519 record_file_path = None
520+ elif isinstance (i , Video ) and not video_file_source :
521+ if i .file .startswith ("file:///" ):
522+ video_file_source = i .file [8 :]
523+ else :
524+ video_file_source = i .file
525+ elif isinstance (i , File ) and not file_source :
526+ file_name = i .name
527+ if i .file_ :
528+ file_path = i .file_
529+ if file_path .startswith ("file:///" ):
530+ file_path = file_path [8 :]
531+ elif file_path .startswith ("file://" ):
532+ file_path = file_path [7 :]
533+ file_source = file_path
534+ elif i .url :
535+ file_source = i .url
457536 else :
458537 logger .debug (f"qq_official 忽略 { i .type } " )
459- return plain_text , image_base64 , image_file_path , record_file_path
538+ return (
539+ plain_text ,
540+ image_base64 ,
541+ image_file_path ,
542+ record_file_path ,
543+ video_file_source ,
544+ file_source ,
545+ file_name ,
546+ )
0 commit comments