diff --git a/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs index 0bbc335f..39b3ea03 100644 --- a/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs +++ b/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs @@ -132,7 +132,7 @@ namespace Discord /// A task that represents an asynchronous send operation for delivering the message. /// Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, - MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Responds to this interaction with a file attachment. @@ -154,8 +154,7 @@ namespace Discord /// #if NETCOREAPP3_0_OR_GREATER async Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(fileStream, fileName)) { @@ -164,8 +163,7 @@ namespace Discord } #else Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null - , MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Responds to this interaction with a file attachment. @@ -187,8 +185,7 @@ namespace Discord /// #if NETCOREAPP3_0_OR_GREATER async Task RespondWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(filePath, fileName)) { @@ -197,8 +194,7 @@ namespace Discord } #else Task RespondWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Responds to this interaction with a file attachment. @@ -219,13 +215,11 @@ namespace Discord /// #if NETCOREAPP3_0_OR_GREATER Task RespondWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None) - => RespondWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => RespondWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); #else Task RespondWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Responds to this interaction with a collection of file attachments. @@ -245,9 +239,7 @@ namespace Discord /// contains the sent message. /// Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None); - + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. /// @@ -265,9 +257,7 @@ namespace Discord /// contains the sent message. /// Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None); - + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. /// @@ -288,19 +278,17 @@ namespace Discord /// #if NETCOREAPP3_0_OR_GREATER async Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(fileStream, fileName)) { - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } #else Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif - /// /// Sends a followup message for this interaction. /// @@ -321,17 +309,16 @@ namespace Discord /// #if NETCOREAPP3_0_OR_GREATER async Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(filePath, fileName)) { - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } #else Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Sends a followup message for this interaction. @@ -352,11 +339,11 @@ namespace Discord /// #if NETCOREAPP3_0_OR_GREATER Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); #else Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Sends a followup message for this interaction. @@ -376,7 +363,7 @@ namespace Discord /// contains the sent message. /// Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Gets the original response for this interaction. /// diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ActionRowComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ActionRowComponent.cs index 855b61ee..202a5687 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ActionRowComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ActionRowComponent.cs @@ -1,27 +1,27 @@ using System.Collections.Generic; -namespace Discord; - -/// -/// Represents a Row for child components to live in. -/// -public class ActionRowComponent : IMessageComponent +namespace Discord { - /// - public ComponentType Type => ComponentType.ActionRow; - - /// - public int? Id { get; internal set; } - /// - /// Gets the child components in this row. + /// Represents a Row for child components to live in. /// - public IReadOnlyCollection Components { get; internal set; } - - internal ActionRowComponent() { } - - internal ActionRowComponent(IReadOnlyCollection components) + public class ActionRowComponent : IMessageComponent { - Components = components; + /// + public ComponentType Type => ComponentType.ActionRow; + + /// + /// Gets the child components in this row. + /// + public IReadOnlyCollection Components { get; internal set; } + + internal ActionRowComponent() { } + + internal ActionRowComponent(List components) + { + Components = components; + } + + string IMessageComponent.CustomId => null; } } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ActionRowBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ActionRowBuilder.cs index 66fb6546..dbbe4e99 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ActionRowBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ActionRowBuilder.cs @@ -8,12 +8,8 @@ namespace Discord; /// /// Represents a class used to build Action rows. /// -public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponentContainer +public class ActionRowBuilder { - public ComponentType Type => ComponentType.ActionRow; - - public int? Id { get; set; } - /// /// The max amount of child components this row can hold. /// @@ -24,7 +20,7 @@ public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponent /// /// cannot be null. /// count exceeds . - public List Components + public List Components { get => _components; set @@ -41,21 +37,7 @@ public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponent } } - - public ActionRowBuilder AddComponents(params IMessageComponentBuilder[] components) - { - foreach (var component in components) - AddComponent(component); - return this; - } - - public ActionRowBuilder WithComponents(IEnumerable components) - { - Components = components.ToList(); - return this; - } - - private List _components = new (); + private List _components = new List(); /// /// Adds a list of components to the current row. @@ -63,7 +45,7 @@ public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponent /// The list of components to add. /// /// The current builder. - public ActionRowBuilder WithComponents(List components) + public ActionRowBuilder WithComponents(List components) { Components = components; return this; @@ -75,7 +57,7 @@ public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponent /// The component to add. /// Components count reached /// The current builder. - public ActionRowBuilder AddComponent(IMessageComponentBuilder component) + public ActionRowBuilder AddComponent(IMessageComponent component) { if (Components.Count >= MaxChildCount) throw new InvalidOperationException($"Components count reached {MaxChildCount}"); @@ -121,11 +103,13 @@ public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponent { if (menu.Options is not null && menu.Options.Distinct().Count() != menu.Options.Count) throw new InvalidOperationException("Please make sure that there is no duplicates values."); - + + var builtMenu = menu.Build(); + if (Components.Count != 0) throw new InvalidOperationException($"A Select Menu cannot exist in a pre-occupied ActionRow."); - AddComponent(menu); + AddComponent(builtMenu); return this; } @@ -168,13 +152,15 @@ public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponent /// The current builder. public ActionRowBuilder WithButton(ButtonBuilder button) { + var builtButton = button.Build(); + if (Components.Count >= 5) throw new InvalidOperationException($"Components count reached {MaxChildCount}"); if (Components.Any(x => x.Type.IsSelectType())) throw new InvalidOperationException($"A button cannot be added to a row with a SelectMenu"); - AddComponent(button); + AddComponent(builtButton); return this; } @@ -185,11 +171,10 @@ public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponent /// A that can be used within a public ActionRowComponent Build() { - return new ActionRowComponent(_components.Select(x => x.Build()).ToList()); + return new ActionRowComponent(_components); } - IMessageComponent IMessageComponentBuilder.Build() => Build(); - internal bool CanTakeComponent(IMessageComponentBuilder component) + internal bool CanTakeComponent(IMessageComponent component) { switch (component.Type) { @@ -210,11 +195,4 @@ public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponent return false; } } - - - IComponentContainer IComponentContainer.AddComponent(IMessageComponentBuilder component) => AddComponent(component); - - IComponentContainer IComponentContainer.AddComponents(params IMessageComponentBuilder[] components) => AddComponents(components); - - IComponentContainer IComponentContainer.WithComponents(IEnumerable components) => WithComponents(components); } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ButtonBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ButtonBuilder.cs index b777e8a0..f72a3a5b 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ButtonBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ButtonBuilder.cs @@ -7,10 +7,8 @@ namespace Discord; /// /// Represents a class used to build 's. /// -public class ButtonBuilder : IInteractableComponentBuilder +public class ButtonBuilder { - public ComponentType Type => ComponentType.Button; - /// /// The max length of a . /// @@ -76,8 +74,6 @@ public class ButtonBuilder : IInteractableComponentBuilder /// public ulong? SkuId { get; set; } - public int? Id { get; set; } - private string _label; private string _customId; @@ -96,7 +92,7 @@ public class ButtonBuilder : IInteractableComponentBuilder /// The emote of this button. /// Disabled this button or not. /// The sku id of this button. - public ButtonBuilder(string label = null, string customId = null, ButtonStyle style = ButtonStyle.Primary, string url = null, IEmote emote = null, bool isDisabled = false, ulong? skuId = null, int? id = null) + public ButtonBuilder(string label = null, string customId = null, ButtonStyle style = ButtonStyle.Primary, string url = null, IEmote emote = null, bool isDisabled = false, ulong? skuId = null) { CustomId = customId; Style = style; @@ -105,7 +101,6 @@ public class ButtonBuilder : IInteractableComponentBuilder IsDisabled = isDisabled; Emote = emote; SkuId = skuId; - Id = id; } /// @@ -120,7 +115,6 @@ public class ButtonBuilder : IInteractableComponentBuilder IsDisabled = button.IsDisabled; Emote = button.Emote; SkuId = button.SkuId; - Id = button.Id; } /// @@ -321,8 +315,6 @@ public class ButtonBuilder : IInteractableComponentBuilder break; } - return new ButtonComponent(Style, Label, Emote, CustomId, Url, IsDisabled, SkuId, Id); + return new ButtonComponent(Style, Label, Emote, CustomId, Url, IsDisabled, SkuId); } - - IMessageComponent IMessageComponentBuilder.Build() => Build(); } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilder.cs index 5193c458..eeb7db85 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilder.cs @@ -98,7 +98,7 @@ public class ComponentBuilder /// The current builder. public ComponentBuilder RemoveComponent(string customId) { - this.ActionRows.ForEach(ar => ar.Components.RemoveAll(c => c is IInteractableComponent i && i.CustomId == customId)); + this.ActionRows.ForEach(ar => ar.Components.RemoveAll(c => c.CustomId == customId)); return this; } @@ -158,15 +158,20 @@ public class ComponentBuilder Preconditions.LessThan(row, MaxActionRowCount, nameof(row)); if (menu.Options is not null && menu.Options.Distinct().Count() != menu.Options.Count) throw new InvalidOperationException("Please make sure that there is no duplicates values."); - + + var builtMenu = menu.Build(); + if (_actionRows == null) { - _actionRows = [new ActionRowBuilder().AddComponent(menu)]; + _actionRows = new List + { + new ActionRowBuilder().AddComponent(builtMenu) + }; } else { if (_actionRows.Count == row) - _actionRows.Add(new ActionRowBuilder().AddComponent(menu)); + _actionRows.Add(new ActionRowBuilder().AddComponent(builtMenu)); else { ActionRowBuilder actionRow; @@ -178,12 +183,12 @@ public class ComponentBuilder _actionRows.Add(actionRow); } - if (actionRow.CanTakeComponent(menu)) - actionRow.AddComponent(menu); + if (actionRow.CanTakeComponent(builtMenu)) + actionRow.AddComponent(builtMenu); else if (row < MaxActionRowCount) WithSelectMenu(menu, row + 1); else - throw new InvalidOperationException($"There is no more row to add a {nameof(menu)}"); + throw new InvalidOperationException($"There is no more row to add a {nameof(builtMenu)}"); } } @@ -238,17 +243,19 @@ public class ComponentBuilder { Preconditions.LessThan(row, MaxActionRowCount, nameof(row)); + var builtButton = button.Build(); + if (_actionRows == null) { _actionRows = new List { - new ActionRowBuilder().AddComponent(button) + new ActionRowBuilder().AddComponent(builtButton) }; } else { if (_actionRows.Count == row) - _actionRows.Add(new ActionRowBuilder().AddComponent(button)); + _actionRows.Add(new ActionRowBuilder().AddComponent(builtButton)); else { ActionRowBuilder actionRow; @@ -260,8 +267,8 @@ public class ComponentBuilder _actionRows.Add(actionRow); } - if (actionRow.CanTakeComponent(button)) - actionRow.AddComponent(button); + if (actionRow.CanTakeComponent(builtButton)) + actionRow.AddComponent(builtButton); else if (row < MaxActionRowCount) WithButton(button, row + 1); else @@ -319,7 +326,7 @@ public class ComponentBuilder _actionRows.RemoveAt(i); return _actionRows != null - ? new MessageComponent(_actionRows.Select(x => x.Build()).OfType().ToList()) + ? new MessageComponent(_actionRows.Select(x => x.Build()).ToList()) : MessageComponent.Empty; } } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilderExtensions.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilderExtensions.cs deleted file mode 100644 index 2c930feb..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilderExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Discord; - -public static class ComponentBuilderExtensions -{ - /// - /// Sets the custom id for the component. - /// - /// - /// The current builder. - /// - public static BuilderT WithId(this BuilderT builder, int? id) - where BuilderT : IMessageComponentBuilder - { - builder.Id = id; - return builder; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilderV2.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilderV2.cs deleted file mode 100644 index 8c119a28..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentBuilderV2.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Discord; - -public class ComponentBuilderV2 : IStaticComponentContainer -{ - /// - /// Gets the maximum number of components that can be added to this container. - /// - public const int MaxComponents = 10; - - private List _components = new(); - - /// - public List Components - { - get => _components; - set - { - _components = value ?? throw new ArgumentNullException(nameof(value), $"{nameof(Components)} cannot be null."); - } - } - - /// - /// Initializes a new instance of . - /// - public ComponentBuilderV2() { } - - /// - public ComponentBuilderV2 AddComponent(IMessageComponentBuilder component) - { - Components.Add(component); - return this; - } - - /// - public ComponentBuilderV2 AddComponents(params IMessageComponentBuilder[] components) - { - foreach (var component in components) - Components.Add(component); - return this; - } - - /// - public ComponentBuilderV2 WithComponents(IEnumerable components) - { - Components = components.ToList(); - return this; - } - - /// - public MessageComponent Build() - { - if (_components.Count is 0 or >MaxComponents) - throw new InvalidOperationException($"The number of components must be between 1 and {MaxComponents}."); - - if (_components.Any(x => - x is not ActionRowBuilder - and not SectionBuilder - and not TextDisplayBuilder - and not MediaGalleryBuilder - and not FileComponentBuilder - and not SeparatorBuilder - and not ContainerBuilder)) - throw new InvalidOperationException($"Only the following components can be at the top level: {nameof(ActionRowBuilder)}, {nameof(TextDisplayBuilder)}, {nameof(SectionBuilder)}, {nameof(MediaGalleryBuilder)}, {nameof(SeparatorBuilder)}, or {nameof(FileComponentBuilder)} components."); - - return new MessageComponent(Components.Select(x => x.Build()).ToList()); - } - - /// - IComponentContainer IComponentContainer.AddComponent(IMessageComponentBuilder component) => AddComponent(component); - - /// - IComponentContainer IComponentContainer.AddComponents(params IMessageComponentBuilder[] components) => AddComponents(components); - - /// - IComponentContainer IComponentContainer.WithComponents(IEnumerable components) => WithComponents(components); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentContainerExtensions.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentContainerExtensions.cs deleted file mode 100644 index bddf0137..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ComponentContainerExtensions.cs +++ /dev/null @@ -1,315 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace Discord; - -public static class ComponentContainerExtensions -{ - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithTextDisplay(this BuilderT container, TextDisplayBuilder textDisplay) - where BuilderT : class, IStaticComponentContainer - { - container.AddComponent(textDisplay); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithTextDisplay(this BuilderT container, - string content, - int? id = null) - where BuilderT : class, IStaticComponentContainer - => container.WithTextDisplay(new TextDisplayBuilder() - .WithContent(content) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithSection(this BuilderT container, SectionBuilder section) - where BuilderT : class, IStaticComponentContainer - { - container.AddComponent(section); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithSection(this BuilderT container, - IEnumerable components, - IMessageComponentBuilder accessory, - bool isSpoiler = false, - int? id = null) - where BuilderT : class, IStaticComponentContainer - => container.WithSection(new SectionBuilder() - .WithComponents(components) - .WithAccessory(accessory) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithMediaGallery(this BuilderT container, MediaGalleryBuilder mediaGallery) - where BuilderT : class, IStaticComponentContainer - { - container.AddComponent(mediaGallery); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithMediaGallery(this BuilderT container, - IEnumerable items, - int? id = null) where BuilderT : class, IStaticComponentContainer - => container.WithMediaGallery(new MediaGalleryBuilder() - .WithItems(items) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithMediaGallery(this BuilderT container, - IEnumerable urls, - int? id = null) - where BuilderT : class, IStaticComponentContainer - => container.WithMediaGallery(new MediaGalleryBuilder() - .WithItems(urls.Select(x => new MediaGalleryItemProperties(new UnfurledMediaItemProperties(x)))) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithSeparator(this BuilderT container, SeparatorBuilder separator) - where BuilderT : class, IStaticComponentContainer - { - container.AddComponent(separator); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithSeparator(this BuilderT container, - SeparatorSpacingSize spacing = SeparatorSpacingSize.Small, - bool isDivider = true, - int? id = null) - where BuilderT : class, IStaticComponentContainer - => container.WithSeparator(new SeparatorBuilder() - .WithSpacing(spacing) - .WithIsDivider(isDivider) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithFile(this BuilderT container, FileComponentBuilder file) - where BuilderT : class, IStaticComponentContainer - { - container.AddComponent(file); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithFile(this BuilderT container, - UnfurledMediaItemProperties file, - bool isSpoiler = false, - int? id = null) - where BuilderT : class, IStaticComponentContainer - => container.WithFile(new FileComponentBuilder() - .WithFile(file) - .WithIsSpoiler(isSpoiler) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithContainer(this BuilderT container, ContainerBuilder containerComponent) - where BuilderT : class, IStaticComponentContainer - { - container.AddComponent(containerComponent); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithContainer(this BuilderT container, - IEnumerable components, - Color? accentColor = null, - bool isSpoiler = false, - int? id = null) - where BuilderT : class, IStaticComponentContainer - => container.WithContainer(new ContainerBuilder() - .WithComponents(components) - .WithAccentColor(accentColor) - .WithSpoiler(isSpoiler) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithContainer(this BuilderT container, - params IMessageComponentBuilder[] components) - where BuilderT : class, IStaticComponentContainer - => container.WithContainer(new ContainerBuilder() - .WithComponents(components)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithButton(this BuilderT container, ButtonBuilder button) - where BuilderT : class, IInteractableComponentContainer - { - container.AddComponent(button); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithButton(this BuilderT container, - string label = null, - string customId = null, - ButtonStyle style = ButtonStyle.Primary, - IEmote emote = null, - string url = null, - bool disabled = false, - ulong? skuId = null, - int? id = null) - where BuilderT : class, IInteractableComponentContainer - => container.WithButton(new ButtonBuilder() - .WithLabel(label) - .WithStyle(style) - .WithEmote(emote) - .WithCustomId(customId) - .WithUrl(url) - .WithDisabled(disabled) - .WithSkuId(skuId) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithSelectMenu(this BuilderT container, SelectMenuBuilder selectMenu) - where BuilderT : class, IInteractableComponentContainer - { - container.AddComponent(selectMenu); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithSelectMenu(this BuilderT container, - string customId, - List options = null, - string placeholder = null, - int minValues = 1, - int maxValues = 1, - bool disabled = false, - int row = 0, - ComponentType type = ComponentType.SelectMenu, - ChannelType[] channelTypes = null, - SelectMenuDefaultValue[] defaultValues = null, - int? id = null) - where BuilderT : class, IInteractableComponentContainer - => container.WithSelectMenu(new SelectMenuBuilder() - .WithCustomId(customId) - .WithOptions(options) - .WithPlaceholder(placeholder) - .WithMaxValues(maxValues) - .WithMinValues(minValues) - .WithDisabled(disabled) - .WithType(type) - .WithChannelTypes(channelTypes) - .WithDefaultValues(defaultValues) - .WithId(id)); - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithActionRow(this BuilderT container, ActionRowBuilder actionRow) - where BuilderT : class, IStaticComponentContainer - { - container.AddComponent(actionRow); - return container; - } - - /// - /// Adds a to the container. - /// - /// - /// The current container. - /// - public static BuilderT WithActionRow(this BuilderT container, - IEnumerable components, - int? id = null) - where BuilderT : class, IStaticComponentContainer - => container.WithActionRow(new ActionRowBuilder() - .WithComponents(components) - .WithId(id)); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ContainerBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ContainerBuilder.cs deleted file mode 100644 index fe179868..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ContainerBuilder.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -namespace Discord; - -public class ContainerBuilder : IMessageComponentBuilder, IStaticComponentContainer -{ - /// - /// The maximum number of components allowed in a container. - /// - public const int MaxComponents = 10; - - /// - public ComponentType Type => ComponentType.Container; - - /// - public int? Id { get; set; } - - private List _components = new(); - - /// - public List Components - { - get => _components; - set => _components = value ?? throw new ArgumentNullException(nameof(value), $"{nameof(Components)} cannot be null."); - } - - /// - /// Gets or sets the accent color of this container. - /// - public uint? AccentColor { get; set; } - - /// - /// Gets or sets whether this container is a spoiler. - /// - public bool? IsSpoiler { get; set; } - - /// - /// Sets the accent color of this container. - /// - /// - /// The current builder. - /// - public ContainerBuilder WithAccentColor(Color? color) - { - AccentColor = color?.RawValue; - return this; - } - - /// - /// Sets whether this container is a spoiler. - /// - /// - /// The current builder. - /// - public ContainerBuilder WithSpoiler(bool isSpoiler) - { - IsSpoiler = isSpoiler; - return this; - } - - /// - public ContainerBuilder AddComponent(IMessageComponentBuilder component) - { - Components.Add(component); - return this; - } - - /// - public ContainerBuilder AddComponents(params IMessageComponentBuilder[] components) - { - foreach (var component in components) - Components.Add(component); - return this; - } - - /// - public ContainerBuilder WithComponents(IEnumerable components) - { - Components = components.ToList(); - return this; - } - - /// - public ContainerComponent Build() - { - if (_components.Count is 0 or > MaxComponents) - throw new InvalidOperationException($"A container must have between 1 and {MaxComponents} components."); - - if (_components.Any(x => x - is not ActionRowBuilder - and not TextDisplayBuilder - and not SectionBuilder - and not MediaGalleryBuilder - and not SeparatorBuilder - and not FileComponentBuilder)) - throw new InvalidOperationException($"A container can only contain {nameof(ActionRowBuilder)}, {nameof(TextDisplayBuilder)}, {nameof(SectionBuilder)}, {nameof(MediaGalleryBuilder)}, {nameof(SeparatorBuilder)}, or {nameof(FileComponentBuilder)} components."); - - return new(Components.ConvertAll(x => x.Build()).ToImmutableArray(), AccentColor, IsSpoiler, Id); - } - - /// - IMessageComponent IMessageComponentBuilder.Build() => Build(); - /// - IComponentContainer IComponentContainer.AddComponent(IMessageComponentBuilder component) => AddComponent(component); - /// - IComponentContainer IComponentContainer.AddComponents(params IMessageComponentBuilder[] components) => AddComponents(components); - /// - IComponentContainer IComponentContainer.WithComponents(IEnumerable components) => WithComponents(components); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/FileComponentBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/FileComponentBuilder.cs deleted file mode 100644 index d2851b7b..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/FileComponentBuilder.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; - -namespace Discord; - -public class FileComponentBuilder : IMessageComponentBuilder -{ - /// - public ComponentType Type => ComponentType.File; - - /// - public int? Id { get; set; } - - /// - /// Gets or sets the file for the component. - /// - /// - /// Only attachment URLs are supported. - /// - public UnfurledMediaItemProperties File { get; set; } - - /// - /// Gets or sets whether the file is a spoiler. - /// - public bool? IsSpoiler { get; set; } - - /// - /// Initializes a new instance of the . - /// - public FileComponentBuilder() {} - - /// - /// Initializes a new instance of the . - /// - public FileComponentBuilder(UnfurledMediaItemProperties media, bool isSpoiler = false, int? id = null) - { - File = media; - Id = id; - IsSpoiler = isSpoiler; - } - - /// - /// Sets the file for the component. - /// - /// - /// The current builder. - /// - public FileComponentBuilder WithFile(UnfurledMediaItemProperties file) - { - File = file; - return this; - } - - /// - /// Sets whether the file is a spoiler. - /// - /// - /// The current builder. - /// - public FileComponentBuilder WithIsSpoiler(bool? isSpoiler) - { - IsSpoiler = isSpoiler; - return this; - } - - /// - public FileComponent Build() - { - if (string.IsNullOrWhiteSpace(File.Url)) - throw new InvalidOperationException("File URL must be set."); - - if (!File.Url.StartsWith("attachment://")) - throw new InvalidOperationException("File URL must be an attachment URL."); - - return new(new UnfurledMediaItem(File.Url), IsSpoiler, Id); - } - - /// - IMessageComponent IMessageComponentBuilder.Build() => Build(); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IComponentContainer.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IComponentContainer.cs deleted file mode 100644 index 2c2734fb..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IComponentContainer.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; - -namespace Discord; - -/// -/// Represents a container with child components. -/// -public interface IComponentContainer -{ - /// - /// Gets the components in the container. - /// - List Components { get; } - - /// - /// Adds a component to the container. - /// - /// - /// The current container. - /// - IComponentContainer AddComponent(IMessageComponentBuilder component); - - /// - /// Adds components to the container. - /// - /// - /// The current container. - /// - IComponentContainer AddComponents(params IMessageComponentBuilder[] components); - - /// - /// Sets the components in the container. - /// - /// - /// The current container. - /// - IComponentContainer WithComponents(IEnumerable components); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IInteractableComponentBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IInteractableComponentBuilder.cs deleted file mode 100644 index 242060fc..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IInteractableComponentBuilder.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Discord; - -/// -/// Represents a builder for an interactable component. -/// -public interface IInteractableComponentBuilder : IMessageComponentBuilder -{ - /// - /// Gets or sets the custom id for the component. - /// - string CustomId { get; set; } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IInteractableComponentContainer.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IInteractableComponentContainer.cs deleted file mode 100644 index c86a189e..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IInteractableComponentContainer.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Discord; - -/// -/// Represents a container for interactable components. -/// -public interface IInteractableComponentContainer : IComponentContainer -{ - -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IMessageComponentBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IMessageComponentBuilder.cs deleted file mode 100644 index 88305308..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IMessageComponentBuilder.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Discord; - -public interface IMessageComponentBuilder -{ - /// - /// Gets the type of the component. - /// - ComponentType Type { get; } - - /// - /// Gets or sets the id for the component. An autoincremented id will be assigned if not set. - /// - int? Id { get; set; } - - /// - /// Runs validation checks and builds the component. - /// - IMessageComponent Build(); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IStaticComponentContainer.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IStaticComponentContainer.cs deleted file mode 100644 index 829b77bd..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/IStaticComponentContainer.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Discord; - -/// -/// Represents a container for static components. -/// -public interface IStaticComponentContainer : IComponentContainer -{ - -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/MediaGalleryBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/MediaGalleryBuilder.cs deleted file mode 100644 index b6121acc..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/MediaGalleryBuilder.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -namespace Discord; - -public class MediaGalleryBuilder : IMessageComponentBuilder -{ - /// - /// Gets the maximum number of items that can be added to a media gallery. - /// - public const int MaxItems = 10; - - /// - public ComponentType Type => ComponentType.MediaGallery; - - /// - public int? Id { get; set; } - - private List _items = new(); - - /// - /// Initializes a new instance of the . - /// - public MediaGalleryBuilder() { } - - /// - /// Initializes a new instance of the . - /// - public MediaGalleryBuilder(IEnumerable items, int? id = null) - { - Items = items.ToList(); - Id = id; - } - - /// - /// Gets or sets the items in this media gallery. - /// - public List Items - { - get => _items; - set => _items = value; - } - - /// - /// Adds a new item to the media gallery. - /// - /// - /// The current builder. - /// - public MediaGalleryBuilder AddItem(MediaGalleryItemProperties item) - { - _items.Add(item); - return this; - } - - /// - /// Adds a new item to the media gallery. - /// - /// - /// The current builder. - /// - public MediaGalleryBuilder AddItem(string url, string description = null, bool isSpoiler = false) - { - _items.Add(new MediaGalleryItemProperties(new UnfurledMediaItemProperties(url), description, isSpoiler)); - return this; - } - - /// - /// Adds a list of items to the media gallery. - /// - /// - /// The current builder. - /// - public MediaGalleryBuilder AddItems(params IEnumerable items) - { - foreach (var item in items) - _items.Add(item); - return this; - } - - /// - /// Sets the items in the media gallery. - /// - /// - /// The current builder. - /// - public MediaGalleryBuilder WithItems(IEnumerable items) - { - _items = items.ToList(); - return this; - } - - /// - public MediaGalleryComponent Build() - { - if (_items.Any(x => (x.Description?.Length ?? 0) > MediaGalleryItemProperties.MaxDescriptionLength)) - throw new ArgumentException($"{nameof(MediaGalleryItemProperties)} description length cannot exceed {MediaGalleryItemProperties.MaxDescriptionLength} characters."); - - if (_items.Any(x => !(x.Media.Url?.StartsWith("http://") ?? false) - && !(x.Media.Url?.StartsWith("https://") ?? false) - && !(x.Media.Url?.StartsWith("attachment://") ?? false))) - throw new ArgumentException($"{nameof(MediaGalleryItemProperties)} description must be a valid URL or attachment."); - - if (_items.Count is 0 or > MaxItems) - throw new ArgumentOutOfRangeException(nameof(Items), $"Media gallery items count must be in range [1, {MaxItems}]"); - - return new(_items.Select(x => new MediaGalleryItem(new UnfurledMediaItem(x.Media.Url), x.Description, x.IsSpoiler)).ToImmutableArray(), Id); - } - - /// - IMessageComponent IMessageComponentBuilder.Build() => Build(); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/MediaGalleryItemProperties.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/MediaGalleryItemProperties.cs deleted file mode 100644 index 32d7d97a..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/MediaGalleryItemProperties.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace Discord; - -public struct MediaGalleryItemProperties -{ - /// - /// The maximum length of the description. - /// - public const int MaxDescriptionLength = 256; - - /// - /// Gets or sets the media item to display. - /// - public UnfurledMediaItemProperties Media { get; set; } - - /// - /// Gets or sets the description of the media item. - /// - public string Description { get; set; } - - /// - /// Gets or sets whether the media item is a spoiler. - /// - public bool IsSpoiler { get; set; } - - /// - /// Initializes a new instance of the . - /// - public MediaGalleryItemProperties() { } - - /// - /// Initializes a new instance of the . - /// - public MediaGalleryItemProperties(UnfurledMediaItemProperties media, string description = null, bool isSpoiler = false) - { - Media = media; - Description = description; - IsSpoiler = isSpoiler; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SectionBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SectionBuilder.cs deleted file mode 100644 index 6c9727f9..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SectionBuilder.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -namespace Discord; - -public class SectionBuilder : IMessageComponentBuilder, IStaticComponentContainer -{ - /// - /// Gets the maximum number of components allowed in this container. - /// - public const int MaxComponents = 3; - - /// - public ComponentType Type => ComponentType.Section; - - /// - public int? Id { get; set; } - - /// - /// Gets or sets the accessory component. - /// - /// - /// Only supports and currently. - /// - public IMessageComponentBuilder Accessory { get; set; } - - private List _components = new(); - - /// - /// - /// Only is supported. - /// - public List Components - { - get => _components; - set => _components = value ?? throw new ArgumentNullException(nameof(value), $"{nameof(Components)} cannot be null."); - } - - /// - /// - /// Only is supported. - /// - public SectionBuilder AddComponent(IMessageComponentBuilder component) - { - Components.Add(component); - return this; - } - - /// - /// - /// Only is supported. - /// - public SectionBuilder AddComponents(params IMessageComponentBuilder[] components) - { - foreach (var component in components) - AddComponent(component); - return this; - } - - /// - /// - /// Only is supported. - /// - public SectionBuilder WithComponents(IEnumerable components) - { - Components = components.ToList(); - return this; - } - - /// - /// Sets the accessory component. - /// - public SectionBuilder WithAccessory(IMessageComponentBuilder accessory) - { - Accessory = accessory; - return this; - } - - /// - public SectionComponent Build() - { - if (_components.Count is 0 or > MaxComponents) - throw new InvalidOperationException($"Section component can only contain {MaxComponents} child components!"); - - if (_components.Any(x => x is not TextDisplayBuilder)) - throw new InvalidOperationException($"Section component can only contain {nameof(TextDisplayBuilder)}!"); - - if (Accessory is null) - throw new ArgumentNullException(nameof(Accessory), "A section must have an accessory"); - - if (Accessory is not ButtonBuilder and not ThumbnailBuilder) - throw new InvalidOperationException($"Accessory component can only be {nameof(ButtonBuilder)} or {nameof(ThumbnailBuilder)}!"); - - return new(Id, Components.Select(x => x.Build()).ToImmutableArray(), Accessory?.Build()); - } - - /// - IMessageComponent IMessageComponentBuilder.Build() => Build(); - /// - IComponentContainer IComponentContainer.AddComponent(IMessageComponentBuilder component) => AddComponent(component); - /// - IComponentContainer IComponentContainer.AddComponents(params IMessageComponentBuilder[] components) => AddComponents(components); - /// - IComponentContainer IComponentContainer.WithComponents(IEnumerable components) => WithComponents(components.ToList()); -} 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 110e6598..95a937d7 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SelectMenuBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SelectMenuBuilder.cs @@ -8,7 +8,7 @@ namespace Discord; /// /// Represents a class used to build 's. /// -public class SelectMenuBuilder : IInteractableComponentBuilder +public class SelectMenuBuilder { /// /// The max length of a . @@ -135,16 +135,13 @@ public class SelectMenuBuilder : IInteractableComponentBuilder } } - /// - public int? Id { get; set; } - - private List _options = []; + private List _options = new List(); private int _minValues = 1; private int _maxValues = 1; private string _placeholder; private string _customId; private ComponentType _type = ComponentType.SelectMenu; - private List _defaultValues = []; + private List _defaultValues = new(); /// /// Creates a new instance of a . @@ -165,7 +162,6 @@ public class SelectMenuBuilder : IInteractableComponentBuilder .Select(x => new SelectMenuOptionBuilder(x.Label, x.Value, x.Description, x.Emote, x.IsDefault)) .ToList(); DefaultValues = selectMenu.DefaultValues?.ToList(); - Id = selectMenu.Id; } /// @@ -180,7 +176,7 @@ public class SelectMenuBuilder : IInteractableComponentBuilder /// 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) + bool isDisabled = false, ComponentType type = ComponentType.SelectMenu, List channelTypes = null, List defaultValues = null) { CustomId = customId; Options = options; @@ -191,7 +187,6 @@ public class SelectMenuBuilder : IInteractableComponentBuilder Type = type; ChannelTypes = channelTypes ?? new(); DefaultValues = defaultValues ?? new(); - Id = id; } /// @@ -405,9 +400,6 @@ 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, IsDisabled, Type, ChannelTypes, DefaultValues); } - - /// - IMessageComponent IMessageComponentBuilder.Build() => Build(); } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SeparatorBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SeparatorBuilder.cs deleted file mode 100644 index d308eddc..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/SeparatorBuilder.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace Discord; - -public class SeparatorBuilder : IMessageComponentBuilder -{ - /// - public ComponentType Type => ComponentType.Separator; - - /// - /// Gets or sets whether the component is a divider. - /// - public bool? IsDivider { get; set; } - - /// - /// Gets or sets the spacing of the separator. - /// - public SeparatorSpacingSize? Spacing { get; set; } - - /// - public int? Id { get; set; } - - /// - /// Sets whether the component is a divider. - /// - /// - /// The current builder. - /// - public SeparatorBuilder WithIsDivider(bool? isDivider) - { - IsDivider = isDivider; - return this; - } - - /// - /// Sets the spacing of the separator. - /// - /// - /// The current builder. - /// - public SeparatorBuilder WithSpacing(SeparatorSpacingSize? spacing) - { - Spacing = spacing; - return this; - } - - /// - public SeparatorComponent Build() - { - return new(IsDivider, Spacing, Id); - } - - /// - IMessageComponent IMessageComponentBuilder.Build() => Build(); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/TextDisplayBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/TextDisplayBuilder.cs deleted file mode 100644 index eb2234eb..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/TextDisplayBuilder.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; - -namespace Discord; - -public class TextDisplayBuilder : IMessageComponentBuilder -{ - /// - /// The maximum length of the content. - /// - public const int MaxContentLength = 4096; - - /// - public ComponentType Type => ComponentType.ActionRow; - - /// - public int? Id { get; set; } - - /// - /// Gets or sets the content of the text display. - /// - public string Content { get; set; } - - /// - /// Initializes a new . - /// - public TextDisplayBuilder() { } - - /// - /// Initializes a new with the specified content. - /// - public TextDisplayBuilder(string content, int? id = null) - { - Content = content; - Id = id; - } - - /// - /// Sets the content of the text display. - /// - /// - /// The current builder. - /// - public TextDisplayBuilder WithContent(string content) - { - Content = content; - return this; - } - - /// - public TextDisplayComponent Build() - { - if (Content.Length > MaxContentLength) - throw new ArgumentException($"Content length must be less than or equal to {MaxContentLength}.", nameof(Content)); - - return new(Content, Id); - } - - /// - IMessageComponent IMessageComponentBuilder.Build() => Build(); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/TextInputBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/TextInputBuilder.cs index 404fe011..c37c39cb 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/TextInputBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/TextInputBuilder.cs @@ -6,10 +6,8 @@ namespace Discord; /// /// Represents a builder for creating a . /// -public class TextInputBuilder : IInteractableComponentBuilder +public class TextInputBuilder { - public ComponentType Type => ComponentType.TextInput; - /// /// The max length of a . /// @@ -101,8 +99,6 @@ public class TextInputBuilder : IInteractableComponentBuilder /// public bool? Required { get; set; } - public int? Id { get; set; } - /// /// Gets or sets the default value of the text input. /// @@ -144,7 +140,7 @@ public class TextInputBuilder : IInteractableComponentBuilder /// The text input's maximum length. /// The text input's required value. public TextInputBuilder(string label, string customId, TextInputStyle style = TextInputStyle.Short, string placeholder = null, - int? minLength = null, int? maxLength = null, bool? required = null, string value = null, int? id = null) + int? minLength = null, int? maxLength = null, bool? required = null, string value = null) { Label = label; Style = style; @@ -154,7 +150,6 @@ public class TextInputBuilder : IInteractableComponentBuilder MaxLength = maxLength; Required = required; Value = value; - Id = id; } /// @@ -262,8 +257,6 @@ public class TextInputBuilder : IInteractableComponentBuilder if (Style is TextInputStyle.Short && Value?.Any(x => x == '\n') is true) throw new ArgumentException($"Value must not contain new line characters when style is {TextInputStyle.Short}.", nameof(Value)); - return new TextInputComponent(CustomId, Label, Placeholder, MinLength, MaxLength, Style, Required, Value, Id); + return new TextInputComponent(CustomId, Label, Placeholder, MinLength, MaxLength, Style, Required, Value); } - - IMessageComponent IMessageComponentBuilder.Build() => Build(); } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ThumbnailBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ThumbnailBuilder.cs deleted file mode 100644 index 79a5fa05..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/ThumbnailBuilder.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; - -namespace Discord; - -public class ThumbnailBuilder : IMessageComponentBuilder -{ - /// - /// Gets the maximum length of the description. - /// - public const int MaxDescriptionLength = 1024; - - /// - public ComponentType Type => ComponentType.Thumbnail; - - /// - public int? Id { get; set; } - - /// - /// Gets or sets the media of the thumbnail. - /// - public UnfurledMediaItemProperties Media { get; set; } - - /// - /// Gets or sets the description of the thumbnail. - /// - public string Description { get; set; } - - /// - /// Gets or sets whether the thumbnail is a spoiler. - /// - public bool IsSpoiler { get; set; } - - /// - /// Initializes a new instance of the . - /// - public ThumbnailBuilder() { } - - /// - /// Initializes a new instance of the . - /// - public ThumbnailBuilder(UnfurledMediaItemProperties media, string description = null, bool isSpoiler = false) - { - Media = media; - Description = description; - IsSpoiler = isSpoiler; - } - - /// - /// Sets the media of the thumbnail. - /// - /// - /// The current builder. - /// - public ThumbnailBuilder WithMedia(UnfurledMediaItemProperties media) - { - Media = media; - return this; - } - - /// - /// Sets the description of the thumbnail. - /// - /// - /// The current builder. - /// - public ThumbnailBuilder WithDescription(string description) - { - Description = description; - return this; - } - - /// - /// Sets whether the thumbnail is a spoiler. - /// - /// - /// The current builder. - /// - public ThumbnailBuilder WithSpoiler(bool isSpoiler) - { - IsSpoiler = isSpoiler; - return this; - } - - /// - public ThumbnailComponent Build() - { - if (Description is not null && Description.Length > MaxDescriptionLength) - throw new ArgumentException($"Description length must be less than or equal to {MaxDescriptionLength}.", nameof(Description)); - - return new(Id, new UnfurledMediaItem(Media.Url), Description, IsSpoiler); - } - - /// - IMessageComponent IMessageComponentBuilder.Build() => Build(); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/UnfurledMediaItemProperties.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/UnfurledMediaItemProperties.cs deleted file mode 100644 index 1bb2f85e..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/Builders/UnfurledMediaItemProperties.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Discord; - -public struct UnfurledMediaItemProperties -{ - /// - /// Gets or sets the URL of the media item. - /// - public string Url { get; set; } - - /// - /// Initializes a new instance of the . - /// - public UnfurledMediaItemProperties() {} - - /// - /// Initializes a new instance of the . - /// - public UnfurledMediaItemProperties(string url) - { - Url = url; - } - - public static implicit operator UnfurledMediaItemProperties(string url) => new(url); -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonComponent.cs index 5a850e20..c387f9ad 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonComponent.cs @@ -3,14 +3,11 @@ namespace Discord; /// /// Represents a Button. /// -public class ButtonComponent : IInteractableComponent +public class ButtonComponent : IMessageComponent { /// public ComponentType Type => ComponentType.Button; - /// - public int? Id { get; } - /// /// Gets the of this button, example buttons with each style can be found Here. /// @@ -59,10 +56,9 @@ public class ButtonComponent : IInteractableComponent public ButtonBuilder ToBuilder() => new (Label, CustomId, Style, Url, Emote, IsDisabled); - internal ButtonComponent(ButtonStyle style, string label, IEmote emote, string customId, string url, bool isDisabled, ulong? skuId, int? id) + internal ButtonComponent(ButtonStyle style, string label, IEmote emote, string customId, string url, bool isDisabled, ulong? skuId) { Style = style; - Id = id; Label = label; Emote = emote; CustomId = customId; diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentType.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentType.cs index 5d5cce5a..0ad3f741 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentType.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentType.cs @@ -44,19 +44,5 @@ namespace Discord /// A select menu for picking from channels. /// ChannelSelect = 8, - - Section = 9, - - TextDisplay = 10, - - Thumbnail = 11, - - MediaGallery = 12, - - File = 13, - - Separator = 14, - - Container = 17, } } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ContainerComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ContainerComponent.cs deleted file mode 100644 index 79a40b15..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ContainerComponent.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; - -namespace Discord; - -/// -/// Represents a container component. -/// -public class ContainerComponent : IMessageComponent -{ - /// - public ComponentType Type => ComponentType.Container; - - /// - public int? Id { get; } - - /// - /// Gets the components in this container. - /// - public IReadOnlyCollection Components { get; } - - /// - /// Gets the accent color of this container. - /// - public uint? AccentColor { get; } - - /// - /// Gets whether this container is a spoiler. - /// - public bool? IsSpoiler { get; } - - internal ContainerComponent(IReadOnlyCollection components, uint? accentColor, bool? isSpoiler, int? id = null) - { - Components = components; - AccentColor = accentColor; - IsSpoiler = isSpoiler; - Id = id; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/FileComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/FileComponent.cs deleted file mode 100644 index 91a3c75f..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/FileComponent.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace Discord; - -/// -/// Represents a file component. -/// -public class FileComponent : IMessageComponent -{ - /// - public ComponentType Type => ComponentType.File; - - /// - public int? Id { get; } - - /// - /// Gets the file of this component. - /// - public UnfurledMediaItem File { get; } - - /// - /// Gets whether this file is a spoiler. - /// - public bool? IsSpoiler { get; } - - internal FileComponent(UnfurledMediaItem file, bool? isSpoiler, int? id = null) - { - File = file; - IsSpoiler = isSpoiler; - Id = id; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IInteractableComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IInteractableComponent.cs deleted file mode 100644 index 01300490..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IInteractableComponent.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Discord; - -/// -/// Represents a message component that can be interacted with. -/// -public interface IInteractableComponent : IMessageComponent -{ - /// - /// Gets the custom id of the component if possible; otherwise . - /// - string CustomId { get; } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IMessageComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IMessageComponent.cs index 6bc1c07d..9366a44d 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IMessageComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IMessageComponent.cs @@ -1,14 +1,18 @@ -namespace Discord; - -/// -/// Represents a message component on a message. -/// -public interface IMessageComponent +namespace Discord { /// - /// Gets the of this Message Component. + /// Represents a message component on a message. /// - ComponentType Type { get; } + public interface IMessageComponent + { + /// + /// Gets the of this Message Component. + /// + ComponentType Type { get; } - int? Id { get; } + /// + /// Gets the custom id of the component if possible; otherwise . + /// + string CustomId { get; } + } } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MediaGalleryComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MediaGalleryComponent.cs deleted file mode 100644 index ce3c3989..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MediaGalleryComponent.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace Discord; - -/// -/// Represents a media gallery component. -/// -public class MediaGalleryComponent : IMessageComponent -{ - /// - public ComponentType Type => ComponentType.MediaGallery; - - /// - public int? Id { get; } - - /// - /// Gets the items in this media gallery. - /// - public IReadOnlyCollection Items { get; } - - internal MediaGalleryComponent(IReadOnlyCollection items, int? id) - { - Items = items; - Id = id; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MediaGalleryItem.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MediaGalleryItem.cs deleted file mode 100644 index da33f7c9..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MediaGalleryItem.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace Discord; - -/// -/// Represents a media gallery item. -/// -public readonly struct MediaGalleryItem -{ - /// - /// Gets the media for this item. - /// - public UnfurledMediaItem Media { get; } - - /// - /// Gets the description for this item. - /// - public string Description { get; } - - /// - /// Gets whether this item is a spoiler. - /// - public bool IsSpoiler { get; } - - internal MediaGalleryItem(UnfurledMediaItem media, string description, bool? isSpoiler) - { - Media = media; - Description = description; - IsSpoiler = isSpoiler ?? false; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MessageComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MessageComponent.cs index 18946a73..72058868 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MessageComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MessageComponent.cs @@ -1,25 +1,26 @@ using System.Collections.Generic; -namespace Discord; - -/// -/// Represents a component object used to send components with messages. -/// -public class MessageComponent +namespace Discord { /// - /// Gets the components to be used in a message. + /// Represents a component object used to send components with messages. /// - public IReadOnlyCollection Components { get; } - - internal MessageComponent(List components) + public class MessageComponent { - Components = components; - } + /// + /// Gets the components to be used in a message. + /// + public IReadOnlyCollection Components { get; } - /// - /// Returns a empty . - /// - internal static MessageComponent Empty - => new([]); + internal MessageComponent(List components) + { + Components = components; + } + + /// + /// Returns a empty . + /// + internal static MessageComponent Empty + => new MessageComponent(new List()); + } } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ResolvedUnfurledMediaItem.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ResolvedUnfurledMediaItem.cs deleted file mode 100644 index d7cfd1b7..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ResolvedUnfurledMediaItem.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace Discord; - -/// -/// Represents a media item that has been unfurled and resolved. -/// -public class ResolvedUnfurledMediaItem : UnfurledMediaItem -{ - /// - /// Gets the proxy URL for this media item. - /// - public string ProxyUrl { get; } - - /// - /// Gets the height of this media item. - /// - public int Height { get; } - - /// - /// Gets the width of this media item. - /// - public int Width { get; } - - /// - /// Gets the content type of this media item. - /// - public string ContentType { get;} - - /// - /// Gets the loading state of this media item. - /// - public UnfurledMediaItemLoadingState LoadingState { get; } - - internal ResolvedUnfurledMediaItem(string url, string proxyUrl, int height, int width, string contentType, UnfurledMediaItemLoadingState loadingState) : base(url) - { - ProxyUrl = proxyUrl; - Height = height; - Width = width; - ContentType = contentType; - LoadingState = loadingState; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SectionComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SectionComponent.cs deleted file mode 100644 index 52d71e34..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SectionComponent.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; - -namespace Discord; - -/// -/// Represents a section component. -/// -public class SectionComponent : IMessageComponent -{ - /// - public ComponentType Type => ComponentType.Section; - - /// - public int? Id { get; } - - /// - /// Gets the components in this section. - /// - public IReadOnlyCollection Components { get; } - - /// - /// Gets the accessory of this section. - /// - public IMessageComponent Accessory { get; } - - internal SectionComponent(int? id, IReadOnlyCollection components, IMessageComponent accessory) - { - Id = id; - Components = components; - Accessory = accessory; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs index 7d1a2558..39631dee 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs @@ -7,14 +7,11 @@ namespace Discord /// /// Represents a select menu component defined at /// - public class SelectMenuComponent : IInteractableComponent + public class SelectMenuComponent : IMessageComponent { /// public ComponentType Type { get; } - /// - public int? Id { get; } - /// public string CustomId { get; } @@ -70,7 +67,7 @@ namespace Discord DefaultValues.ToList()); internal SelectMenuComponent(string customId, List options, string placeholder, int minValues, int maxValues, - bool disabled, ComponentType type, int? id, IEnumerable channelTypes = null, IEnumerable defaultValues = null) + bool disabled, ComponentType type, IEnumerable channelTypes = null, IEnumerable defaultValues = null) { CustomId = customId; Options = options; @@ -79,9 +76,8 @@ namespace Discord MaxValues = maxValues; IsDisabled = disabled; Type = type; - Id = id; - ChannelTypes = channelTypes?.ToArray() ?? []; - DefaultValues = defaultValues?.ToArray() ?? []; + ChannelTypes = channelTypes?.ToArray() ?? Array.Empty(); + DefaultValues = defaultValues?.ToArray() ?? Array.Empty(); } } } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SeparatorComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SeparatorComponent.cs deleted file mode 100644 index 00c2e7cb..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SeparatorComponent.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace Discord; - -/// -/// Represents a separator component. -/// -public class SeparatorComponent : IMessageComponent -{ - /// - public ComponentType Type => ComponentType.Separator; - - /// - public int? Id { get; } - - /// - /// Gets whether this component is a divider. - /// - public bool? IsDivider { get; } - - /// - /// Gets the spacing of this component. - /// - public SeparatorSpacingSize? Spacing { get; } - - internal SeparatorComponent(bool? isDivider, SeparatorSpacingSize? spacing, int? id = null) - { - IsDivider = isDivider; - Spacing = spacing; - Id = id; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SeparatorSpacingSize.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SeparatorSpacingSize.cs deleted file mode 100644 index 0336eb74..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SeparatorSpacingSize.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Discord; - -/// -/// Represents the spacing of a separator component. -/// -public enum SeparatorSpacingSize -{ - /// - /// The separator has a small spacing. - /// - Small = 1, - - /// - /// The separator has a large spacing. - /// - Large = 2 -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextDisplayComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextDisplayComponent.cs deleted file mode 100644 index e2aec7e8..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextDisplayComponent.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Discord; - -/// -/// Represents a text display component. -/// -public class TextDisplayComponent : IMessageComponent -{ - /// - public ComponentType Type => ComponentType.TextDisplay; - - /// - public int? Id { get; } - - /// - /// Gets the content of this component. - /// - public string Content { get; } - - internal TextDisplayComponent(string content, int? id = null) - { - Id = id; - Content = content; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputComponent.cs index d76014bc..e2da1132 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputComponent.cs @@ -3,7 +3,7 @@ namespace Discord /// /// Represents a text input. /// - public class TextInputComponent : IInteractableComponent + public class TextInputComponent : IMessageComponent { /// public ComponentType Type => ComponentType.TextInput; @@ -11,9 +11,6 @@ namespace Discord /// public string CustomId { get; } - /// - public int? Id { get; } - /// /// Gets the label of the component; this is the text shown above it. /// @@ -50,7 +47,7 @@ namespace Discord public string Value { get; } internal TextInputComponent(string customId, string label, string placeholder, int? minLength, int? maxLength, - TextInputStyle style, bool? required, string value, int? id) + TextInputStyle style, bool? required, string value) { CustomId = customId; Label = label; @@ -60,7 +57,6 @@ namespace Discord Style = style; Required = required; Value = value; - Id = id; } } } diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputStyle.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputStyle.cs index 292f26b4..9bbcf687 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputStyle.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/TextInputStyle.cs @@ -6,7 +6,6 @@ namespace Discord /// Intended for short, single-line text. /// Short = 1, - /// /// Intended for longer or multiline text. /// diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ThumbnailComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ThumbnailComponent.cs deleted file mode 100644 index b4223392..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ThumbnailComponent.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Discord; - -/// -/// Represents a thumbnail component. -/// -public class ThumbnailComponent : IMessageComponent -{ - /// - public ComponentType Type => ComponentType.Thumbnail; - - /// - public int? Id { get; } - - /// - /// Gets the media of the component. - /// - public UnfurledMediaItem Media { get; } - - /// - /// Gets the description of the component. - /// - public string Description { get; } - - /// - /// Gets whether the component is a spoiler. - /// - public bool IsSpoiler { get; } - - internal ThumbnailComponent(int? id, UnfurledMediaItem media, string description, bool? isSpoiler) - { - Id = id; - Media = media; - Description = description; - IsSpoiler = isSpoiler ?? false; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/UnfurledMediaItem.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/UnfurledMediaItem.cs deleted file mode 100644 index 52177794..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/UnfurledMediaItem.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Discord; - -/// -/// Represents a media item that has been unfurled. -/// -public class UnfurledMediaItem -{ - /// - /// Gets the URL of this media item. - /// - public string Url { get; } - - internal UnfurledMediaItem(string url) - { - Url = url; - } -} diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/UnfurledMediaItemLoadingState.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/UnfurledMediaItemLoadingState.cs deleted file mode 100644 index f6df157c..00000000 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/UnfurledMediaItemLoadingState.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Discord; - -public enum UnfurledMediaItemLoadingState -{ - /// - /// The state of the media item is unknown. - /// - Unknown = 0, - - /// - /// The media item is currently loading. - /// - Loading = 1, - - /// - /// The media item was successfully loaded. - /// - LoadingSuccess = 2, - - /// - /// The media item was not found. - /// - LoadingNotFound = 3 -} diff --git a/src/Discord.Net.Core/Entities/Interactions/Modals/Modal.cs b/src/Discord.Net.Core/Entities/Interactions/Modals/Modal.cs index 6062db0c..a435d33e 100644 --- a/src/Discord.Net.Core/Entities/Interactions/Modals/Modal.cs +++ b/src/Discord.Net.Core/Entities/Interactions/Modals/Modal.cs @@ -1,10 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Discord { /// /// Represents a modal interaction. /// - public class Modal + public class Modal : IMessageComponent { + /// + public ComponentType Type => throw new NotSupportedException("Modals do not have a component type."); + /// /// Gets the title of the modal. /// diff --git a/src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs index 89b29ae1..242c316a 100644 --- a/src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/Modals/ModalBuilder.cs @@ -111,20 +111,21 @@ namespace Discord } /// - /// Gets a by the specified . + /// Gets a by the specified . /// - /// The type of the component to get. - /// The of the component to get. + /// The type of the component to get. + /// The of the component to get. /// - /// The component of type that was found, otherwise. + /// The component of type that was found, otherwise. /// - public TMessageComponentBuilder GetComponent(string customId) - where TMessageComponentBuilder : class, IInteractableComponentBuilder + public TMessageComponent GetComponent(string customId) + where TMessageComponent : class, IMessageComponent { Preconditions.NotNull(customId, nameof(customId)); - return Components.ActionRows?.SelectMany(r => r.Components.OfType()) - .FirstOrDefault(c => c.CustomId == customId); + return Components.ActionRows + ?.SelectMany(r => r.Components.OfType()) + .FirstOrDefault(c => c?.CustomId == customId); } /// @@ -140,7 +141,7 @@ namespace Discord { Preconditions.NotNull(customId, nameof(customId)); - var component = GetComponent(customId) ?? throw new ArgumentException($"There is no component of type {nameof(TextInputComponent)} with the specified custom ID in this modal builder.", nameof(customId)); + var component = GetComponent(customId) ?? throw new ArgumentException($"There is no component of type {nameof(TextInputComponent)} with the specified custom ID in this modal builder.", nameof(customId)); var row = Components.ActionRows.First(r => r.Components.Contains(component)); var builder = new TextInputBuilder @@ -158,7 +159,7 @@ namespace Discord updateTextInput(builder); row.Components.Remove(component); - row.AddComponent(builder); + row.AddComponent(builder.Build()); return this; } @@ -178,13 +179,13 @@ namespace Discord /// /// Removes a component from this builder by the specified . /// - /// The of the component to remove. + /// The of the component to remove. /// The current builder. public ModalBuilder RemoveComponent(string customId) { Preconditions.NotNull(customId, nameof(customId)); - Components.ActionRows?.ForEach(r => r.Components.RemoveAll(c => c is IInteractableComponentBuilder ic && ic.CustomId == customId)); + Components.ActionRows?.ForEach(r => r.Components.RemoveAll(c => c.CustomId == customId)); return this; } @@ -225,7 +226,7 @@ namespace Discord public class ModalComponentBuilder { /// - /// The max length of a . + /// The max length of a . /// public const int MaxCustomIdLength = 100; @@ -313,17 +314,19 @@ namespace Discord { Preconditions.LessThan(row, MaxActionRowCount, nameof(row)); + var builtButton = text.Build(); + if (_actionRows == null) { _actionRows = new List { - new ActionRowBuilder().AddComponent(text) + new ActionRowBuilder().AddComponent(builtButton) }; } else { if (_actionRows.Count == row) - _actionRows.Add(new ActionRowBuilder().AddComponent(text)); + _actionRows.Add(new ActionRowBuilder().AddComponent(builtButton)); else { ActionRowBuilder actionRow; @@ -335,8 +338,8 @@ namespace Discord _actionRows.Add(actionRow); } - if (actionRow.CanTakeComponent(text)) - actionRow.AddComponent(text); + if (actionRow.CanTakeComponent(builtButton)) + actionRow.AddComponent(builtButton); else if (row < MaxActionRowCount) WithTextInput(text, row + 1); else diff --git a/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs b/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs index c43b3f3e..57bb8ba2 100644 --- a/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs +++ b/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs @@ -123,16 +123,5 @@ namespace Discord _isDisposed = true; } } - - /// - /// Gets the url formatted with attachment:// protocol. - /// - /// - /// The formatted url. - /// - public string GetAttachmentUrl() - { - return $"attachment://{FileName}"; - } } } diff --git a/src/Discord.Net.Core/Entities/Messages/MessageFlags.cs b/src/Discord.Net.Core/Entities/Messages/MessageFlags.cs index 6219e8fc..10f1aeba 100644 --- a/src/Discord.Net.Core/Entities/Messages/MessageFlags.cs +++ b/src/Discord.Net.Core/Entities/Messages/MessageFlags.cs @@ -57,10 +57,5 @@ namespace Discord /// This message is a voice message. /// VoiceMessage = 1 << 13, - - /// - /// This message is using v2 components. - /// - ComponentsV2 = 1 << 15, } } diff --git a/src/Discord.Net.Core/Utils/Preconditions.cs b/src/Discord.Net.Core/Utils/Preconditions.cs index 372238bf..83da3a66 100644 --- a/src/Discord.Net.Core/Utils/Preconditions.cs +++ b/src/Discord.Net.Core/Utils/Preconditions.cs @@ -401,11 +401,5 @@ namespace Discord } #endregion - - public static void ValidateMessageFlags(MessageFlags flags) - { - if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification and not MessageFlags.ComponentsV2 and not MessageFlags.Ephemeral) - throw new ArgumentException("The only valid MessageFlags are Ephemeral, SuppressEmbeds, SuppressNotification, ComponentsV2 and None.", nameof(flags)); - } } } diff --git a/src/Discord.Net.Interactions/InteractionModuleBase.cs b/src/Discord.Net.Interactions/InteractionModuleBase.cs index 5b9b90f3..62e5c3ab 100644 --- a/src/Discord.Net.Interactions/InteractionModuleBase.cs +++ b/src/Discord.Net.Interactions/InteractionModuleBase.cs @@ -44,55 +44,55 @@ namespace Discord.Interactions protected virtual Task DeferAsync(bool ephemeral = false, RequestOptions options = null) => Context.Interaction.DeferAsync(ephemeral, options); - /// + /// protected virtual Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null) + => Context.Interaction.RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.RespondWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.RespondWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task RespondWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.RespondWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.RespondWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task RespondWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.RespondWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.RespondWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.RespondWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.RespondWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null) + => Context.Interaction.FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => Context.Interaction.FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); /// protected virtual Task ReplyAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, diff --git a/src/Discord.Net.Interactions/RestInteractionModuleBase.cs b/src/Discord.Net.Interactions/RestInteractionModuleBase.cs index cdcc4c89..1778b7ef 100644 --- a/src/Discord.Net.Interactions/RestInteractionModuleBase.cs +++ b/src/Discord.Net.Interactions/RestInteractionModuleBase.cs @@ -43,8 +43,8 @@ namespace Discord.Interactions /// A Task representing the operation of creating the interaction response. /// /// Thrown if the interaction isn't a type of . - protected override Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => HandleInteractionAsync(x => x.Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags)); + protected override Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null) + => HandleInteractionAsync(x => x.Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll)); /// /// Responds to the interaction with a modal. diff --git a/src/Discord.Net.Rest/API/Common/ActionRowComponent.cs b/src/Discord.Net.Rest/API/Common/ActionRowComponent.cs index 4ee6311e..e97ca71d 100644 --- a/src/Discord.Net.Rest/API/Common/ActionRowComponent.cs +++ b/src/Discord.Net.Rest/API/Common/ActionRowComponent.cs @@ -8,9 +8,6 @@ namespace Discord.API [JsonProperty("type")] public ComponentType Type { get; set; } - [JsonProperty("id")] - public Optional Id { get; set; } - [JsonProperty("components")] public IMessageComponent[] Components { get; set; } @@ -32,10 +29,9 @@ namespace Discord.API _ => null }; }).ToArray(); - Id = c.Id ?? Optional.Unspecified; } [JsonIgnore] - int? IMessageComponent.Id => Id.ToNullable(); + string IMessageComponent.CustomId => null; } } diff --git a/src/Discord.Net.Rest/API/Common/ButtonComponent.cs b/src/Discord.Net.Rest/API/Common/ButtonComponent.cs index 84f6e0c8..f820fc02 100644 --- a/src/Discord.Net.Rest/API/Common/ButtonComponent.cs +++ b/src/Discord.Net.Rest/API/Common/ButtonComponent.cs @@ -2,14 +2,11 @@ using Newtonsoft.Json; namespace Discord.API { - internal class ButtonComponent : IInteractableComponent + internal class ButtonComponent : IMessageComponent { [JsonProperty("type")] public ComponentType Type { get; set; } - [JsonProperty("id")] - public Optional Id { get; set; } - [JsonProperty("style")] public ButtonStyle Style { get; set; } @@ -42,7 +39,6 @@ namespace Discord.API Url = c.Url; Disabled = c.IsDisabled; SkuId = c.SkuId ?? Optional.Unspecified; - Id = c.Id ?? Optional.Unspecified; if (c.Emote != null) { @@ -66,9 +62,6 @@ namespace Discord.API } [JsonIgnore] - string IInteractableComponent.CustomId => CustomId.GetValueOrDefault(); - - [JsonIgnore] - int? IMessageComponent.Id => Id.ToNullable(); + string IMessageComponent.CustomId => CustomId.GetValueOrDefault(); } } diff --git a/src/Discord.Net.Rest/API/Common/ContainerComponent.cs b/src/Discord.Net.Rest/API/Common/ContainerComponent.cs deleted file mode 100644 index 969906bc..00000000 --- a/src/Discord.Net.Rest/API/Common/ContainerComponent.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Discord.Rest; -using Newtonsoft.Json; -using System.Linq; - -namespace Discord.API; - -internal class ContainerComponent : IMessageComponent -{ - [JsonProperty("type")] - public ComponentType Type { get; set; } - - [JsonProperty("id")] - public Optional Id { get; set; } - - [JsonProperty("accent_color")] - public Optional AccentColor { get; set; } - - [JsonProperty("spoiler")] - public Optional IsSpoiler { get; set; } - - [JsonProperty("components")] - public IMessageComponent[] Components { get; set; } - - public ContainerComponent() { } - - public ContainerComponent(Discord.ContainerComponent component) - { - Type = component.Type; - Id = component.Id ?? Optional.Unspecified; - AccentColor = component.AccentColor ?? Optional.Unspecified; - IsSpoiler = component.IsSpoiler ?? Optional.Unspecified; - Components = component.Components.Select(x => x.ToModel()).ToArray(); - } - - int? IMessageComponent.Id => Id.ToNullable(); -} diff --git a/src/Discord.Net.Rest/API/Common/FileComponent.cs b/src/Discord.Net.Rest/API/Common/FileComponent.cs deleted file mode 100644 index 81f189ae..00000000 --- a/src/Discord.Net.Rest/API/Common/FileComponent.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Discord.Rest; -using Newtonsoft.Json; - -namespace Discord.API; - -internal class FileComponent : IMessageComponent -{ - [JsonProperty("type")] - public ComponentType Type { get; set; } - [JsonProperty("id")] - public Optional Id { get; set; } - - [JsonProperty("file")] - public UnfurledMediaItem File { get; set; } - - [JsonProperty("spoiler")] - public Optional IsSpoiler { get; set; } - - public FileComponent() { } - - public FileComponent(Discord.FileComponent component) - { - Type = component.Type; - Id = component.Id ?? Optional.Unspecified; - File = component.File.ToModel(); - IsSpoiler = component.IsSpoiler ?? Optional.Unspecified; - } - - int? IMessageComponent.Id => Id.ToNullable(); -} diff --git a/src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs b/src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs index 88743246..c64920e3 100644 --- a/src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs +++ b/src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs @@ -17,7 +17,7 @@ internal class ForumThreadMessage public Optional AllowedMentions { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } [JsonProperty("sticker_ids")] public Optional Stickers { get; set; } diff --git a/src/Discord.Net.Rest/API/Common/InteractionCallbackData.cs b/src/Discord.Net.Rest/API/Common/InteractionCallbackData.cs index 2596c490..0b3302dd 100644 --- a/src/Discord.Net.Rest/API/Common/InteractionCallbackData.cs +++ b/src/Discord.Net.Rest/API/Common/InteractionCallbackData.cs @@ -21,7 +21,7 @@ namespace Discord.API public Optional Flags { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } [JsonProperty("choices")] public Optional Choices { get; set; } diff --git a/src/Discord.Net.Rest/API/Common/MediaGalleryComponent.cs b/src/Discord.Net.Rest/API/Common/MediaGalleryComponent.cs deleted file mode 100644 index cc26cbd1..00000000 --- a/src/Discord.Net.Rest/API/Common/MediaGalleryComponent.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Discord.Rest; -using Newtonsoft.Json; -using System.Linq; - -namespace Discord.API; - -internal class MediaGalleryComponent : IMessageComponent -{ - [JsonProperty("type")] - public ComponentType Type { get; set; } - - [JsonProperty("id")] - public Optional Id { get; set; } - - [JsonProperty("items")] - public MediaGalleryItem[] Items { get; set; } - - public MediaGalleryComponent() { } - - public MediaGalleryComponent(Discord.MediaGalleryComponent component) - { - Type = component.Type; - Id = component.Id ?? Optional.Unspecified; - Items = component.Items.Select(x => new MediaGalleryItem - { - Description = x.Description, - IsSpoiler = x.IsSpoiler, - Media = x.Media.ToModel() - }).ToArray(); - } - - int? IMessageComponent.Id => Id.ToNullable(); -} diff --git a/src/Discord.Net.Rest/API/Common/MediaGalleryItem.cs b/src/Discord.Net.Rest/API/Common/MediaGalleryItem.cs deleted file mode 100644 index dda02dc5..00000000 --- a/src/Discord.Net.Rest/API/Common/MediaGalleryItem.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Newtonsoft.Json; - -namespace Discord.API; - -internal class MediaGalleryItem -{ - [JsonProperty("media")] - public UnfurledMediaItem Media { get; set; } - - [JsonProperty("description")] - public Optional Description { get; set; } - - [JsonProperty("spoiler")] - public Optional IsSpoiler { get; set; } -} diff --git a/src/Discord.Net.Rest/API/Common/SectionComponent.cs b/src/Discord.Net.Rest/API/Common/SectionComponent.cs deleted file mode 100644 index 76ea893d..00000000 --- a/src/Discord.Net.Rest/API/Common/SectionComponent.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Discord.Rest; -using Newtonsoft.Json; -using System.Linq; - -namespace Discord.API; - -internal class SectionComponent : IMessageComponent -{ - [JsonProperty("type")] - public ComponentType Type { get; set; } - - [JsonProperty("id")] - public Optional Id { get; set; } - - [JsonProperty("components")] - public IMessageComponent[] Components { get; set; } - - [JsonProperty("accessory")] - public IMessageComponent Accessory { get; set; } - - public SectionComponent() { } - - public SectionComponent(Discord.SectionComponent component) - { - Type = component.Type; - Id = component.Id ?? Optional.Unspecified; - Components = component.Components.Select(x => x.ToModel()).ToArray(); - Accessory = component.Accessory.ToModel(); - } - - int? IMessageComponent.Id => Id.ToNullable(); -} diff --git a/src/Discord.Net.Rest/API/Common/SelectMenuComponent.cs b/src/Discord.Net.Rest/API/Common/SelectMenuComponent.cs index f605d75b..c7a69568 100644 --- a/src/Discord.Net.Rest/API/Common/SelectMenuComponent.cs +++ b/src/Discord.Net.Rest/API/Common/SelectMenuComponent.cs @@ -3,14 +3,11 @@ using System.Linq; namespace Discord.API { - internal class SelectMenuComponent : IInteractableComponent + internal class SelectMenuComponent : IMessageComponent { [JsonProperty("type")] public ComponentType Type { get; set; } - [JsonProperty("id")] - public Optional Id { get; set; } - [JsonProperty("custom_id")] public string CustomId { get; set; } @@ -55,8 +52,5 @@ namespace Discord.API ChannelTypes = component.ChannelTypes.ToArray(); DefaultValues = component.DefaultValues.Select(x => new SelectMenuDefaultValue {Id = x.Id, Type = x.Type}).ToArray(); } - - [JsonIgnore] - int? IMessageComponent.Id => Id.ToNullable(); } } diff --git a/src/Discord.Net.Rest/API/Common/SeparatorComponent.cs b/src/Discord.Net.Rest/API/Common/SeparatorComponent.cs deleted file mode 100644 index f01affac..00000000 --- a/src/Discord.Net.Rest/API/Common/SeparatorComponent.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Newtonsoft.Json; - -namespace Discord.API; - -internal class SeparatorComponent : IMessageComponent -{ - [JsonProperty("type")] - public ComponentType Type { get; set; } - - [JsonProperty("id")] - public Optional Id { get; set; } - - [JsonProperty("divider")] - public Optional IsDivider { get; set; } - - [JsonProperty("spacing")] - public Optional Spacing { get; set; } - - public SeparatorComponent() { } - - public SeparatorComponent(Discord.SeparatorComponent component) - { - Type = component.Type; - Id = component.Id ?? Optional.Unspecified; - IsDivider = component.IsDivider ?? Optional.Unspecified; - Spacing = component.Spacing ?? Optional.Unspecified; - } - - int? IMessageComponent.Id => Id.ToNullable(); -} diff --git a/src/Discord.Net.Rest/API/Common/TextDisplayComponent.cs b/src/Discord.Net.Rest/API/Common/TextDisplayComponent.cs deleted file mode 100644 index 04d66e06..00000000 --- a/src/Discord.Net.Rest/API/Common/TextDisplayComponent.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Newtonsoft.Json; - -namespace Discord.API; - -internal class TextDisplayComponent : IMessageComponent -{ - [JsonProperty("type")] - public ComponentType Type { get; set; } - - [JsonProperty("id")] - public Optional Id { get; set; } - - [JsonProperty("content")] - public string Content { get; set; } - - public TextDisplayComponent() { } - - public TextDisplayComponent(Discord.TextDisplayComponent component) - { - Type = component.Type; - Id = component.Id ?? Optional.Unspecified; - Content = component.Content; - } - - int? IMessageComponent.Id => Id.ToNullable(); -} diff --git a/src/Discord.Net.Rest/API/Common/TextInputComponent.cs b/src/Discord.Net.Rest/API/Common/TextInputComponent.cs index 458cdaca..a475345f 100644 --- a/src/Discord.Net.Rest/API/Common/TextInputComponent.cs +++ b/src/Discord.Net.Rest/API/Common/TextInputComponent.cs @@ -2,14 +2,11 @@ using Newtonsoft.Json; namespace Discord.API { - internal class TextInputComponent : IInteractableComponent + internal class TextInputComponent : IMessageComponent { [JsonProperty("type")] public ComponentType Type { get; set; } - [JsonProperty("id")] - public Optional Id { get; set; } - [JsonProperty("style")] public TextInputStyle Style { get; set; } @@ -47,10 +44,6 @@ namespace Discord.API MaxLength = component.MaxLength ?? Optional.Unspecified; Required = component.Required ?? Optional.Unspecified; Value = component.Value ?? Optional.Unspecified; - Id = component.Id ?? Optional.Unspecified; } - - [JsonIgnore] - int? IMessageComponent.Id => Id.ToNullable(); } } diff --git a/src/Discord.Net.Rest/API/Common/ThumbnailComponent.cs b/src/Discord.Net.Rest/API/Common/ThumbnailComponent.cs deleted file mode 100644 index bc8b40dc..00000000 --- a/src/Discord.Net.Rest/API/Common/ThumbnailComponent.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Discord.Rest; -using Newtonsoft.Json; - -namespace Discord.API; - -internal class ThumbnailComponent : IMessageComponent -{ - [JsonProperty("type")] - public ComponentType Type { get; set; } - - [JsonProperty("id")] - public Optional Id { get; set; } - - [JsonProperty("media")] - public UnfurledMediaItem Media { get; set; } - - [JsonProperty("description")] - public Optional Description { get; set; } - - [JsonProperty("spoiler")] - public Optional IsSpoiler { get; set; } - - public ThumbnailComponent() { } - - public ThumbnailComponent(Discord.ThumbnailComponent component) - { - Type = component.Type; - Id = component.Id ?? Optional.Unspecified; - Media = component.Media.ToModel(); - Description = component.Description; - IsSpoiler = component.IsSpoiler; - } - - int? IMessageComponent.Id => Id.ToNullable(); -} diff --git a/src/Discord.Net.Rest/API/Common/UnfurledMediaItem.cs b/src/Discord.Net.Rest/API/Common/UnfurledMediaItem.cs deleted file mode 100644 index b7e3e9dd..00000000 --- a/src/Discord.Net.Rest/API/Common/UnfurledMediaItem.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Newtonsoft.Json; - -namespace Discord.API; - -internal class UnfurledMediaItem -{ - [JsonProperty("url")] - public string Url { get; set; } - - [JsonProperty("proxy_url")] - public Optional ProxyUrl { get; set; } - - [JsonProperty("height")] - public Optional Height { get; set; } - - [JsonProperty("width")] - public Optional Width { get; set; } - - [JsonProperty("content_type")] - public Optional ContentType { get; set; } - - [JsonProperty("loading_state")] - public Optional LoadingState { get; set; } -} diff --git a/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs b/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs index 42174ab9..e22f8fbd 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs @@ -24,7 +24,7 @@ namespace Discord.API.Rest public Optional MessageReference { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } [JsonProperty("sticker_ids")] public Optional Stickers { get; set; } diff --git a/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs b/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs index 710e14ac..85cffe13 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs @@ -24,7 +24,7 @@ namespace Discord.API.Rest public Optional Content { get; set; } public Optional Embeds { get; set; } public Optional AllowedMentions { get; set; } - public Optional MessageComponent { get; set; } + public Optional MessageComponent { get; set; } public Optional Flags { get; set; } public Optional Stickers { get; set; } public Optional TagIds { get; set; } diff --git a/src/Discord.Net.Rest/API/Rest/CreatePostParams.cs b/src/Discord.Net.Rest/API/Rest/CreatePostParams.cs index f568cb9d..d74678f6 100644 --- a/src/Discord.Net.Rest/API/Rest/CreatePostParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreatePostParams.cs @@ -1,22 +1,28 @@ using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; -namespace Discord.API.Rest; - -internal class CreatePostParams +namespace Discord.API.Rest { - // thread - [JsonProperty("name")] - public string Title { get; set; } + internal class CreatePostParams + { + // thread + [JsonProperty("name")] + public string Title { get; set; } - [JsonProperty("auto_archive_duration")] - public ThreadArchiveDuration ArchiveDuration { get; set; } + [JsonProperty("auto_archive_duration")] + public ThreadArchiveDuration ArchiveDuration { get; set; } - [JsonProperty("rate_limit_per_user")] - public Optional Slowmode { get; set; } + [JsonProperty("rate_limit_per_user")] + public Optional Slowmode { get; set; } - [JsonProperty("message")] - public ForumThreadMessage Message { get; set; } + [JsonProperty("message")] + public ForumThreadMessage Message { get; set; } - [JsonProperty("applied_tags")] - public Optional Tags { get; set; } + [JsonProperty("applied_tags")] + public Optional Tags { get; set; } + } } diff --git a/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs b/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs index e3b10738..52dd1806 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs @@ -3,7 +3,6 @@ using Discord.Net.Rest; using Newtonsoft.Json; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; namespace Discord.API.Rest @@ -38,7 +37,7 @@ namespace Discord.API.Rest public Optional Flags { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } [JsonProperty("file")] public Optional File { get; set; } @@ -56,7 +55,6 @@ namespace Discord.API.Rest { var d = new Dictionary(); - var extraFlags = MessageFlags.None; if (File.IsSpecified) { d["file"] = File.Value; @@ -79,21 +77,14 @@ namespace Discord.API.Rest payload["embeds"] = Embeds.Value; if (AllowedMentions.IsSpecified) payload["allowed_mentions"] = AllowedMentions.Value; - - if (Components.IsSpecified) - { payload["components"] = Components.Value; - if (Components.Value.Any(x => x.Type is not ComponentType.ActionRow)) - extraFlags |= MessageFlags.ComponentsV2; - } - - payload["flags"] = Flags.GetValueOrDefault(MessageFlags.None) | extraFlags; - if (ThreadName.IsSpecified) payload["thread_name"] = ThreadName.Value; if (AppliedTags.IsSpecified) payload["applied_tags"] = AppliedTags.Value; + if (Flags.IsSpecified) + payload["flags"] = Flags.Value; if (Poll.IsSpecified) payload["poll"] = Poll.Value; diff --git a/src/Discord.Net.Rest/API/Rest/ModifyInteractionResponseParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyInteractionResponseParams.cs index 2afc4641..a2c7cbee 100644 --- a/src/Discord.Net.Rest/API/Rest/ModifyInteractionResponseParams.cs +++ b/src/Discord.Net.Rest/API/Rest/ModifyInteractionResponseParams.cs @@ -14,7 +14,7 @@ namespace Discord.API.Rest public Optional AllowedMentions { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } [JsonProperty("flags")] public Optional Flags { get; set; } diff --git a/src/Discord.Net.Rest/API/Rest/ModifyMessageParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyMessageParams.cs index 3bee0675..3dba45a5 100644 --- a/src/Discord.Net.Rest/API/Rest/ModifyMessageParams.cs +++ b/src/Discord.Net.Rest/API/Rest/ModifyMessageParams.cs @@ -1,21 +1,19 @@ using Newtonsoft.Json; -namespace Discord.API.Rest; - -internal class ModifyMessageParams +namespace Discord.API.Rest { - [JsonProperty("content")] - public Optional Content { get; set; } - - [JsonProperty("embeds")] - public Optional Embeds { get; set; } - - [JsonProperty("components")] - public Optional Components { get; set; } - - [JsonProperty("flags")] - public Optional Flags { get; set; } - - [JsonProperty("allowed_mentions")] - public Optional AllowedMentions { get; set; } + [JsonObject(MemberSerialization = MemberSerialization.OptIn)] + internal class ModifyMessageParams + { + [JsonProperty("content")] + public Optional Content { get; set; } + [JsonProperty("embeds")] + public Optional Embeds { get; set; } + [JsonProperty("components")] + public Optional Components { get; set; } + [JsonProperty("flags")] + public Optional Flags { get; set; } + [JsonProperty("allowed_mentions")] + public Optional AllowedMentions { get; set; } + } } diff --git a/src/Discord.Net.Rest/API/Rest/ModifyWebhookMessageParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyWebhookMessageParams.cs index db80eba7..e73efaf3 100644 --- a/src/Discord.Net.Rest/API/Rest/ModifyWebhookMessageParams.cs +++ b/src/Discord.Net.Rest/API/Rest/ModifyWebhookMessageParams.cs @@ -1,18 +1,17 @@ using Newtonsoft.Json; -namespace Discord.API.Rest; - -internal class ModifyWebhookMessageParams +namespace Discord.API.Rest { - [JsonProperty("content")] - public Optional Content { get; set; } - - [JsonProperty("embeds")] - public Optional Embeds { get; set; } - - [JsonProperty("allowed_mentions")] - public Optional AllowedMentions { get; set; } - - [JsonProperty("components")] - public Optional Components { get; set; } + [JsonObject(MemberSerialization = MemberSerialization.OptIn)] + internal class ModifyWebhookMessageParams + { + [JsonProperty("content")] + public Optional Content { get; set; } + [JsonProperty("embeds")] + public Optional Embeds { get; set; } + [JsonProperty("allowed_mentions")] + public Optional AllowedMentions { get; set; } + [JsonProperty("components")] + public Optional Components { get; set; } + } } diff --git a/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs b/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs index 5a103534..c1e4309e 100644 --- a/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs +++ b/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs @@ -21,7 +21,7 @@ namespace Discord.API.Rest public Optional Embeds { get; set; } public Optional AllowedMentions { get; set; } public Optional MessageReference { get; set; } - public Optional MessageComponent { get; set; } + public Optional MessageComponent { get; set; } public Optional Flags { get; set; } public Optional Stickers { get; set; } public Optional Poll { get; set; } diff --git a/src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs b/src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs index 0497495d..dcdc7e65 100644 --- a/src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs +++ b/src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs @@ -21,7 +21,7 @@ namespace Discord.API.Rest public Optional IsTTS { get; set; } public Optional Embeds { get; set; } public Optional AllowedMentions { get; set; } - public Optional MessageComponents { get; set; } + public Optional MessageComponents { get; set; } public Optional Flags { get; set; } public Optional Poll { get; set; } @@ -44,10 +44,8 @@ namespace Discord.API.Rest { var d = new Dictionary(); - var extraFlags = MessageFlags.None; - if (Files.Any(x => x.Waveform is not null && x.DurationSeconds is not null)) - extraFlags |= MessageFlags.VoiceMessage; + Flags = Flags.GetValueOrDefault(MessageFlags.None) | MessageFlags.VoiceMessage; var payload = new Dictionary(); payload["type"] = Type; @@ -57,26 +55,20 @@ namespace Discord.API.Rest data["content"] = Content.Value; if (IsTTS.IsSpecified) data["tts"] = IsTTS.Value; + if (MessageComponents.IsSpecified) + data["components"] = MessageComponents.Value; if (Embeds.IsSpecified) data["embeds"] = Embeds.Value; if (AllowedMentions.IsSpecified) data["allowed_mentions"] = AllowedMentions.Value; - - if (MessageComponents.IsSpecified) - { - data["components"] = MessageComponents.Value; - if (MessageComponents.Value.Any(x => x.Type is not ComponentType.ActionRow)) - extraFlags |= MessageFlags.ComponentsV2; - } - - data["flags"] = Flags.GetValueOrDefault(MessageFlags.None) | extraFlags; - + if (Flags.IsSpecified) + data["flags"] = Flags.Value; if (Poll.IsSpecified) data["poll"] = Poll.Value; - List attachments = []; + List attachments = new(); - for (var n = 0; n != Files.Length; n++) + for (int n = 0; n != Files.Length; n++) { var attachment = Files[n]; diff --git a/src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs b/src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs index 4da38e9d..f33eecfb 100644 --- a/src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs +++ b/src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs @@ -22,7 +22,7 @@ namespace Discord.API.Rest public Optional AvatarUrl { get; set; } public Optional Embeds { get; set; } public Optional AllowedMentions { get; set; } - public Optional MessageComponents { get; set; } + public Optional MessageComponents { get; set; } public Optional Flags { get; set; } public Optional ThreadName { get; set; } public Optional AppliedTags { get; set; } @@ -37,10 +37,8 @@ namespace Discord.API.Rest { var d = new Dictionary(); - var extraFlags = MessageFlags.None; - if (Files.Any(x => x.Waveform is not null && x.DurationSeconds is not null)) - extraFlags |= MessageFlags.VoiceMessage; + Flags = Flags.GetValueOrDefault(MessageFlags.None) | MessageFlags.VoiceMessage; var payload = new Dictionary(); if (Content.IsSpecified) @@ -53,20 +51,14 @@ namespace Discord.API.Rest payload["username"] = Username.Value; if (AvatarUrl.IsSpecified) payload["avatar_url"] = AvatarUrl.Value; + if (MessageComponents.IsSpecified) + payload["components"] = MessageComponents.Value; if (Embeds.IsSpecified) payload["embeds"] = Embeds.Value; if (AllowedMentions.IsSpecified) payload["allowed_mentions"] = AllowedMentions.Value; - - if (MessageComponents.IsSpecified) - { - payload["components"] = MessageComponents.Value; - if (MessageComponents.Value.Any(x => x.Type is not ComponentType.ActionRow)) - extraFlags |= MessageFlags.ComponentsV2; - } - - payload["flags"] = Flags.GetValueOrDefault(MessageFlags.None) | extraFlags; - + if (Flags.IsSpecified) + payload["flags"] = Flags.Value; if (ThreadName.IsSpecified) payload["thread_name"] = ThreadName.Value; if (AppliedTags.IsSpecified) diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 97a3be95..e5257c8d 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -2779,8 +2779,6 @@ namespace Discord.API if (threadId.HasValue) querys.Add($"thread_id={threadId}"); - querys.Add("with_components=true"); - return $"{string.Join("&", querys)}"; } diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs index fad06a3b..7a76732d 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs @@ -308,10 +308,10 @@ namespace Discord.Rest Preconditions.AtMost(stickers.Length, 3, nameof(stickers), "A max of 3 stickers are allowed."); } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; + if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification) + throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds, SuppressNotification and none.", nameof(flags)); - Preconditions.ValidateMessageFlags(flags); + var args = new CreateMessageParams { @@ -320,7 +320,7 @@ namespace Discord.Rest Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel(), MessageReference = messageReference?.ToModel(), - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional.Unspecified, Flags = flags, Poll = poll?.ToModel() ?? Optional.Unspecified @@ -429,10 +429,8 @@ namespace Discord.Rest } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - - Preconditions.ValidateMessageFlags(flags); + if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification) + throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds, SuppressNotification and none.", nameof(flags)); if (stickers != null) { @@ -446,7 +444,7 @@ namespace Discord.Rest Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageReference = messageReference?.ToModel() ?? Optional.Unspecified, - MessageComponent = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + MessageComponent = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional.Unspecified, Flags = flags, Poll = poll?.ToModel() ?? Optional.Unspecified diff --git a/src/Discord.Net.Rest/Entities/Channels/ThreadHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ThreadHelper.cs index 29be16cb..a133211d 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ThreadHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ThreadHelper.cs @@ -163,7 +163,7 @@ namespace Discord.Rest Content = text, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, Flags = flags, - Components = components?.Components?.Any() ?? false ? components.Components.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + Components = components?.Components?.Any() ?? false ? components.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified, Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional.Unspecified, }, Tags = tagIds @@ -224,7 +224,7 @@ namespace Discord.Rest Content = text, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, Flags = flags, - MessageComponent = components?.Components?.Any() ?? false ? components.Components.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + MessageComponent = components?.Components?.Any() ?? false ? components.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified, Slowmode = slowmode, Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional.Unspecified, Title = title, diff --git a/src/Discord.Net.Rest/Entities/Interactions/CommandBase/RestCommandBase.cs b/src/Discord.Net.Rest/Entities/Interactions/CommandBase/RestCommandBase.cs index ef16c0f5..dae9b890 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/CommandBase/RestCommandBase.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/CommandBase/RestCommandBase.cs @@ -1,11 +1,12 @@ using Discord.API.Rest; - +using Discord.Net.Rest; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Threading.Tasks; - +using DataModel = Discord.API.ApplicationCommandInteractionData; using Model = Discord.API.Interaction; namespace Discord.Rest @@ -80,8 +81,7 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -89,7 +89,7 @@ namespace Discord.Rest if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -123,12 +123,8 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -156,13 +152,12 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -177,15 +172,13 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Poll = poll?.ToModel() ?? Optional.Unspecified, - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; + if (ephemeral) + args.Flags = MessageFlags.Ephemeral; + return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } @@ -201,8 +194,7 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -211,7 +203,7 @@ namespace Discord.Rest Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); using (var file = new FileAttachment(fileStream, fileName)) - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } /// @@ -226,8 +218,7 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { Preconditions.NotNullOrEmpty(filePath, nameof(filePath), "Path must exist"); @@ -235,7 +226,7 @@ namespace Discord.Rest Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); using (var file = new FileAttachment(File.OpenRead(filePath), fileName)) - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } /// @@ -249,10 +240,9 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { - return FollowupWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); } /// @@ -266,13 +256,12 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -300,22 +289,23 @@ namespace Discord.Rest { throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); } - }; + } + + var flags = MessageFlags.None; + + if (ephemeral) + flags |= MessageFlags.Ephemeral; var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) - { - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, - Content = text, - IsTTS = isTTS, - Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, - AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Poll = poll?.ToModel() ?? Optional.Unspecified - }; + { + Flags = flags, + Content = text, + IsTTS = isTTS, + Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified + }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } diff --git a/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs b/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs index ce07a294..6afbf74e 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs @@ -430,8 +430,8 @@ namespace Discord.Rest Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Unspecified, Components = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, }; return client.ApiClient.ModifyInteractionFollowupMessageAsync(apiArgs, message.Id, message.Token, options); @@ -478,7 +478,8 @@ namespace Discord.Rest Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Components = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, Flags = args.Flags }; @@ -494,7 +495,8 @@ namespace Discord.Rest Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, MessageComponents = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] : Optional.Unspecified + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified }; return client.ApiClient.ModifyInteractionResponseAsync(apiArgs, token, options); diff --git a/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponent.cs b/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponent.cs index 8748ef4a..811b4560 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponent.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponent.cs @@ -77,8 +77,7 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -86,7 +85,7 @@ namespace Discord.Rest if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -120,16 +119,14 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel(), Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Poll = poll?.ToModel() ?? Optional.Unspecified, - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified } }; + if (ephemeral) + response.Data.Value.Flags = MessageFlags.Ephemeral; + lock (_lock) { if (HasResponded) @@ -211,8 +208,8 @@ namespace Discord.Rest AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, Components = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified } }; @@ -230,8 +227,8 @@ namespace Discord.Rest AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, MessageComponents = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified }; @@ -259,13 +256,12 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -280,15 +276,14 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : MessageFlags.None, Poll = poll?.ToModel() ?? Optional.Unspecified }; + if (ephemeral) + args.Flags = MessageFlags.Ephemeral; + return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } @@ -304,8 +299,7 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -314,7 +308,7 @@ namespace Discord.Rest Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); using (var file = new FileAttachment(fileStream, fileName)) - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } /// @@ -329,8 +323,7 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { Preconditions.NotNullOrEmpty(filePath, nameof(filePath), "Path must exist"); @@ -338,7 +331,7 @@ namespace Discord.Rest Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); using (var file = new FileAttachment(File.OpenRead(filePath), fileName)) - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } /// @@ -352,10 +345,9 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { - return FollowupWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); } /// @@ -369,13 +361,12 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -405,18 +396,19 @@ namespace Discord.Rest } } + var flags = MessageFlags.None; + + if (ephemeral) + flags |= MessageFlags.Ephemeral; + var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Flags = flags, Content = text, IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); diff --git a/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponentData.cs b/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponentData.cs index f72eceec..bc44d0df 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponentData.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponentData.cs @@ -93,7 +93,7 @@ namespace Discord.Rest } } - internal RestMessageComponentData(IInteractableComponent component, BaseDiscordClient discord, IGuild guild) + internal RestMessageComponentData(IMessageComponent component, BaseDiscordClient discord, IGuild guild) { CustomId = component.CustomId; Type = component.Type; diff --git a/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs b/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs index e7d08e41..edeeea0b 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs @@ -3,7 +3,6 @@ using Discord.Rest; using System; using System.Collections.Generic; -using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; @@ -138,13 +137,12 @@ namespace Discord.Rest MessageComponent component = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -159,15 +157,13 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = component?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Poll = poll?.ToModel() ?? Optional.Unspecified, - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ??Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; + if (ephemeral) + args.Flags = MessageFlags.Ephemeral; + return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } @@ -198,13 +194,12 @@ namespace Discord.Rest MessageComponent component = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -221,16 +216,14 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = component?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, File = fileStream is not null ? new MultipartFile(fileStream, fileName) : Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified, - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, }; + if (ephemeral) + args.Flags = MessageFlags.Ephemeral; + return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } @@ -261,13 +254,12 @@ namespace Discord.Rest MessageComponent component = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -287,16 +279,14 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = component?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, File = fileStream != null ? new MultipartFile(fileStream, fileName) : Optional.Unspecified, - Poll = poll?.ToModel() ?? Optional.Unspecified, - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Poll = poll?.ToModel() ?? Optional.Unspecified }; + if (ephemeral) + args.Flags = MessageFlags.Ephemeral; + return await InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } @@ -325,8 +315,7 @@ namespace Discord.Rest MessageComponent component = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -334,7 +323,7 @@ namespace Discord.Rest if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -368,12 +357,8 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, - Components = component?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -405,13 +390,12 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -441,18 +425,19 @@ namespace Discord.Rest } } + var flags = MessageFlags.None; + + if (ephemeral) + flags |= MessageFlags.Ephemeral; + var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { - Flags = ephemeral - ? flags | MessageFlags.Ephemeral - : flags == MessageFlags.None - ? Optional.Unspecified - : flags, + Flags = flags, Content = text, IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); @@ -469,10 +454,9 @@ namespace Discord.Rest MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { - return FollowupWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); } /// @@ -557,8 +541,8 @@ namespace Discord.Rest AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, Components = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified } }; @@ -567,7 +551,7 @@ namespace Discord.Rest } else { - var attachments = args.Attachments.Value?.ToArray() ?? []; + var attachments = args.Attachments.Value?.ToArray() ?? Array.Empty(); var response = new API.Rest.UploadInteractionFileParams(attachments) { @@ -576,8 +560,8 @@ namespace Discord.Rest AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, MessageComponents = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified }; diff --git a/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModalData.cs b/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModalData.cs index 1831d4b5..c1f329e7 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModalData.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModalData.cs @@ -1,5 +1,8 @@ +using System; using System.Collections.Generic; using System.Linq; +using DataModel = Discord.API.MessageComponentInteractionData; +using InterationModel = Discord.API.Interaction; using Model = Discord.API.ModalInteractionData; namespace Discord.Rest @@ -23,7 +26,7 @@ namespace Discord.Rest { CustomId = model.CustomId; Components = model.Components - .SelectMany(x => x.Components.OfType()) + .SelectMany(x => x.Components) .Select(x => new RestMessageComponentData(x, discord, guild)) .ToArray(); } diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs b/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs index 82751d17..f2f2404b 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs @@ -342,7 +342,7 @@ namespace Discord.Rest /// public abstract string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -361,7 +361,7 @@ namespace Discord.Rest /// contains the sent message. /// public abstract Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -382,7 +382,7 @@ namespace Discord.Rest /// contains the sent message. /// public abstract Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -403,7 +403,7 @@ namespace Discord.Rest /// contains the sent message. /// public abstract Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -423,7 +423,7 @@ namespace Discord.Rest /// contains the sent message. /// public abstract Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -443,7 +443,7 @@ namespace Discord.Rest /// contains the sent message. /// public abstract Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// public Task DeleteOriginalResponseAsync(RequestOptions options = null) @@ -462,7 +462,7 @@ namespace Discord.Rest /// Task IDiscordInteraction.RespondAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, - MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) + MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => Task.FromResult(Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll)); /// Task IDiscordInteraction.DeferAsync(bool ephemeral, RequestOptions options) @@ -470,48 +470,45 @@ namespace Discord.Rest /// Task IDiscordInteraction.RespondWithModalAsync(Modal modal, RequestOptions options) => Task.FromResult(RespondWithModal(modal, options)); - /// async Task IDiscordInteraction.FollowupAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, - MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// async Task IDiscordInteraction.GetOriginalResponseAsync(RequestOptions options) => await GetOriginalResponseAsync(options).ConfigureAwait(false); /// async Task IDiscordInteraction.ModifyOriginalResponseAsync(Action func, RequestOptions options) => await ModifyOriginalResponseAsync(func, options).ConfigureAwait(false); - /// async Task IDiscordInteraction.FollowupWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, - AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// async Task IDiscordInteraction.FollowupWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, - AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupWithFileAsync(filePath, text, fileName, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(filePath, text, fileName, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// async Task IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, - bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// async Task IDiscordInteraction.FollowupWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, - bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); - + bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// Task IDiscordInteraction.RespondWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, bool ephemeral, - AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) => throw new NotSupportedException("REST-Based interactions don't support files."); + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => throw new NotSupportedException("REST-Based interactions don't support files."); #if NETCOREAPP3_0_OR_GREATER != true /// Task IDiscordInteraction.RespondWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, - AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) => throw new NotSupportedException("REST-Based interactions don't support files."); + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => throw new NotSupportedException("REST-Based interactions don't support files."); /// Task IDiscordInteraction.RespondWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, - bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) => throw new NotSupportedException("REST-Based interactions don't support files."); + bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => throw new NotSupportedException("REST-Based interactions don't support files."); /// Task IDiscordInteraction.RespondWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, - AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) => throw new NotSupportedException("REST-Based interactions don't support files."); + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => throw new NotSupportedException("REST-Based interactions don't support files."); #endif #endregion } diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestPingInteraction.cs b/src/Discord.Net.Rest/Entities/Interactions/RestPingInteraction.cs index 5b931275..82b44c25 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/RestPingInteraction.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/RestPingInteraction.cs @@ -37,11 +37,11 @@ namespace Discord.Rest public override string Defer(bool ephemeral = false, RequestOptions options = null) => throw new NotSupportedException(); public override string RespondWithModal(Modal modal, RequestOptions options = null) => throw new NotSupportedException(); - public override string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException(); - public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException(); - public override Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException(); - public override Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException(); - public override Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException(); - public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException(); + public override string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); } } diff --git a/src/Discord.Net.Rest/Entities/Interactions/SlashCommands/RestAutocompleteInteraction.cs b/src/Discord.Net.Rest/Entities/Interactions/SlashCommands/RestAutocompleteInteraction.cs index 6c60990b..dcad1dbd 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/SlashCommands/RestAutocompleteInteraction.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/SlashCommands/RestAutocompleteInteraction.cs @@ -100,17 +100,17 @@ namespace Discord.Rest => Respond(result, options); public override string Defer(bool ephemeral = false, RequestOptions options = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); public override string RespondWithModal(Modal modal, RequestOptions options = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); diff --git a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs index f7b26d09..ac1eeb11 100644 --- a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs +++ b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs @@ -55,16 +55,16 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); // check that user flag and user Id list are exclusive, same with role flag and role Id list - if (allowedMentions is { AllowedTypes: not null }) + if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) { if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) && - allowedMentions.UserIds is { Count: > 0 }) + allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) { throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions)); } if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) && - allowedMentions.RoleIds is { Count: > 0 }) + allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) { throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); } @@ -93,13 +93,13 @@ namespace Discord.Rest Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value : Optional.Create(), AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Create(), - Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] : Optional.Unspecified, + Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() : Optional.Unspecified, }; return client.ApiClient.ModifyMessageAsync(channelId, msgId, apiArgs, options); } else { - var attachments = args.Attachments.Value?.ToArray() ?? []; + var attachments = args.Attachments.Value?.ToArray() ?? Array.Empty(); var apiArgs = new UploadFileParams(attachments) { @@ -107,7 +107,7 @@ namespace Discord.Rest Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value : Optional.Create(), AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Create(), - MessageComponent = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] : Optional.Unspecified + MessageComponent = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() : Optional.Unspecified }; return client.ApiClient.ModifyMessageAsync(channelId, msgId, apiArgs, options); diff --git a/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs index c418c485..132f1c97 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs @@ -95,12 +95,12 @@ namespace Discord.Rest /// public PurchaseNotification PurchaseNotification { get; private set; } - + /// public MessageCallData? CallData { get; private set; } /// - public IReadOnlyCollection Components { get; private set; } + public IReadOnlyCollection Components { get; private set; } /// /// Gets a collection of the mentioned users in the message. /// @@ -150,7 +150,7 @@ namespace Discord.Rest if (model.Activity.IsSpecified) { // create a new Activity from the API model - Activity = new MessageActivity + Activity = new MessageActivity() { Type = model.Activity.Value.Type.Value, PartyId = model.Activity.Value.PartyId.GetValueOrDefault() @@ -170,9 +170,62 @@ namespace Discord.Rest }; } - Components = model.Components.IsSpecified - ? model.Components.Value.Select(x => x.ToEntity()).ToImmutableArray() - : []; + if (model.Components.IsSpecified) + { + Components = model.Components.Value.Where(x => x.Type is ComponentType.ActionRow) + .Select(x => new ActionRowComponent(((API.ActionRowComponent)x).Components.Select(y => + { + switch (y.Type) + { + case ComponentType.Button: + { + var parsed = (API.ButtonComponent)y; + return new Discord.ButtonComponent( + parsed.Style, + parsed.Label.GetValueOrDefault(), + parsed.Emote.IsSpecified + ? parsed.Emote.Value.Id.HasValue + ? new Emote(parsed.Emote.Value.Id.Value, parsed.Emote.Value.Name, parsed.Emote.Value.Animated.GetValueOrDefault()) + : new Emoji(parsed.Emote.Value.Name) + : null, + parsed.CustomId.GetValueOrDefault(), + parsed.Url.GetValueOrDefault(), + parsed.Disabled.GetValueOrDefault(), + parsed.SkuId.ToNullable()); + } + case ComponentType.SelectMenu or ComponentType.ChannelSelect or ComponentType.RoleSelect or ComponentType.MentionableSelect or ComponentType.UserSelect: + { + var parsed = (API.SelectMenuComponent)y; + return new SelectMenuComponent( + parsed.CustomId, + parsed.Options?.Select(z => new SelectMenuOption( + z.Label, + z.Value, + z.Description.GetValueOrDefault(), + z.Emoji.IsSpecified + ? z.Emoji.Value.Id.HasValue + ? new Emote(z.Emoji.Value.Id.Value, z.Emoji.Value.Name, z.Emoji.Value.Animated.GetValueOrDefault()) + : new Emoji(z.Emoji.Value.Name) + : null, + z.Default.ToNullable())).ToList(), + parsed.Placeholder.GetValueOrDefault(), + parsed.MinValues, + parsed.MaxValues, + parsed.Disabled, + parsed.Type, + parsed.ChannelTypes.GetValueOrDefault(), + parsed.DefaultValues.IsSpecified + ? parsed.DefaultValues.Value.Select(x => new SelectMenuDefaultValue(x.Id, x.Type)) + : Array.Empty() + ); + } + default: + return null; + } + }).ToList())).ToImmutableArray(); + } + else + Components = new List(); if (model.Flags.IsSpecified) Flags = model.Flags.Value; @@ -183,16 +236,15 @@ namespace Discord.Rest if (value.Length > 0) { var reactions = ImmutableArray.CreateBuilder(value.Length); - foreach (var t in value) - reactions.Add(RestReaction.Create(t)); - + for (int i = 0; i < value.Length; i++) + reactions.Add(RestReaction.Create(value[i])); _reactions = reactions.ToImmutable(); } else - _reactions = []; + _reactions = ImmutableArray.Create(); } else - _reactions = []; + _reactions = ImmutableArray.Create(); if (model.Interaction.IsSpecified) { @@ -237,11 +289,11 @@ namespace Discord.Rest ? new GuildProductPurchase(model.PurchaseNotification.Value.ProductPurchase.Value.ListingId, model.PurchaseNotification.Value.ProductPurchase.Value.ProductName) : null); } - + if (model.Call.IsSpecified) CallData = new MessageCallData(model.Call.Value.Participants, model.Call.Value.EndedTimestamp.ToNullable()); } - + /// public async Task UpdateAsync(RequestOptions options = null) { diff --git a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs index fb5a8985..4f80fa43 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs @@ -84,7 +84,7 @@ namespace Discord.Rest if (model.MentionEveryone.IsSpecified) _isMentioningEveryone = model.MentionEveryone.Value; if (model.RoleMentions.IsSpecified) - _roleMentionIds = [..model.RoleMentions.Value]; + _roleMentionIds = model.RoleMentions.Value.ToImmutableArray(); if (model.Attachments.IsSpecified) { @@ -92,13 +92,12 @@ namespace Discord.Rest if (value.Length > 0) { var attachments = ImmutableArray.CreateBuilder(value.Length); - foreach (var t in value) - attachments.Add(Attachment.Create(t, Discord)); - + for (int i = 0; i < value.Length; i++) + attachments.Add(Attachment.Create(value[i], Discord)); _attachments = attachments.ToImmutable(); } else - _attachments = []; + _attachments = ImmutableArray.Create(); } if (model.Embeds.IsSpecified) @@ -107,13 +106,12 @@ namespace Discord.Rest if (value.Length > 0) { var embeds = ImmutableArray.CreateBuilder(value.Length); - foreach (var t in value) - embeds.Add(t.ToEntity()); - + for (int i = 0; i < value.Length; i++) + embeds.Add(value[i].ToEntity()); _embeds = embeds.ToImmutable(); } else - _embeds = []; + _embeds = ImmutableArray.Create(); } var guildId = (Channel as IGuildChannel)?.GuildId; @@ -125,7 +123,7 @@ namespace Discord.Rest model.Content = text; } - if (model.ReferencedMessage is { IsSpecified: true, Value: not null }) + if (model.ReferencedMessage.IsSpecified && model.ReferencedMessage.Value != null) { var refMsg = model.ReferencedMessage.Value; IUser refMsgAuthor = MessageHelper.GetAuthor(Discord, guild, refMsg.Author.Value, refMsg.WebhookId.ToNullable()); @@ -143,7 +141,7 @@ namespace Discord.Rest _stickers = stickers.ToImmutable(); } else - _stickers = []; + _stickers = ImmutableArray.Create(); } if (model.Resolved.IsSpecified) diff --git a/src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs b/src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs deleted file mode 100644 index 96893f7e..00000000 --- a/src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System.Collections.Immutable; -using System.Linq; - -namespace Discord.Rest; - -internal static class MessageComponentExtension -{ - internal static IMessageComponent ToModel(this IMessageComponent component) - { - switch (component) - { - case ActionRowComponent actionRow: - return new API.ActionRowComponent(actionRow); - - case ButtonComponent btn: - return new API.ButtonComponent(btn); - - case SelectMenuComponent select: - return new API.SelectMenuComponent(select); - - case TextInputComponent textInput: - return new API.TextInputComponent(textInput); - - case TextDisplayComponent textDisplay: - return new API.TextDisplayComponent(textDisplay); - - case SectionComponent section: - return new API.SectionComponent(section); - - case ThumbnailComponent thumbnail: - return new API.ThumbnailComponent(thumbnail); - - case MediaGalleryComponent mediaGallery: - return new API.MediaGalleryComponent(mediaGallery); - - case SeparatorComponent separator: - return new API.SeparatorComponent(separator); - - case FileComponent file: - return new API.FileComponent(file); - - case ContainerComponent container: - return new API.ContainerComponent(container); - } - - return null; - } - - internal static IMessageComponent ToEntity(this IMessageComponent component) - { - switch (component.Type) - { - case ComponentType.ActionRow: - { - var parsed = (API.ActionRowComponent)component; - return new ActionRowComponent - { - Id = component.Id, - Components = parsed.Components.Select(x => x.ToEntity()).ToImmutableArray() - }; - } - - case ComponentType.Button: - { - var parsed = (API.ButtonComponent)component; - return new ButtonComponent( - parsed.Style, - parsed.Label.GetValueOrDefault(), - parsed.Emote.IsSpecified - ? parsed.Emote.Value.Id.HasValue - ? new Emote(parsed.Emote.Value.Id.Value, parsed.Emote.Value.Name, parsed.Emote.Value.Animated.GetValueOrDefault()) - : new Emoji(parsed.Emote.Value.Name) - : null, - parsed.CustomId.GetValueOrDefault(), - parsed.Url.GetValueOrDefault(), - parsed.Disabled.GetValueOrDefault(), - parsed.SkuId.ToNullable(), - parsed.Id.ToNullable()); - } - - case ComponentType.SelectMenu or ComponentType.ChannelSelect or ComponentType.RoleSelect or ComponentType.MentionableSelect or ComponentType.UserSelect: - { - var parsed = (API.SelectMenuComponent)component; - return new SelectMenuComponent( - parsed.CustomId, - parsed.Options?.Select(z => new SelectMenuOption( - z.Label, - z.Value, - z.Description.GetValueOrDefault(), - z.Emoji.IsSpecified - ? z.Emoji.Value.Id.HasValue - ? new Emote(z.Emoji.Value.Id.Value, z.Emoji.Value.Name, z.Emoji.Value.Animated.GetValueOrDefault()) - : new Emoji(z.Emoji.Value.Name) - : null, - z.Default.ToNullable())).ToList(), - parsed.Placeholder.GetValueOrDefault(), - parsed.MinValues, - parsed.MaxValues, - parsed.Disabled, - parsed.Type, - parsed.Id.ToNullable(), - parsed.ChannelTypes.GetValueOrDefault(), - parsed.DefaultValues.IsSpecified - ? parsed.DefaultValues.Value.Select(x => new SelectMenuDefaultValue(x.Id, x.Type)) - : [] - ); - } - - case ComponentType.TextInput: - { - var parsed = (API.TextInputComponent)component; - return new TextInputComponent(parsed.CustomId, - parsed.Label, - parsed.Placeholder.GetValueOrDefault(null), - parsed.MinLength.ToNullable(), - parsed.MaxLength.ToNullable(), - parsed.Style, - parsed.Required.ToNullable(), - parsed.Value.GetValueOrDefault(null), - parsed.Id.ToNullable()); - } - - case ComponentType.TextDisplay: - { - var parsed = (API.TextDisplayComponent)component; - return new TextDisplayComponent(parsed.Content, parsed.Id.ToNullable()); - } - - case ComponentType.Section: - { - var parsed = (API.SectionComponent)component; - return new SectionComponent(parsed.Id.ToNullable(), - parsed.Components.Select(x => x.ToEntity()).ToImmutableArray(), - parsed.Accessory.ToEntity()); - } - - case ComponentType.Thumbnail: - { - var parsed = (API.ThumbnailComponent)component; - return new ThumbnailComponent(parsed.Id.ToNullable(), - parsed.Media.ToEntity(), - parsed.Description.GetValueOrDefault(null), - parsed.IsSpoiler.ToNullable()); - } - - case ComponentType.MediaGallery: - { - var parsed = (API.MediaGalleryComponent)component; - - return new MediaGalleryComponent( - parsed.Items.Select(x => new MediaGalleryItem(x.Media.ToEntity(), x.Description.GetValueOrDefault(null), x.IsSpoiler.GetValueOrDefault(false))).ToList(), - parsed.Id.ToNullable()); - } - - case ComponentType.Separator: - { - var parsed = (API.SeparatorComponent)component; - return new SeparatorComponent(parsed.IsDivider.ToNullable(), parsed.Spacing.ToNullable(), parsed.Id.ToNullable()); - } - - case ComponentType.File: - { - var parsed = (API.FileComponent)component; - return new FileComponent(parsed.File.ToEntity(), parsed.IsSpoiler.ToNullable(), parsed.Id.ToNullable()); - } - - case ComponentType.Container: - { - var parsed = (API.ContainerComponent)component; - return new ContainerComponent(parsed.Components.Select(x => x.ToEntity()).ToImmutableArray(), - parsed.AccentColor.GetValueOrDefault(null), - parsed.IsSpoiler.ToNullable(), - parsed.Id.ToNullable()); - } - - default: - return null; - } - } - - internal static UnfurledMediaItem ToEntity(this API.UnfurledMediaItem mediaItem) - { - return new ResolvedUnfurledMediaItem(mediaItem.Url, - mediaItem.ProxyUrl.GetValueOrDefault(null), - mediaItem.Height.GetValueOrDefault(0).GetValueOrDefault(0), - mediaItem.Width.GetValueOrDefault(0).GetValueOrDefault(0), - mediaItem.ContentType.GetValueOrDefault(null), - mediaItem.LoadingState.GetValueOrDefault(UnfurledMediaItemLoadingState.Unknown)); - } - - internal static API.UnfurledMediaItem ToModel(this UnfurledMediaItem mediaItem) - { - return new API.UnfurledMediaItem - { - Url = mediaItem.Url - }; - } -} diff --git a/src/Discord.Net.Rest/Net/Converters/MessageComponentConverter.cs b/src/Discord.Net.Rest/Net/Converters/MessageComponentConverter.cs index 0f229f33..7888219b 100644 --- a/src/Discord.Net.Rest/Net/Converters/MessageComponentConverter.cs +++ b/src/Discord.Net.Rest/Net/Converters/MessageComponentConverter.cs @@ -1,13 +1,12 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; -using System.ComponentModel; namespace Discord.Net.Converters { internal class MessageComponentConverter : JsonConverter { - public static MessageComponentConverter Instance => new (); + public static MessageComponentConverter Instance => new MessageComponentConverter(); public override bool CanRead => true; public override bool CanWrite => false; @@ -40,27 +39,6 @@ namespace Discord.Net.Converters case ComponentType.TextInput: messageComponent = new API.TextInputComponent(); break; - case ComponentType.TextDisplay: - messageComponent = new API.TextDisplayComponent(); - break; - case ComponentType.Thumbnail: - messageComponent = new API.ThumbnailComponent(); - break; - case ComponentType.Section: - messageComponent = new API.SectionComponent(); - break; - case ComponentType.MediaGallery: - messageComponent = new API.MediaGalleryComponent(); - break; - case ComponentType.Separator: - messageComponent = new API.SeparatorComponent(); - break; - case ComponentType.File: - messageComponent = new API.FileComponent(); - break; - case ComponentType.Container: - messageComponent = new API.ContainerComponent(); - break; } serializer.Populate(jsonObject.CreateReader(), messageComponent); return messageComponent; diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponent.cs b/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponent.cs index 984c8984..f24a4be6 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponent.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponent.cs @@ -82,8 +82,7 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -91,7 +90,7 @@ namespace Discord.WebSocket if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -116,13 +115,6 @@ namespace Discord.WebSocket } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); - var response = new API.Rest.UploadInteractionFileParams(attachments?.ToArray()) { Type = InteractionResponseType.ChannelMessageWithSource, @@ -130,8 +122,8 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions != null ? allowedMentions?.ToModel() : Optional.Unspecified, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, IsTTS = isTTS, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Flags = flags, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; @@ -157,8 +149,7 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -166,7 +157,7 @@ namespace Discord.WebSocket if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -176,28 +167,21 @@ namespace Discord.WebSocket Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list - if (allowedMentions is { AllowedTypes: not null }) + if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) { if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) && - allowedMentions.UserIds is { Count: > 0 }) + allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) { throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions)); } if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) && - allowedMentions.RoleIds is { Count: > 0 }) + allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) { throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); - var response = new API.InteractionResponse { Type = InteractionResponseType.ChannelMessageWithSource, @@ -207,8 +191,8 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions?.ToModel(), Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, - Flags = flags, - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -266,13 +250,13 @@ namespace Discord.WebSocket { var allowedMentions = args.AllowedMentions.Value; if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) - && allowedMentions.UserIds is { Count: > 0 }) + && allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) { throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(args.AllowedMentions)); } if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) - && allowedMentions.RoleIds is { Count: > 0 }) + && allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) { throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(args.AllowedMentions)); } @@ -289,8 +273,8 @@ namespace Discord.WebSocket AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, Components = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified } }; @@ -299,7 +283,7 @@ namespace Discord.WebSocket } else { - var attachments = args.Attachments.Value?.ToArray() ?? []; + var attachments = args.Attachments.Value?.ToArray() ?? Array.Empty(); var response = new API.Rest.UploadInteractionFileParams(attachments) { @@ -308,8 +292,8 @@ namespace Discord.WebSocket AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, MessageComponents = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified }; @@ -337,13 +321,12 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -352,25 +335,19 @@ namespace Discord.WebSocket Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); Preconditions.ValidatePoll(poll); - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); - - var args = new API.Rest.CreateWebhookMessageParams { Content = text, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Poll = poll?.ToModel() ?? Optional.Unspecified, - Flags = flags, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; + if (ephemeral) + args.Flags = MessageFlags.Ephemeral; + return InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options); } @@ -385,13 +362,12 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -409,24 +385,23 @@ namespace Discord.WebSocket if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) { if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) && - allowedMentions.UserIds is { Count: > 0 }) + allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) { throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions)); } if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) && - allowedMentions.RoleIds is { Count: > 0 }) + allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) { throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; + + var flags = MessageFlags.None; + if (ephemeral) flags |= MessageFlags.Ephemeral; - Preconditions.ValidateMessageFlags(flags); - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, @@ -434,7 +409,7 @@ namespace Discord.WebSocket IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponentData.cs b/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponentData.cs index 718cc3b1..b193b77f 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponentData.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponentData.cs @@ -90,13 +90,13 @@ namespace Discord.WebSocket } } - internal SocketMessageComponentData(IInteractableComponent component, DiscordSocketClient discord, ClientState state, SocketGuild guild, API.User dmUser) + internal SocketMessageComponentData(IMessageComponent component, DiscordSocketClient discord, ClientState state, SocketGuild guild, API.User dmUser) { CustomId = component.CustomId; Type = component.Type; Value = component.Type == ComponentType.TextInput - ? ((TextInputComponent)component).Value + ? (component as API.TextInputComponent).Value.Value : null; if (component is API.SelectMenuComponent select) diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModal.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModal.cs index a6de28d3..7b1b0a65 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModal.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModal.cs @@ -79,8 +79,7 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -88,7 +87,7 @@ namespace Discord.WebSocket if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -112,12 +111,6 @@ namespace Discord.WebSocket throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); var response = new API.Rest.UploadInteractionFileParams(attachments?.ToArray()) { @@ -126,8 +119,8 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions != null ? allowedMentions?.ToModel() : Optional.Unspecified, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, IsTTS = isTTS, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Flags = flags, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; @@ -143,7 +136,7 @@ namespace Discord.WebSocket HasResponded = true; } - /// + /// public override async Task RespondAsync( string text = null, Embed[] embeds = null, @@ -153,8 +146,7 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -162,7 +154,7 @@ namespace Discord.WebSocket if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -172,28 +164,21 @@ namespace Discord.WebSocket Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list - if (allowedMentions is { AllowedTypes: not null }) + if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) { if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) && - allowedMentions.UserIds is { Count: > 0 }) + allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0) { throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions)); } if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) && - allowedMentions.RoleIds is { Count: > 0 }) + allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0) { throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); - var response = new API.InteractionResponse { Type = InteractionResponseType.ChannelMessageWithSource, @@ -203,8 +188,8 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions?.ToModel(), Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, - Flags = flags, - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -285,11 +270,9 @@ namespace Discord.WebSocket AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, Components = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, - Flags = args.Flags.IsSpecified - ? args.Flags.Value ?? Optional.Unspecified - : Optional.Unspecified + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, + Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified } }; @@ -306,8 +289,8 @@ namespace Discord.WebSocket AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional.Unspecified, Embeds = apiEmbeds?.ToArray() ?? Optional.Unspecified, MessageComponents = args.Components.IsSpecified - ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] - : Optional.Unspecified, + ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty() + : Optional.Unspecified, Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional.Unspecified : Optional.Unspecified }; @@ -335,13 +318,12 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -350,24 +332,20 @@ namespace Discord.WebSocket Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); Preconditions.ValidatePoll(poll); - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); - var args = new API.Rest.CreateWebhookMessageParams { Content = text, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Flags = flags, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; + if (ephemeral) + args.Flags = MessageFlags.Ephemeral; + return InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options); } @@ -382,13 +360,12 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -418,13 +395,11 @@ namespace Discord.WebSocket } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; + var flags = MessageFlags.None; + if (ephemeral) flags |= MessageFlags.Ephemeral; - Preconditions.ValidateMessageFlags(flags); - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, @@ -432,7 +407,7 @@ namespace Discord.WebSocket IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModalData.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModalData.cs index a7787666..52c7615b 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModalData.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModalData.cs @@ -1,6 +1,8 @@ -using Discord.Rest; +using System; using System.Collections.Generic; using System.Linq; +using DataModel = Discord.API.MessageComponentInteractionData; +using InterationModel = Discord.API.Interaction; using Model = Discord.API.ModalInteractionData; namespace Discord.WebSocket @@ -24,7 +26,7 @@ namespace Discord.WebSocket { CustomId = model.CustomId; Components = model.Components - .SelectMany(x => x.Components.Select(y => y.ToEntity()).OfType()) + .SelectMany(x => x.Components) .Select(x => new SocketMessageComponentData(x, discord, state, guild, dmUser)) .ToArray(); } diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SlashCommands/SocketAutocompleteInteraction.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SlashCommands/SocketAutocompleteInteraction.cs index c4521513..7e6b484a 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/SlashCommands/SocketAutocompleteInteraction.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/SlashCommands/SocketAutocompleteInteraction.cs @@ -91,15 +91,15 @@ namespace Discord.WebSocket /// public Task RespondAsync(RequestOptions options = null, params AutocompleteResult[] result) => RespondAsync(result, options); - public override Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); public override Task DeferAsync(bool ephemeral = false, RequestOptions options = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + public override Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); /// diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs index 075e4e31..3b6da477 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs @@ -77,8 +77,7 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -86,7 +85,7 @@ namespace Discord.WebSocket if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -111,13 +110,6 @@ namespace Discord.WebSocket } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); - var response = new API.InteractionResponse { Type = InteractionResponseType.ChannelMessageWithSource, @@ -127,8 +119,8 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Flags = flags, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -191,8 +183,7 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -200,7 +191,7 @@ namespace Discord.WebSocket if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck) throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -225,13 +216,6 @@ namespace Discord.WebSocket } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); - var response = new API.Rest.UploadInteractionFileParams(attachments?.ToArray()) { Type = InteractionResponseType.ChannelMessageWithSource, @@ -239,8 +223,8 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions != null ? allowedMentions?.ToModel() : Optional.Unspecified, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, IsTTS = isTTS, - Flags = flags, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; @@ -266,13 +250,12 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -281,24 +264,19 @@ namespace Discord.WebSocket Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); Preconditions.ValidatePoll(poll); - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - if (ephemeral) - flags |= MessageFlags.Ephemeral; - - Preconditions.ValidateMessageFlags(flags); - var args = new API.Rest.CreateWebhookMessageParams { Content = text ?? Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, - Poll = poll?.ToModel() ?? Optional.Unspecified, - Flags = flags, + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; + if (ephemeral) + args.Flags = MessageFlags.Ephemeral; + return InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options); } @@ -313,13 +291,12 @@ namespace Discord.WebSocket MessageComponent components = null, Embed embed = null, RequestOptions options = null, - PollProperties poll = null, - MessageFlags flags = MessageFlags.None) + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); - embeds ??= []; + embeds ??= Array.Empty(); if (embed != null) embeds = new[] { embed }.Concat(embeds).ToArray(); @@ -349,13 +326,11 @@ namespace Discord.WebSocket } } - if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; + var flags = MessageFlags.None; + if (ephemeral) flags |= MessageFlags.Ephemeral; - Preconditions.ValidateMessageFlags(flags); - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, @@ -363,7 +338,7 @@ namespace Discord.WebSocket IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Poll = poll?.ToModel() ?? Optional.Unspecified }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs index cadb24d8..685d57ff 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs @@ -216,7 +216,7 @@ namespace Discord.WebSocket /// Message content is too long, length must be less or equal to . /// The parameters provided were invalid or the token was invalid. public abstract Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, - bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Responds to this interaction with a file attachment. @@ -237,11 +237,11 @@ namespace Discord.WebSocket /// contains the sent message. /// public async Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(fileStream, fileName)) { - await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } @@ -264,11 +264,11 @@ namespace Discord.WebSocket /// contains the sent message. /// public async Task RespondWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(filePath, fileName)) { - await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } @@ -290,8 +290,8 @@ namespace Discord.WebSocket /// contains the sent message. /// public Task RespondWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => RespondWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => RespondWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); /// /// Responds to this interaction with a collection of file attachments. @@ -311,7 +311,7 @@ namespace Discord.WebSocket /// contains the sent message. /// public abstract Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -329,7 +329,7 @@ namespace Discord.WebSocket /// The sent message. /// public abstract Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -349,11 +349,11 @@ namespace Discord.WebSocket /// The sent message. /// public async Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(fileStream, fileName)) { - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } @@ -375,11 +375,11 @@ namespace Discord.WebSocket /// The sent message. /// public async Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(filePath, fileName)) { - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } @@ -401,8 +401,8 @@ namespace Discord.WebSocket /// contains the sent message. /// public Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None) - => FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); /// /// Sends a followup message for this interaction. @@ -422,7 +422,7 @@ namespace Discord.WebSocket /// contains the sent message. /// public abstract Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Gets the original response for this interaction. @@ -509,26 +509,26 @@ namespace Discord.WebSocket => await ModifyOriginalResponseAsync(func, options).ConfigureAwait(false); /// async Task IDiscordInteraction.RespondAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, - Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + Embed embed, RequestOptions options, PollProperties poll) + => await RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// async Task IDiscordInteraction.FollowupAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, - MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// async Task IDiscordInteraction.FollowupWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, - bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); #if NETCOREAPP3_0_OR_GREATER != true /// - async Task IDiscordInteraction.FollowupWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - async Task IDiscordInteraction.FollowupWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - async Task IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) - => await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); #endif #endregion } diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs index 46e48fce..05423c33 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; - using Model = Discord.API.Message; namespace Discord.WebSocket @@ -65,8 +64,8 @@ namespace Discord.WebSocket /// public MessageReference Reference { get; private set; } - /// - public IReadOnlyCollection Components { get; private set; } + /// + public IReadOnlyCollection Components { get; private set; } /// /// Gets the interaction this message is a response to. @@ -214,9 +213,62 @@ namespace Discord.WebSocket }; } - Components = model.Components.IsSpecified - ? model.Components.Value.Select(x => x.ToEntity()).ToImmutableArray() - : []; + if (model.Components.IsSpecified) + { + Components = model.Components.Value.Where(x => x.Type is ComponentType.ActionRow) + .Select(x => new ActionRowComponent(((API.ActionRowComponent)x).Components.Select(y => + { + switch (y.Type) + { + case ComponentType.Button: + { + var parsed = (API.ButtonComponent)y; + return new Discord.ButtonComponent( + parsed.Style, + parsed.Label.GetValueOrDefault(), + parsed.Emote.IsSpecified + ? parsed.Emote.Value.Id.HasValue + ? new Emote(parsed.Emote.Value.Id.Value, parsed.Emote.Value.Name, parsed.Emote.Value.Animated.GetValueOrDefault()) + : new Emoji(parsed.Emote.Value.Name) + : null, + parsed.CustomId.GetValueOrDefault(), + parsed.Url.GetValueOrDefault(), + parsed.Disabled.GetValueOrDefault(), + parsed.SkuId.ToNullable()); + } + case ComponentType.SelectMenu: + { + var parsed = (API.SelectMenuComponent)y; + return new SelectMenuComponent( + parsed.CustomId, + parsed.Options.Select(z => new SelectMenuOption( + z.Label, + z.Value, + z.Description.GetValueOrDefault(), + z.Emoji.IsSpecified + ? z.Emoji.Value.Id.HasValue + ? new Emote(z.Emoji.Value.Id.Value, z.Emoji.Value.Name, z.Emoji.Value.Animated.GetValueOrDefault()) + : new Emoji(z.Emoji.Value.Name) + : null, + z.Default.ToNullable())).ToList(), + parsed.Placeholder.GetValueOrDefault(), + parsed.MinValues, + parsed.MaxValues, + parsed.Disabled, + parsed.Type, + parsed.ChannelTypes.GetValueOrDefault(), + parsed.DefaultValues.IsSpecified + ? parsed.DefaultValues.Value.Select(x => new SelectMenuDefaultValue(x.Id, x.Type)) + : Array.Empty() + ); + } + default: + return null; + } + }).ToList())).ToImmutableArray(); + } + else + Components = new List(); if (model.UserMentions.IsSpecified) { @@ -281,7 +333,7 @@ namespace Discord.WebSocket ? new GuildProductPurchase(model.PurchaseNotification.Value.ProductPurchase.Value.ListingId, model.PurchaseNotification.Value.ProductPurchase.Value.ProductName) : null); } - + if (model.Call.IsSpecified) CallData = new MessageCallData(model.Call.Value.Participants, model.Call.Value.EndedTimestamp.ToNullable()); } diff --git a/src/Discord.Net.Webhook/WebhookClientHelper.cs b/src/Discord.Net.Webhook/WebhookClientHelper.cs index b8861de9..47db9a21 100644 --- a/src/Discord.Net.Webhook/WebhookClientHelper.cs +++ b/src/Discord.Net.Webhook/WebhookClientHelper.cs @@ -29,11 +29,6 @@ namespace Discord.Webhook MessageFlags flags, ulong? threadId = null, string threadName = null, ulong[] appliedTags = null, PollProperties poll = null) { - if (components?.Components.Any(x => x.Type is not ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - - Preconditions.ValidateMessageFlags(flags); - var args = new CreateWebhookMessageParams { Content = text, @@ -53,7 +48,7 @@ namespace Discord.Webhook if (allowedMentions != null) args.AllowedMentions = allowedMentions.ToModel(); if (components != null) - args.Components = components?.Components.Select(x => x.ToModel()).ToArray(); + args.Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray(); if (threadName is not null) args.ThreadName = threadName; if (appliedTags != null) @@ -61,6 +56,8 @@ namespace Discord.Webhook if (poll != null) args.Poll = poll.ToModel(); + if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification) + throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds, SuppressNotification and none.", nameof(flags)); var model = await client.ApiClient.CreateWebhookMessageAsync(client.Webhook.Id, args, options: options, threadId: threadId).ConfigureAwait(false); return model.Id; @@ -111,14 +108,14 @@ namespace Discord.Webhook AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Create(), - Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified, }; return client.ApiClient.ModifyWebhookMessageAsync(client.Webhook.Id, messageId, apiArgs, options, threadId); } else { - var attachments = args.Attachments.Value?.ToArray() ?? []; + var attachments = args.Attachments.Value?.ToArray() ?? Array.Empty(); var apiArgs = new UploadWebhookFileParams(attachments) { @@ -130,7 +127,7 @@ namespace Discord.Webhook AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Create(), - MessageComponents = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + MessageComponents = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional.Unspecified, }; return client.ApiClient.ModifyWebhookMessageAsync(client.Webhook.Id, messageId, apiArgs, options, threadId); @@ -196,10 +193,8 @@ namespace Discord.Webhook } } - if (components?.Components.Any(x => x.Type is not ComponentType.ActionRow) ?? false) - flags |= MessageFlags.ComponentsV2; - - Preconditions.ValidateMessageFlags(flags); + if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification) + throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds, SuppressNotification and none.", nameof(flags)); var args = new UploadWebhookFileParams(attachments.ToArray()) { @@ -209,7 +204,7 @@ namespace Discord.Webhook IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, - MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Flags = flags, ThreadName = threadName, AppliedTags = appliedTags,