From f506b9878043aa7396a07d30ff46034420656049 Mon Sep 17 00:00:00 2001 From: quin lynch Date: Fri, 28 May 2021 05:07:36 -0300 Subject: [PATCH] Closes #6. Closes #4. Fix emote parsing, added components to socket and rest messages. --- .../Message Components/ActionRowComponent.cs | 6 +- .../Message Components/ButtonComponent.cs | 9 +-- .../Message Components/ComponentBuilder.cs | 20 ++++-- .../Message Components/MessageComponent.cs | 5 +- .../API/Common/ActionRowComponent.cs | 25 ++++++++ .../API/Common/ButtonComponent.cs | 64 +++++++++++++++++++ ...teractionApplicationCommandCallbackData.cs | 2 +- src/Discord.Net.Rest/API/Common/Message.cs | 2 +- .../API/Rest/CreateMessageParams.cs | 2 +- .../API/Rest/CreateWebhookMessageParams.cs | 2 +- .../API/Rest/UploadFileParams.cs | 2 +- .../Entities/Channels/ChannelHelper.cs | 4 +- .../Entities/Messages/RestMessage.cs | 13 +++- .../SocketMessageComponent.cs | 4 +- .../Slash Commands/SocketSlashCommand.cs | 4 +- .../Entities/Messages/SocketMessage.cs | 13 +++- 16 files changed, 139 insertions(+), 38 deletions(-) create mode 100644 src/Discord.Net.Rest/API/Common/ActionRowComponent.cs create mode 100644 src/Discord.Net.Rest/API/Common/ButtonComponent.cs diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ActionRowComponent.cs b/src/Discord.Net.Core/Entities/Interactions/Message Components/ActionRowComponent.cs index 7151cc5af..fb6168218 100644 --- a/src/Discord.Net.Core/Entities/Interactions/Message Components/ActionRowComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/Message Components/ActionRowComponent.cs @@ -9,14 +9,12 @@ namespace Discord { public class ActionRowComponent : IMessageComponent { - [JsonProperty("type")] public ComponentType Type { get; } = ComponentType.ActionRow; - [JsonProperty("components")] - public IReadOnlyCollection Components { get; internal set; } + public IReadOnlyCollection Components { get; internal set; } internal ActionRowComponent() { } - internal ActionRowComponent(IReadOnlyCollection components) + internal ActionRowComponent(List components) { this.Components = components; } diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonComponent.cs b/src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonComponent.cs index 2e2b98f98..973e24da5 100644 --- a/src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonComponent.cs @@ -9,25 +9,18 @@ namespace Discord { public class ButtonComponent : IMessageComponent { - [JsonProperty("type")] public ComponentType Type { get; } = ComponentType.Button; - [JsonProperty("style")] public ButtonStyle Style { get; } - [JsonProperty("label")] public string Label { get; } - [JsonProperty("emoji")] public IEmote Emote { get; } - [JsonProperty("custom_id")] public string CustomId { get; } - [JsonProperty("url")] public string Url { get; } - [JsonProperty("disabled")] public bool Disabled { get; } internal ButtonComponent(ButtonStyle style, string label, IEmote emote, string customId, string url, bool disabled) @@ -39,5 +32,7 @@ namespace Discord this.Url = url; this.Disabled = disabled; } + + } } diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs index 147667e72..e4937a795 100644 --- a/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs @@ -87,7 +87,7 @@ namespace Discord public class ActionRowBuilder { public const int MaxChildCount = 5; - public List Components + public List Components { get => _components; set @@ -99,18 +99,18 @@ namespace Discord } } - private List _components { get; set; } + private List _components { get; set; } - public ActionRowBuilder WithComponents(List components) + public ActionRowBuilder WithComponents(List components) { this.Components = components; return this; } - public ActionRowBuilder WithComponent(IMessageComponent component) + public ActionRowBuilder WithComponent(ButtonComponent component) { if (this.Components == null) - this.Components = new List(); + this.Components = new List(); this.Components.Add(component); @@ -118,7 +118,15 @@ namespace Discord } public ActionRowComponent Build() - => new ActionRowComponent(this._components); + { + if (this.Components == null) + throw new ArgumentNullException($"{nameof(Components)} cannot be null!"); + + if (this.Components.Count == 0) + throw new ArgumentException("There must be at least 1 component in a row"); + + return new ActionRowComponent(this._components); + } } public class ButtonBuilder diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/MessageComponent.cs b/src/Discord.Net.Core/Entities/Interactions/Message Components/MessageComponent.cs index 1ee8dd953..7356b8c5b 100644 --- a/src/Discord.Net.Core/Entities/Interactions/Message Components/MessageComponent.cs +++ b/src/Discord.Net.Core/Entities/Interactions/Message Components/MessageComponent.cs @@ -8,7 +8,7 @@ namespace Discord { public class MessageComponent { - public IReadOnlyCollection Components { get; } + public IReadOnlyCollection Components { get; } internal MessageComponent(List components) { @@ -17,8 +17,5 @@ namespace Discord internal static MessageComponent Empty => new MessageComponent(new List()); - - internal IMessageComponent[] ToModel() - => this.Components.ToArray(); } } diff --git a/src/Discord.Net.Rest/API/Common/ActionRowComponent.cs b/src/Discord.Net.Rest/API/Common/ActionRowComponent.cs new file mode 100644 index 000000000..7fddac1cf --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/ActionRowComponent.cs @@ -0,0 +1,25 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discord.API +{ + internal class ActionRowComponent + { + [JsonProperty("type")] + public ComponentType Type { get; set; } + + [JsonProperty("components")] + public List Components { get; set; } + + internal ActionRowComponent() { } + internal ActionRowComponent(Discord.ActionRowComponent c) + { + this.Type = c.Type; + this.Components = c.Components?.Select(x => new ButtonComponent(x)).ToList(); + } + } +} diff --git a/src/Discord.Net.Rest/API/Common/ButtonComponent.cs b/src/Discord.Net.Rest/API/Common/ButtonComponent.cs new file mode 100644 index 000000000..3c8fcca8c --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/ButtonComponent.cs @@ -0,0 +1,64 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discord.API +{ + internal class ButtonComponent + { + [JsonProperty("type")] + public ComponentType Type { get; set; } + + [JsonProperty("style")] + public ButtonStyle Style { get; set; } + + [JsonProperty("label")] + public string Label { get; set; } + + [JsonProperty("emoji")] + public Emoji Emote { get; set; } + + [JsonProperty("custom_id")] + public string CustomId { get; set; } + + [JsonProperty("url")] + public string Url { get; set; } + + [JsonProperty("disabled")] + public bool Disabled { get; set; } + + + public ButtonComponent() { } + + public ButtonComponent(Discord.ButtonComponent c) + { + this.Type = c.Type; + this.Style = c.Style; + this.Label = c.Label; + this.CustomId = c.CustomId; + this.Url = c.Url; + this.Disabled = c.Disabled; + + if (c.Emote is Emote e) + { + this.Emote = new Emoji() + { + Name = e.Name, + Animated = e.Animated, + Id = e.Id, + }; + } + else + { + this.Emote = new Emoji() + { + Name = c.Emote.Name + }; + } + + } + } +} diff --git a/src/Discord.Net.Rest/API/Common/InteractionApplicationCommandCallbackData.cs b/src/Discord.Net.Rest/API/Common/InteractionApplicationCommandCallbackData.cs index f5ce75250..3f7cf93e0 100644 --- a/src/Discord.Net.Rest/API/Common/InteractionApplicationCommandCallbackData.cs +++ b/src/Discord.Net.Rest/API/Common/InteractionApplicationCommandCallbackData.cs @@ -26,7 +26,7 @@ namespace Discord.API public Optional Flags { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } public InteractionApplicationCommandCallbackData() { } public InteractionApplicationCommandCallbackData(string text) diff --git a/src/Discord.Net.Rest/API/Common/Message.cs b/src/Discord.Net.Rest/API/Common/Message.cs index c3d88eedb..4ce8956eb 100644 --- a/src/Discord.Net.Rest/API/Common/Message.cs +++ b/src/Discord.Net.Rest/API/Common/Message.cs @@ -59,6 +59,6 @@ namespace Discord.API [JsonProperty("referenced_message")] public Optional ReferencedMessage { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } } } diff --git a/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs b/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs index 703101313..0d6710a03 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs @@ -25,7 +25,7 @@ namespace Discord.API.Rest public Optional MessageReference { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } public CreateMessageParams(string content) { Content = content; diff --git a/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs b/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs index c668ee484..528bf8e07 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs @@ -31,7 +31,7 @@ namespace Discord.API.Rest public Optional Flags { get; set; } [JsonProperty("components")] - public Optional Components { get; set; } + public Optional Components { get; set; } public CreateWebhookMessageParams(string content) { diff --git a/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs b/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs index 3b78489aa..27336a11a 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 Embed { get; set; } public Optional AllowedMentions { get; set; } public Optional MessageReference { get; set; } - public Optional MessageComponent { get; set; } + public Optional MessageComponent { get; set; } public bool IsSpoiler { get; set; } = false; public UploadFileParams(Stream file) diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs index 69fcd2cb4..894b820c8 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs @@ -221,7 +221,7 @@ namespace Discord.Rest } } - var args = new CreateMessageParams(text) { IsTTS = isTTS, Embed = embed?.ToModel(), AllowedMentions = allowedMentions?.ToModel(), MessageReference = messageReference?.ToModel(), Components = component?.ToModel() }; + var args = new CreateMessageParams(text) { IsTTS = isTTS, Embed = embed?.ToModel(), AllowedMentions = allowedMentions?.ToModel(), MessageReference = messageReference?.ToModel(), Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; var model = await client.ApiClient.CreateMessageAsync(channel.Id, args, options).ConfigureAwait(false); return RestUserMessage.Create(client, channel, client.CurrentUser, model); } @@ -281,7 +281,7 @@ namespace Discord.Rest } } - var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS, Embed = embed?.ToModel() ?? Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageReference = messageReference?.ToModel() ?? Optional.Unspecified, MessageComponent = component?.ToModel() ?? Optional.Unspecified, IsSpoiler = isSpoiler }; + var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS, Embed = embed?.ToModel() ?? Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageReference = messageReference?.ToModel() ?? Optional.Unspecified, MessageComponent = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, IsSpoiler = isSpoiler }; var model = await client.ApiClient.UploadFileAsync(channel.Id, args, options).ConfigureAwait(false); return RestUserMessage.Create(client, channel, client.CurrentUser, model); } diff --git a/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs index 068ed1511..1a568992b 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs @@ -129,9 +129,16 @@ namespace Discord.Rest if (model.Components.IsSpecified) { - Components = model.Components.Value.Select(x => - (x as Newtonsoft.Json.Linq.JToken).ToObject() - ).ToList(); + Components = model.Components.Value.Select(x => new ActionRowComponent(x.Components.Select(x => + new ButtonComponent( + x.Style, + x.Label, + x.Emote.Id.HasValue ? new Emote(x.Emote.Id.Value, x.Emote.Name, x.Emote.Animated.GetValueOrDefault()) : new Emoji(x.Emote.Name), + x.CustomId, + x.Url, + x.Disabled) + ).ToList() + )).ToList(); } else Components = new List(); diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs index a05fae3cc..7d5ddfb17 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs @@ -94,7 +94,7 @@ namespace Discord.WebSocket ? new API.Embed[] { embed.ToModel() } : Optional.Unspecified, TTS = isTTS, - Components = component?.ToModel() ?? Optional.Unspecified + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified } }; @@ -134,7 +134,7 @@ namespace Discord.WebSocket Embeds = embed != null ? new API.Embed[] { embed.ToModel() } : Optional.Unspecified, - Components = component?.ToModel() ?? Optional.Unspecified + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; if (ephemeral) diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs index da94c4625..9010d1eea 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/Slash Commands/SocketSlashCommand.cs @@ -110,7 +110,7 @@ namespace Discord.WebSocket ? new API.Embed[] { embed.ToModel() } : Optional.Unspecified, TTS = isTTS, - Components = component?.ToModel() ?? Optional.Unspecified + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified } }; @@ -149,7 +149,7 @@ namespace Discord.WebSocket Embeds = embed != null ? new API.Embed[] { embed.ToModel() } : Optional.Unspecified, - Components = component?.ToModel() ?? Optional.Unspecified + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; if (ephemeral) diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs index 5df2d1acb..e6052c179 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs @@ -162,9 +162,16 @@ namespace Discord.WebSocket if (model.Components.IsSpecified) { - Components = model.Components.Value.Select(x => - (x as Newtonsoft.Json.Linq.JToken).ToObject() - ).ToList(); + Components = model.Components.Value.Select(x => new ActionRowComponent(x.Components.Select(x => + new ButtonComponent( + x.Style, + x.Label, + x.Emote.Id.HasValue ? new Emote(x.Emote.Id.Value, x.Emote.Name, x.Emote.Animated.GetValueOrDefault()) : new Emoji(x.Emote.Name), + x.CustomId, + x.Url, + x.Disabled) + ).ToList() + )).ToList(); } else Components = new List();