Skip to content

Commit 3476afc

Browse files
authored
feat: supports send markdown message in qqofficial (#5173)
* feat: supports send markdown message in qqofficial closes: #1093 #918 #4180 #4264 * ruff format
1 parent 9b0e24e commit 3476afc

File tree

1 file changed

+70
-16
lines changed

1 file changed

+70
-16
lines changed

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

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77

88
import aiofiles
99
import botpy
10+
import botpy.errors
1011
import botpy.message
1112
import botpy.types
1213
import botpy.types.message
1314
from botpy import Client
1415
from botpy.http import Route
1516
from botpy.types import message
16-
from botpy.types.message import Media
17+
from botpy.types.message import MarkdownPayload, Media
1718

1819
from astrbot.api import logger
1920
from astrbot.api.event import AstrMessageEvent, MessageChain
@@ -25,6 +26,8 @@
2526

2627

2728
class 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

Comments
 (0)