Following the guide I found on the Discord.Net documentation site, I've built a command with the following definition:
Imports Discord
Imports Discord.Interactions
Public Class TestCommands
Inherits InteractionModuleBase(Of SocketInteractionContext)
Public Property Commands As InteractionService
Private _handler As CommandHandler
Public Sub New(ByVal handler As CommandHandler)
_handler = handler
End Sub
<SlashCommand("faq", "View frequently asked questions")>
Public Async Function FAQ() As Task
Dim FAQMenu As New SelectMenuBuilder
Dim FAQSelect As New ComponentBuilder
With FAQMenu
.WithPlaceholder("What's your question?")
.WithCustomId("faq_menu")
.WithMinValues(1)
.WithMaxValues(1)
.AddOption("Question #1?", "faq1")
.AddOption("Question #2?", "faq2")
.AddOption("Question #3?", "faq3")
.AddOption("Question #4?", "faq4")
End With
FAQSelect.WithSelectMenu(FAQMenu)
Await ReplyAsync("Select one of the following Frequently Asked Questions:", components:=FAQSelect.Build)
End Function
End Class
When I run my bot and type /faq
in my Discord client, it correctly displays my selection menu, but right above it I see a message saying "The application did not respond"
I'm guessing that the bot is waiting for the selection, and I understand that there's a short timeout for the bot to receive input, but I definitely don't want my users to see that and think that there's a problem with the bot. Is there a better way to post the select menu component to prevent this message from popping up?
EDIT: Sorry, I forgot to include the CommandHandler
object definition. Perhaps that's where the timeout is occurring. There's a lot of unfinished code in here, but maybe it'll help diagnose why I'm getting this message:
Imports System.Reflection
Imports Microsoft.Extensions.Configuration
Imports Discord
Imports Discord.Interactions
Imports Discord.WebSocket
Imports Ichthus.Bot
Public Class CommandHandler
Private ServerLogChannel As UInt64 = 0
Public Async Function InitializeAsync() As Task
' add the public modules that inherit InteractionModuleBase<T> to the InteractionService
Await Settings.BotCommands.AddModulesAsync(Assembly.GetEntryAssembly(), Settings.BotProvider)
' process the InteractionCreated payloads to execute Interactions commands
AddHandler Settings.Bot.InteractionCreated, AddressOf HandleInteraction
AddHandler Settings.Bot.ButtonExecuted, AddressOf HandleButton
AddHandler Settings.Bot.SelectMenuExecuted, AddressOf HandleMenu
' process the command execution results
AddHandler Settings.BotCommands.SlashCommandExecuted, AddressOf SlashCommandExecuted
AddHandler Settings.BotCommands.ContextCommandExecuted, AddressOf ContextCommandExecuted
AddHandler Settings.BotCommands.ComponentCommandExecuted, AddressOf ComponentCommandExecuted
End Function
Private Function ComponentCommandExecuted(ByVal Command As ComponentCommandInfo, ByVal Context As IInteractionContext, ByVal Result As IResult) As Task
If Not Result.IsSuccess Then
Select Case Result.[Error]
Case InteractionCommandError.UnmetPrecondition
Case InteractionCommandError.UnknownCommand
Case InteractionCommandError.BadArgs
Case InteractionCommandError.Exception
Case InteractionCommandError.Unsuccessful
Case Else
End Select
End If
Return Task.CompletedTask
End Function
Private Function ContextCommandExecuted(ByVal Command As ContextCommandInfo, ByVal Context As IInteractionContext, ByVal Result As IResult) As Task
If Not Result.IsSuccess Then
Select Case Result.[Error]
Case InteractionCommandError.UnmetPrecondition
Case InteractionCommandError.UnknownCommand
Case InteractionCommandError.BadArgs
Case InteractionCommandError.Exception
Case InteractionCommandError.Unsuccessful
Case Else
End Select
End If
Return Task.CompletedTask
End Function
Private Function SlashCommandExecuted(ByVal Command As SlashCommandInfo, ByVal Context As IInteractionContext, ByVal Result As IResult) As Task
If Not Result.IsSuccess Then
Select Case Result.[Error]
Case InteractionCommandError.UnmetPrecondition
Case InteractionCommandError.UnknownCommand
Case InteractionCommandError.BadArgs
Case InteractionCommandError.Exception
Case InteractionCommandError.Unsuccessful
Case Else
End Select
End If
Return Task.CompletedTask
End Function
Private Async Function HandleInteraction(ByVal Interaction As SocketInteraction) As Task
Try
' create an execution context that matches the generic type parameter of your InteractionModuleBase<T> modules
Dim Context As New SocketInteractionContext(Settings.Bot, Interaction)
Dim Result As IResult = Await Settings.BotCommands.ExecuteCommandAsync(Context, Settings.BotProvider)
If Not Result.IsSuccess Then
Select Case Result.[Error]
Case InteractionCommandError.UnmetPrecondition
Case Else
End Select
End If
Catch ex As Exception
Console.WriteLine(ex)
' if a Slash Command execution fails it is most likely that the original interaction acknowledgment will persist. It is a good idea to delete the original
' response, or at least let the user know that something went wrong during the command execution.
If Interaction.Type = InteractionType.ApplicationCommand Then
Interaction.GetOriginalResponseAsync().ContinueWith(Function(msg) msg.Result.DeleteAsync()).Wait()
End If
End Try
End Function
Private Async Function HandleMenu(ByVal Selection As SocketMessageComponent) As Task
For Each Selected As String In Selection.Data.Values
Select Case Selected
Case "faq1"
Await Selection.RespondAsync("Response #1.")
Case "faq2"
Await Selection.RespondAsync("Response #2.")
Case "faq3"
Await Selection.RespondAsync("Response #3.")
Case "faq4"
Await Selection.RespondAsync("Response #4.")
Case Else
Await Selection.RespondAsync($"{Selection.User.Mention} has selected something I don't recognize")
End Select
Next Selected
End Function
Private Async Function HandleButton(ByVal Button As SocketMessageComponent) As Task
Select Case Button.Data.CustomId
Case "faq1"
Await Button.RespondAsync($"{Button.User.Mention} has clicked the first button")
Case "faq2"
Await Button.RespondAsync($"{Button.User.Mention} has clicked the second button")
Case "faq3"
Await Button.RespondAsync($"{Button.User.Mention} has clicked the third button")
Case Else
Await Button.RespondAsync($"{Button.User.Mention} has clicked something I don't recognize")
End Select
End Function
End Class
This issue occurs because you are not responding to the interaction. ReplyAsync
simply sends a message to the channel it does not send a message in response to the interaction. As such, as far as Discord is concerned, your application did not respond, just as the error says. When using Slash Commands you should use RespondAsync
to send a message in response to the command. ReplyAsync
is meant for standard Text Commands.
Note that Slash Command responses usually look similar to how the error message is formatted in your image. The original command is shown at the top and the command response is shown immediately below it as if you used Discord's reply feature.