diff --git a/src/Discord.Net.Rest/Entities/Messages/RestReactionMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestReactionMessage.cs
new file mode 100644
index 000000000..8d0c35d75
--- /dev/null
+++ b/src/Discord.Net.Rest/Entities/Messages/RestReactionMessage.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using Model = Discord.API.Message;
+
+namespace Discord.Rest
+{
+ ///
+ /// Represents a REST-based mesage that reactions can be added to.
+ ///
+ [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
+ public abstract class RestReactionMessage : RestMessage, IReactionMessage
+ {
+ private ImmutableArray _reactions = ImmutableArray.Create();
+
+ ///
+ public IReadOnlyDictionary Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me });
+
+ internal RestReactionMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source)
+ : base(discord, id, channel, author, source)
+ {
+ }
+
+ internal override void Update(Model model)
+ {
+ base.Update(model);
+
+ 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(RestReaction.Create(value[i]));
+ _reactions = reactions.ToImmutable();
+ }
+ else
+ _reactions = ImmutableArray.Create();
+ }
+ else
+ _reactions = ImmutableArray.Create();
+ }
+
+ ///
+ public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
+ => MessageHelper.AddReactionAsync(this, emote, Discord, options);
+ ///
+ public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null)
+ => MessageHelper.RemoveReactionAsync(this, user.Id, emote, Discord, options);
+ ///
+ public Task RemoveReactionAsync(IEmote emote, ulong userId, RequestOptions options = null)
+ => MessageHelper.RemoveReactionAsync(this, userId, emote, Discord, options);
+ ///
+ public Task RemoveAllReactionsAsync(RequestOptions options = null)
+ => MessageHelper.RemoveAllReactionsAsync(this, Discord, options);
+ ///
+ public IAsyncEnumerable> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null)
+ => MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options);
+ }
+}
diff --git a/src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs
index 89a651eb7..bfd620698 100644
--- a/src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs
+++ b/src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs
@@ -7,7 +7,7 @@ namespace Discord.Rest
/// Represents a REST-based system message.
///
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
- public class RestSystemMessage : RestMessage, ISystemMessage
+ public class RestSystemMessage : RestReactionMessage, ISystemMessage
{
///
public MessageType Type { get; private set; }
diff --git a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs
index 3260ecf70..ed58e7bfd 100644
--- a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs
+++ b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
-using System.Linq;
using System.Threading.Tasks;
using Model = Discord.API.Message;
@@ -12,14 +11,13 @@ namespace Discord.Rest
/// Represents a REST-based message sent by a user.
///
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
- public class RestUserMessage : RestMessage, IUserMessage
+ public class RestUserMessage : RestReactionMessage, IUserMessage
{
private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed;
private long? _editedTimestampTicks;
private ImmutableArray _attachments = ImmutableArray.Create();
private ImmutableArray