Skip to content

[Bug] 指令组无法正确处理管理员权限的过滤器 #2198

@jiongjiongJOJO

Description

@jiongjiongJOJO

发生了什么

插件代码如下:

from astrbot.api.event import filter, AstrMessageEvent, MessageEventResult
from astrbot.api.star import Context, Star, register
from astrbot.api import logger

@register("helloworld", "YourName", "一个简单的 Hello World 插件", "1.0.0")
class MyPlugin(Star):
    def __init__(self, context: Context):
        super().__init__(context)

    async def initialize(self):
        """可选择实现异步的插件初始化方法,当实例化该插件类之后会自动调用该方法。"""

    @filter.command_group("math")
    @filter.permission_type(filter.PermissionType.ADMIN)
    def math(self):
        pass

    @math.command("add")
    async def add(self, event: AstrMessageEvent, a: int, b: int):
        # /math add 1 2 -> 结果是: 3
        yield event.plain_result(f"结果是: {a + b}")

    @math.command("sub")
    async def sub(self, event: AstrMessageEvent, a: int, b: int):
        # /math sub 1 2 -> 结果是: -1
        yield event.plain_result(f"结果是: {a - b}")

其中重点为:

    @filter.command_group("math")
    @filter.permission_type(filter.PermissionType.ADMIN)
    def math(self):

对指令组进行了permission_type装饰器设置。

触发指令

/math

预期返回结果:

您(ID: astrbot)的权限不足以使用此指令。通过 /sid 获取 ID 并请管理员添加。

实际返回结果

插件 helloworld: 参数不足。math 指令组下有如下指令,请参考:
math
├── add (a(int),b(int))
├── sub (a(int),b(int))

经过排查发现astrbot/core/pipeline/waking_check/stage.py

for filter in handler.event_filters:
try:
if isinstance(filter, PermissionTypeFilter):
if not filter.filter(event, self.ctx.astrbot_config):
permission_not_pass = True
permission_filter_raise_error = filter.raise_error
else:
if not filter.filter(event, self.ctx.astrbot_config):
passed = False
break
except Exception as e:
await event.send(
MessageEventResult().message(
f"插件 {star_map[handler.handler_module_path].name}: {e}"
)
)
event.stop_event()
passed = False
break
if passed:
if permission_not_pass:
if not permission_filter_raise_error:
# 跳过
continue
if self.no_permission_reply:
await event.send(
MessageChain().message(
f"您(ID: {event.get_sender_id()})的权限不足以使用此指令。通过 /sid 获取 ID 并请管理员添加。"
)
)
logger.info(
f"触发 {star_map[handler.handler_module_path].name} 时, 用户(ID={event.get_sender_id()}) 权限不足。"
)
event.stop_event()
return

L125会有两个过滤器:[astrbot.core.star.filter.permission.PermissionTypeFilter object, astrbot.core.star.filter.command_group.CommandGroupFilter object]
第一个过滤器在L128经过权限过滤器进行判断是否符合权限。不符合权限的话,则permission_not_pass为True.
紧接着进行第二个过滤器的判定,此时判定/math指令作为指令组命令,有没有提供后面的参数。没提供的话,则在command_group.py中(见下一行引用内容)抛出了ValueError,并被L135捕获,event.send输出对应的错误。
if event.message_str.strip() in complete_command_names:
tree = (
self.group_name
+ "\n"
+ self.print_cmd_tree(self.sub_command_filters, event=event, cfg=cfg)
)
raise ValueError(
f"参数不足。{self.group_name} 指令组下有如下指令,请参考:\n"
+ tree
)

此时,因为强制抛出了ValueError,并且被捕获,导致后面passed判定未否,则不处理。

因为过滤器的条件是AND,则任意一个条件不满足,则可以直接退出,所以这里建议在L128判定为真时直接break,跳过后续过滤器的判定,经测试此场景下返回结果与预期相符。

如果没问题的话,我将以上述解决方案提交一份pr来解决这个问题。

如何复现?

如上描述

AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器

master分支(bd270ae)代码运行
无提供商
消息平台适配器:目前测试了旧版本的aiocqhttp和master最新版的webui对话,理论上是同一个问题。

操作系统

Windows

报错日志

无报错日志

你愿意提交 PR 吗?

  • 是的,我愿意提交 PR!

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions