77
88import aiofiles
99import botpy
10+ import botpy .errors
1011import botpy .message
1112import botpy .types
1213import botpy .types .message
1314from botpy import Client
1415from botpy .http import Route
1516from botpy .types import message
16- from botpy .types .message import Media
17+ from botpy .types .message import MarkdownPayload , Media
1718
1819from astrbot .api import logger
1920from astrbot .api .event import AstrMessageEvent , MessageChain
2526
2627
2728class QQOfficialMessageEvent (AstrMessageEvent ):
29+ MARKDOWN_NOT_ALLOWED_ERROR = "不允许发送原生 markdown"
30+
2831 def __init__ (
2932 self ,
3033 message_str : str ,
@@ -114,7 +117,9 @@ async def _post_send(self, stream: dict | None = None):
114117 return None
115118
116119 payload : dict = {
117- "content" : plain_text ,
120+ # "content": plain_text,
121+ "markdown" : MarkdownPayload (content = plain_text ) if plain_text else None ,
122+ "msg_type" : 2 ,
118123 "msg_id" : self .message_obj .message_id ,
119124 }
120125
@@ -145,9 +150,13 @@ async def _post_send(self, stream: dict | None = None):
145150 )
146151 payload ["media" ] = media
147152 payload ["msg_type" ] = 7
148- ret = await self .bot .api .post_group_message (
149- group_openid = source .group_openid ,
150- ** payload ,
153+ ret = await self ._send_with_markdown_fallback (
154+ send_func = lambda retry_payload : self .bot .api .post_group_message (
155+ group_openid = source .group_openid , # type: ignore
156+ ** retry_payload ,
157+ ),
158+ payload = payload ,
159+ plain_text = plain_text ,
151160 )
152161
153162 case botpy .message .C2CMessage ():
@@ -168,30 +177,49 @@ async def _post_send(self, stream: dict | None = None):
168177 payload ["media" ] = media
169178 payload ["msg_type" ] = 7
170179 if stream :
171- ret = await self .post_c2c_message (
172- openid = source .author .user_openid ,
173- ** payload ,
174- stream = stream ,
180+ ret = await self ._send_with_markdown_fallback (
181+ send_func = lambda retry_payload : self .post_c2c_message (
182+ openid = source .author .user_openid ,
183+ ** retry_payload ,
184+ stream = stream ,
185+ ),
186+ payload = payload ,
187+ plain_text = plain_text ,
175188 )
176189 else :
177- ret = await self .post_c2c_message (
178- openid = source .author .user_openid ,
179- ** payload ,
190+ ret = await self ._send_with_markdown_fallback (
191+ send_func = lambda retry_payload : self .post_c2c_message (
192+ openid = source .author .user_openid ,
193+ ** retry_payload ,
194+ ),
195+ payload = payload ,
196+ plain_text = plain_text ,
180197 )
181198 logger .debug (f"Message sent to C2C: { ret } " )
182199
183200 case botpy .message .Message ():
184201 if image_path :
185202 payload ["file_image" ] = image_path
186- ret = await self .bot .api .post_message (
187- channel_id = source .channel_id ,
188- ** payload ,
203+ ret = await self ._send_with_markdown_fallback (
204+ send_func = lambda retry_payload : self .bot .api .post_message (
205+ channel_id = source .channel_id ,
206+ ** retry_payload ,
207+ ),
208+ payload = payload ,
209+ plain_text = plain_text ,
189210 )
190211
191212 case botpy .message .DirectMessage ():
192213 if image_path :
193214 payload ["file_image" ] = image_path
194- ret = await self .bot .api .post_dms (guild_id = source .guild_id , ** payload )
215+ ret = await self ._send_with_markdown_fallback (
216+ send_func = lambda retry_payload : self .bot .api .post_dms (
217+ guild_id = source .guild_id ,
218+ ** retry_payload ,
219+ ),
220+ payload = payload ,
221+ plain_text = plain_text ,
222+ )
195223
196224 case _:
197225 pass
@@ -202,6 +230,32 @@ async def _post_send(self, stream: dict | None = None):
202230
203231 return ret
204232
233+ async def _send_with_markdown_fallback (
234+ self ,
235+ send_func ,
236+ payload : dict ,
237+ plain_text : str ,
238+ ):
239+ try :
240+ return await send_func (payload )
241+ except botpy .errors .ServerError as err :
242+ if (
243+ self .MARKDOWN_NOT_ALLOWED_ERROR not in str (err )
244+ or not payload .get ("markdown" )
245+ or not plain_text
246+ ):
247+ raise
248+
249+ logger .warning (
250+ "[QQOfficial] markdown 发送被拒绝,回退到 content 模式重试。"
251+ )
252+ fallback_payload = payload .copy ()
253+ fallback_payload ["markdown" ] = None
254+ fallback_payload ["content" ] = plain_text
255+ if fallback_payload .get ("msg_type" ) == 2 :
256+ fallback_payload ["msg_type" ] = 0
257+ return await send_func (fallback_payload )
258+
205259 async def upload_group_and_c2c_image (
206260 self ,
207261 image_base64 : str ,
0 commit comments