Search code examples
listdiscorddiscord.pycommandbots

How to get a list of slash commands (discord.py)


I have this command that lists all the cogs and all the commands inside of that cog. Sadly this doesn't detect slash commands.

@app_commands.command(name="help", description="help msg")
    async def help(self, interaction: discord.Interaction):
        em = discord.Embed(
            title="Help", 
            description="list of all commands",
            color=discord.Color.blurple())
        em.set_thumbnail(
            url=self.bot.user.avatar.url)

        cmdstr = ""
        for cogname, cog in self.bot.cogs.items():
            cogcmds = cog.walk_commands()
            for command in cogcmds:
                cmdstr += f"{command.name}\n"
            em.add_field(
                name=cogname,
                value=cmdstr,
                inline=False)
            cmdstr = ""

        await interaction.response.send_message(embed=em)

Is it even possible to get a list of slash commands? I know that a user can just press "/" and see a list of them, but they will be displayed in alphabetical order. I want a list so that I could make a help command and group all those slash commands neatly into their own categories. Something like that would be both easier to navigate and more engaging.


Solution

  • You can get a list of slash commands by using walk_commands() on the CommandTree of the bot.

    @app_commands.command(name="help", description="help msg")
    async def help(self, interaction: discord.Interaction):
        em = discord.Embed(
            title="Help",
            description="list of all commands",
            color=discord.Color.blurple())
        em.set_thumbnail(
            url=self.bot.user.avatar.url)
    
        for slash_command in self.bot.tree.walk_commands():
            em.add_field(name=slash_command.name, 
                         value=slash_command.description if slash_command.description else slash_command.name, 
                         inline=False) 
                         # fallbacks to the command name incase command description is not defined
    
        await interaction.response.send_message(embed=em)
    

    More on Bot.tree.walk_commands(): https://discordpy.readthedocs.io/en/latest/interactions/api.html#discord.app_commands.CommandTree.walk_commands

    Additional answer : To separate Commands and display Group commands on a new embed, you can separate ordinary commands and group commands from walk_commands() then you can iterate them to create embeds for the commands. You can use a for loops for that or you can use list comprehension on walk_commands() for a shorter code

    @app_commands.command(name="help", description="help msg")
        async def help(self, interaction: discord.Interaction):
            em = discord.Embed(
                title="Help",
                description="list of all commands",
                color=discord.Color.blurple())
            em.set_thumbnail(
                url=self.bot.user.avatar.url)
            
            commands = [com for com in self.bot.tree.walk_commands() if isinstance(com, app_commands.Command)]
            groups = [com for com in self.bot.tree.walk_commands() if isinstance(com, app_commands.Group)]
    
            for slash_command in commands:
                em.add_field(name=slash_command.name,
                             value=slash_command.description if slash_command.description else slash_command.name,
                             inline=False)
                # fallbacks to the command name incase command description is not defined
    
            embeds = [em]
    
            for group_command in groups:
                emb = discord.Embed(title=group_command.name,
                                    description=group_command.description if group_command.description else None,
                                    color=discord.Color.blurple())
                for comm in group_command.commands:
                    emb.add_field(name=comm.name,
                                  value=comm.description if comm.description else comm.name,
                                  inline=False)
                embeds.append(emb)
    
            await interaction.response.send_message(embeds=embeds)