Search code examples
pythondiscorddiscord.py

How do I know if a command requires the user to have a certain permission (to function)?


How do I go about retrieving a list of commands (Commands) that require the user to have the 'administrator' permission (to use them)? I am making a 'help' command; I would like to be able to retrieve all commands that require a certain permission in a list.

For example:

class Moderate(commands.Cog):
      @commands.command()
      @has_permissions(administrator=True)
      async def kick(ctx, member):
          #kick member

cog = Moderate
print(cog.commands.checks) -> {"kick" : administrator=True} #How to get this or the commands my bot has with this permission requirement?

Solution

  • Here's a less hacky way of doing it that I personally prefer:

    We can use a decorator to set a special attribute in the Command object, which we can then look at later. (Note: it is important that the @special decorator is placed before the @client.command. It needs to work off the Command object, not the actual callable function itself.)

    def special(command):
        command.__special_flag__ = None  # the value is irrelevant, you just need to set it
        return command
    
    @special
    @client.command()
    async def special_command(ctx):
        await ctx.send('hi')
    
    @special
    @client.command()
    async def list_special_commands(ctx):
        for command in client.commands:
            if hasattr(command, '__special_flag__'):  # this checks if "__special_flag__" is set
                await ctx.send(f'special command! {command}')
        await ctx.send('ok')
    

    You can then iterate through every command in the client and check if that flag is set. You can then add this extra decorator to any command you want to check permissions for. Then, in your help command, only display commands with this flag set.

    Output looks like this:

    enter image description here


    As @The Amateur Coder mentioned, this might take a bit of time to add them all, so you can make this combined decorator that does all of it:

    def combine_stuff(function):
        function = commands.has_permissions(...)(function)
        command = client.command(...)(function)
        command = special(command)