diff --git a/src/Disqord.Bot/Commands/Implementation/Components/ExecutionSteps/BindValues.cs b/src/Disqord.Bot/Commands/Implementation/Components/ExecutionSteps/BindValues.cs index 456533766..87b2ece37 100644 --- a/src/Disqord.Bot/Commands/Implementation/Components/ExecutionSteps/BindValues.cs +++ b/src/Disqord.Bot/Commands/Implementation/Components/ExecutionSteps/BindValues.cs @@ -190,6 +190,20 @@ protected virtual MultiString GetRawArgumentFromModalComponent(IModalComponent m { return ToMultiString(fileUploadComponent.AttachmentIds.Select(static id => id.ToString())); } + case IModalRadioGroupComponent radioGroupComponent: + { + return radioGroupComponent.Value != null + ? new MultiString(radioGroupComponent.Value) + : default; + } + case IModalCheckboxGroupComponent checkboxGroupComponent: + { + return ToMultiString(checkboxGroupComponent.Values); + } + case IModalCheckboxComponent checkboxComponent: + { + return new MultiString(checkboxComponent.Value.ToString()); + } default: { ThrowNotImplementedException($"{nameof(BindValues)}.{nameof(GetRawArgumentFromModalComponent)}() does not support the modal component of type: {modalComponent.Type} (ID: {modalComponent.Id})."); diff --git a/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalCheckboxComponent.cs b/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalCheckboxComponent.cs new file mode 100644 index 000000000..23ab967c4 --- /dev/null +++ b/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalCheckboxComponent.cs @@ -0,0 +1,6 @@ +namespace Disqord; + +public interface IModalCheckboxComponent : IModalComponent, ICustomIdentifiableEntity +{ + bool Value { get; } +} diff --git a/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalCheckboxGroupComponent.cs b/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalCheckboxGroupComponent.cs new file mode 100644 index 000000000..5f2999618 --- /dev/null +++ b/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalCheckboxGroupComponent.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Disqord; + +public interface IModalCheckboxGroupComponent : IModalComponent, ICustomIdentifiableEntity +{ + IReadOnlyList Values { get; } +} diff --git a/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalRadioGroupComponent.cs b/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalRadioGroupComponent.cs new file mode 100644 index 000000000..8944e0b02 --- /dev/null +++ b/src/Disqord.Core/Entities/Core/Interactions/Components/Modal/IModalRadioGroupComponent.cs @@ -0,0 +1,6 @@ +namespace Disqord; + +public interface IModalRadioGroupComponent : IModalComponent, ICustomIdentifiableEntity +{ + string? Value { get; } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxComponentExtensions.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxComponentExtensions.cs new file mode 100644 index 000000000..4ba3deb8a --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxComponentExtensions.cs @@ -0,0 +1,25 @@ +namespace Disqord; + +public static class LocalCheckboxComponentExtensions +{ + public static TCheckboxComponent WithLabel(this TCheckboxComponent checkboxComponent, string label) + where TCheckboxComponent : LocalCheckboxComponent + { + checkboxComponent.Label = label; + return checkboxComponent; + } + + public static TCheckboxComponent WithIsDefault(this TCheckboxComponent checkboxComponent, bool isDefault = true) + where TCheckboxComponent : LocalCheckboxComponent + { + checkboxComponent.IsDefault = isDefault; + return checkboxComponent; + } + + public static TCheckboxComponent WithIsDisabled(this TCheckboxComponent checkboxComponent, bool isDisabled = true) + where TCheckboxComponent : LocalCheckboxComponent + { + checkboxComponent.IsDisabled = isDisabled; + return checkboxComponent; + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxGroupComponentExtensions.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxGroupComponentExtensions.cs new file mode 100644 index 000000000..d29b18b6f --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxGroupComponentExtensions.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using Qommon; + +namespace Disqord; + +public static class LocalCheckboxGroupComponentExtensions +{ + public static TCheckboxGroupComponent AddOption(this TCheckboxGroupComponent component, string label, string value, string? description = null, bool isDefault = false) + where TCheckboxGroupComponent : LocalCheckboxGroupComponent + { + var option = new LocalCheckboxGroupOption(label, value) + { + IsDefault = isDefault + }; + + if (description != null) + option.Description = description; + + return component.AddOption(option); + } + + public static TCheckboxGroupComponent AddOption(this TCheckboxGroupComponent component, LocalCheckboxGroupOption option) + where TCheckboxGroupComponent : LocalCheckboxGroupComponent + { + if (component.Options.Add(option, out var list)) + component.Options = new(list); + + return component; + } + + public static TCheckboxGroupComponent WithOptions(this TCheckboxGroupComponent component, IEnumerable options) + where TCheckboxGroupComponent : LocalCheckboxGroupComponent + { + Guard.IsNotNull(options); + + if (component.Options.With(options, out var list)) + component.Options = new(list); + + return component; + } + + public static TCheckboxGroupComponent WithOptions(this TCheckboxGroupComponent component, params LocalCheckboxGroupOption[] options) + where TCheckboxGroupComponent : LocalCheckboxGroupComponent + => component.WithOptions((IEnumerable) options); + + public static TCheckboxGroupComponent WithMinimumSelectedOptions(this TCheckboxGroupComponent checkboxGroupComponent, int minimumSelectedOptions) + where TCheckboxGroupComponent : LocalCheckboxGroupComponent + { + checkboxGroupComponent.MinimumSelectedOptions = minimumSelectedOptions; + return checkboxGroupComponent; + } + + public static TCheckboxGroupComponent WithMaximumSelectedOptions(this TCheckboxGroupComponent checkboxGroupComponent, int maximumSelectedOptions) + where TCheckboxGroupComponent : LocalCheckboxGroupComponent + { + checkboxGroupComponent.MaximumSelectedOptions = maximumSelectedOptions; + return checkboxGroupComponent; + } + + public static TCheckboxGroupComponent WithIsRequired(this TCheckboxGroupComponent checkboxGroupComponent, bool isRequired = true) + where TCheckboxGroupComponent : LocalCheckboxGroupComponent + { + checkboxGroupComponent.IsRequired = isRequired; + return checkboxGroupComponent; + } + + public static TCheckboxGroupComponent WithIsDisabled(this TCheckboxGroupComponent checkboxGroupComponent, bool isDisabled = true) + where TCheckboxGroupComponent : LocalCheckboxGroupComponent + { + checkboxGroupComponent.IsDisabled = isDisabled; + return checkboxGroupComponent; + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxGroupOptionExtensions.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxGroupOptionExtensions.cs new file mode 100644 index 000000000..0b7acae21 --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalCheckboxGroupOptionExtensions.cs @@ -0,0 +1,30 @@ +using Qommon; + +namespace Disqord; + +public static class LocalCheckboxGroupOptionExtensions +{ + public static LocalCheckboxGroupOption WithLabel(this LocalCheckboxGroupOption option, string label) + { + option.Label = label; + return option; + } + + public static LocalCheckboxGroupOption WithValue(this LocalCheckboxGroupOption option, string value) + { + option.Value = value; + return option; + } + + public static LocalCheckboxGroupOption WithDescription(this LocalCheckboxGroupOption option, string description) + { + option.Description = description; + return option; + } + + public static LocalCheckboxGroupOption WithIsDefault(this LocalCheckboxGroupOption option, bool isDefault = true) + { + option.IsDefault = isDefault; + return option; + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalRadioGroupComponentExtensions.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalRadioGroupComponentExtensions.cs new file mode 100644 index 000000000..ebd0cb4d3 --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalRadioGroupComponentExtensions.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using Qommon; + +namespace Disqord; + +public static class LocalRadioGroupComponentExtensions +{ + public static TRadioGroupComponent AddOption(this TRadioGroupComponent component, string label, string value, string? description = null, bool isDefault = false) + where TRadioGroupComponent : LocalRadioGroupComponent + { + var option = new LocalRadioGroupOption(label, value) + { + IsDefault = isDefault + }; + + if (description != null) + option.Description = description; + + return component.AddOption(option); + } + + public static TRadioGroupComponent AddOption(this TRadioGroupComponent component, LocalRadioGroupOption option) + where TRadioGroupComponent : LocalRadioGroupComponent + { + if (component.Options.Add(option, out var list)) + component.Options = new(list); + + return component; + } + + public static TRadioGroupComponent WithOptions(this TRadioGroupComponent component, IEnumerable options) + where TRadioGroupComponent : LocalRadioGroupComponent + { + Guard.IsNotNull(options); + + if (component.Options.With(options, out var list)) + component.Options = new(list); + + return component; + } + + public static TRadioGroupComponent WithOptions(this TRadioGroupComponent component, params LocalRadioGroupOption[] options) + where TRadioGroupComponent : LocalRadioGroupComponent + => component.WithOptions((IEnumerable) options); + + public static TRadioGroupComponent WithIsRequired(this TRadioGroupComponent radioGroupComponent, bool isRequired = true) + where TRadioGroupComponent : LocalRadioGroupComponent + { + radioGroupComponent.IsRequired = isRequired; + return radioGroupComponent; + } + + public static TRadioGroupComponent WithIsDisabled(this TRadioGroupComponent radioGroupComponent, bool isDisabled = true) + where TRadioGroupComponent : LocalRadioGroupComponent + { + radioGroupComponent.IsDisabled = isDisabled; + return radioGroupComponent; + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalRadioGroupOptionExtensions.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalRadioGroupOptionExtensions.cs new file mode 100644 index 000000000..c4a5e988a --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/Extensions/LocalRadioGroupOptionExtensions.cs @@ -0,0 +1,30 @@ +using Qommon; + +namespace Disqord; + +public static class LocalRadioGroupOptionExtensions +{ + public static LocalRadioGroupOption WithLabel(this LocalRadioGroupOption option, string label) + { + option.Label = label; + return option; + } + + public static LocalRadioGroupOption WithValue(this LocalRadioGroupOption option, string value) + { + option.Value = value; + return option; + } + + public static LocalRadioGroupOption WithDescription(this LocalRadioGroupOption option, string description) + { + option.Description = description; + return option; + } + + public static LocalRadioGroupOption WithIsDefault(this LocalRadioGroupOption option, bool isDefault = true) + { + option.IsDefault = isDefault; + return option; + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.Construction.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.Construction.cs index 583defad4..6842912b1 100644 --- a/src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.Construction.cs +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.Construction.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Disqord; @@ -160,4 +160,24 @@ public static LocalFileUploadComponent FileUpload(string customId) return new LocalFileUploadComponent() .WithCustomId(customId); } + + public static LocalRadioGroupComponent RadioGroup(string customId, params IEnumerable options) + { + return new LocalRadioGroupComponent() + .WithCustomId(customId) + .WithOptions(options); + } + + public static LocalCheckboxGroupComponent CheckboxGroup(string customId, params IEnumerable options) + { + return new LocalCheckboxGroupComponent() + .WithCustomId(customId) + .WithOptions(options); + } + + public static LocalCheckboxComponent Checkbox(string customId) + { + return new LocalCheckboxComponent() + .WithCustomId(customId); + } } diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.cs index bff3ec61b..c601c9ba0 100644 --- a/src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.cs +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/LocalComponent.cs @@ -1,256 +1,300 @@ -using System; -using System.Linq; -using Disqord.Models; -using Qommon; - -namespace Disqord; - -public abstract partial class LocalComponent : ILocalConstruct, IJsonConvertible -{ - /// - /// Gets or sets the ID of this component. - /// If not set, Discord will set it based on an incrementing value. - /// - public Optional Id { get; set; } - - protected LocalComponent() - { } - - protected LocalComponent(LocalComponent other) - { - Id = other.Id; - } - - /// - public abstract LocalComponent Clone(); - - /// - public virtual BaseComponentJsonModel ToModel() - { - if (!IsComponentV2()) - { - return CreateComponentJsonModel(); - } - - BaseComponentJsonModel model; - switch (this) - { - case LocalSectionComponent section: - { - model = new SectionComponentJsonModel - { - Components = Optional.ConvertOrDefault(section.Components, static components => components.Select(static component => component.ToModel()).ToArray()) ?? [], - Accessory = Optional.ConvertOrDefault(section.Accessory, static accessory => accessory.ToModel())! - }; - - break; - } - case LocalTextDisplayComponent textDisplay: - { - OptionalGuard.HasValue(textDisplay.Content); - - model = new TextDisplayComponentJsonModel - { - Content = textDisplay.Content.Value - }; - - break; - } - case LocalThumbnailComponent thumbnail: - { - OptionalGuard.HasValue(thumbnail.Media); - - model = new ThumbnailComponentJsonModel - { - Media = thumbnail.Media.Value.ToModel(), - Description = thumbnail.Description, - Spoiler = thumbnail.IsSpoiler - }; - - break; - } - case LocalMediaGalleryComponent mediaGallery: - { - model = new MediaGalleryComponentJsonModel - { - Items = Optional.ConvertOrDefault(mediaGallery.Items, static items => items.Select(static item => item.ToModel()).ToArray()) ?? [] - }; - - break; - } - case LocalFileComponent file: - { - OptionalGuard.HasValue(file.File); - - model = new FileComponentJsonModel - { - File = file.File.Value.ToModel(), - Spoiler = file.IsSpoiler - }; - - break; - } - case LocalSeparatorComponent separator: - { - model = new SeparatorComponentJsonModel - { - Divider = separator.IsDivider, - Spacing = separator.SpacingSize - }; - - break; - } - case LocalContainerComponent container: - { - model = new ContainerComponentJsonModel - { - Components = Optional.ConvertOrDefault(container.Components, static components => components.Select(static component => component.ToModel()).ToArray()) ?? [], - AccentColor = Optional.Convert(container.AccentColor, static color => color?.RawValue), - Spoiler = container.IsSpoiler - }; - - break; - } - case LocalLabelComponent label: - { - OptionalGuard.HasValue(label.Label); - OptionalGuard.HasValue(label.Component); - - model = new LabelComponentJsonModel - { - Label = label.Label.Value, - Description = label.Description, - Component = label.Component.Value.ToModel() - }; - - break; - } - case LocalFileUploadComponent fileUpload: - { - OptionalGuard.HasValue(fileUpload.CustomId); - - model = new FileUploadComponentJsonModel - { - CustomId = fileUpload.CustomId.Value, - MinValues = fileUpload.MinimumUploadedFiles, - MaxValues = fileUpload.MaximumUploadedFiles, - Required = fileUpload.IsRequired, - }; - - break; - } - default: - { - throw new InvalidOperationException("Unknown local component type."); - } - } - - model.Id = Id; - - return model; - } - - private ComponentJsonModel CreateComponentJsonModel() - { - // TODO: maybe split this via inheritance - var model = new ComponentJsonModel(); - - if (this is ILocalCustomIdentifiableEntity customIdentifiableEntity) - model.CustomId = customIdentifiableEntity.CustomId; - - if (this is LocalRowComponent rowComponent) - { - model.Type = ComponentType.Row; - model.Components = Optional.Convert(rowComponent.Components, components => components.Select(component => component.ToModel()).ToArray()); - } - else if (this is LocalButtonComponentBase buttonComponentBase) - { - model.Type = ComponentType.Button; - model.Label = buttonComponentBase.Label; - model.Emoji = Optional.Convert(buttonComponentBase.Emoji, emoji => emoji.ToModel()); - model.Disabled = buttonComponentBase.IsDisabled; - - if (buttonComponentBase is LocalButtonComponent buttonComponent) - { - model.Style = Optional.Convert(buttonComponent.Style, style => (byte) style); - } - else if (buttonComponentBase is LocalLinkButtonComponent linkButtonComponent) - { - model.Style = (byte) ButtonComponentStyle.Link; - model.Url = linkButtonComponent.Url; - } - else - { - throw new InvalidOperationException("Unknown local button component type."); - } - } - else if (this is LocalSelectionComponent selectionComponent) - { - model.Type = (ComponentType) selectionComponent.Type; - model.ChannelTypes = Optional.Convert(selectionComponent.ChannelTypes, channelTypes => channelTypes?.ToArray())!; - model.Placeholder = selectionComponent.Placeholder; - model.DefaultValues = Optional.Convert(selectionComponent.DefaultValues, defaultValues => defaultValues.Select(defaultValue => defaultValue.ToModel()).ToArray()); - model.MinValues = selectionComponent.MinimumSelectedOptions; - model.MaxValues = selectionComponent.MaximumSelectedOptions; - model.Disabled = selectionComponent.IsDisabled; - model.Options = Optional.Convert(selectionComponent.Options, options => options.Select(option => option.ToModel()).ToArray()); - model.Required = selectionComponent.IsRequired; - } - else if (this is LocalTextInputComponent textInputComponent) - { - model.Type = ComponentType.TextInput; - model.Style = Optional.Convert(textInputComponent.Style, style => (byte) style); - model.CustomId = textInputComponent.CustomId; - -#pragma warning disable CS0618 // Type or member is obsolete - model.Label = textInputComponent.Label; -#pragma warning restore CS0618 // Type or member is obsolete - - model.MinLength = textInputComponent.MinimumInputLength; - model.MaxLength = textInputComponent.MaximumInputLength; - model.Required = textInputComponent.IsRequired; - model.Value = textInputComponent.PrefilledValue; - model.Placeholder = textInputComponent.Placeholder; - } - else - { - throw new InvalidOperationException("Unknown local component type."); - } - - return model; - } - - /// - /// Converts the specified component to a . - /// - /// The component to convert. - /// - /// The output . - /// - public static LocalComponent CreateFrom(IComponent component) - { - return component switch - { - IRowComponent rowComponent => LocalRowComponent.CreateFrom(rowComponent), - IButtonComponent buttonComponent => LocalButtonComponentBase.CreateFrom(buttonComponent), - ISelectionComponent selectionComponent => LocalSelectionComponent.CreateFrom(selectionComponent), - ITextInputComponent textInputComponent => LocalTextInputComponent.CreateFrom(textInputComponent), - ISectionComponent sectionComponent => LocalSectionComponent.CreateFrom(sectionComponent), - ITextDisplayComponent textDisplayComponent => LocalTextDisplayComponent.CreateFrom(textDisplayComponent), - IThumbnailComponent thumbnailComponent => LocalThumbnailComponent.CreateFrom(thumbnailComponent), - IMediaGalleryComponent mediaGalleryComponent => LocalMediaGalleryComponent.CreateFrom(mediaGalleryComponent), - IFileComponent => Throw.ArgumentException( - "Cannot convert file components to local file components as they do not support arbitrary external urls." - + "You must use the `attachment://` reference system instead."), - ISeparatorComponent separatorComponent => LocalSeparatorComponent.CreateFrom(separatorComponent), - IContainerComponent containerComponent => LocalContainerComponent.CreateFrom(containerComponent), - ILabelComponent labelComponent => LocalLabelComponent.CreateFrom(labelComponent), - _ => Throw.ArgumentException("Unsupported component type.", nameof(component)) - }; - } - - internal bool IsComponentV2() - { - return this is not (LocalRowComponent or LocalButtonComponentBase or LocalSelectionComponent or LocalTextInputComponent); - } -} +using System; +using System.Linq; +using Disqord.Models; +using Qommon; + +namespace Disqord; + +public abstract partial class LocalComponent : ILocalConstruct, IJsonConvertible +{ + /// + /// Gets or sets the ID of this component. + /// If not set, Discord will set it based on an incrementing value. + /// + public Optional Id { get; set; } + + protected LocalComponent() + { } + + protected LocalComponent(LocalComponent other) + { + Id = other.Id; + } + + /// + public abstract LocalComponent Clone(); + + /// + public virtual BaseComponentJsonModel ToModel() + { + if (!IsComponentV2()) + { + return CreateComponentJsonModel(); + } + + BaseComponentJsonModel model; + switch (this) + { + case LocalSectionComponent section: + { + model = new SectionComponentJsonModel + { + Components = Optional.ConvertOrDefault(section.Components, static components => components.Select(static component => component.ToModel()).ToArray()) ?? [], + Accessory = Optional.ConvertOrDefault(section.Accessory, static accessory => accessory.ToModel())! + }; + + break; + } + case LocalTextDisplayComponent textDisplay: + { + OptionalGuard.HasValue(textDisplay.Content); + + model = new TextDisplayComponentJsonModel + { + Content = textDisplay.Content.Value + }; + + break; + } + case LocalThumbnailComponent thumbnail: + { + OptionalGuard.HasValue(thumbnail.Media); + + model = new ThumbnailComponentJsonModel + { + Media = thumbnail.Media.Value.ToModel(), + Description = thumbnail.Description, + Spoiler = thumbnail.IsSpoiler + }; + + break; + } + case LocalMediaGalleryComponent mediaGallery: + { + model = new MediaGalleryComponentJsonModel + { + Items = Optional.ConvertOrDefault(mediaGallery.Items, static items => items.Select(static item => item.ToModel()).ToArray()) ?? [] + }; + + break; + } + case LocalFileComponent file: + { + OptionalGuard.HasValue(file.File); + + model = new FileComponentJsonModel + { + File = file.File.Value.ToModel(), + Spoiler = file.IsSpoiler + }; + + break; + } + case LocalSeparatorComponent separator: + { + model = new SeparatorComponentJsonModel + { + Divider = separator.IsDivider, + Spacing = separator.SpacingSize + }; + + break; + } + case LocalContainerComponent container: + { + model = new ContainerComponentJsonModel + { + Components = Optional.ConvertOrDefault(container.Components, static components => components.Select(static component => component.ToModel()).ToArray()) ?? [], + AccentColor = Optional.Convert(container.AccentColor, static color => color?.RawValue), + Spoiler = container.IsSpoiler + }; + + break; + } + case LocalLabelComponent label: + { + OptionalGuard.HasValue(label.Label); + OptionalGuard.HasValue(label.Component); + + model = new LabelComponentJsonModel + { + Label = label.Label.Value, + Description = label.Description, + Component = label.Component.Value.ToModel() + }; + + break; + } + case LocalFileUploadComponent fileUpload: + { + OptionalGuard.HasValue(fileUpload.CustomId); + + model = new FileUploadComponentJsonModel + { + CustomId = fileUpload.CustomId.Value, + MinValues = fileUpload.MinimumUploadedFiles, + MaxValues = fileUpload.MaximumUploadedFiles, + Required = fileUpload.IsRequired, + }; + + break; + } + case LocalRadioGroupComponent radioGroup: + { + OptionalGuard.HasValue(radioGroup.CustomId); + + model = new RadioGroupComponentJsonModel + { + CustomId = radioGroup.CustomId.Value, + Options = Optional.Convert(radioGroup.Options, static options => options.Select(static option => option.ToModel()).ToArray()), + Required = radioGroup.IsRequired, + Disabled = radioGroup.IsDisabled + }; + + break; + } + case LocalCheckboxGroupComponent checkboxGroup: + { + OptionalGuard.HasValue(checkboxGroup.CustomId); + + model = new CheckboxGroupComponentJsonModel + { + CustomId = checkboxGroup.CustomId.Value, + Options = Optional.Convert(checkboxGroup.Options, static options => options.Select(static option => option.ToModel()).ToArray()), + MinValues = checkboxGroup.MinimumSelectedOptions, + MaxValues = checkboxGroup.MaximumSelectedOptions, + Required = checkboxGroup.IsRequired, + Disabled = checkboxGroup.IsDisabled + }; + + break; + } + case LocalCheckboxComponent checkbox: + { + OptionalGuard.HasValue(checkbox.CustomId); + + model = new CheckboxComponentJsonModel + { + CustomId = checkbox.CustomId.Value, + Default = checkbox.IsDefault, + Label = checkbox.Label, + Disabled = checkbox.IsDisabled + }; + + break; + } + default: + { + throw new InvalidOperationException("Unknown local component type."); + } + } + + model.Id = Id; + + return model; + } + + private ComponentJsonModel CreateComponentJsonModel() + { + // TODO: maybe split this via inheritance + var model = new ComponentJsonModel(); + + if (this is ILocalCustomIdentifiableEntity customIdentifiableEntity) + model.CustomId = customIdentifiableEntity.CustomId; + + if (this is LocalRowComponent rowComponent) + { + model.Type = ComponentType.Row; + model.Components = Optional.Convert(rowComponent.Components, components => components.Select(component => component.ToModel()).ToArray()); + } + else if (this is LocalButtonComponentBase buttonComponentBase) + { + model.Type = ComponentType.Button; + model.Label = buttonComponentBase.Label; + model.Emoji = Optional.Convert(buttonComponentBase.Emoji, emoji => emoji.ToModel()); + model.Disabled = buttonComponentBase.IsDisabled; + + if (buttonComponentBase is LocalButtonComponent buttonComponent) + { + model.Style = Optional.Convert(buttonComponent.Style, style => (byte) style); + } + else if (buttonComponentBase is LocalLinkButtonComponent linkButtonComponent) + { + model.Style = (byte) ButtonComponentStyle.Link; + model.Url = linkButtonComponent.Url; + } + else + { + throw new InvalidOperationException("Unknown local button component type."); + } + } + else if (this is LocalSelectionComponent selectionComponent) + { + model.Type = (ComponentType) selectionComponent.Type; + model.ChannelTypes = Optional.Convert(selectionComponent.ChannelTypes, channelTypes => channelTypes?.ToArray())!; + model.Placeholder = selectionComponent.Placeholder; + model.DefaultValues = Optional.Convert(selectionComponent.DefaultValues, defaultValues => defaultValues.Select(defaultValue => defaultValue.ToModel()).ToArray()); + model.MinValues = selectionComponent.MinimumSelectedOptions; + model.MaxValues = selectionComponent.MaximumSelectedOptions; + model.Disabled = selectionComponent.IsDisabled; + model.Options = Optional.Convert(selectionComponent.Options, options => options.Select(option => option.ToModel()).ToArray()); + model.Required = selectionComponent.IsRequired; + } + else if (this is LocalTextInputComponent textInputComponent) + { + model.Type = ComponentType.TextInput; + model.Style = Optional.Convert(textInputComponent.Style, style => (byte) style); + model.CustomId = textInputComponent.CustomId; + +#pragma warning disable CS0618 // Type or member is obsolete + model.Label = textInputComponent.Label; +#pragma warning restore CS0618 // Type or member is obsolete + + model.MinLength = textInputComponent.MinimumInputLength; + model.MaxLength = textInputComponent.MaximumInputLength; + model.Required = textInputComponent.IsRequired; + model.Value = textInputComponent.PrefilledValue; + model.Placeholder = textInputComponent.Placeholder; + } + else + { + throw new InvalidOperationException("Unknown local component type."); + } + + return model; + } + + /// + /// Converts the specified component to a . + /// + /// The component to convert. + /// + /// The output . + /// + public static LocalComponent CreateFrom(IComponent component) + { + return component switch + { + IRowComponent rowComponent => LocalRowComponent.CreateFrom(rowComponent), + IButtonComponent buttonComponent => LocalButtonComponentBase.CreateFrom(buttonComponent), + ISelectionComponent selectionComponent => LocalSelectionComponent.CreateFrom(selectionComponent), + ITextInputComponent textInputComponent => LocalTextInputComponent.CreateFrom(textInputComponent), + ISectionComponent sectionComponent => LocalSectionComponent.CreateFrom(sectionComponent), + ITextDisplayComponent textDisplayComponent => LocalTextDisplayComponent.CreateFrom(textDisplayComponent), + IThumbnailComponent thumbnailComponent => LocalThumbnailComponent.CreateFrom(thumbnailComponent), + IMediaGalleryComponent mediaGalleryComponent => LocalMediaGalleryComponent.CreateFrom(mediaGalleryComponent), + IFileComponent => Throw.ArgumentException( + "Cannot convert file components to local file components as they do not support arbitrary external urls." + + "You must use the `attachment://` reference system instead."), + ISeparatorComponent separatorComponent => LocalSeparatorComponent.CreateFrom(separatorComponent), + IContainerComponent containerComponent => LocalContainerComponent.CreateFrom(containerComponent), + ILabelComponent labelComponent => LocalLabelComponent.CreateFrom(labelComponent), + _ => Throw.ArgumentException("Unsupported component type.", nameof(component)) + }; + } + + internal bool IsComponentV2() + { + return this is not (LocalRowComponent or LocalButtonComponentBase or LocalSelectionComponent or LocalTextInputComponent); + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxComponent.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxComponent.cs new file mode 100644 index 000000000..4bc14bf7c --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxComponent.cs @@ -0,0 +1,31 @@ +using Disqord.Models; +using Qommon; + +namespace Disqord; + +public class LocalCheckboxComponent : LocalComponent, ILocalCustomIdentifiableEntity, ILocalConstruct +{ + public Optional CustomId { get; set; } + + public Optional IsDefault { get; set; } + + public new Optional Label { get; set; } + + public Optional IsDisabled { get; set; } + + public LocalCheckboxComponent() + { } + + protected LocalCheckboxComponent(LocalCheckboxComponent other) : base(other) + { + CustomId = other.CustomId; + IsDefault = other.IsDefault; + Label = other.Label; + IsDisabled = other.IsDisabled; + } + + public override LocalCheckboxComponent Clone() + { + return new(this); + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxGroupComponent.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxGroupComponent.cs new file mode 100644 index 000000000..15a5fadf7 --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxGroupComponent.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using Disqord.Models; +using Qommon; + +namespace Disqord; + +public class LocalCheckboxGroupComponent : LocalComponent, ILocalCustomIdentifiableEntity, ILocalConstruct +{ + public Optional CustomId { get; set; } + + public Optional> Options { get; set; } + + public Optional MinimumSelectedOptions { get; set; } + + public Optional MaximumSelectedOptions { get; set; } + + public Optional IsRequired { get; set; } + + public Optional IsDisabled { get; set; } + + public LocalCheckboxGroupComponent() + { } + + protected LocalCheckboxGroupComponent(LocalCheckboxGroupComponent other) : base(other) + { + CustomId = other.CustomId; + Options = other.Options.DeepClone(); + MinimumSelectedOptions = other.MinimumSelectedOptions; + MaximumSelectedOptions = other.MaximumSelectedOptions; + IsRequired = other.IsRequired; + IsDisabled = other.IsDisabled; + } + + public override LocalCheckboxGroupComponent Clone() + { + return new(this); + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxGroupOption.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxGroupOption.cs new file mode 100644 index 000000000..08953ec4b --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalCheckboxGroupOption.cs @@ -0,0 +1,51 @@ +using Disqord.Models; +using Qommon; + +namespace Disqord; + +public class LocalCheckboxGroupOption : ILocalConstruct, IJsonConvertible +{ + public Optional Label { get; set; } + + public Optional Value { get; set; } + + public Optional Description { get; set; } + + public Optional IsDefault { get; set; } + + public LocalCheckboxGroupOption(string label, string value) + { + Label = label; + Value = value; + } + + public LocalCheckboxGroupOption() + { } + + protected LocalCheckboxGroupOption(LocalCheckboxGroupOption other) + { + Label = other.Label; + Value = other.Value; + Description = other.Description; + IsDefault = other.IsDefault; + } + + public LocalCheckboxGroupOption Clone() + { + return new(this); + } + + public CheckboxGroupOptionJsonModel ToModel() + { + OptionalGuard.HasValue(Label); + OptionalGuard.HasValue(Value); + + return new CheckboxGroupOptionJsonModel + { + Label = Label.Value, + Value = Value.Value, + Description = Description, + Default = IsDefault + }; + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalRadioGroupComponent.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalRadioGroupComponent.cs new file mode 100644 index 000000000..a97ab7924 --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalRadioGroupComponent.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using Disqord.Models; +using Qommon; + +namespace Disqord; + +public class LocalRadioGroupComponent : LocalComponent, ILocalCustomIdentifiableEntity, ILocalConstruct +{ + public Optional CustomId { get; set; } + + public Optional> Options { get; set; } + + public Optional IsRequired { get; set; } + + public Optional IsDisabled { get; set; } + + public LocalRadioGroupComponent() + { } + + protected LocalRadioGroupComponent(LocalRadioGroupComponent other) : base(other) + { + CustomId = other.CustomId; + Options = other.Options.DeepClone(); + IsRequired = other.IsRequired; + IsDisabled = other.IsDisabled; + } + + public override LocalRadioGroupComponent Clone() + { + return new(this); + } +} diff --git a/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalRadioGroupOption.cs b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalRadioGroupOption.cs new file mode 100644 index 000000000..31d5eccd5 --- /dev/null +++ b/src/Disqord.Core/Entities/Local/Interaction/Components/V2/LocalRadioGroupOption.cs @@ -0,0 +1,51 @@ +using Disqord.Models; +using Qommon; + +namespace Disqord; + +public class LocalRadioGroupOption : ILocalConstruct, IJsonConvertible +{ + public Optional Label { get; set; } + + public Optional Value { get; set; } + + public Optional Description { get; set; } + + public Optional IsDefault { get; set; } + + public LocalRadioGroupOption(string label, string value) + { + Label = label; + Value = value; + } + + public LocalRadioGroupOption() + { } + + protected LocalRadioGroupOption(LocalRadioGroupOption other) + { + Label = other.Label; + Value = other.Value; + Description = other.Description; + IsDefault = other.IsDefault; + } + + public LocalRadioGroupOption Clone() + { + return new(this); + } + + public RadioGroupOptionJsonModel ToModel() + { + OptionalGuard.HasValue(Label); + OptionalGuard.HasValue(Value); + + return new RadioGroupOptionJsonModel + { + Label = Label.Value, + Value = Value.Value, + Description = Description, + Default = IsDefault + }; + } +} diff --git a/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalCheckboxComponent.cs b/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalCheckboxComponent.cs new file mode 100644 index 000000000..48128075c --- /dev/null +++ b/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalCheckboxComponent.cs @@ -0,0 +1,13 @@ +using Disqord.Models; + +namespace Disqord; + +public class TransientModalCheckboxComponent : TransientModalComponent, IModalCheckboxComponent +{ + public string CustomId => Model.CustomId; + + public bool Value => Model.Value; + + public TransientModalCheckboxComponent(ModalCheckboxComponentJsonModel model) : base(model) + { } +} diff --git a/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalCheckboxGroupComponent.cs b/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalCheckboxGroupComponent.cs new file mode 100644 index 000000000..691a03183 --- /dev/null +++ b/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalCheckboxGroupComponent.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using Disqord.Models; + +namespace Disqord; + +public class TransientModalCheckboxGroupComponent : TransientModalComponent, IModalCheckboxGroupComponent +{ + public string CustomId => Model.CustomId; + + public IReadOnlyList Values => Model.Values; + + public TransientModalCheckboxGroupComponent(ModalCheckboxGroupComponentJsonModel model) : base(model) + { } +} diff --git a/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalComponent.cs b/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalComponent.cs index 80add4fe7..90b888276 100644 --- a/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalComponent.cs +++ b/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalComponent.cs @@ -15,6 +15,9 @@ public static IModalComponent Create(ModalBaseComponentJsonModel model) ComponentType.TextDisplay => new TransientModalTextDisplayComponent(Guard.IsOfType(model)), ComponentType.Label => new TransientModalLabelComponent(Guard.IsOfType(model)), ComponentType.FileUpload => new TransientModalFileUploadComponent(Guard.IsOfType(model)), + ComponentType.RadioGroup => new TransientModalRadioGroupComponent(Guard.IsOfType(model)), + ComponentType.CheckboxGroup => new TransientModalCheckboxGroupComponent(Guard.IsOfType(model)), + ComponentType.Checkbox => new TransientModalCheckboxComponent(Guard.IsOfType(model)), _ => new TransientModalComponent(model) }; } diff --git a/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalRadioGroupComponent.cs b/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalRadioGroupComponent.cs new file mode 100644 index 000000000..c7a82105a --- /dev/null +++ b/src/Disqord.Core/Entities/Transient/Interactions/Components/Modal/TransientModalRadioGroupComponent.cs @@ -0,0 +1,13 @@ +using Disqord.Models; + +namespace Disqord; + +public class TransientModalRadioGroupComponent : TransientModalComponent, IModalRadioGroupComponent +{ + public string CustomId => Model.CustomId; + + public string? Value => Model.Value.HasValue ? Model.Value.Value : null; + + public TransientModalRadioGroupComponent(ModalRadioGroupComponentJsonModel model) : base(model) + { } +} diff --git a/src/Disqord.Core/Enums/Interactions/Components/ComponentType.cs b/src/Disqord.Core/Enums/Interactions/Components/ComponentType.cs index f8d8e09b4..0a82ee994 100644 --- a/src/Disqord.Core/Enums/Interactions/Components/ComponentType.cs +++ b/src/Disqord.Core/Enums/Interactions/Components/ComponentType.cs @@ -1,39 +1,45 @@ -namespace Disqord; - -public enum ComponentType : byte -{ - Row = 1, - - Button = 2, - - StringSelection = 3, - - TextInput = 4, - - UserSelection = 5, - - RoleSelection = 6, - - MentionableSelection = 7, - - ChannelSelection = 8, - - // Components V2 - Section = 9, - - TextDisplay = 10, - - Thumbnail = 11, - - MediaGallery = 12, - - File = 13, - - Separator = 14, - - Container = 17, - - Label = 18, - - FileUpload = 19, -} +namespace Disqord; + +public enum ComponentType : byte +{ + Row = 1, + + Button = 2, + + StringSelection = 3, + + TextInput = 4, + + UserSelection = 5, + + RoleSelection = 6, + + MentionableSelection = 7, + + ChannelSelection = 8, + + // Components V2 + Section = 9, + + TextDisplay = 10, + + Thumbnail = 11, + + MediaGallery = 12, + + File = 13, + + Separator = 14, + + Container = 17, + + Label = 18, + + FileUpload = 19, + + RadioGroup = 21, + + CheckboxGroup = 22, + + Checkbox = 23, +} diff --git a/src/Disqord.Core/Models/Interactions/Components/Modal/ModalCheckboxComponentJsonModel.cs b/src/Disqord.Core/Models/Interactions/Components/Modal/ModalCheckboxComponentJsonModel.cs new file mode 100644 index 000000000..0dcdbaa6f --- /dev/null +++ b/src/Disqord.Core/Models/Interactions/Components/Modal/ModalCheckboxComponentJsonModel.cs @@ -0,0 +1,17 @@ +using Disqord.Serialization.Json; + +namespace Disqord.Models; + +public class ModalCheckboxComponentJsonModel : ModalBaseComponentJsonModel +{ + [JsonProperty("custom_id")] + public string CustomId = null!; + + [JsonProperty("value")] + public bool Value; + + public ModalCheckboxComponentJsonModel() + { + Type = ComponentType.Checkbox; + } +} diff --git a/src/Disqord.Core/Models/Interactions/Components/Modal/ModalCheckboxGroupComponentJsonModel.cs b/src/Disqord.Core/Models/Interactions/Components/Modal/ModalCheckboxGroupComponentJsonModel.cs new file mode 100644 index 000000000..79feffe19 --- /dev/null +++ b/src/Disqord.Core/Models/Interactions/Components/Modal/ModalCheckboxGroupComponentJsonModel.cs @@ -0,0 +1,17 @@ +using Disqord.Serialization.Json; + +namespace Disqord.Models; + +public class ModalCheckboxGroupComponentJsonModel : ModalBaseComponentJsonModel +{ + [JsonProperty("custom_id")] + public string CustomId = null!; + + [JsonProperty("values")] + public string[] Values = null!; + + public ModalCheckboxGroupComponentJsonModel() + { + Type = ComponentType.CheckboxGroup; + } +} diff --git a/src/Disqord.Core/Models/Interactions/Components/Modal/ModalRadioGroupComponentJsonModel.cs b/src/Disqord.Core/Models/Interactions/Components/Modal/ModalRadioGroupComponentJsonModel.cs new file mode 100644 index 000000000..8a241e05f --- /dev/null +++ b/src/Disqord.Core/Models/Interactions/Components/Modal/ModalRadioGroupComponentJsonModel.cs @@ -0,0 +1,18 @@ +using Disqord.Serialization.Json; +using Qommon; + +namespace Disqord.Models; + +public class ModalRadioGroupComponentJsonModel : ModalBaseComponentJsonModel +{ + [JsonProperty("custom_id")] + public string CustomId = null!; + + [JsonProperty("value")] + public Optional Value; + + public ModalRadioGroupComponentJsonModel() + { + Type = ComponentType.RadioGroup; + } +} diff --git a/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxComponentJsonModel.cs b/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxComponentJsonModel.cs new file mode 100644 index 000000000..43e66c654 --- /dev/null +++ b/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxComponentJsonModel.cs @@ -0,0 +1,24 @@ +using Disqord.Serialization.Json; +using Qommon; + +namespace Disqord.Models; + +public class CheckboxComponentJsonModel : BaseComponentJsonModel +{ + [JsonProperty("custom_id")] + public string CustomId = null!; + + [JsonProperty("default")] + public Optional Default; + + [JsonProperty("label")] + public Optional Label; + + [JsonProperty("disabled")] + public Optional Disabled; + + public CheckboxComponentJsonModel() + { + Type = ComponentType.Checkbox; + } +} diff --git a/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxGroupComponentJsonModel.cs b/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxGroupComponentJsonModel.cs new file mode 100644 index 000000000..e508732d3 --- /dev/null +++ b/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxGroupComponentJsonModel.cs @@ -0,0 +1,30 @@ +using Disqord.Serialization.Json; +using Qommon; + +namespace Disqord.Models; + +public class CheckboxGroupComponentJsonModel : BaseComponentJsonModel +{ + [JsonProperty("custom_id")] + public string CustomId = null!; + + [JsonProperty("options")] + public Optional Options; + + [JsonProperty("min_values")] + public Optional MinValues; + + [JsonProperty("max_values")] + public Optional MaxValues; + + [JsonProperty("required")] + public Optional Required; + + [JsonProperty("disabled")] + public Optional Disabled; + + public CheckboxGroupComponentJsonModel() + { + Type = ComponentType.CheckboxGroup; + } +} diff --git a/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxGroupOptionJsonModel.cs b/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxGroupOptionJsonModel.cs new file mode 100644 index 000000000..e4eb1c56c --- /dev/null +++ b/src/Disqord.Core/Models/Interactions/Components/V2/CheckboxGroupOptionJsonModel.cs @@ -0,0 +1,19 @@ +using Disqord.Serialization.Json; +using Qommon; + +namespace Disqord.Models; + +public class CheckboxGroupOptionJsonModel : JsonModel +{ + [JsonProperty("label")] + public string Label = null!; + + [JsonProperty("value")] + public string Value = null!; + + [JsonProperty("description")] + public Optional Description; + + [JsonProperty("default")] + public Optional Default; +} diff --git a/src/Disqord.Core/Models/Interactions/Components/V2/RadioGroupComponentJsonModel.cs b/src/Disqord.Core/Models/Interactions/Components/V2/RadioGroupComponentJsonModel.cs new file mode 100644 index 000000000..585ec1bb5 --- /dev/null +++ b/src/Disqord.Core/Models/Interactions/Components/V2/RadioGroupComponentJsonModel.cs @@ -0,0 +1,24 @@ +using Disqord.Serialization.Json; +using Qommon; + +namespace Disqord.Models; + +public class RadioGroupComponentJsonModel : BaseComponentJsonModel +{ + [JsonProperty("custom_id")] + public string CustomId = null!; + + [JsonProperty("options")] + public Optional Options; + + [JsonProperty("required")] + public Optional Required; + + [JsonProperty("disabled")] + public Optional Disabled; + + public RadioGroupComponentJsonModel() + { + Type = ComponentType.RadioGroup; + } +} diff --git a/src/Disqord.Core/Models/Interactions/Components/V2/RadioGroupOptionJsonModel.cs b/src/Disqord.Core/Models/Interactions/Components/V2/RadioGroupOptionJsonModel.cs new file mode 100644 index 000000000..9e8e92290 --- /dev/null +++ b/src/Disqord.Core/Models/Interactions/Components/V2/RadioGroupOptionJsonModel.cs @@ -0,0 +1,19 @@ +using Disqord.Serialization.Json; +using Qommon; + +namespace Disqord.Models; + +public class RadioGroupOptionJsonModel : JsonModel +{ + [JsonProperty("label")] + public string Label = null!; + + [JsonProperty("value")] + public string Value = null!; + + [JsonProperty("description")] + public Optional Description; + + [JsonProperty("default")] + public Optional Default; +} diff --git a/src/Disqord.Core/Serialization/Json/Default/Entities/Converters/ModalComponentConverter.cs b/src/Disqord.Core/Serialization/Json/Default/Entities/Converters/ModalComponentConverter.cs index 9cde6cbc0..2f52d5efe 100644 --- a/src/Disqord.Core/Serialization/Json/Default/Entities/Converters/ModalComponentConverter.cs +++ b/src/Disqord.Core/Serialization/Json/Default/Entities/Converters/ModalComponentConverter.cs @@ -39,6 +39,9 @@ private static ModalBaseComponentJsonModel CreateComponentJsonModel(ComponentTyp ComponentType.TextDisplay => new ModalTextDisplayComponentJsonModel(), ComponentType.Label => new ModalLabelComponentJsonModel(), ComponentType.FileUpload => new ModalFileUploadComponentJsonModel(), + ComponentType.RadioGroup => new ModalRadioGroupComponentJsonModel(), + ComponentType.CheckboxGroup => new ModalCheckboxGroupComponentJsonModel(), + ComponentType.Checkbox => new ModalCheckboxComponentJsonModel(), _ => new ModalBaseComponentJsonModel() }; }