feat: support QQ official(Websockets only) button interactions #9355
Open
kamicry wants to merge 6 commits into
Open
feat: support QQ official(Websockets only) button interactions #9355kamicry wants to merge 6 commits into
kamicry wants to merge 6 commits into
Conversation
Contributor
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Contributor
There was a problem hiding this comment.
Hey - I've found 2 issues, and left some high level feedback:
- Consider extracting the QQ interaction result codes (0–5) into named constants or an Enum that can be shared between the platform adapter and plugin docs to avoid magic numbers and keep behavior consistent if codes ever change.
- The QQOfficialPlatformAdapter construction pattern is repeated across the new tests; consider pulling it into a small helper/factory within the test module to reduce duplication and make future changes to the adapter setup easier.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider extracting the QQ interaction result codes (0–5) into named constants or an Enum that can be shared between the platform adapter and plugin docs to avoid magic numbers and keep behavior consistent if codes ever change.
- The QQOfficialPlatformAdapter construction pattern is repeated across the new tests; consider pulling it into a small helper/factory within the test module to reduce duplication and make future changes to the adapter setup easier.
## Individual Comments
### Comment 1
<location path="astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py" line_range="349-353" />
<code_context>
+ continue
+ if result is None:
+ continue
+ if type(result) is int and 0 <= result <= 5:
+ result_code = result
+ break
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The strict `type(result) is int` check may reject valid integer-like return values.
This strict type check excludes valid `int` subclasses (e.g., `numpy.int64`) that behave like integers. To accept integer-like values while still excluding booleans, consider `isinstance(result, int) and not isinstance(result, bool)` instead.
```suggestion
if result is None:
continue
if isinstance(result, int) and not isinstance(result, bool) and 0 <= result <= 5:
result_code = result
break
```
</issue_to_address>
### Comment 2
<location path="astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py" line_range="331" />
<code_context>
self.test_mode = os.environ.get("TEST_MODE", "off") == "on"
+ async def dispatch_interaction(self, interaction: Any) -> None:
+ """Dispatch a QQ Official callback-button interaction and acknowledge it.
+
</code_context>
<issue_to_address>
**issue (complexity):** Consider refactoring `dispatch_interaction` into smaller helper methods for result normalization, handler execution, and interaction acknowledgment to simplify control flow and logging.
You can keep the feature exactly as-is while slimming `dispatch_interaction` by extracting the responsibilities the reviewer mentioned.
For example, you can:
1. Extract result normalization.
2. Extract a “run handlers” helper.
3. Extract an “acknowledge interaction” helper.
That flattens control flow, removes nested `try`/`except`, and isolates logging.
```python
# helpers
def _normalize_result_code(self, result: Any, default: int) -> int:
if result is None:
return default
if type(result) is int and 0 <= result <= 5:
return result
logger.warning(
f"QQ Official interaction handler returned an invalid result code: {result!r}"
)
return default
async def _run_interaction_handlers(self, interaction: Any) -> int:
result_code = 1 # default
for handler in star_handlers_registry.get_handlers_by_event_type(
EventType.OnQQOfficialInteractionEvent
):
try:
result = await handler.handler(interaction)
except Exception:
logger.exception(
f"QQ Official interaction handler failed: {handler.handler_full_name}"
)
continue
# normalize and maybe override result_code
new_code = self._normalize_result_code(result, result_code)
if new_code != result_code:
result_code = new_code
break
return result_code
async def _acknowledge_interaction(self, interaction: Any, result_code: int) -> None:
interaction_id = str(getattr(interaction, "id", ""))
if not interaction_id:
logger.warning(
"QQ Official interaction has no id; cannot acknowledge it."
)
return
try:
await self.client.api.on_interaction_result(interaction_id, result_code)
except Exception:
logger.exception(
f"Failed to acknowledge QQ Official interaction: {interaction_id}"
)
```
Then `dispatch_interaction` becomes orchestration-only:
```python
async def dispatch_interaction(self, interaction: Any) -> None:
"""Dispatch a QQ Official callback-button interaction and acknowledge it."""
result_code = await self._run_interaction_handlers(interaction)
await self._acknowledge_interaction(interaction, result_code)
```
Behavior remains the same:
- All handlers are called in order.
- Exceptions in handlers are logged and skipped.
- Only int result codes in [0, 5] override the default; invalid codes are warned.
- Interaction is always acknowledged (or logged if it cannot be).
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
kamicry
marked this pull request as draft
July 22, 2026 18:17
kamicry
marked this pull request as ready for review
July 22, 2026 20:28
Contributor
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Contributor
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The new WebSocket interaction tests are mixed into
test_qqofficial_group_message_create.py; consider moving the interaction-specific helpers and cases into a dedicatedtest_qqofficial_interaction.pyto keep message and interaction behavior isolated and easier to maintain. - In
_normalize_interaction_result_code, logging a warning for every invalid plugin return may become noisy in production; you might want to downgrade this toinfo/debugor include some rate limiting to avoid log spam from misbehaving plugins.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new WebSocket interaction tests are mixed into `test_qqofficial_group_message_create.py`; consider moving the interaction-specific helpers and cases into a dedicated `test_qqofficial_interaction.py` to keep message and interaction behavior isolated and easier to maintain.
- In `_normalize_interaction_result_code`, logging a warning for every invalid plugin return may become noisy in production; you might want to downgrade this to `info`/`debug` or include some rate limiting to avoid log spam from misbehaving plugins.
## Individual Comments
### Comment 1
<location path="astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py" line_range="394" />
<code_context>
+ f"QQ Official interaction handler failed: {handler.handler_full_name}"
+ )
+ continue
+ normalized_result = self._normalize_interaction_result_code(result)
+ if normalized_result is not None:
+ result_code = normalized_result
</code_context>
<issue_to_address>
**suggestion:** Include handler identity when logging invalid interaction result codes for easier debugging.
When `_normalize_interaction_result_code` logs an invalid result code, the log entry doesn’t indicate which handler produced it. Since `dispatch_interaction` has `handler.handler_full_name`, either pass the handler name into `_normalize_interaction_result_code` or emit the warning here so the log includes both the invalid value and the handler identity for easier debugging of misbehaving plugins.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
中文说明
Backward Compatibility / 向后兼容性
@filter.on_qqofficial_interaction()is opt-in and handles QQ Official WebSocketaction.type = 1callbacks only. /@filter.on_qqofficial_interaction()为可选钩子,仅处理 QQ 官方 WebSocket 的action.type = 1回调。Fixes #9208
Validation
中文验证
Summary by Sourcery
Add QQ Official WebSocket button interaction handling and expose a plugin hook for acknowledging interactions with QQ-specific result codes.
New Features:
Enhancements:
Documentation:
Tests: