Discord.py Create a check decorator for number of arguments

Viewed 472

On discord.py 1.7.3, when I want to make sure a command errors out if it is given arguments, I do:

    @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')

I wanted to create a check decorator has describe in the documentation, to have something a bit more elegant: https://discordpy.readthedocs.io/en/stable/ext/commands/api.html#checks

So I did:

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')

but ctx.args and ctx.kwargs are always empty, no matter the number of arguments I pass to the command (aka {prefix}hi 1 2 3 yield the same print as {prefix}hi)

Is there a better way to do this? What am I missing?

1 Answers

When using @commands.command(name='hi') you can pass ignore_extra so it raises an TooManyArguments error. Example: @commands.command(name='hi', ignore_extra=False)
If you would like to use decorators, this does work in my initial testing(SEE NOTE):

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')

NOTE: When using second method(custom decorator) this decorator just creates an instance of commands.Command. If @commands.command does any extra checks except instantiation of Command this method would skip those checks.

Related