fix(session_waiter): bind empty-mention waiter to the initiating sender (#9377) - #9422
fix(session_waiter): bind empty-mention waiter to the initiating sender (#9377)#9422Qixuan112 wants to merge 2 commits into
Conversation
…er to avoid intercepting other group members (AstrBotDevs#9377)
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- Consider moving
_SenderSessionFilterout ofhandle_empty_mentioninto module scope so it isn’t redefined on every call and can be reused or tested independently. - When building the session key in
_SenderSessionFilter.filter, consider explicitly handling cases whereget_sender_id()might beNoneor unexpected to avoid collisions or hard-to-debug behavior.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider moving `_SenderSessionFilter` out of `handle_empty_mention` into module scope so it isn’t redefined on every call and can be reused or tested independently.
- When building the session key in `_SenderSessionFilter.filter`, consider explicitly handling cases where `get_sender_id()` might be `None` or unexpected to avoid collisions or hard-to-debug behavior.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
Addressed both suggestions in dfd6c00:
(🤖 Addressed by Claude Code) |
xiaoyuyu6420
left a comment
There was a problem hiding this comment.
Review
Reviewed in the context of issue #9377 alongside the other open PRs (#9378, #9442).
Strengths
- Minimal diff — only touches
main.py, adds a small private class. Lowest risk of unintended side effects. - Private
_SenderSessionFilter— scoped to the module, no new public API surface to maintain. __unknown_sender__sentinel — degrades gracefully whensender_idis unavailable instead of skipping the waiter entirely.
Issues
1. No tests
This is a bug fix with zero test coverage. Given that two other PRs for the same issue provide extensive tests, this is a significant gap. At minimum, the following should be tested:
- Two senders in the same group produce different keys
- The original sender's follow-up is still captured
- Cross-conversation isolation
__unknown_sender__sentinel behavior
2. Does not fix the non-text message swallowing bug (mentioned in #9377 as a "连带问题")
The handler body is unchanged:
if not event.message_str or not event.message_str.strip():
return # pure images are still silently dropped3. Does not fix the _cleanup race condition (mentioned in #9377)
USER_SESSIONS.pop(self.session_id) in _cleanup() can evict a newer waiter registered under the same key.
4. Only fixes empty_mention_waiter, not is_wake_prefix_only
The issue report states the cross-user interception also applies to the wake-prefix-only path, which still uses DefaultSessionFilter.
5. __unknown_sender__ could collide with a real sender_id
While extremely unlikely, a platform could theoretically return "__unknown_sender__" as an actual user ID. A value like "<unknown>" (with angle brackets) or a UUID-based sentinel would be safer since real IDs never contain brackets. Alternatively, PR #9378's approach of skipping the waiter (with a log warning) avoids the collision entirely.
6. Key collision with : separator
The format f"{ev.unified_msg_origin}:{sender_id}" uses : as separator, but unified_msg_origin already contains : (e.g., napcat2:GroupMessage:984306989). While in practice this does not cause ambiguity because the format is fixed (platform:Type:id), a Telegram topic-group origin like telegram:GroupMessage:-100123#42 combined with a sender ID containing : could theoretically produce collisions. PR #9378 addresses this with length-prefixed encoding.
Summary
This is the most minimal fix for the core cross-user interception bug, but it lacks tests and does not address the two related issues (non-text swallowing, cleanup race) documented in #9377. The sentinel value and key format have minor theoretical concerns that are unlikely to cause problems in practice but worth noting.
Correction to my earlier reviewI need to correct issue #4 in my previous review. I wrote that the After re-reading the control flow: both Thanks to @hedssaz's response on #9378 for catching this — I made the same error in both reviews. The other points (missing tests, non-text swallowing, cleanup race) still stand. |
Summary
Fixes #9377
Problem
When a user sent an empty @mention (or wake-prefix-only message) in a group chat, the
empty_mention_waiterusedDefaultSessionFilterwhich keyed sessions only byevent.unified_msg_origin(the group/conversation ID). This meant any subsequent message from any member in that group would trigger the waiter and be consumed viaevent.stop_event(), causing other members' messages to be silently intercepted.Fix
Added a custom
_SenderSessionFilterthat includesevent.get_sender_id()in the session key:This ensures the waiter only responds to messages from the same sender who initiated the empty mention, matching expected multi-user group chat behavior.
Changes
astrbot/builtin_stars/astrbot/main.py: importedSessionFilter, added a sender-scoped filter forempty_mention_waiter(+6/-1 lines)Summary by Sourcery
Bug Fixes: