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
19 changes: 19 additions & 0 deletions astrbot/core/star/command_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ def _apply_config_to_runtime(
descriptor.filter_ref,
[str(x) for x in resolved_aliases if str(x).strip()],
)
if isinstance(descriptor.filter_ref, CommandGroupFilter):
_refresh_sub_command_names(descriptor.filter_ref)


def _bind_configs_to_descriptors(
Expand Down Expand Up @@ -485,6 +487,23 @@ def _set_filter_fragment(
filter_ref._cmpl_cmd_names = None


def _refresh_sub_command_names(group_filter: CommandGroupFilter) -> None:
"""Propagate a group rename/alias change to its sub-filters.

Sub-filters snapshot ``parent_command_names`` at registration and cache
their complete names, so after the group's fragment or aliases change they
would keep matching only the old prefix. Refresh the snapshots and clear
the caches (recursively for nested groups).
"""
for sub in group_filter.sub_command_filters:
if isinstance(sub, CommandGroupFilter):
sub._cmpl_cmd_names = None
_refresh_sub_command_names(sub)
elif isinstance(sub, CommandFilter):
sub.parent_command_names = group_filter.get_complete_command_names()
sub._cmpl_cmd_names = None


def _set_filter_aliases(
filter_ref: CommandFilter | CommandGroupFilter,
aliases: list[str],
Expand Down
80 changes: 80 additions & 0 deletions tests/test_command_management.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""指令组重命名/别名向子指令传播(#9366)。"""

from types import SimpleNamespace

from astrbot.core.star.command_management import (
_apply_config_to_runtime,
_refresh_sub_command_names,
_set_filter_aliases,
)
from astrbot.core.star.filter.command import CommandFilter
from astrbot.core.star.filter.command_group import CommandGroupFilter


def _group_with_child() -> tuple[CommandGroupFilter, CommandFilter]:
group = CommandGroupFilter("example_cmd_group")
child = CommandFilter("sub_cmd", parent_command_names=["example_cmd_group"])
group.add_sub_command_filter(child)
return group, child


def test_refresh_updates_child_parent_names_and_cache():
group, child = _group_with_child()
assert child.get_complete_command_names() == ["example_cmd_group sub_cmd"]
group.group_name = "/example_cmd_group"

_refresh_sub_command_names(group)

assert child.parent_command_names == ["/example_cmd_group"]
assert child._cmpl_cmd_names is None
assert child.get_complete_command_names() == ["/example_cmd_group sub_cmd"]


def test_refresh_recurses_into_nested_groups():
root = CommandGroupFilter("root_group")
sub_group = CommandGroupFilter("mid_group", parent_group=root)
leaf = CommandFilter("leaf", parent_command_names=["root_group mid_group"])
sub_group.add_sub_command_filter(leaf)
root.add_sub_command_filter(sub_group)

sub_group.get_complete_command_names()
leaf.get_complete_command_names()
root.group_name = "/root_group"

_refresh_sub_command_names(root)

# the nested group's cache is rebuilt fresh from the renamed root
assert sub_group._cmpl_cmd_names == ["/root_group mid_group"]
assert leaf.parent_command_names == ["/root_group mid_group"]
assert leaf.get_complete_command_names() == ["/root_group mid_group leaf"]


def test_apply_config_to_runtime_propagates_group_rename():
group, child = _group_with_child()
descriptor = SimpleNamespace(
handler=SimpleNamespace(enabled=True),
filter_ref=group,
current_fragment="/example_cmd_group",
)
config = SimpleNamespace(
enabled=True, resolved_command="/example_cmd_group", extra_data={}
)

_apply_config_to_runtime(descriptor, config)

assert group.group_name == "/example_cmd_group"
assert child.parent_command_names == ["/example_cmd_group"]
assert child.get_complete_command_names() == ["/example_cmd_group sub_cmd"]


def test_apply_config_to_runtime_propagates_group_aliases():
group, child = _group_with_child()
_set_filter_aliases(group, ["eg"])

_refresh_sub_command_names(group)

assert child.parent_command_names == ["example_cmd_group", "eg"]
assert child.get_complete_command_names() == [
"example_cmd_group sub_cmd",
"eg sub_cmd",
]
Loading