From 0aff637ecf4a868e7baa93e308ad18249f54ddf8 Mon Sep 17 00:00:00 2001 From: d4n Date: Sun, 9 Nov 2025 17:12:17 -0500 Subject: [PATCH] Add select menu `IsRequired` property and fix usage of `DefaultValues` (#3199) --- .../Builders/SelectMenuBuilder.cs | 30 +++++++++++++-- .../MessageComponents/SelectMenuComponent.cs | 8 +++- .../Interactions/Modals/ModalBuilder.cs | 38 ++++++++++++------- .../API/Common/SelectMenuComponent.cs | 4 ++ .../Extensions/MessageComponentExtension.cs | 1 + 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SelectMenuBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SelectMenuBuilder.cs index 96a49740..5adf48dc 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SelectMenuBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SelectMenuBuilder.cs @@ -121,6 +121,11 @@ public class SelectMenuBuilder : IInteractableComponentBuilder } } + /// + /// Gets or sets whether the current menu is required to answer in a modal (defaults to ). + /// + public bool IsRequired { get ; set; } = true; + /// /// Gets or sets whether the current menu is disabled. /// @@ -168,11 +173,13 @@ public class SelectMenuBuilder : IInteractableComponentBuilder CustomId = selectMenu.CustomId; MaxValues = selectMenu.MaxValues; MinValues = selectMenu.MinValues; + IsRequired = selectMenu.IsRequired; IsDisabled = selectMenu.IsDisabled; Type = selectMenu.Type; Options = selectMenu.Options? .Select(x => new SelectMenuOptionBuilder(x.Label, x.Value, x.Description, x.Emote, x.IsDefault)) .ToList(); + ChannelTypes = selectMenu.ChannelTypes?.ToList(); DefaultValues = selectMenu.DefaultValues?.ToList(); Id = selectMenu.Id; } @@ -188,12 +195,16 @@ public class SelectMenuBuilder : IInteractableComponentBuilder /// Disabled this select menu or not. /// The of this select menu. /// The types of channels this menu can select (only valid on s) - public SelectMenuBuilder(string customId, List options = null, string placeholder = null, int maxValues = 1, int minValues = 1, - bool isDisabled = false, ComponentType type = ComponentType.SelectMenu, List channelTypes = null, List defaultValues = null, int? id = null) + /// The list of default values. + /// An optional id for the component. + /// Whether the current menu is required to answer in a modal. + public SelectMenuBuilder(string customId, List options = null, string placeholder = null, int maxValues = 1, int minValues = 1, bool isDisabled = false, + ComponentType type = ComponentType.SelectMenu, List channelTypes = null, List defaultValues = null, int? id = null, bool isRequired = true) { CustomId = customId; Options = options; Placeholder = placeholder; + IsRequired = isRequired; IsDisabled = isDisabled; MaxValues = maxValues; MinValues = minValues; @@ -352,6 +363,19 @@ public class SelectMenuBuilder : IInteractableComponentBuilder return this; } + /// + /// Sets whether the current menu is required to answer in a modal. + /// + /// Whether the current menu is required to answer in a modal. + /// + /// The current builder. + /// + public SelectMenuBuilder WithRequired(bool isRequired) + { + IsRequired = isRequired; + return this; + } + /// /// Sets whether the current menu is disabled. /// @@ -414,7 +438,7 @@ public class SelectMenuBuilder : IInteractableComponentBuilder { var options = Options?.Select(x => x.Build()).ToList(); - return new SelectMenuComponent(CustomId, options, Placeholder, MinValues, MaxValues, IsDisabled, Type, Id, ChannelTypes, DefaultValues); + return new SelectMenuComponent(CustomId, options, Placeholder, MinValues, MaxValues, IsRequired, IsDisabled, Type, Id, ChannelTypes, DefaultValues); } /// diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs index daac300a..5a93142b 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs @@ -37,6 +37,11 @@ public class SelectMenuComponent : IInteractableComponent /// public int MaxValues { get; } + /// + /// Gets whether this menu is required to answer in a modal. + /// + public bool IsRequired { get;} + /// /// Gets whether this menu is disabled or not. /// @@ -58,7 +63,7 @@ public class SelectMenuComponent : IInteractableComponent public SelectMenuBuilder ToBuilder() => new(this); - internal SelectMenuComponent(string customId, List options, string placeholder, int minValues, int maxValues, + internal SelectMenuComponent(string customId, List options, string placeholder, int minValues, int maxValues, bool required, bool disabled, ComponentType type, int? id, IEnumerable channelTypes = null, IEnumerable defaultValues = null) { CustomId = customId; @@ -66,6 +71,7 @@ public class SelectMenuComponent : IInteractableComponent Placeholder = placeholder; MinValues = minValues; MaxValues = maxValues; + IsRequired = required; IsDisabled = disabled; Type = type; Id = id; diff --git a/src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs index 7afe85c3..759d2853 100644 --- a/src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs @@ -165,7 +165,7 @@ namespace Discord return this; } - /// + /// /// The current . public ModalBuilder AddSelectMenu( string label, @@ -174,9 +174,11 @@ namespace Discord string placeholder = null, int minValues = 1, int maxValues = 1, + bool required = true, bool disabled = false, ComponentType type = ComponentType.SelectMenu, ChannelType[] channelTypes = null, + SelectMenuDefaultValue[] defaultValues = null, int? id = null, string description = null, int? labelId = null @@ -189,9 +191,11 @@ namespace Discord placeholder, minValues, maxValues, + required, disabled, type, channelTypes, + defaultValues, id, description, labelId @@ -624,9 +628,11 @@ namespace Discord /// The placeholder of the . /// The min values of the . /// The max values of the . + /// Whether the is required to be answered. /// Whether the is disabled. /// The type of the . /// The channel types of the . + /// The default values of the . /// The id of the . /// The description around the . /// @@ -640,9 +646,11 @@ namespace Discord string placeholder = null, int minValues = 1, int maxValues = 1, + bool required = true, bool disabled = false, ComponentType type = ComponentType.SelectMenu, ChannelType[] channelTypes = null, + SelectMenuDefaultValue[] defaultValues = null, int? id = null, string description = null, int? labelId = null @@ -655,9 +663,11 @@ namespace Discord .WithPlaceholder(placeholder) .WithMaxValues(maxValues) .WithMinValues(minValues) + .WithRequired(required) .WithDisabled(disabled) .WithType(type) - .WithChannelTypes(channelTypes), + .WithChannelTypes(channelTypes) + .WithDefaultValues(defaultValues), description, labelId ); @@ -695,11 +705,11 @@ namespace Discord /// Constructs and adds a with the provided /// to the current . /// - /// The label around the . + /// The label around the . /// The file upload to add. - /// The description around the . + /// The description around the . /// - /// The id of the wrapping the . + /// The id of the wrapping the . /// /// The current . public ModalComponentBuilder WithFileUpload( @@ -713,15 +723,15 @@ namespace Discord /// Constructs and adds a with a /// to the current . /// - /// The label around the . + /// The label around the . /// The custom id of the . /// The min values of the . /// The max values of the . /// Whether the is required. /// The id of the . - /// The description around the . + /// The description around the . /// - /// The id of the wrapping the . + /// The id of the wrapping the . /// /// The current . public ModalComponentBuilder WithFileUpload( @@ -767,11 +777,11 @@ namespace Discord /// Constructs and adds a with the provided to /// the current . /// - /// The label around the . + /// The label around the . /// The text input to add. - /// The description around the . + /// The description around the . /// - /// The id of the wrapping the . + /// The id of the wrapping the . /// /// The current . public ModalComponentBuilder WithTextInput( @@ -823,7 +833,7 @@ namespace Discord /// Constructs and adds a with a /// to the current . /// - /// The label around the . + /// The label around the . /// The custom id of the . /// The style of the . /// The placeholder of the . @@ -833,9 +843,9 @@ namespace Discord /// Whether the is required. /// The value of the . /// The id of the . - /// The description around the . + /// The description around the . /// - /// The id of the wrapping the . + /// The id of the wrapping the . /// /// The current . public ModalComponentBuilder WithTextInput( diff --git a/src/Discord.Net.Rest/API/Common/SelectMenuComponent.cs b/src/Discord.Net.Rest/API/Common/SelectMenuComponent.cs index bfd6fb67..bf6e1065 100644 --- a/src/Discord.Net.Rest/API/Common/SelectMenuComponent.cs +++ b/src/Discord.Net.Rest/API/Common/SelectMenuComponent.cs @@ -26,6 +26,9 @@ namespace Discord.API [JsonProperty("max_values")] public int MaxValues { get; set; } + [JsonProperty("required")] + public bool Required { get; set; } + [JsonProperty("disabled")] public bool Disabled { get; set; } @@ -51,6 +54,7 @@ namespace Discord.API Placeholder = component.Placeholder; MinValues = component.MinValues; MaxValues = component.MaxValues; + Required = component.IsRequired; Disabled = component.IsDisabled; ChannelTypes = component.ChannelTypes.ToArray(); DefaultValues = component.DefaultValues.Select(x => new SelectMenuDefaultValue {Id = x.Id, Type = x.Type}).ToArray(); diff --git a/src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs b/src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs index a65533b0..1a831a81 100644 --- a/src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs +++ b/src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs @@ -102,6 +102,7 @@ internal static class MessageComponentExtension parsed.Placeholder.GetValueOrDefault(), parsed.MinValues, parsed.MaxValues, + parsed.Required, parsed.Disabled, parsed.Type, parsed.Id.ToNullable(),