diff --git a/DisCatSharp.Docs/articles/beyond_basics/components/select_menus.md b/DisCatSharp.Docs/articles/beyond_basics/components/select_menus.md index 05ad111a3..db5e619d3 100644 --- a/DisCatSharp.Docs/articles/beyond_basics/components/select_menus.md +++ b/DisCatSharp.Docs/articles/beyond_basics/components/select_menus.md @@ -1,139 +1,139 @@ --- uid: advanced_topics_select_menus title: Select Menus --- # Introduction The select menus, like the [buttons](xref:advanced_topics_buttons), are message components. You will want to familarize yourself with the [message builder](xref:beyond_basics_messagebuilder) as it and similar builder objects will be used throughout this article. A row can only have one select menu. An row containing a select menu cannot also contain buttons. Since a message can have up to 5 rows, you can add up to 5 select menus to a message. # Select Menus > [!WARNING] > Component Ids and option values should be unique, as this is what's sent back when a user selects one (or more) option. Select menus consist of five parts: - Id - Placeholder - Options - MinOptions - MaxOptions - Disabled The id of the select menu is a settable string, and is specified by the developer. Discord sends this id back in the [interaction object](https://discord.dev/interactions/slash-commands#interaction). **Placeholder** is a settable string that appears in the select menu when nothing is selected. **Options** is an array of options for the user to select. Their maximum number in one select menu is 25. You can let users choose 1 or more options using **MinOptions** and **MaxOptions**. Options consist of five parts: - Label - Value - Description - IsDefault - Emoji Menu creation, for easier understanding, can be divided into two stages: ```cs // First, create an array of options. var options = new DiscordSelectComponentOption[] { new DiscordSelectComponentOption("First option", "first_option", "This is the first option, you can add your description of it here.", false, new DiscordComponentEmoji("😀")), new DiscordSelectComponentOption("Second option", "second_option", "This is the second option, you can add your description of it here.", false, new DiscordComponentEmoji("😎")) }; // Now let's create a select menu with the options created above. var selectMenu = new DiscordSelectComponent("my_select_menu", "Please select one of the options", options); ``` This will create a select menu with two options and the text "Please select one of the options". When a user select **one** option, `"my_select_menu"` will be sent back as the `Id` property on the event. -This is expanded on in the [how to respond to select menus](#responding-to-options-selected). +This is expanded on in the [how to respond to select menus](#responding-to-select-menus). You can increase the maximum/minimum number of selections in the select menu constructor. You can also block the select menu, or options. Description and emoji of options are optional. The label, value and description can be up to 100 characters in length. The emoji of a option is a [partial emoji object](https://discord.dev/interactions/message-components#component-object), which means that **any valid emoji is usable**, even if your bot does not have access to it's origin server. # Adding Select Menu Adding a selec menu is no different than adding a button. We have already created the select menu above, now we will just create a new message builder add the select menu to it. ```cs var builder = new DiscordMessageBuilder() .WithContent("This message has select menu! Pretty neat innit?") .AddComponents(selectMenu); ``` Now you have a message with a select menu. Congratulations! It's important to note that `.AddComponents()` will create a new row with each call, so **add everything you want on one row in one call!** Lets also add a second row with select menu with the ability to choose any number of options. ```cs var secondOptions = new DiscordSelectComponentOption[] { new DiscordSelectComponentOption("First option", "first_option", "This is the first option, you can add your description of it here.", false, new DiscordComponentEmoji("😀")), new DiscordSelectComponentOption("Second option", "second_option", "This is the second option, you can add your description of it here.", false, new DiscordComponentEmoji("😎")) new DiscordSelectComponentOption("Third option", "third_option", "This is the third option, you can add your description of it here.", false, new DiscordComponentEmoji("😘")) }; var secondSelectMenu = new DiscordSelectComponent("my_second_select_menu", "Please select up to 3 options", secondOptions, 1, 3); builder.AddComponents(secondSelectMenu); ``` And you're done! The select menu will now be sent when the user closes the select menu with 1 to 3 options selected. # Responding to select menus When any select menu is pressed, it will fire the [ComponentInteractionCreated](xref:DisCatSharp.DiscordClient#DisCatSharp_DiscordClient_ComponentInteractionCreated) event. In the event args, `Id` will be the id of the select menu you specified. There's also an `Interaction` property, which contains the interaction the event created. It's important to respond to an interaction within 3 seconds, or it will time out. Responding after this period will throw a `NotFoundException`. With select menus, there are two new response types: `DefferedMessageUpdate` and `UpdateMessage`. Using `DeferredMessageUpdate` lets you create followup messages via the [followup message builder](xref:DisCatSharp.Entities.DiscordFollowupMessageBuilder). You have 15 minutes from that point to make followup messages. Responding to that interaction looks like this: ```cs client.ComponentInteractionCreated += async (s, e) => { await e.Interaction.CreateResponseAsync(InteractionResponseType.DefferedMessageUpdate); // Do things.. // } ``` If you would like to update the message when an select menu option selected, however, you'd use `UpdateMessage` instead, and pass a `DiscordInteractionResponseBuilder` with the new content you'd like. ```cs client.ComponentInteractionCreated += async (s, e) => { await e.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, new DiscordInteractionResponseBuilder().WithContent("No more select menu for you >:)")); } ``` This will update the message, and without the infamous (edited) next to it. Nice. # Interactivity Along with the typical `WaitForMessageAsync` and `WaitForReactionAsync` methods provided by interactivity, there are also select menus implementations as well. More information about how interactivity works can be found in [the interactivity article](xref:interactivity) Since select menus create interactions, there are also two additional properties in the configuration: - RepsonseBehavior - ResponseMessage ResponseBehavior is what interactivity will do when handling something that isn't a valid select menu, in the context of waiting for a specific select menu. It defaults to `Ignore`, which will cause the interaction fail. Alternatively, setting it to `Ack` will acknowledge the select menu, and continue waiting. Respond will reply with an ephemeral message with the aforementioned response message. ResponseBehavior only applies to the overload accepting a string id of the select menu to wait for. diff --git a/DisCatSharp.Docs/articles/important_changes/9_8_3.md b/DisCatSharp.Docs/articles/important_changes/9_8_3.md index 35273a842..fbdef8da8 100644 --- a/DisCatSharp.Docs/articles/important_changes/9_8_3.md +++ b/DisCatSharp.Docs/articles/important_changes/9_8_3.md @@ -1,73 +1,74 @@ --- uid: important_changes_9_8_3 title: Version 9.8.3 --- # What changed? We [changed](https://canary.discord.com/channels/858089281214087179/858099438580006913/890973133148926004) the option to restrict channel types in Slash Commands to an extra Attribute named `ChannelTypes` in favour of the application command autocompletion. You can read about it [here](https://github.com/discord/discord-api-docs/pull/3849). ## Upgrade from **9.8.2** to **9.8.3** In **DisCatSharp.ApplicationComands** you restricted channel types like this: ```cs [SlashCommand("openstage", "Opens a stage")] public static async Task OpenStageAsync(InteractionContext ctx, [Option("stage", "Stage Channel", ChannelType.Stage)] DiscordChannel stage, [Option("topic", "Topic of stage")] string topic, [Option("notify", "Whether to notify people")] bool notify = false, [Option("make_public", "Whether the stage channel will be public")] bool make_public = false) { try { await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent("Opening stage").AsEphemeral(true)); await stage.OpenStageAsync(topic, notify, make_public ? StagePrivacyLevel.PUBLIC : StagePrivacyLevel.GUILD_ONLY); await ctx.EditResponseAsync(new() { Content = "Stage channel has been successfully opened." }); } catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(ex.Message + " " + ex.StackTrace)); } } ``` In **DisCatSharp.ApplicationComands** you restrict channel types now like this: ```cs [SlashCommand("openstage", "Opens a stage")] public static async Task OpenStageAsync(InteractionContext ctx, [Option("stage", "Stage Channel"), ChannelTypes(ChannelType.Stage)] DiscordChannel stage, [Option("topic", "Topic of stage")] string topic, [Option("notify", "Whether to notify people")] bool notify = false, [Option("make_public", "Whether the stage channel will be public")] bool make_public = false) { try { await ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, new DiscordInteractionResponseBuilder().WithContent("Opening stage").AsEphemeral(true)); await stage.OpenStageAsync(topic, notify, make_public ? StagePrivacyLevel.PUBLIC : StagePrivacyLevel.GUILD_ONLY); await ctx.EditResponseAsync(new() { Content = "Stage channel has been successfully opened." }); } catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(ex.Message + " " + ex.StackTrace)); } } ``` ## New function: Application Command Autocompletion: Examples: > Autocomplete Option: https://github.com/Aiko-IT-Systems/DisCatSharp.Support/blob/main/Commands/Tasks/ConduitTasks.cs#L78 + > Autocomplete Provider: https://github.com/Aiko-IT-Systems/DisCatSharp.Support/blob/main/Providers/ConduitProvider.cs#L108 Docs: https://docs.dcs.aitsys.dev/api/DisCatSharp.ApplicationCommands.Attributes.AutocompleteAttribute.html https://docs.dcs.aitsys.dev/api/DisCatSharp.ApplicationCommands.Attributes.IAutocompleteProvider.html https://docs.dcs.aitsys.dev/api/DisCatSharp.Entities.DiscordApplicationCommandAutocompleteChoice.html https://docs.dcs.aitsys.dev/api/DisCatSharp.ApplicationCommands.OptionAttribute.html#DisCatSharp_ApplicationCommands_OptionAttribute__ctor_System_String_System_String_System_Boolean_ diff --git a/DisCatSharp.Docs/articles/toc.yml b/DisCatSharp.Docs/articles/toc.yml index e5b8c0042..d59c77dde 100644 --- a/DisCatSharp.Docs/articles/toc.yml +++ b/DisCatSharp.Docs/articles/toc.yml @@ -1,91 +1,91 @@ - name: Preamble href: preamble.md +- name: Important Changes + items: + - name: Version 9.8.3 + href: important_changes/9_8_3.md + - name: Version 9.8.2 + href: important_changes/9_8_2.md - name: The Basics items: - name: Creating a Bot Account href: basics/bot_account.md - name: Writing Your First Bot href: basics/first_bot.md - name: Beyond Basics items: - name: Events href: beyond_basics/events.md - name: Logging href: beyond_basics/logging/default.md items: - name: The Default Logger href: beyond_basics/logging/default.md - name: Third Party Loggers href: beyond_basics/logging/third_party.md - name: Intents href: beyond_basics/intents.md - name: Sharding href: beyond_basics/sharding.md - name: Message Builder href: beyond_basics/messagebuilder.md - name: Components items: - name: Buttons href: beyond_basics/components/buttons.md - name: Select Menu href: beyond_basics/components/select_menus.md - name: Workarounds href: beyond_basics/workarounds.md - name: Application Commands items: - name: Introduction href: application_commands/intro.md - name: Options href: application_commands/options.md - name: Events href: application_commands/events.md - name: Commands items: - name: Introduction href: commands/intro.md - name: Command Attributes href: commands/command_attributes.md - name: Dependency Injection href: commands/dependency_injection.md - name: Customization items: - name: Help Formatter href: commands/help_formatter.md - name: Argument Converters href: commands/argument_converters.md - name: Command Handler href: commands/command_handler.md - name: Audio items: - name: Lavalink items: - name: Setup href: audio/lavalink/setup.md - name: Configuration href: audio/lavalink/configuration.md - name: Music Commands href: audio/lavalink/music_commands.md - name: VoiceNext items: - name: Prerequisites href: audio/voicenext/prerequisites.md - name: Transmitting href: audio/voicenext/transmit.md - name: Receiving href: audio/voicenext/receive.md - name: Interactivity href: interactivity.md -- name: Important Changes - items: - - name: Version 9.8.2 - href: important_changes/9_8_2.md - - name: Version 9.8.3 - href: important_changes/9_8_3.md - name: Hosting href: hosting.md - name: Miscellaneous items: - name: Nightly Builds href: misc/nightly_builds.md - name: Reporting Issues href: misc/reporting_issues.md