Skip to content

fix: 从 QQ 引用消息的 JSON 卡片中提取文本 | extract text from quoted QQ JSON cards - #9680

Open
SweetenedSuzuka wants to merge 3 commits into
AstrBotDevs:masterfrom
SweetenedSuzuka:fix/quoted-qq-json-card-extraction
Open

fix: 从 QQ 引用消息的 JSON 卡片中提取文本 | extract text from quoted QQ JSON cards#9680
SweetenedSuzuka wants to merge 3 commits into
AstrBotDevs:masterfrom
SweetenedSuzuka:fix/quoted-qq-json-card-extraction

Conversation

@SweetenedSuzuka

@SweetenedSuzuka SweetenedSuzuka commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

摘要 / Summary

修复群内引用 QQ JSON 卡片消息(如 QQ 小程序分享卡片)时,机器人无法看到引用内容的问题。
Fixes the bot being unable to see the content of a quoted QQ JSON card message (e.g. QQ mini-program shares).

问题 / Problem

引用消息解析器在两条抽取路径上都会静默丢弃非 com.tencent.multimsg 的 JSON 卡片:组件链路径(_extract_text_from_component_chain)没有 Json 组件分支;onebot 段路径(_parse_onebot_segments)只处理 com.tencent.multimsg 转发卡片。结果引用 JSON 卡片时 LLM 收到 "[Empty Text]"
The quoted-message parser silently dropped generic QQ JSON cards in both extraction paths: _extract_text_from_component_chain had no Json component branch, and _parse_onebot_segments only handled com.tencent.multimsg forward cards. As a result the LLM received "[Empty Text]" when quoting a JSON card.

改动 / Changes

  • chain_parser.py 新增 _extract_text_from_json_card:从卡片顶层 promptmeta.*.title/desc/url 提取可读文本,逐字段反转义 HTML 实体并设总长度上限。
  • 该函数对 com.tencent.multimsg 卡片继续委派给原 _extract_text_from_multimsg_json,多转发卡片行为不变。
  • 两条抽取路径(组件链与 onebot json 段)均接入该函数,并补充测试。
  • Added _extract_text_from_json_card in chain_parser.py to extract readable text from a card's top-level prompt and meta.*.title/desc/url fields, HTML-unescaping each field and capping total length.
  • com.tencent.multimsg cards still delegate to the existing _extract_text_from_multimsg_json, so forward-card behavior is unchanged.
  • Wired the helper into both extraction paths (component chain and onebot json segment) and added tests.

测试 / Tests

相关测试套件全部通过(test_quoted_message_parser.pytest_astr_main_agent.pytest_group_chat_context_wiring.pytest_group_message_history.py)。
Related test suites pass (test_quoted_message_parser.py, test_astr_main_agent.py, test_group_chat_context_wiring.py, test_group_message_history.py).

范围说明 / Scope

本 PR 只修复引用(reply/quote)消息路径;群聊上下文记忆中引用 JSON 卡片显示为 [Quote(...: [Json])] 的既有展示局限不在本 PR 范围。
This PR only fixes the quoted(reply/quote) message path; the pre-existing group-context memory display of a quoted JSON card as [Quote(...: [Json])] is out of scope.

Fixes #9565

Summary by Sourcery

Handle text extraction from generic QQ JSON card messages in quoted replies so bots can access their contents instead of returning empty text.

New Features:

  • Support extracting readable text from generic QQ JSON cards (e.g., mini-app cards) in quoted message chains and OneBot json segments.

Bug Fixes:

  • Fix quoted QQ JSON card messages being parsed as empty text, ensuring their main content, titles, descriptions, and URLs are surfaced to the LLM.

Enhancements:

  • Preserve existing behavior for com.tencent.multimsg forward cards while routing all JSON card handling through a unified extractor that unescapes HTML entities and caps extracted length.

Tests:

  • Add coverage for JSON card text extraction in both component-chain and get_msg fallback paths, including multimsg cards, HTML entity unescaping, double-encoded wrappers, and length capping.

The quoted-message parser dropped generic QQ JSON cards (e.g. mini-program
shares) in both extraction paths: _extract_text_from_component_chain had no
Json component branch, and _parse_onebot_segments only handled
com.tencent.multimsg forward cards.

Add _extract_text_from_json_card to read the top-level prompt and
meta.*.title/desc/url fields (HTML-unescaped and length-capped), delegating
multimsg cards to the existing handler so their behavior is unchanged.
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. labels Aug 14, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="astrbot/core/utils/quoted_message/chain_parser.py" line_range="324" />
<code_context>
+        if cleaned:
+            _append(f"{label}: {cleaned}")
+
+    _append(_clean_json_card_text(parsed.get("prompt")))
+
+    meta = parsed.get("meta")
</code_context>
<issue_to_address>
**suggestion:** Avoid passing a possible None into `_append` to better align with its signature and intent.

`_append` is annotated to take a `str`, but `_clean_json_card_text` can return `None`. While the current `if value and ...` logic is safe, it breaks the function’s type contract and may confuse readers or type checkers. Consider only calling `_append` when the cleaned prompt is truthy:

```python
prompt = _clean_json_card_text(parsed.get("prompt"))
if prompt:
    _append(prompt)
```

```suggestion
    prompt = _clean_json_card_text(parsed.get("prompt"))
    if prompt:
        _append(prompt)
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread astrbot/core/utils/quoted_message/chain_parser.py Outdated
SweetenedSuzuka and others added 2 commits August 14, 2026 14:19
Only call _append with a truthy prompt to match the str-typed signature
(_clean_json_card_text may return None). No behavior change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 在群内引用QQ小程序卡片消息时,bot无法看到内容

1 participant