| @@ -15,16 +15,16 @@ Setting up labs in your project is really simple, here's how to do it: | |||||
| ## Branches | ## Branches | ||||
| ### Dev | ### Dev | ||||
| The main branch we pull off of to introduce new features into, the dev branch is the same as Discord.Nets dev branch | |||||
| This branch is kept up to date with dnets dev branch. we pull of it to ensure that labs will work with pre existing dnet code. | |||||
| ### Interactions | |||||
| This branch is for anything todo with Discord Interactions, such as [Slash commands](https://discord.com/developers/docs/interactions/slash-commands) and [Message Components](https://discord.com/developers/docs/interactions/message-components). This branch is stable enough to use but does not contain all the features of interactions. | |||||
| ### release/2.x | |||||
| This branch is what will be pushed to nuget, sometimes its not up to date as we wait for other features to be finished. | |||||
| ### SlashCommandService | |||||
| This branch is on pause and does not work currently, Once everything is stable with the Interaction branch we will continue working on a slash command service for it. | |||||
| ### old/SlashCommandService | |||||
| This branch is on pause and does not work currently, There is a pull request open to implement a working version of a slash command service. It can be found [here](https://github.com/Discord-Net-Labs/Discord.Net-Labs/pull/52) | |||||
| ### web/SlashCommandService | |||||
| webmilio's spin on the SlashCommandService branch, again the state of this is unknown. | |||||
| ### feature/xyz | |||||
| These branches are features for new things, you are more than welcome to clone them and give feedback in the discord server or issues tab. | |||||
| ## Listening for interactions | ## Listening for interactions | ||||
| ```cs | ```cs | ||||
| @@ -32,52 +32,65 @@ webmilio's spin on the SlashCommandService branch, again the state of this is un | |||||
| client.InteractionCreated += Client_InteractionCreated; | client.InteractionCreated += Client_InteractionCreated; | ||||
| ... | ... | ||||
| private async Task Client_InteractionCreated(SocketInteraction arg) | |||||
| private async Task Client_InteractionCreated(SocketInteraction interaction) | |||||
| { | { | ||||
| switch (arg.Type) // We want to check the type of this interaction | |||||
| // Checking the type of this interaction | |||||
| switch (interaction) | |||||
| { | { | ||||
| //Slash commands | |||||
| case InteractionType.ApplicationCommand: | |||||
| await MySlashCommandHandler(arg); | |||||
| // Slash commands | |||||
| case SocketSlashCommand commandInteraction: | |||||
| await MySlashCommandHandler(commandInteraction); | |||||
| break; | break; | ||||
| //Button clicks/selection dropdowns | |||||
| case InteractionType.MessageComponent: | |||||
| await MyMessageComponentHandler(arg); | |||||
| // Button clicks/selection dropdowns | |||||
| case SocketMessageComponent componentInteraction: | |||||
| await MyMessageComponentHandler(componentInteraction); | |||||
| break; | break; | ||||
| //Unused | |||||
| case InteractionType.Ping: | |||||
| break; | |||||
| //Unknown/Unsupported | |||||
| // Unused or Unknown/Unsupported | |||||
| default: | default: | ||||
| Console.WriteLine("Unsupported interaction type: " + arg.Type); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| ``` | ``` | ||||
| ### Handling button clicks and selection dropdowns | |||||
| ### Simple handling slash commands | |||||
| ```cs | ```cs | ||||
| private async Task MyMessageComponentHandler(SocketInteraction arg) | |||||
| private async Task MySlashCommandHandler(SocketSlashCommand interaction) | |||||
| { | |||||
| // Checking command name | |||||
| if (interaction.Data.Name == "ping") | |||||
| { | |||||
| // Respond to interaction with message. | |||||
| // You can also use "ephemeral" so that only the original user of the interaction sees the message | |||||
| await interaction.RespondAsync($"Pong!", ephemeral: true); | |||||
| // Also you can followup with a additional messages, which also can be "ephemeral" | |||||
| await interaction.FollowupAsync($"PongPong!", ephemeral: true); | |||||
| } | |||||
| } | |||||
| ``` | |||||
| ### Simple handling button clicks and selection dropdowns | |||||
| ```cs | |||||
| private async Task MyMessageComponentHandler(SocketMessageComponent interaction) | |||||
| { | { | ||||
| // Parse the arg | |||||
| var parsedArg = (SocketMessageComponent) arg; | |||||
| // Get the custom ID | // Get the custom ID | ||||
| var customId = parsedArg.Data.CustomId; | |||||
| var customId = interaction.Data.CustomId; | |||||
| // Get the user | // Get the user | ||||
| var user = (SocketGuildUser) arg.User; | |||||
| var user = (SocketGuildUser) interaction.User; | |||||
| // Get the guild | // Get the guild | ||||
| var guild = user.Guild; | var guild = user.Guild; | ||||
| // Respond with the update message response type. This edits the original message if you have set AlwaysAcknowledgeInteractions to false. | |||||
| // You can also use "ephemeral" so that only the original user of the interaction sees the message | |||||
| await parsedArg.RespondAsync($"Clicked {parsedArg.Data.CustomId}!", type: InteractionResponseType.UpdateMessage, ephemeral: true); | |||||
| // Respond with the update message. This edits the message which this component resides. | |||||
| await interaction.UpdateAsync(msgProps => msgProps.Content = $"Clicked {interaction.Data.CustomId}!"); | |||||
| // You can also followup with a second message | |||||
| await parsedArg.FollowupAsync($"Clicked {parsedArg.Data.CustomId}!", type: InteractionResponseType.ChannelMessageWithSource, ephemeral: true); | |||||
| // Also you can followup with a additional messages | |||||
| await interaction.FollowupAsync($"Clicked {interaction.Data.CustomId}!", ephemeral: true); | |||||
| //If you are using selection dropdowns, you can get the selected label and values using these: | |||||
| var selectedLabel = ((SelectMenu) parsedArg.Message.Components.First().Components.First()).Options.FirstOrDefault(x => x.Value == parsedArg.Data.Values.FirstOrDefault())?.Label; | |||||
| var selectedValue = parsedArg.Data.Values.First(); | |||||
| // If you are using selection dropdowns, you can get the selected label and values using these | |||||
| var selectedLabel = ((SelectMenu) interaction.Message.Components.First().Components.First()).Options.FirstOrDefault(x => x.Value == interaction.Data.Values.FirstOrDefault())?.Label; | |||||
| var selectedValue = interaction.Data.Values.First(); | |||||
| } | } | ||||
| ``` | ``` | ||||
| @@ -97,22 +110,18 @@ var builder = new ComponentBuilder() | |||||
| .WithSelectMenu(new SelectMenuBuilder() | .WithSelectMenu(new SelectMenuBuilder() | ||||
| .WithCustomId("id_2") | .WithCustomId("id_2") | ||||
| .WithPlaceholder("This is a placeholder") | .WithPlaceholder("This is a placeholder") | ||||
| .WithOptions(new List<SelectMenuOptionBuilder>() | |||||
| { | |||||
| new SelectMenuOptionBuilder() | |||||
| .WithLabel("Option A") | |||||
| .WithEmote(Emote.Parse("<:evanpog:810017136814194698>")) | |||||
| .WithDescription("Evan pog champ") | |||||
| .WithValue("value1"), | |||||
| new SelectMenuOptionBuilder() | |||||
| .WithLabel("Option B") | |||||
| .WithDescription("Option B is poggers") | |||||
| .WithValue("value2") | |||||
| })); | |||||
| .AddOption( | |||||
| label: "Option", | |||||
| value: "value1", | |||||
| description: "Evan pog champ", | |||||
| emote: Emote.Parse("<:evanpog:810017136814194698>") | |||||
| ) | |||||
| .AddOption("Option B", "value2", "Option B is poggers"); | |||||
| await Context.Channel.SendMessageAsync("Test selection!", component: builder.Build()); | await Context.Channel.SendMessageAsync("Test selection!", component: builder.Build()); | ||||
| ``` | ``` | ||||
| > Note: You can only have 5 buttons per row and 5 rows per message. If a row contains a selection dropdown it cannot contain any buttons. | > Note: You can only have 5 buttons per row and 5 rows per message. If a row contains a selection dropdown it cannot contain any buttons. | ||||
| ## Slash commands | ## Slash commands | ||||
| Slash command example how to's can be found [here](https://github.com/Discord-Net-Labs/Discord.Net-Labs/tree/Interactions/docs/guides/slash-commands). If you want to read some code using slash commands, you can do that [here](https://github.com/quinchs/SwissbotCore/blob/master/SwissbotCore/Handlers/AutoMod/Censor.cs) | |||||
| Slash command example how to's can be found [here](https://github.com/Discord-Net-Labs/Discord.Net-Labs/tree/Interactions/docs/guides/slash-commands). | |||||