I've been testing out the basics of writing a discord bot for a little project I'm working on, and I noticed that while the bot responds as intended when given a slash command, the sent command its self says that the application failed to respond. If anyone can point out where I'm being stupid, that would be much appreciated!
Here are some images of the problem
I send the command... it works... but the application didn't respond apparently?
Here's the test slash command that I'm using
@tree.command(name = "test", description = "test", guild=discord.Object(id=(idnu))
async def lal(ctx, last: str):
response = "strresponse"
await ctx.channel.send(response)
I also looked at a couple posts which are similar, I.E Discord bot "The application did not respond" yet the command send? but none seemed to answer my question, as I'm already responding last?
Thank you!
You are using discord.app_commands
, not discord.ext.commands
.
When definig a command using app_commands
, the first command parameter is not from type commands.Context
, its discord.Interaction
.
Both objects (ctx
and interaction
) has a channel object as property so the message is being sent. However, this is not the way you are suppose to handle an interaction.
All app_commands
must have a response, that can be sent using the response
object property from the interaction
object.
This is how your command should look like:
from discord import app_commands, Interaction
@bot.tree.command(name='test', description='command description')
@app_commands.describe(last = '"last" parameter description') # Optional line
async def test(interaction : Interaction, last : str):
response = "str_response"
await interaction.response.send_message(response)
My previous sentence:
"All app_commands must have a response, that can be sent using the response attribute from the interaction object"
doesn't mean that you can't send "standard message" (channel.send()
) as part of the command, but that you have to response to the interaction at least once.
Interaction responses are the type of messages that look like this:
If you want your command to only include "standard messages", you can set to True
the ephemeral
parameter when responding to the interaction with the send_message()
coroutine from the response object.
Making the response ephemeral
makes the interaction response only visible for the user that executed the command, and it can be deleted at any time clicking on "Delete this message" (or "Eliminar este mensaje" in the next picture, sorry, I have Discord in Spanish):
@bot.tree.command(name='test', description='command description')
@app_commands.describe(last = '"last" parameter description')
async def test(interaction : Interaction, last : str):
response = "str_response"
await interaction.channel.send(response)
await interaction.response.send_message(content='Message Sent!', ephemeral=True)
Finally, if you want your command to include more than one interaction response, or you are expecting the command execution to not be brief (slow code, etc.) you have to defer
the response, and then send the responses using interaction.followup.send()
instead of interaction.response.send_message()
:
@bot.tree.command(name='test', description='command description')
@app_commands.describe(last = '"last" parameter description')
async def test(interaction : Interaction, last : str):
await interaction.response.defer()
await interaction.followup.send('str_response')
await interaction.followup.send('Another response!')
Now you are ready to join the app_commands
commands side! 👀