diff --git a/src/Discord.Net.Core/API/Common/Message.cs b/src/Discord.Net.Core/API/Common/Message.cs index 2c19780b1..f812d0622 100644 --- a/src/Discord.Net.Core/API/Common/Message.cs +++ b/src/Discord.Net.Core/API/Common/Message.cs @@ -36,5 +36,7 @@ namespace Discord.API public Optional Embeds { get; set; } [JsonProperty("pinned")] public Optional Pinned { get; set; } + [JsonProperty("reactions")] + public Optional Reactions { get; set; } } } diff --git a/src/Discord.Net.Core/API/Common/Reaction.cs b/src/Discord.Net.Core/API/Common/Reaction.cs index 69dbf4b0c..e143004ef 100644 --- a/src/Discord.Net.Core/API/Common/Reaction.cs +++ b/src/Discord.Net.Core/API/Common/Reaction.cs @@ -4,17 +4,15 @@ using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; -namespace Discord.API.Common +namespace Discord.API { public class Reaction { - [JsonProperty("user_id")] - public ulong UserId { get; set; } - [JsonProperty("message_id")] - public ulong MessageId { get; set; } + [JsonProperty("count")] + public int Count { get; set; } + [JsonProperty("me")] + public bool Me { get; set; } [JsonProperty("emoji")] public Emoji Emoji { get; set; } - [JsonProperty("channel_id")] - public ulong ChannelId { get; set; } } } diff --git a/src/Discord.Net.Core/Entities/Messages/IMessage.cs b/src/Discord.Net.Core/Entities/Messages/IMessage.cs index 6bb44368b..13f3b662a 100644 --- a/src/Discord.Net.Core/Entities/Messages/IMessage.cs +++ b/src/Discord.Net.Core/Entities/Messages/IMessage.cs @@ -31,6 +31,8 @@ namespace Discord IReadOnlyCollection Attachments { get; } /// Returns all embeds included in this message. IReadOnlyCollection Embeds { get; } + /// Returns all reactions included in this message. + IReadOnlyCollection Reactions { get; } /// Returns all tags included in this message's content. IReadOnlyCollection Tags { get; } /// Returns the ids of channels mentioned in this message. diff --git a/src/Discord.Net.Core/Entities/Messages/IReaction.cs b/src/Discord.Net.Core/Entities/Messages/IReaction.cs new file mode 100644 index 000000000..5d7eae44e --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/IReaction.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Discord +{ + public interface IReaction + { + API.Emoji Emoji { get; } + } +} diff --git a/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs index ea064dd81..41cff4380 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestMessage.cs @@ -27,6 +27,7 @@ namespace Discord.Rest public virtual IReadOnlyCollection MentionedRoleIds => ImmutableArray.Create(); public virtual IReadOnlyCollection MentionedUsers => ImmutableArray.Create(); public virtual IReadOnlyCollection Tags => ImmutableArray.Create(); + public virtual IReadOnlyCollection Reactions => ImmutableArray.Create(); public virtual ulong? WebhookId => null; public bool IsWebhook => WebhookId != null; @@ -70,5 +71,6 @@ namespace Discord.Rest IReadOnlyCollection IMessage.Attachments => Attachments; IReadOnlyCollection IMessage.Embeds => Embeds; IReadOnlyCollection IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); + IReadOnlyCollection IMessage.Reactions => Reactions; } } diff --git a/src/Discord.Net.Rest/Entities/Messages/RestReaction.cs b/src/Discord.Net.Rest/Entities/Messages/RestReaction.cs new file mode 100644 index 000000000..2fb534ce4 --- /dev/null +++ b/src/Discord.Net.Rest/Entities/Messages/RestReaction.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Model = Discord.API.Reaction; + +namespace Discord +{ + public class RestReaction : IReaction + { + internal RestReaction(Model model) + { + _emoji = model.Emoji; + _count = model.Count; + + } + + internal readonly API.Emoji _emoji; + internal readonly int _count; + internal readonly bool _me; + + public API.Emoji Emoji => _emoji; + public int Count => _count; + public bool Me => _me; + } +} diff --git a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs index 66d270fdd..2625718c7 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs @@ -18,6 +18,7 @@ namespace Discord.Rest private ImmutableArray _attachments; private ImmutableArray _embeds; private ImmutableArray _tags; + private ImmutableArray _reactions; public override bool IsTTS => _isTTS; public override bool IsPinned => _isPinned; @@ -29,6 +30,7 @@ namespace Discord.Rest public override IReadOnlyCollection MentionedRoleIds => MessageHelper.FilterTagsByKey(TagType.RoleMention, _tags); public override IReadOnlyCollection MentionedUsers => MessageHelper.FilterTagsByValue(TagType.UserMention, _tags); public override IReadOnlyCollection Tags => _tags; + public override IReadOnlyCollection Reactions => _reactions; internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, RestUser author, IGuild guild) : base(discord, id, channel, author, guild) @@ -103,6 +105,20 @@ namespace Discord.Rest } } + if (model.Reactions.IsSpecified) + { + var value = model.Reactions.Value; + if (value.Length > 0) + { + var reactions = ImmutableArray.CreateBuilder(value.Length); + for (int i = 0; i < value.Length; i++) + reactions.Add(new RestReaction(value[i])); + _reactions = reactions.ToImmutable(); + } + else + _reactions = ImmutableArray.Create(); + } + if (model.Content.IsSpecified) { var text = model.Content.Value; diff --git a/src/Discord.Net.Rpc/Entities/Messages/RpcMessage.cs b/src/Discord.Net.Rpc/Entities/Messages/RpcMessage.cs index d0464487b..35e4ef52e 100644 --- a/src/Discord.Net.Rpc/Entities/Messages/RpcMessage.cs +++ b/src/Discord.Net.Rpc/Entities/Messages/RpcMessage.cs @@ -28,6 +28,7 @@ namespace Discord.Rpc public virtual IReadOnlyCollection MentionedRoleIds => ImmutableArray.Create(); public virtual IReadOnlyCollection MentionedUserIds => ImmutableArray.Create(); public virtual IReadOnlyCollection Tags => ImmutableArray.Create(); + public virtual IReadOnlyCollection Reactions => ImmutableArray.Create(); public virtual ulong? WebhookId => null; public bool IsWebhook => WebhookId != null; diff --git a/src/Discord.Net.WebSocket/API/Gateway/GatewayReaction.cs b/src/Discord.Net.WebSocket/API/Gateway/GatewayReaction.cs new file mode 100644 index 000000000..096159478 --- /dev/null +++ b/src/Discord.Net.WebSocket/API/Gateway/GatewayReaction.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace Discord.API.Gateway +{ + public class GatewayReaction : Reaction + { + [JsonProperty("user_id")] + public ulong UserId { get; set; } + [JsonProperty("message_id")] + public ulong MessageId { get; set; } + [JsonProperty("channel_id")] + public ulong ChannelId { get; set; } + [JsonProperty("emoji")] + public Discord.API.Emoji Emoji { get; set; } + } +} diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs index 0b09d2d22..3f7512295 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs @@ -27,6 +27,7 @@ namespace Discord.WebSocket public virtual IReadOnlyCollection MentionedRoles => ImmutableArray.Create(); public virtual IReadOnlyCollection MentionedUsers => ImmutableArray.Create(); public virtual IReadOnlyCollection Tags => ImmutableArray.Create(); + public virtual IReadOnlyCollection Reactions => ImmutableArray.Create(); public virtual ulong? WebhookId => null; public bool IsWebhook => WebhookId != null; diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs new file mode 100644 index 000000000..b96513cc1 --- /dev/null +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Model = Discord.API.Gateway.GatewayReaction; + +namespace Discord.WebSocket +{ + public class SocketReaction : IReaction + { + internal SocketReaction(Model model) + { + UserId = model.UserId; + MessageId = model.MessageId; + ChannelId = model.ChannelId; + Emoji = model.Emoji; + } + + public ulong UserId { get; internal set; } + public ulong MessageId { get; internal set; } + public ulong ChannelId { get; internal set; } + public API.Emoji Emoji { get; internal set; } + } +} diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs index 4174ff899..5ccf1825f 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Threading.Tasks; +using Discord.API.Gateway; using Model = Discord.API.Message; namespace Discord.WebSocket @@ -18,6 +19,7 @@ namespace Discord.WebSocket private ImmutableArray _attachments; private ImmutableArray _embeds; private ImmutableArray _tags; + private ImmutableArray _reactions; public override bool IsTTS => _isTTS; public override bool IsPinned => _isPinned; @@ -29,6 +31,7 @@ namespace Discord.WebSocket public override IReadOnlyCollection MentionedChannels => MessageHelper.FilterTagsByValue(TagType.ChannelMention, _tags); public override IReadOnlyCollection MentionedRoles => MessageHelper.FilterTagsByValue(TagType.RoleMention, _tags); public override IReadOnlyCollection MentionedUsers => MessageHelper.FilterTagsByValue(TagType.UserMention, _tags); + public override IReadOnlyCollection Reactions => _reactions; internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author) : base(discord, id, channel, author) @@ -101,6 +104,20 @@ namespace Discord.WebSocket } } + if (model.Reactions.IsSpecified) + { + var value = model.Reactions.Value; + if (value.Length > 0) + { + var reactions = ImmutableArray.CreateBuilder(value.Length); + for (int i = 0; i < value.Length; i++) + reactions.Add(new SocketReaction(value[i] as GatewayReaction)); + _reactions = reactions.ToImmutable(); + } + else + _reactions = ImmutableArray.Create(); + } + if (model.Content.IsSpecified) { var text = model.Content.Value;