diff --git a/src/Discord.Net.Core/Entities/Emotes/Emoji.cs b/src/Discord.Net.Core/Entities/Emotes/Emoji.cs new file mode 100644 index 000000000..96226c715 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Emotes/Emoji.cs @@ -0,0 +1,23 @@ +namespace Discord +{ + /// + /// A unicode emoji + /// + public class Emoji : IEmote + { + // TODO: need to constrain this to unicode-only emojis somehow + /// + /// Creates a unciode emoji. + /// + /// The pure UTF-8 encoding of an emoji + public Emoji(string unicode) + { + Name = unicode; + } + + /// + /// The unicode representation of this emote. + /// + public string Name { get; } + } +} diff --git a/src/Discord.Net.Core/Entities/Emotes/Emote.cs b/src/Discord.Net.Core/Entities/Emotes/Emote.cs new file mode 100644 index 000000000..b1ca272eb --- /dev/null +++ b/src/Discord.Net.Core/Entities/Emotes/Emote.cs @@ -0,0 +1,63 @@ +using System; +using System.Globalization; + +namespace Discord +{ + /// + /// A custom image-based emote + /// + public class Emote : IEmote, ISnowflakeEntity + { + /// + /// The display name (tooltip) of this emote + /// + public string Name { get; } + /// + /// The ID of this emote + /// + public ulong Id { get; } + public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + public string Url => CDN.GetEmojiUrl(Id); + + internal Emote(ulong id, string name) + { + Id = id; + Name = name; + } + + /// + /// Parse an Emote from its raw format + /// + /// The raw encoding of an emote; for example, <:dab:277855270321782784> + /// An emote + public static Emote Parse(string text) + { + if (TryParse(text, out Emote result)) + return result; + throw new ArgumentException("Invalid emote format", nameof(text)); + } + + public static bool TryParse(string text, out Emote result) + { + result = null; + if (text.Length >= 4 && text[0] == '<' && text[1] == ':' && text[text.Length - 1] == '>') + { + int splitIndex = text.IndexOf(':', 2); + if (splitIndex == -1) + return false; + + if (!ulong.TryParse(text.Substring(splitIndex + 1, text.Length - splitIndex - 2), NumberStyles.None, CultureInfo.InvariantCulture, out ulong id)) + return false; + + string name = text.Substring(2, splitIndex - 2); + result = new Emote(id, name); + return true; + } + return false; + + } + + private string DebuggerDisplay => $"{Name} ({Id})"; + public override string ToString() => Name; + } +} diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildEmoji.cs b/src/Discord.Net.Core/Entities/Emotes/GuildEmote.cs similarity index 66% rename from src/Discord.Net.Core/Entities/Guilds/GuildEmoji.cs rename to src/Discord.Net.Core/Entities/Emotes/GuildEmote.cs index e925991eb..e883c707e 100644 --- a/src/Discord.Net.Core/Entities/Guilds/GuildEmoji.cs +++ b/src/Discord.Net.Core/Entities/Emotes/GuildEmote.cs @@ -3,19 +3,18 @@ using System.Diagnostics; namespace Discord { + /// + /// An image-based emote that is attached to a guild + /// [DebuggerDisplay(@"{DebuggerDisplay,nq}")] - public struct GuildEmoji + public class GuildEmote : Emote { - public ulong Id { get; } - public string Name { get; } public bool IsManaged { get; } public bool RequireColons { get; } public IReadOnlyList RoleIds { get; } - internal GuildEmoji(ulong id, string name, bool isManaged, bool requireColons, IReadOnlyList roleIds) + internal GuildEmote(ulong id, string name, bool isManaged, bool requireColons, IReadOnlyList roleIds) : base(id, name) { - Id = id; - Name = name; IsManaged = isManaged; RequireColons = requireColons; RoleIds = roleIds; diff --git a/src/Discord.Net.Core/Entities/Emotes/IEmote.cs b/src/Discord.Net.Core/Entities/Emotes/IEmote.cs new file mode 100644 index 000000000..fac61402a --- /dev/null +++ b/src/Discord.Net.Core/Entities/Emotes/IEmote.cs @@ -0,0 +1,13 @@ +namespace Discord +{ + /// + /// A general container for any type of emote in a message. + /// + public interface IEmote + { + /// + /// The display name or unicode representation of this emote + /// + string Name { get; } + } +} diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index 8da731855..506cbd3e4 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -45,7 +45,7 @@ namespace Discord /// Gets the built-in role containing all users in this guild. IRole EveryoneRole { get; } /// Gets a collection of all custom emojis for this guild. - IReadOnlyCollection Emojis { get; } + IReadOnlyCollection Emotes { get; } /// Gets a collection of all extra features added to this guild. IReadOnlyCollection Features { get; } /// Gets a collection of all roles in this guild. diff --git a/src/Discord.Net.Core/Entities/Messages/Emoji.cs b/src/Discord.Net.Core/Entities/Messages/Emoji.cs deleted file mode 100644 index a9c5a6bbd..000000000 --- a/src/Discord.Net.Core/Entities/Messages/Emoji.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Diagnostics; -using System.Globalization; - -namespace Discord -{ - [DebuggerDisplay("{DebuggerDisplay,nq}")] - public struct Emoji - { - public ulong? Id { get; } - public string Name { get; } - - public string Url => Id != null ? CDN.GetEmojiUrl(Id.Value) : null; - - internal Emoji(ulong? id, string name) - { - Id = id; - Name = name; - } - - public static Emoji Parse(string text) - { - if (TryParse(text, out Emoji result)) - return result; - throw new ArgumentException("Invalid emoji format", nameof(text)); - } - - public static bool TryParse(string text, out Emoji result) - { - result = default(Emoji); - if (text.Length >= 4 && text[0] == '<' && text[1] == ':' && text[text.Length - 1] == '>') - { - int splitIndex = text.IndexOf(':', 2); - if (splitIndex == -1) - return false; - - if (!ulong.TryParse(text.Substring(splitIndex + 1, text.Length - splitIndex - 2), NumberStyles.None, CultureInfo.InvariantCulture, out ulong id)) - return false; - - string name = text.Substring(2, splitIndex - 2); - result = new Emoji(id, name); - return true; - } - return false; - - } - - private string DebuggerDisplay => $"{Name} ({Id})"; - public override string ToString() => Name; - } -} diff --git a/src/Discord.Net.Core/Entities/Messages/IReaction.cs b/src/Discord.Net.Core/Entities/Messages/IReaction.cs index 7145fce7f..37ead42ae 100644 --- a/src/Discord.Net.Core/Entities/Messages/IReaction.cs +++ b/src/Discord.Net.Core/Entities/Messages/IReaction.cs @@ -2,6 +2,6 @@ { public interface IReaction { - Emoji Emoji { get; } + IEmote Emote { get; } } } diff --git a/src/Discord.Net.Core/Entities/Messages/IUserMessage.cs b/src/Discord.Net.Core/Entities/Messages/IUserMessage.cs index f238ca6bc..61f908394 100644 --- a/src/Discord.Net.Core/Entities/Messages/IUserMessage.cs +++ b/src/Discord.Net.Core/Entities/Messages/IUserMessage.cs @@ -14,16 +14,12 @@ namespace Discord Task UnpinAsync(RequestOptions options = null); /// Returns all reactions included in this message. - IReadOnlyDictionary Reactions { get; } + IReadOnlyDictionary Reactions { get; } /// Adds a reaction to this message. - Task AddReactionAsync(Emoji emoji, RequestOptions options = null); - /// Adds a reaction to this message. - Task AddReactionAsync(string emoji, RequestOptions options = null); + Task AddReactionAsync(IEmote emote, RequestOptions options = null); /// Removes a reaction from message. - Task RemoveReactionAsync(Emoji emoji, IUser user, RequestOptions options = null); - /// Removes a reaction from this message. - Task RemoveReactionAsync(string emoji, IUser user, RequestOptions options = null); + Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null); /// Removes all reactions from this message. Task RemoveAllReactionsAsync(RequestOptions options = null); Task> GetReactionUsersAsync(string emoji, int limit = 100, ulong? afterUserId = null, RequestOptions options = null); diff --git a/src/Discord.Net.Core/Utils/MentionUtils.cs b/src/Discord.Net.Core/Utils/MentionUtils.cs index 2af254fde..6c69827b4 100644 --- a/src/Discord.Net.Core/Utils/MentionUtils.cs +++ b/src/Discord.Net.Core/Utils/MentionUtils.cs @@ -252,7 +252,7 @@ namespace Discord { if (mode != TagHandling.Remove) { - Emoji emoji = (Emoji)tag.Value; + Emote emoji = (Emote)tag.Value; //Remove if its name contains any bad chars (prevents a few tag exploits) for (int i = 0; i < emoji.Name.Length; i++) diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index 5a47fce81..8b5598ffe 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Linq; using System.Threading.Tasks; -using Model = Discord.API.Guild; using EmbedModel = Discord.API.GuildEmbed; -using System.Linq; +using Model = Discord.API.Guild; namespace Discord.Rest { @@ -14,7 +14,7 @@ namespace Discord.Rest public class RestGuild : RestEntity, IGuild, IUpdateable { private ImmutableDictionary _roles; - private ImmutableArray _emojis; + private ImmutableArray _emotes; private ImmutableArray _features; public string Name { get; private set; } @@ -39,7 +39,7 @@ namespace Discord.Rest public RestRole EveryoneRole => GetRole(Id); public IReadOnlyCollection Roles => _roles.ToReadOnlyCollection(); - public IReadOnlyCollection Emojis => _emojis; + public IReadOnlyCollection Emotes => _emotes; public IReadOnlyCollection Features => _features; internal RestGuild(BaseDiscordClient client, ulong id) @@ -69,13 +69,13 @@ namespace Discord.Rest if (model.Emojis != null) { - var emojis = ImmutableArray.CreateBuilder(model.Emojis.Length); + var emotes = ImmutableArray.CreateBuilder(model.Emojis.Length); for (int i = 0; i < model.Emojis.Length; i++) - emojis.Add(model.Emojis[i].ToEntity()); - _emojis = emojis.ToImmutableArray(); + emotes.Add(model.Emojis[i].ToEntity()); + _emotes = emotes.ToImmutableArray(); } else - _emojis = ImmutableArray.Create(); + _emotes = ImmutableArray.Create(); if (model.Features != null) _features = model.Features.ToImmutableArray(); diff --git a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs index 285cf0e74..ccb683d1f 100644 --- a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs +++ b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs @@ -28,19 +28,14 @@ namespace Discord.Rest await client.ApiClient.DeleteMessageAsync(msg.Channel.Id, msg.Id, options).ConfigureAwait(false); } - public static async Task AddReactionAsync(IMessage msg, Emoji emoji, BaseDiscordClient client, RequestOptions options) - => await AddReactionAsync(msg, $"{emoji.Name}:{emoji.Id}", client, options).ConfigureAwait(false); - public static async Task AddReactionAsync(IMessage msg, string emoji, BaseDiscordClient client, RequestOptions options) + public static async Task AddReactionAsync(IMessage msg, IEmote emote, BaseDiscordClient client, RequestOptions options) { - await client.ApiClient.AddReactionAsync(msg.Channel.Id, msg.Id, emoji, options).ConfigureAwait(false); + await client.ApiClient.AddReactionAsync(msg.Channel.Id, msg.Id, emote is Emote e ? $"{e.Name}:{e.Id}" : emote.Name, options).ConfigureAwait(false); } - public static async Task RemoveReactionAsync(IMessage msg, IUser user, Emoji emoji, BaseDiscordClient client, RequestOptions options) - => await RemoveReactionAsync(msg, user, emoji.Id == null ? emoji.Name : $"{emoji.Name}:{emoji.Id}", client, options).ConfigureAwait(false); - public static async Task RemoveReactionAsync(IMessage msg, IUser user, string emoji, BaseDiscordClient client, - RequestOptions options) + public static async Task RemoveReactionAsync(IMessage msg, IUser user, IEmote emote, BaseDiscordClient client, RequestOptions options) { - await client.ApiClient.RemoveReactionAsync(msg.Channel.Id, msg.Id, user.Id, emoji, options).ConfigureAwait(false); + await client.ApiClient.RemoveReactionAsync(msg.Channel.Id, msg.Id, user.Id, emote is Emote e ? $"{e.Name}:{e.Id}" : emote.Name, options).ConfigureAwait(false); } public static async Task RemoveAllReactionsAsync(IMessage msg, BaseDiscordClient client, RequestOptions options) @@ -109,8 +104,8 @@ namespace Discord.Rest mentionedRole = guild.GetRole(id); tags.Add(new Tag(TagType.RoleMention, index, content.Length, id, mentionedRole)); } - else if (Emoji.TryParse(content, out var emoji)) - tags.Add(new Tag(TagType.Emoji, index, content.Length, emoji.Id ?? 0, emoji)); + else if (Emote.TryParse(content, out var emoji)) + tags.Add(new Tag(TagType.Emoji, index, content.Length, emoji.Id, emoji)); else //Bad Tag { index = index + 1; diff --git a/src/Discord.Net.Rest/Entities/Messages/RestReaction.cs b/src/Discord.Net.Rest/Entities/Messages/RestReaction.cs index 933833d56..05c817935 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestReaction.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestReaction.cs @@ -4,19 +4,24 @@ namespace Discord.Rest { public class RestReaction : IReaction { - public Emoji Emoji { get; } + public IEmote Emote { get; } public int Count { get; } public bool Me { get; } - internal RestReaction(Emoji emoji, int count, bool me) + internal RestReaction(IEmote emote, int count, bool me) { - Emoji = emoji; + Emote = emote; Count = count; Me = me; } internal static RestReaction Create(Model model) { - return new RestReaction(new Emoji(model.Emoji.Id, model.Emoji.Name), model.Count, model.Me); + IEmote emote; + if (model.Emoji.Id.HasValue) + emote = new Emote(model.Emoji.Id.Value, model.Emoji.Name); + else + emote = new Emoji(model.Emoji.Name); + return new RestReaction(emote, model.Count, model.Me); } } } diff --git a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs index 00ab0c299..c79c67b38 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs @@ -27,7 +27,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 IReadOnlyDictionary Reactions => _reactions.ToDictionary(x => x.Emoji, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me }); + public IReadOnlyDictionary Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me }); internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source) : base(discord, id, channel, author, source) @@ -130,21 +130,15 @@ namespace Discord.Rest Update(model); } - public Task AddReactionAsync(Emoji emoji, RequestOptions options = null) - => MessageHelper.AddReactionAsync(this, emoji, Discord, options); - public Task AddReactionAsync(string emoji, RequestOptions options = null) - => MessageHelper.AddReactionAsync(this, emoji, Discord, options); - - public Task RemoveReactionAsync(Emoji emoji, IUser user, RequestOptions options = null) - => MessageHelper.RemoveReactionAsync(this, user, emoji, Discord, options); - public Task RemoveReactionAsync(string emoji, IUser user, RequestOptions options = null) - => MessageHelper.RemoveReactionAsync(this, user, emoji, Discord, options); - + 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, emote, Discord, options); public Task RemoveAllReactionsAsync(RequestOptions options = null) => MessageHelper.RemoveAllReactionsAsync(this, Discord, options); public Task> GetReactionUsersAsync(string emoji, int limit = 100, ulong? afterUserId = null, RequestOptions options = null) - => MessageHelper.GetReactionUsersAsync(this, emoji, x => { x.Limit = limit; x.AfterUserId = afterUserId.HasValue ? afterUserId.Value : Optional.Create(); }, Discord, options); + => MessageHelper.GetReactionUsersAsync(this, emoji, x => { x.Limit = limit; x.AfterUserId = afterUserId ?? Optional.Create(); }, Discord, options); public Task PinAsync(RequestOptions options = null) diff --git a/src/Discord.Net.Rest/Extensions/EntityExtensions.cs b/src/Discord.Net.Rest/Extensions/EntityExtensions.cs index f59b8f7a3..b88a5b515 100644 --- a/src/Discord.Net.Rest/Extensions/EntityExtensions.cs +++ b/src/Discord.Net.Rest/Extensions/EntityExtensions.cs @@ -5,9 +5,9 @@ namespace Discord.Rest { internal static class EntityExtensions { - public static GuildEmoji ToEntity(this API.Emoji model) + public static GuildEmote ToEntity(this API.Emoji model) { - return new GuildEmoji(model.Id.Value, model.Name, model.Managed, model.RequireColons, ImmutableArray.Create(model.Roles)); + return new GuildEmote(model.Id.Value, model.Name, model.Managed, model.RequireColons, ImmutableArray.Create(model.Roles)); } public static Embed ToEntity(this API.Embed model) diff --git a/src/Discord.Net.Rpc/Entities/Messages/RpcUserMessage.cs b/src/Discord.Net.Rpc/Entities/Messages/RpcUserMessage.cs index cdcff4a07..91a8d7b31 100644 --- a/src/Discord.Net.Rpc/Entities/Messages/RpcUserMessage.cs +++ b/src/Discord.Net.Rpc/Entities/Messages/RpcUserMessage.cs @@ -29,7 +29,7 @@ namespace Discord.Rpc public override IReadOnlyCollection MentionedRoleIds => MessageHelper.FilterTagsByKey(TagType.RoleMention, _tags); public override IReadOnlyCollection MentionedUserIds => MessageHelper.FilterTagsByKey(TagType.UserMention, _tags); public override IReadOnlyCollection Tags => _tags; - public IReadOnlyDictionary Reactions => ImmutableDictionary.Create(); + public IReadOnlyDictionary Reactions => ImmutableDictionary.Create(); internal RpcUserMessage(DiscordRpcClient discord, ulong id, RestVirtualMessageChannel channel, RpcUser author, MessageSource source) : base(discord, id, channel, author, source) @@ -102,16 +102,10 @@ namespace Discord.Rpc public Task ModifyAsync(Action func, RequestOptions options) => MessageHelper.ModifyAsync(this, Discord, func, options); - public Task AddReactionAsync(Emoji emoji, RequestOptions options = null) - => MessageHelper.AddReactionAsync(this, emoji, Discord, options); - public Task AddReactionAsync(string emoji, RequestOptions options = null) - => MessageHelper.AddReactionAsync(this, emoji, Discord, options); - - public Task RemoveReactionAsync(Emoji emoji, IUser user, RequestOptions options = null) - => MessageHelper.RemoveReactionAsync(this, user, emoji, Discord, options); - public Task RemoveReactionAsync(string emoji, IUser user, RequestOptions options = null) - => MessageHelper.RemoveReactionAsync(this, user, emoji, Discord, options); - + 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, emote, Discord, options); public Task RemoveAllReactionsAsync(RequestOptions options = null) => MessageHelper.RemoveAllReactionsAsync(this, Discord, options); diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index 6535ecf9a..f396243d8 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -30,7 +30,7 @@ namespace Discord.WebSocket private ConcurrentDictionary _members; private ConcurrentDictionary _roles; private ConcurrentDictionary _voiceStates; - private ImmutableArray _emojis; + private ImmutableArray _emotes; private ImmutableArray _features; private AudioClient _audioClient; @@ -93,7 +93,7 @@ namespace Discord.WebSocket return channels.Select(x => state.GetChannel(x) as SocketGuildChannel).Where(x => x != null).ToReadOnlyCollection(channels); } } - public IReadOnlyCollection Emojis => _emojis; + public IReadOnlyCollection Emotes => _emotes; public IReadOnlyCollection Features => _features; public IReadOnlyCollection Users => _members.ToReadOnlyCollection(); public IReadOnlyCollection Roles => _roles.ToReadOnlyCollection(); @@ -102,7 +102,7 @@ namespace Discord.WebSocket : base(client, id) { _audioLock = new SemaphoreSlim(1, 1); - _emojis = ImmutableArray.Create(); + _emotes = ImmutableArray.Create(); _features = ImmutableArray.Create(); } internal static SocketGuild Create(DiscordSocketClient discord, ClientState state, ExtendedModel model) @@ -201,13 +201,13 @@ namespace Discord.WebSocket if (model.Emojis != null) { - var emojis = ImmutableArray.CreateBuilder(model.Emojis.Length); + var emojis = ImmutableArray.CreateBuilder(model.Emojis.Length); for (int i = 0; i < model.Emojis.Length; i++) emojis.Add(model.Emojis[i].ToEntity()); - _emojis = emojis.ToImmutable(); + _emotes = emojis.ToImmutable(); } else - _emojis = ImmutableArray.Create(); + _emotes = ImmutableArray.Create(); if (model.Features != null) _features = model.Features.ToImmutableArray(); @@ -253,10 +253,10 @@ namespace Discord.WebSocket internal void Update(ClientState state, EmojiUpdateModel model) { - var emojis = ImmutableArray.CreateBuilder(model.Emojis.Length); + var emotes = ImmutableArray.CreateBuilder(model.Emojis.Length); for (int i = 0; i < model.Emojis.Length; i++) - emojis.Add(model.Emojis[i].ToEntity()); - _emojis = emojis.ToImmutable(); + emotes.Add(model.Emojis[i].ToEntity()); + _emotes = emotes.ToImmutable(); } //General diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs index c12d0fdea..9f58f1cf6 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketReaction.cs @@ -9,20 +9,25 @@ namespace Discord.WebSocket public ulong MessageId { get; } public Optional Message { get; } public ISocketMessageChannel Channel { get; } - public Emoji Emoji { get; } + public IEmote Emote { get; } - internal SocketReaction(ISocketMessageChannel channel, ulong messageId, Optional message, ulong userId, Optional user, Emoji emoji) + internal SocketReaction(ISocketMessageChannel channel, ulong messageId, Optional message, ulong userId, Optional user, IEmote emoji) { Channel = channel; MessageId = messageId; Message = message; UserId = userId; User = user; - Emoji = emoji; + Emote = emoji; } internal static SocketReaction Create(Model model, ISocketMessageChannel channel, Optional message, Optional user) { - return new SocketReaction(channel, model.MessageId, message, model.UserId, user, new Emoji(model.Emoji.Id, model.Emoji.Name)); + IEmote emote; + if (model.Emoji.Id.HasValue) + emote = new Emote(model.Emoji.Id.Value, model.Emoji.Name); + else + emote = new Emoji(model.Emoji.Name); + return new SocketReaction(channel, model.MessageId, message, model.UserId, user, emote); } } } diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs index 8b9acf118..40588e55a 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs @@ -28,7 +28,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 IReadOnlyDictionary Reactions => _reactions.GroupBy(r => r.Emoji).ToDictionary(x => x.Key, x => new ReactionMetadata { ReactionCount = x.Count(), IsMe = x.Any(y => y.UserId == Discord.CurrentUser.Id) }); + public IReadOnlyDictionary Reactions => _reactions.GroupBy(r => r.Emote).ToDictionary(x => x.Key, x => new ReactionMetadata { ReactionCount = x.Count(), IsMe = x.Any(y => y.UserId == Discord.CurrentUser.Id) }); internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source) : base(discord, id, channel, author, source) @@ -124,16 +124,10 @@ namespace Discord.WebSocket public Task ModifyAsync(Action func, RequestOptions options = null) => MessageHelper.ModifyAsync(this, Discord, func, options); - public Task AddReactionAsync(Emoji emoji, RequestOptions options = null) - => MessageHelper.AddReactionAsync(this, emoji, Discord, options); - public Task AddReactionAsync(string emoji, RequestOptions options = null) - => MessageHelper.AddReactionAsync(this, emoji, Discord, options); - - public Task RemoveReactionAsync(Emoji emoji, IUser user, RequestOptions options = null) - => MessageHelper.RemoveReactionAsync(this, user, emoji, Discord, options); - public Task RemoveReactionAsync(string emoji, IUser user, RequestOptions options = null) - => MessageHelper.RemoveReactionAsync(this, user, emoji, Discord, options); - + 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, emote, Discord, options); public Task RemoveAllReactionsAsync(RequestOptions options = null) => MessageHelper.RemoveAllReactionsAsync(this, Discord, options);