Repository navigation
Conversation
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py" line_range="643" />
<code_context>
if payload.get("msg_id"):
fallback_payload = payload.copy()
fallback_payload.pop("msg_id", None)
+ # 主动发送兜底同样去掉引用:引用 id 失效不应阻断正文送达
+ fallback_payload.pop("message_reference", None)
try:
</code_context>
<issue_to_address>
**Valid quote context is lost**
When a quoted reply fails initially for an unrelated caught error and the retry succeeds, `_send_with_markdown_fallback` removes `message_reference` before retrying, so the recipient gets the message body without its valid quote context.
Remove `message_reference` and retry only when the initial error indicates that the reference was rejected.
Also at `astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py:644`.
</issue_to_address>
### Comment 2
<location path="tests/test_qqofficial_group_message_create.py" line_range="257" />
<code_context>
+@pytest.mark.asyncio
+async def test_parse_to_qqofficial_extracts_reply_reference():
+ parsed = await QQOfficialMessageEvent._parse_to_qqofficial(
+ MessageChain(chain=[Reply(id="quoted-1"), Plain("hello")])
+ )
+
</code_context>
<issue_to_address>
**Replies only tested at chain start**
When a `Reply` component follows another component in the chain, a parser that checks only the first chain component for `Reply` passes these cases because each test puts `Reply` first; it still misses replies after preceding text, so the tests do not catch that broken extraction behavior.
Add a parser case with `Plain` before `Reply` and assert the reference is extracted.
Also at `tests/test_qqofficial_group_message_create.py:280`.
</issue_to_address>Sourcery assessment
Needs a human reviewer. 2 findings to address first, and if the extracted or attached reference is wrong, sent messages could contain an incorrect reply target or fail through the QQ API when the reference is rejected. Reverting stops future references but cannot remove metadata from messages already delivered, though the impact is bounded to those messages and can be corrected by sending another message.
Blocking findings: astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py:643, tests/test_qqofficial_group_message_create.py:257
| if payload.get("msg_id"): | ||
| fallback_payload = payload.copy() | ||
| fallback_payload.pop("msg_id", None) | ||
| # 主动发送兜底同样去掉引用:引用 id 失效不应阻断正文送达 |
There was a problem hiding this comment.
🟡 Medium · Valid quote context is lost
When a quoted reply fails initially for an unrelated caught error and the retry succeeds, _send_with_markdown_fallback removes message_reference before retrying, so the recipient gets the message body without its valid quote context.
Remove message_reference and retry only when the initial error indicates that the reference was rejected.
Also at astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py:644.
Prompt for AI agents
In `astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py` at line 643:
**Valid quote context is lost**
When a quoted reply fails initially for an unrelated caught error and the retry succeeds, `_send_with_markdown_fallback` removes `message_reference` before retrying, so the recipient gets the message body without its valid quote context.
Remove `message_reference` and retry only when the initial error indicates that the reference was rejected.
Also at `astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py:644`.Inbound quotes already work: the adapter reads message_reference off incoming messages and builds a Reply component from it. The outbound half was never wired up, so a plugin quoting a message with Comp.Reply(id=...) produced plain text with no quote bubble. _parse_to_qqofficial() now returns the first Reply component's message id alongside the media fields, and both send paths (_post_send_one and _send_by_session_common) attach it as message_reference. All four send APIs used here (v2 groups, v2 C2C, guild channel, guild DM) accept that field. The active-send fallback drops the reference together with msg_id, so a stale quote id degrades to plain text instead of blocking the message.
2284ebf to
0a89b87
Compare
…nd fallback Address review findings: - The passive-to-active fallback stripped message_reference together with msg_id on any failure, so an unrelated send error (markdown rejection, transient server error) lost a perfectly valid quote context. The active retry now keeps the reference first and only drops it when the retry with the reference also fails, since a dead reference id must not block the message body either. - The Reply extraction tests only covered Reply at the chain start. Added a Plain-before-Reply parser case and two fallback-behavior cases.
|
Both findings addressed in 117240d:
|
Fixes #10391.
Inbound quotes already work: the adapter reads
message_referenceoff incoming messages and builds aReplycomponent from it. The outbound half was never wired up._parse_to_qqofficial()droppedReplycomponents in its fallback branch, and althoughpost_c2c_message()declares amessage_referenceparameter, no call site ever passed one, so a plugin quoting a message withComp.Reply(id=...)produced plain text with no quote bubble.Changes:
_parse_to_qqofficial()now also returns the firstReplycomponent's message id. Empty or missing ids are ignored, so quote-free chains behave exactly as before._post_send_one()and_send_by_session_common()attachmessage_reference: {"message_id": ...}to the payload when such an id is present. All four send APIs used here (v2 groups, v2 C2C, guild channel, guild DM) accept that field._send_with_markdown_fallback()drops the reference together withmsg_id, so a stale or rejected quote id degrades to plain text instead of blocking the whole message.Tests:
message_reference, C2C send carries it through thepost_c2c_messagewrapper into the request JSON, and quote-free group sends do not gain the key.Verified with
pytest tests/test_qqofficial_group_message_create.py tests/test_platform_audio_media_resolver.py(44 + 5 passed) andruff format/ruff checkclean on the touched files. I could not exercise the real QQ API from here; the payload shape follows themessage_referencecontract linked in the issue and botpy'sReferenceTypedDict.Summary by Sourcery
Enable QQ Official outbound messages to carry message references from
Replycomponents while gracefully degrading when a reference is unavailable or rejected.New Features:
Replycomponents as quoted replies across group, C2C, guild channel, and guild DM APIs.Bug Fixes:
Tests: