There are two kinds of Context Menu Commands: User Commands and Message Commands.
@@ -96,4 +101,5 @@ public async Task Client_Ready()
```
**Note**: Application commands only need to be created once. They do _not_ have to be 'created' on every startup or connection. The example simple shows creating them in the ready event as it's simpler than creating normal bot commands to register application commands.
> [!NOTE]
> Application commands only need to be created once. They do _not_ have to be 'created' on every startup or connection. The example simple shows creating them in the ready event as it's simpler than creating normal bot commands to register application commands.
User commands and Message commands have their own unique objects returned. Different from Slash commands. To get the appropriate object returned, you can use a similar method to the slash commands.
User commands and Message commands have their own unique event just like the other interaction types. For user commands the event is `UserCommandExecuted` and for message commands the event is `MessageCommandExecuted`.
@@ -5,40 +5,25 @@ title: Receiving and Responding to Slash Commands
# Responding to interactions.
Interactions are the base thing sent over by Discord. Slash commands are one of the interaction types. In order to receive a slash command we have to listen to the `InteractionCreated` event. Let's add this to our code.
Interactions are the base thing sent over by Discord. Slash commands are one of the interaction types. We can listen to the `SlashCommandExecuted` event to respond to them. Lets add this to our code:
Now that we have the interaction event, let's talk about the `SocketInteraction` argument. The interaction can be cast to either a `SocketSlashCommand` or a `SocketMessageComponent`. In our case, we're trying to use slash commands so let's cast it to a `SocketSlashCommand`.
// we now have an instance of a SocketSlashCommand named command.
}
}
```
With every type of interaction there is a `Data` field. This is where the relevant information lives about our command that was executed. In our case, `Data` is a `SocketSlashCommandData` instance. In the data class, we can access the name of the command triggered as well as the options if there were any. For this example, we're just going to respond with the name of the command executed.
Let's go over the response types quickly, as you would only change them for style points :P
> [!NOTE]
> After receiving an interaction, you must respond to acknowledge it. You can choose to respond with a message immediately using `RespondAsync()` or you can choose to send a deferred response with `DeferAsync()`.
> If choosing a deferred response, the user will see a loading state for the interaction, and you'll have up to 15 minutes to edit the original deferred response using `ModifyOriginalResponseAsync()`. You can read more about response types [here](https://discord.com/developers/docs/interactions/slash-commands#interaction-response)
What is an ephemeral response? Basically, only the user who executed the command can see the result of it, this is pretty simple to implement.
**Note**: You don't have to run arg.DeferAsync() to capture the interaction, you can use arg.RespondAsync() with a message to capture it, this also follows the ephemeral rule.
> [!NOTE]
> You don't have to run arg.DeferAsync() to capture the interaction, you can use arg.RespondAsync() with a message to capture it, this also follows the ephemeral rule.
When responding with either `FollowupAsync` or `RespondAsync` you can pass in an `ephemeral` property. When setting it to true it will respond ephemerally, false and it will respond non-ephemerally.
> **Note:** Your `ApplicationCommandOptionType` specifies which type your choices are, you need to use `ApplicationCommandOptionType.Integer` if choices whos value are numbers and `ApplicationCommandOptionType.String` for string values.
> [!NOTE]
> Your `ApplicationCommandOptionType` specifies which type your choices are, you need to use `ApplicationCommandOptionType.Integer` for choices whos values are whole numbers, `ApplicationCommandOptionType.Number` for choices whos values are doubles, and `ApplicationCommandOptionType.String` for string values.
We have defined 5 choices for the user to pick from, each choice has a value assigned to it. The value can either be a string or an int. In our case we're going to use an int. This is what the command looks like:
@@ -50,23 +50,20 @@ We have defined 5 choices for the user to pick from, each choice has a value ass
Message components are a framework for adding interactive elements to a message your app or bot sends. They're accessible, customizable, and easy to use.
public async Task MyInteractionHandler(SocketInteraction arg)
{
// first we check the type of the interaction, this can be done with a switch statement
switch(arg)
{
case SocketMessageComponent component:
// we now have a variable defined as 'component' which contains our component data, lets pass it to a different handler.
break;
}
}
public async Task MyButtonHandler(SocketMessageComponent component)
{
// We can now check for our custom id
@@ -41,14 +34,4 @@ public async Task MyButtonHandler(SocketMessageComponent component)
Running it and clicking the button:

### Method 2: Hooking the ButtonExecuted Event
This method skips the first switch statement because the `ButtonExecuted` event is only fired when a button is clicked, meaning we dont have to check the type of the interaction.
```cs
client.ButtonExecuted += MyButtonHandler;
```
The rest of the code is the same and produces the same result.
Select menus allow users to select from a range of options, this can be quite useful with configuration commands etc.
@@ -48,7 +53,7 @@ And opening the menu we see:

Lets handle the selection of an option, as before we can hook the `InteractionCreated` event and check the type ourself but for this example im just going to use the `SelectMenuExecuted` event
Lets handle the selection of an option, We can hook the `SelectMenuExecuted` event to handle our select menu:
Lets say you have some components on an ephemeral slash command, and you want to modify the message that the button is on. The issue with this is that ephemeral messages are not stored and can not be get via rest or other means.
@@ -45,31 +50,38 @@ break;
Now, let's listen to the select menu executed event and add a case for `select-1`
```cs
switch (arg.Data.CustomId)
client.SelectMenuExecuted += SelectMenuHandler;
...
public async Task SelectMenuHandler(SocketMessageComponent arg)
{
case "select-1":
var value = arg.Data.Values.First();
var menu = new SelectMenuBuilder()
{
CustomId = "select-1",
Placeholder = $"{(arg.Message.Components.First().Components.First() as SelectMenu).Options.FirstOrDefault(x => x.Value == value).Label}",
MaxValues = 1,
MinValues = 1,
Disabled = true
};
menu.AddOption("Meh", "1", "Its not gaming.")
.AddOption("Ish", "2", "Some would say that this is gaming.")
.AddOption("Moderate", "3", "It could pass as gaming")
.AddOption("Confirmed", "4", "We are gaming")
.AddOption("Excellent", "5", "It is renowned as gaming nation wide", new Emoji("🔥"));
// We use UpdateAsync to update the message and its original content and components.
await arg.UpdateAsync(x =>
{
x.Content = $"Thank you {arg.User.Mention} for rating us {value}/5 on the gaming scale";
x.Components = new ComponentBuilder().WithSelectMenu(menu).Build();
});
break;
switch (arg.Data.CustomId)
{
case "select-1":
var value = arg.Data.Values.First();
var menu = new SelectMenuBuilder()
{
CustomId = "select-1",
Placeholder = $"{(arg.Message.Components.First().Components.First() as SelectMenu).Options.FirstOrDefault(x => x.Value == value).Label}",
MaxValues = 1,
MinValues = 1,
Disabled = true
};
menu.AddOption("Meh", "1", "Its not gaming.")
.AddOption("Ish", "2", "Some would say that this is gaming.")
.AddOption("Moderate", "3", "It could pass as gaming")
.AddOption("Confirmed", "4", "We are gaming")
.AddOption("Excellent", "5", "It is renowned as gaming nation wide", new Emoji("🔥"));
// We use UpdateAsync to update the message and its original content and components.
await arg.UpdateAsync(x =>
{
x.Content = $"Thank you {arg.User.Mention} for rating us {value}/5 on the gaming scale";
x.Components = new ComponentBuilder().WithSelectMenu(menu).Build();
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.