Discord.py 为参数数量创建一个检查装饰器

Discord.py Create a check decorator for number of arguments

在 discord.py 1.7.3 上,当我想确保命令在给定参数时出错时,我会这样做:

    @commands.command(name='hi')
    @commands.is_owner()
    async def hi(self, ctx, *, arg=None):
        if arg:
            raise commands.TooManyArguments
        else:
            await ctx.send(f'hi')

我想创建一个已在文档中描述的检查装饰器,以获得更优雅的东西:https://discordpy.readthedocs.io/en/stable/ext/commands/api.html#checks

所以我做到了:

def has_args():
    def predicate(ctx):
        print(ctx.args, ctx.kwargs)
        if len(ctx.args) > 2 or kwargs:
            raise commands.TooManyArguments
        return True
    return commands.check(predicate)
    ...
    @commands.command(name='hi')
    @commands.is_owner()
    @has_args()
    async def hi(self, ctx, *, arg=None):
        await ctx.send(f'hi')

但是 ctx.args 和 ctx.kwargs 总是空的,无论我传递给命令的参数数量是多少(又名 {prefix}hi 1 2 3 产生与 {prefix}hi 相同的打印)

有更好的方法吗?我错过了什么?

使用 @commands.command(name='hi') 时,您可以传递 ignore_extra,因此会引发 TooManyArguments 错误。 例子: @commands.command(name='hi', ignore_extra=False)
如果您想使用装饰器,这在我的初始测试中确实有效(参见注释):

def custom_command(**kwargs):
    kwargs['ignore_extra'] = False
    def decorator(func):
        return commands.Command(func, **kwargs)
    return decorator

@custom_command(name='hi')
@commands.is_owner()
async def hi(self, ctx, *, arg=None):
    await ctx.send(f'hi')

注意:使用第二种方法(自定义装饰器)时,此装饰器仅创建 commands.Command 的实例。如果 @commands.command 除了 Command 的实例化之外进行任何额外检查,此方法将跳过这些检查。