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
8 changes: 6 additions & 2 deletions astrbot/core/star/filter/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
from . import HandlerFilter
from .custom_filter import CustomFilter

# Preserve @nickname(ID) as one argument even when the nickname contains spaces.
# IDs are platform-specific and may be strings (for example Slack/Lark IDs).
COMMAND_ARGUMENT_PATTERN = re.compile(r"@[^@]*\([^()\s]+\)(?=\s|$)|[^\s]+")


class GreedyStr(str):
"""标记指令完成其他参数接收后的所有剩余文本。"""
Expand Down Expand Up @@ -205,8 +209,8 @@ def filter(self, event: AstrMessageEvent, cfg: AstrBotConfig) -> bool:
if not ok:
return False

# 分割为列表
ls = message_str.split(" ")
# Split into arguments while preserving @nickname(ID) mentions as one token.
ls = COMMAND_ARGUMENT_PATTERN.findall(message_str)
# 去除空字符串
ls = [param for param in ls if param]
params = {}
Expand Down
59 changes: 59 additions & 0 deletions tests/unit/test_command_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import pytest

from astrbot.core.star.filter.command import CommandFilter


class FakeCommandEvent:
def __init__(self, message_str: str):
self.message_str = message_str
self.is_at_or_wake_command = True
self.extras = {}

def get_message_str(self) -> str:
return self.message_str

def set_extra(self, key: str, value) -> None:
self.extras[key] = value


@pytest.mark.parametrize(
("command_name", "message_str", "handler_params", "expected_params"),
[
(
"修改好感度",
"修改好感度 @Heaven Whisper(488267082) 64",
{"target": str, "value": int},
{"target": "@Heaven Whisper(488267082)", "value": 64},
),
(
"修改好感度",
"修改好感度 @Jane Doe(U01ABC-DEF) 64",
{"target": str, "value": int},
{"target": "@Jane Doe(U01ABC-DEF)", "value": 64},
),
(
"修改好感度",
"修改好感度 488267082 64",
{"target": str, "value": int},
{"target": "488267082", "value": 64},
),
(
"修改关系",
"修改关系 @Alice One(U1) @Bob Two(U2)",
{"source": str, "target": str},
{"source": "@Alice One(U1)", "target": "@Bob Two(U2)"},
),
],
)
def test_command_filter_keeps_at_mentions_with_spaces_as_single_params(
command_name,
message_str,
handler_params,
expected_params,
):
command_filter = CommandFilter(command_name)
command_filter.handler_params = handler_params
event = FakeCommandEvent(message_str)

assert command_filter.filter(event, cfg=None)
assert event.extras["parsed_params"] == expected_params