Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions astrbot/core/utils/session_waiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ def filter(self, event: AstrMessageEvent) -> str:

class DefaultSessionFilter(SessionFilter):
def filter(self, event: AstrMessageEvent) -> str:
"""默认实现,返回统一消息来源字符串作为会话标识符"""
return event.unified_msg_origin
"""Return a session identifier scoped to the current sender and chat."""
return f"{event.unified_msg_origin}:{event.get_sender_id()}"

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 (bug_risk): The delimiter-based key f"{event.unified_msg_origin}:{event.get_sender_id()}" is not injective: a colon in the chat/session origin or sender ID produces the same key as a different origin/sender pair. Those distinct waiters overwrite or trigger one another in USER_SESSIONS.

Triggers: When a platform supplies a session origin or sender ID containing :.

Suggested fix: Encode the two components without ambiguity, for example by using a tuple key or length-prefixed/escaped serialization.



class SessionWaiter:
Expand Down
39 changes: 39 additions & 0 deletions tests/unit/test_session_waiter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from unittest.mock import MagicMock

from astrbot.core.utils.session_waiter import DefaultSessionFilter


def _event(umo: str, sender_id: str) -> MagicMock:
event = MagicMock()
event.unified_msg_origin = umo
event.get_sender_id.return_value = sender_id
return event


def test_default_filter_isolates_group_members() -> None:
session_filter = DefaultSessionFilter()
umo = "qq:GroupMessage:123"

first_member = session_filter.filter(_event(umo, "user-1"))
second_member = session_filter.filter(_event(umo, "user-2"))

assert first_member != second_member


def test_default_filter_keeps_same_sender_in_same_chat() -> None:
session_filter = DefaultSessionFilter()
umo = "qq:GroupMessage:123"

first_message = session_filter.filter(_event(umo, "user-1"))
next_message = session_filter.filter(_event(umo, "user-1"))

assert first_message == next_message


def test_default_filter_isolates_same_sender_across_chats() -> None:
session_filter = DefaultSessionFilter()

first_chat = session_filter.filter(_event("qq:GroupMessage:123", "user-1"))
second_chat = session_filter.filter(_event("qq:GroupMessage:456", "user-1"))

assert first_chat != second_chat