[Bug] QQ频道消息无法回复:markdown 回退顺序有误,误用主动消息导致 304049 限频
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 82/100
Direzione di ricerca
Parti da _send_with_markdown_fallback() nel file sorgente della piattaforma QQ Official qqofficial_message_event.py; leggi il ramo except _QQOFFICIAL_SEND_API_ERRORS riga per riga per verificare che msg_id venga estratto (pop) prima che il markdown venga rimosso. La correzione si ramifica prima sull'errore 50056 'markdown not allowed' — elimina markdown, imposta content testuale semplice e adatta msg_type, mantenendo msg_id — e passa all'invio proattivo (senza msg_id) solo per gli altri errori. Il risultato atteso è che una risposta di canale abbia successo come messaggio passivo senza 304049, mentre il comportamento del markdown nella chat individuale resta invariato.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
🐛 问题描述
QQ 频道场景下机器人无法回复消息,报错「主动消息限频」—— 但这只是普通被动回复。
🌍 环境
- AstrBot
4.28.2(4.29.0-beta.1/master/dev同样存在) - 平台:QQ 官方机器人(
qq_official) - 配置:
use_markdown = true
🔁 复现
use_markdown = true- 用户在 QQ 频道给机器人发消息
- 机器人回复失败
📜 日志
[QQOfficial] 回复消息失败: 不允许发送原生 markdown, 尝试使用主动发送接口。
botpy.errors.NotFoundError: 私信主动消息数限频
https://api.sgroup.qq.com/dms/{guild_id}/messages → 404
🔑 错误码
| 错误码 | 含义 |
|---|---|
50056 |
不允许发送 markdown content(触发点) |
304049 |
私信主动消息数限频(最终失败) |
🔍 根因
qqofficial_message_event.py 的 _send_with_markdown_fallback():
except _QQOFFICIAL_SEND_API_ERRORS as err:
if payload.get("msg_id"):
fallback_payload = payload.copy()
fallback_payload.pop("msg_id", None) # ❌ 先去 msg_id → 变主动消息
return await send_func(fallback_payload) # → 撞 304049
...
# 去掉 markdown、保留 msg_id(正确做法,但轮不到执行)
回退没按错误类型分流:markdown 被拒(50056)时应保留 msg_id、只去掉 markdown。
而官方规定「私信每个用户每天仅 2 条主动消息」,额度一空频道就彻底无法回复。
🛠 建议修复
在去掉 msg_id 之前先处理 markdown:
if (QQOfficialMessageEvent.MARKDOWN_NOT_ALLOWED_ERROR in str(err)
and payload.get("markdown") and plain_text):
md_payload = payload.copy()
md_payload.pop("markdown", None)
md_payload["content"] = plain_text
if md_payload.get("msg_type") == 2:
md_payload["msg_type"] = 0
try:
return await send_func(md_payload) # 保留 msg_id,走被动通道
except _QQOFFICIAL_SEND_API_ERRORS as e2:
err, payload = e2, md_payload
✔️ 验证情况(已实测通过 ✅)
实测方式:临时禁用所有插件层规避手段(即让 markdown 真正被发送),
完整触发 50056 → 回退 链路,观察补丁行为。
实测日志(20:01):
[20:01:34] 频道用户发送消息
[20:01:38] [QQOfficial] 回复消息失败: 不允许发送原生 markdown, 尝试使用主动发送接口。
[20:01:39] [QQOfficial] markdown 不被支持,已改用纯文本(保留被动回复)。 ← 补丁生效
[20:01:39] → 消息发送成功(无 Failed to send)
结果:
- ✅ 频道私信回复恢复正常
- ✅ 回退逻辑按预期执行:保留
msg_id、仅去掉markdown(走被动通道) - ✅ 不再出现
304049 私信主动消息数限频 - ✅ 单聊 markdown 不受影响(`)频道才降级)**
其他已验证项:
- ✅ 根因判断:逐行核对
_send_with_markdown_fallback控制流 - ✅ 补丁可应用性:
patch -p1成功,结果与修复后文件逐字节一致 - ✅ 补丁语法:
py_compile通过
- Lingua principale
- Python
- Stelle
- 41.4k
- Fork
- 3k
- Merge medio
- 1g 5h
- PR unite (30g)
- 145
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di AstrBotDevs/AstrBot
-
Text-to-image rendering suppresses asyncio task cancellationForse già presa @kilisamemarisaaa l’ha presa 4 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 80/100
AstrBotDevs/AstrBot#10389 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
AstrBotDevs/AstrBot#10388 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Boxlite boot treats any HTTP response as a healthy sandboxForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
AstrBotDevs/AstrBot#10385 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
[Feature] 移除「切换到旧版知识库」入口Forse già presa @silvaling l’ha presa 6 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
AstrBotDevs/AstrBot#10340 · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
AstrBotDevs/AstrBot#10322 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di AstrBotDevs/AstrBot
Issue simili
-
Broken link in index.rstApertadocumentation
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 65/100
ansys/pydpf-core#3547 ·
I maintainer di solito rispondono entro 1 giorno
-
core
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
vectorize-io/hindsight#5457 ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: LangChain drops OpenAI Responses text blocks from session recordingForse già presa @ktz03 l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
volcengine/OpenViking#5806 ·
I maintainer di solito rispondono entro 1 giorno
-
HTML: <template> content is extracted as document textForse già presa @ryanmeowy l’ha presa oggi. Apertabug html
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 82/100
docling-project/docling#4714 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
APIv2 event data accepts a non-string reply and a NaN upper_boundForse già presa @awss1i l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
freedomofpress/securedrop#7946 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni