Imaginary
Imaginary

Reputation: 125

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.

Upvotes: 0

Views: 1998

Answers (1)

Bruh
Bruh

Reputation: 140

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)

Upvotes: 1

Related Questions