Skip to content

feat: QQOfficialPlatformAdapter 消息解析新增 appid 参数以确保能获取用户头像地址;移除多余的 At 组件,仅给群聊类型添加 At 组件 (#6741)#7289

Open
FlanChanXwO wants to merge 4 commits intoAstrBotDevs:masterfrom
FlanChanXwO:feat/6741

Conversation

@FlanChanXwO
Copy link
Copy Markdown

@FlanChanXwO FlanChanXwO commented Apr 2, 2026

Closes #6741

Modifications / 改动点

1. _parse_from_qqofficial 方法新增 appid 参数

  • 方法签名新增 appid: str 参数
  • 所有调用该方法的入口(群消息、频道消息、私聊消息)都传入 self.platform.appid

2. 修复 self_id 的赋值逻辑

  • 之前:硬编码为 "unknown_selfid""qq_official"
  • 现在:使用实际的 appid,正确标识机器人身份

3. 优化 At 组件的添加逻辑

  • 之前:对所有消息类型都添加 At(qq="qq_official"),这是不正确的
  • 现在:
    • 群聊消息:添加 At(qq=appid) 用于 @ 机器人自身
    • 私聊消息:不再添加 At 组件

涉及文件

  • astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py

  • astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

self_id使用appid后这使得一些需要获取头像的插件可以正常使用,可以使用https://q.qlogo.cn/qqapp/{self_id}/{user_id}/100以获取用户头像;以及避免了无效的 At 组件影响判断私聊和群聊的判断

5da52876cfc0c127df0f9d2100ca0952

Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Update QQ Official platform message parsing to use the platform appid for self-identification and adjust mention handling for different message types.

New Features:

  • Pass the platform appid into QQOfficialPlatformAdapter message parsing to support correct bot identity and avatar-related features.

Bug Fixes:

  • Use the actual platform appid as self_id instead of hardcoded placeholder values in QQ Official messages.
  • Stop adding unnecessary At components to non-group QQ Official messages to avoid misclassifying private and group chats.

Enhancements:

  • Only add an At component for QQ Official group messages, targeting the bot appid to represent self-mentions.
  • Tighten the pipeline stage process method return type annotation to a simpler AsyncGenerator form.
  • Default test fixture file writing to the environment's default encoding instead of hardcoding UTF-8.
  • Remove an unused utils package initializer file.

Tests:

  • Adjust the local filesystem component test to rely on the default string encoding when writing the demo skill file.

Copilot AI review requested due to automatic review settings April 2, 2026 07:20
@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Apr 2, 2026
@auto-assign auto-assign bot requested review from LIghtJUNction and Soulter April 2, 2026 07:20
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

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, and left some high level feedback:

  • The type hint change in PipelineStage.process from AsyncGenerator[None, None] to AsyncGenerator[None] is not valid for AsyncGenerator (it expects two type parameters: yield and send); if you only need a stream of values, consider keeping AsyncGenerator[None, None] or switching to AsyncIterator[None] instead.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The type hint change in `PipelineStage.process` from `AsyncGenerator[None, None]` to `AsyncGenerator[None]` is not valid for `AsyncGenerator` (it expects two type parameters: yield and send); if you only need a stream of values, consider keeping `AsyncGenerator[None, None]` or switching to `AsyncIterator[None]` instead.

## Individual Comments

### Comment 1
<location path="tests/test_local_filesystem_component.py" line_range="30" />
<code_context>

     skill_path = tmp_path / "skills" / "demo.txt"
     skill_path.parent.mkdir(parents=True, exist_ok=True)
-    skill_path.write_bytes("技能内容".encode("utf-8"))
+    skill_path.write_bytes("技能内容".encode())

     result = asyncio.run(LocalFileSystemComponent().read_file(str(skill_path)))
</code_context>
<issue_to_address>
**issue (testing):** Using `.encode()` without an explicit encoding makes this test dependent on the environment’s default encoding and weakens its intent.

Given the test name (`...prefers_utf8_before_windows_locale`), using `encode("utf-8")` made the file content unambiguously UTF‑8 and aligned with the test’s intent. With plain `.encode()`, the bytes now vary with the system locale (e.g., cp1252/cp936 on Windows), so the test may behave differently across environments.

To keep the test deterministic and accurately exercise `LocalFileSystemComponent`’s UTF‑8 preference, please restore `encode("utf-8")` (or pass an explicit UTF‑8 encoding via the API you use).
</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.


skill_path = tmp_path / "skills" / "demo.txt"
skill_path.parent.mkdir(parents=True, exist_ok=True)
skill_path.write_bytes("技能内容".encode("utf-8"))
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.

issue (testing): Using .encode() without an explicit encoding makes this test dependent on the environment’s default encoding and weakens its intent.

Given the test name (...prefers_utf8_before_windows_locale), using encode("utf-8") made the file content unambiguously UTF‑8 and aligned with the test’s intent. With plain .encode(), the bytes now vary with the system locale (e.g., cp1252/cp936 on Windows), so the test may behave differently across environments.

To keep the test deterministic and accurately exercise LocalFileSystemComponent’s UTF‑8 preference, please restore encode("utf-8") (or pass an explicit UTF‑8 encoding via the API you use).

@dosubot dosubot bot added the area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. label Apr 2, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the QQ Official platform adapters’ message parsing so downstream plugins can correctly identify the bot (self_id) and avoid receiving misleading At components (especially in private chats), addressing #6741.

Changes:

  • Add an appid parameter to QQOfficialPlatformAdapter._parse_from_qqofficial and pass self.platform.appid from all entrypoints.
  • Fix self_id assignment to use appid, and only prepend an At(qq=appid) component for group messages (not private/C2C).
  • Includes a few unrelated refactors/adjustments in pipeline typing and tests.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py Pass appid into parsing, set self_id more accurately, restrict At insertion to group messages.
astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py Propagate appid into the shared parsing helper for webhook mode.
astrbot/core/pipeline/stage.py Adjust Stage process() return type annotation (currently introduces an invalid AsyncGenerator generic).
tests/test_local_filesystem_component.py Make UTF-8 test setup use implicit .encode() instead of explicit UTF-8.
tests/fixtures/helpers.py Switch Callable import to collections.abc.
astrbot/utils/__init__.py Remove empty __init__.py.

self,
event: AstrMessageEvent,
) -> None | AsyncGenerator[None, None]:
) -> None | AsyncGenerator[None]:
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

collections.abc.AsyncGenerator expects two type parameters (yield type, send type). Using AsyncGenerator[None] is not a valid generic specialization for type checkers and is inconsistent with other Stage implementations in this repo (which use AsyncGenerator[None, None]). Consider changing this back to None | AsyncGenerator[None, None] (or switching to AsyncIterator[None] if you don’t need .asend() typing) and keep the docstring’s return type in sync.

Suggested change
) -> None | AsyncGenerator[None]:
) -> None | AsyncGenerator[None, None]:

Copilot uses AI. Check for mistakes.
skill_path = tmp_path / "skills" / "demo.txt"
skill_path.parent.mkdir(parents=True, exist_ok=True)
skill_path.write_bytes("技能内容".encode("utf-8"))
skill_path.write_bytes("技能内容".encode())
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

This test is specifically about UTF-8 vs Windows locale fallbacks; using .encode() makes the intended encoding implicit. Consider keeping .encode('utf-8') here to make the test’s setup unambiguous.

Suggested change
skill_path.write_bytes("技能内容".encode())
skill_path.write_bytes("技能内容".encode("utf-8"))

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the QQ Official platform adapter to use a unified appid for identifying the bot across different message types, replacing hardcoded strings. It also includes minor refactoring in the pipeline stage type hints and test helper imports. The review identified a potential IndexError risk in the channel message handling logic where message.mentions[0].id is used, and suggested maintaining consistency by using appid for At components in channel messages to ensure compatibility with plugins that rely on message chain metadata.

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:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 关于qq官方Bot的部分参数

2 participants