How to mimic the builtin help command within commands.Bot() to bot.tree?
Question:
What I want to do is trigger the bot command help that is included with commands.Bot()
(e.g /help
returns all slash commands registered, and /help <command>
returns the description of that slash command).
A portion of my code:
class MyHelp(commands.HelpCommand):
async def send_bot_help(self, mapping):
if self.context.guild.id != master_guild:
return
names = [command.name for command in bot.tree.get_commands()] # iterating through the commands objects getting names
available_commands = "n".join(names) # joining the list of names by a new line
embed = discord.Embed(title=f"Commands ({len(names)}):",description=available_commands)
embed.set_footer(text=f" {prefix}help <command> (e.g {prefix}help {random.choice(names)})")
await self.context.send(embed=embed)
async def send_command_help(self, command): # I am in the process of making this work for slash commands
if self.context.guild.id != master_guild:
return
if len(command.description) == 0:
desc = "No description provided"
else:
desc = command.description
e = discord.Embed(title=command.name,description=desc)
e.set_footer(text="Usage: "+command.usage)
await self.context.send(embed=e)
bot = commands.Bot(command_prefix=prefix, intents=discord.Intents.all(), help_command=MyHelp()) #help_command obviously not needed
@bot.event
async def on_ready():
try:
synced = await bot.tree.sync()
print(f"Synced {len(synced)} command{'s' if len(synced) > 1 else ''}.")
except Exception as e:
print(f"Error syncing commands: {e}")
@bot.tree.command(description = "Sends help")
@app_commands.describe(command = "Enter command")
async def help(ctx: discord.Interaction, command_str=None):
await ctx.channel.send_help(ctx.command)
Answers:
What you mean is called syncing and its a necessary step for any app_command to work, including slash commands.
The easiest way is for you to make a prefixed (aka regular) command that does await bot.tree.copy_global_to(guild=guild)
where guild is an object containing the guild you want to copy it to. This ensures that there is a copy of the command tree on the guild you specified.
If having a per-guild tree is not a problem you can also use await bot.tree.sync()
which will copy it globally
Your slash command is not correctly done, but even if it were, if you don’t sync your command tree with discord, it won’t show the slash commands when the bot is up
Did some experimenting and found a working solution:
@bot.tree.command(description = "Sends help")
@app_commands.describe(command = "The command to get help for")
async def help(interaction: discord.Interaction, command_str=None):
if command is not None:
for c in bot.tree.get_commands(): # Iterates through registered slash commands
if c.name == command: # Checks if command iterated is the command requested
command = c
break
else:
continue
try:
embed = discord.Embed(title=command.name,description=command.description)
await interaction.response.send_message(embed=embed)
except AttributeError: # if command is not found
e = discord.Embed(title="Error:",description=f"Command {command} not found", color=0xFF0000)
await interaction.response.send_message(embed=e)
return
# ran if command is None
names = [command.name for command in bot.tree.get_commands()] # iterates through all the names of registered slash commands and compiles them into a list
available_commands = "n".join(names) # joins the list of names with a new
embed = discord.Embed(title=f"Commands ({len(names)}):",description=available_commands)
embed.set_footer(text=f" /help <command> (e.g /help {random.choice(names)})")
await interaction.response.send_message(embed=embed)
What I want to do is trigger the bot command help that is included with commands.Bot()
(e.g /help
returns all slash commands registered, and /help <command>
returns the description of that slash command).
A portion of my code:
class MyHelp(commands.HelpCommand):
async def send_bot_help(self, mapping):
if self.context.guild.id != master_guild:
return
names = [command.name for command in bot.tree.get_commands()] # iterating through the commands objects getting names
available_commands = "n".join(names) # joining the list of names by a new line
embed = discord.Embed(title=f"Commands ({len(names)}):",description=available_commands)
embed.set_footer(text=f" {prefix}help <command> (e.g {prefix}help {random.choice(names)})")
await self.context.send(embed=embed)
async def send_command_help(self, command): # I am in the process of making this work for slash commands
if self.context.guild.id != master_guild:
return
if len(command.description) == 0:
desc = "No description provided"
else:
desc = command.description
e = discord.Embed(title=command.name,description=desc)
e.set_footer(text="Usage: "+command.usage)
await self.context.send(embed=e)
bot = commands.Bot(command_prefix=prefix, intents=discord.Intents.all(), help_command=MyHelp()) #help_command obviously not needed
@bot.event
async def on_ready():
try:
synced = await bot.tree.sync()
print(f"Synced {len(synced)} command{'s' if len(synced) > 1 else ''}.")
except Exception as e:
print(f"Error syncing commands: {e}")
@bot.tree.command(description = "Sends help")
@app_commands.describe(command = "Enter command")
async def help(ctx: discord.Interaction, command_str=None):
await ctx.channel.send_help(ctx.command)
What you mean is called syncing and its a necessary step for any app_command to work, including slash commands.
The easiest way is for you to make a prefixed (aka regular) command that does await bot.tree.copy_global_to(guild=guild)
where guild is an object containing the guild you want to copy it to. This ensures that there is a copy of the command tree on the guild you specified.
If having a per-guild tree is not a problem you can also use await bot.tree.sync()
which will copy it globally
Your slash command is not correctly done, but even if it were, if you don’t sync your command tree with discord, it won’t show the slash commands when the bot is up
Did some experimenting and found a working solution:
@bot.tree.command(description = "Sends help")
@app_commands.describe(command = "The command to get help for")
async def help(interaction: discord.Interaction, command_str=None):
if command is not None:
for c in bot.tree.get_commands(): # Iterates through registered slash commands
if c.name == command: # Checks if command iterated is the command requested
command = c
break
else:
continue
try:
embed = discord.Embed(title=command.name,description=command.description)
await interaction.response.send_message(embed=embed)
except AttributeError: # if command is not found
e = discord.Embed(title="Error:",description=f"Command {command} not found", color=0xFF0000)
await interaction.response.send_message(embed=e)
return
# ran if command is None
names = [command.name for command in bot.tree.get_commands()] # iterates through all the names of registered slash commands and compiles them into a list
available_commands = "n".join(names) # joins the list of names with a new
embed = discord.Embed(title=f"Commands ({len(names)}):",description=available_commands)
embed.set_footer(text=f" /help <command> (e.g /help {random.choice(names)})")
await interaction.response.send_message(embed=embed)