[Feature] Super reactions support (#2707)
* super reactions * add type to `GetReactionUsers` methods * add `MeBurst`
This commit is contained in:
@@ -202,6 +202,7 @@ namespace Discord
|
|||||||
|
|
||||||
#region Reactions (90XXX)
|
#region Reactions (90XXX)
|
||||||
ReactionBlocked = 90001,
|
ReactionBlocked = 90001,
|
||||||
|
CannotUseBurstReaction = 90002,
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region API Status (130XXX)
|
#region API Status (130XXX)
|
||||||
|
|||||||
@@ -323,9 +323,11 @@ namespace Discord
|
|||||||
/// <param name="emoji">The emoji that represents the reaction that you wish to get.</param>
|
/// <param name="emoji">The emoji that represents the reaction that you wish to get.</param>
|
||||||
/// <param name="limit">The number of users to request.</param>
|
/// <param name="limit">The number of users to request.</param>
|
||||||
/// <param name="options">The options to be used when sending the request.</param>
|
/// <param name="options">The options to be used when sending the request.</param>
|
||||||
|
/// <param name="type">The type of the reaction you wish to get users for.</param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// Paged collection of users.
|
/// Paged collection of users.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emoji, int limit, RequestOptions options = null);
|
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emoji, int limit, RequestOptions options = null,
|
||||||
|
ReactionType type = ReactionType.Normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
namespace Discord
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Discord;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a generic reaction object.
|
||||||
|
/// </summary>
|
||||||
|
public interface IReaction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a generic reaction object.
|
/// The <see cref="IEmote" /> used in the reaction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IReaction
|
IEmote Emote { get; }
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="IEmote" /> used in the reaction.
|
/// Gets colors used for the super reaction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IEmote Emote { get; }
|
/// <remarks>
|
||||||
}
|
/// The collection will be empty if the reaction is a normal reaction.
|
||||||
|
/// </remarks>
|
||||||
|
public IReadOnlyCollection<Color> BurstColors { get; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,40 @@
|
|||||||
namespace Discord
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Discord;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata containing reaction information.
|
||||||
|
/// </summary>
|
||||||
|
public struct ReactionMetadata
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A metadata containing reaction information.
|
/// Gets the number of reactions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct ReactionMetadata
|
/// <returns>
|
||||||
{
|
/// An <see cref="int"/> representing the number of this reactions that has been added to this message.
|
||||||
/// <summary>
|
/// </returns>
|
||||||
/// Gets the number of reactions.
|
public int ReactionCount { get; internal set; }
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
/// <summary>
|
||||||
/// An <see cref="int"/> representing the number of this reactions that has been added to this message.
|
/// Gets a value that indicates whether the current user has reacted to this.
|
||||||
/// </returns>
|
/// </summary>
|
||||||
public int ReactionCount { get; internal set; }
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if the user has reacted to the message; otherwise <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public bool IsMe { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value that indicates whether the current user has reacted to this.
|
/// Gets the number of burst reactions added to this message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>
|
public int BurstCount { get; internal set; }
|
||||||
/// <see langword="true" /> if the user has reacted to the message; otherwise <see langword="false" />.
|
|
||||||
/// </returns>
|
/// <summary>
|
||||||
public bool IsMe { get; internal set; }
|
/// Gets the number of normal reactions added to this message.
|
||||||
}
|
/// </summary>
|
||||||
|
public int NormalCount { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets colors used for super reaction.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyCollection<Color> BurstColors { get; internal set; }
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/Discord.Net.Core/Entities/Messages/ReactionType.cs
Normal file
14
src/Discord.Net.Core/Entities/Messages/ReactionType.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace Discord;
|
||||||
|
|
||||||
|
public enum ReactionType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The reaction is a normal reaction.
|
||||||
|
/// </summary>
|
||||||
|
Normal = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The reaction is a super reaction.
|
||||||
|
/// </summary>
|
||||||
|
Burst = 1,
|
||||||
|
}
|
||||||
@@ -1,14 +1,24 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Discord.API
|
namespace Discord.API;
|
||||||
|
|
||||||
|
internal class Reaction
|
||||||
{
|
{
|
||||||
internal class Reaction
|
[JsonProperty("count")]
|
||||||
{
|
public int Count { get; set; }
|
||||||
[JsonProperty("count")]
|
|
||||||
public int Count { get; set; }
|
[JsonProperty("me")]
|
||||||
[JsonProperty("me")]
|
public bool Me { get; set; }
|
||||||
public bool Me { get; set; }
|
|
||||||
[JsonProperty("emoji")]
|
[JsonProperty("me_burst")]
|
||||||
public Emoji Emoji { get; set; }
|
public bool MeBurst { get; set; }
|
||||||
}
|
|
||||||
|
[JsonProperty("emoji")]
|
||||||
|
public Emoji Emoji { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("count_details")]
|
||||||
|
public ReactionCountDetails CountDetails { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("burst_colors")]
|
||||||
|
public Color[] Colors { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/Discord.Net.Rest/API/Common/ReactionCountDetails.cs
Normal file
12
src/Discord.Net.Rest/API/Common/ReactionCountDetails.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Discord.API;
|
||||||
|
|
||||||
|
internal class ReactionCountDetails
|
||||||
|
{
|
||||||
|
[JsonProperty("normal")]
|
||||||
|
public int NormalCount { get; set;}
|
||||||
|
|
||||||
|
[JsonProperty("burst")]
|
||||||
|
public int BurstCount { get; set;}
|
||||||
|
}
|
||||||
@@ -1143,7 +1143,8 @@ namespace Discord.API
|
|||||||
|
|
||||||
await SendAsync("DELETE", () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}", ids, options: options).ConfigureAwait(false);
|
await SendAsync("DELETE", () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}", ids, options: options).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
public async Task<IReadOnlyCollection<User>> GetReactionUsersAsync(ulong channelId, ulong messageId, string emoji, GetReactionUsersParams args, RequestOptions options = null)
|
|
||||||
|
public async Task<IReadOnlyCollection<User>> GetReactionUsersAsync(ulong channelId, ulong messageId, string emoji, GetReactionUsersParams args, ReactionType reactionType, RequestOptions options = null)
|
||||||
{
|
{
|
||||||
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
||||||
Preconditions.NotEqual(messageId, 0, nameof(messageId));
|
Preconditions.NotEqual(messageId, 0, nameof(messageId));
|
||||||
@@ -1158,9 +1159,10 @@ namespace Discord.API
|
|||||||
ulong afterUserId = args.AfterUserId.GetValueOrDefault(0);
|
ulong afterUserId = args.AfterUserId.GetValueOrDefault(0);
|
||||||
|
|
||||||
var ids = new BucketIds(channelId: channelId);
|
var ids = new BucketIds(channelId: channelId);
|
||||||
Expression<Func<string>> endpoint = () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}?limit={limit}&after={afterUserId}";
|
Expression<Func<string>> endpoint = () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}?limit={limit}&after={afterUserId}&type={(int)reactionType}";
|
||||||
return await SendAsync<IReadOnlyCollection<User>>("GET", endpoint, ids, options: options).ConfigureAwait(false);
|
return await SendAsync<IReadOnlyCollection<User>>("GET", endpoint, ids, options: options).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AckMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
|
public async Task AckMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
|
||||||
{
|
{
|
||||||
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ namespace Discord.Rest
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IMessage msg, IEmote emote,
|
public static IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IMessage msg, IEmote emote,
|
||||||
int? limit, BaseDiscordClient client, RequestOptions options)
|
int? limit, BaseDiscordClient client, ReactionType reactionType, RequestOptions options)
|
||||||
{
|
{
|
||||||
Preconditions.NotNull(emote, nameof(emote));
|
Preconditions.NotNull(emote, nameof(emote));
|
||||||
var emoji = (emote is Emote e ? $"{e.Name}:{e.Id}" : UrlEncode(emote.Name));
|
var emoji = (emote is Emote e ? $"{e.Name}:{e.Id}" : UrlEncode(emote.Name));
|
||||||
@@ -181,7 +181,7 @@ namespace Discord.Rest
|
|||||||
if (info.Position != null)
|
if (info.Position != null)
|
||||||
args.AfterUserId = info.Position.Value;
|
args.AfterUserId = info.Position.Value;
|
||||||
|
|
||||||
var models = await client.ApiClient.GetReactionUsersAsync(msg.Channel.Id, msg.Id, emoji, args, options).ConfigureAwait(false);
|
var models = await client.ApiClient.GetReactionUsersAsync(msg.Channel.Id, msg.Id, emoji, args, reactionType, options).ConfigureAwait(false);
|
||||||
return models.Select(x => RestUser.Create(client, x)).ToImmutableArray();
|
return models.Select(x => RestUser.Create(client, x)).ToImmutableArray();
|
||||||
},
|
},
|
||||||
nextPage: (info, lastPage) =>
|
nextPage: (info, lastPage) =>
|
||||||
|
|||||||
@@ -316,7 +316,14 @@ namespace Discord.Rest
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me });
|
public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata
|
||||||
|
{
|
||||||
|
ReactionCount = x.Count,
|
||||||
|
IsMe = x.Me,
|
||||||
|
BurstColors = x.BurstColors,
|
||||||
|
BurstCount = x.BurstCount,
|
||||||
|
NormalCount = x.NormalCount,
|
||||||
|
});
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
|
public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
|
||||||
@@ -334,7 +341,7 @@ namespace Discord.Rest
|
|||||||
public Task RemoveAllReactionsForEmoteAsync(IEmote emote, RequestOptions options = null)
|
public Task RemoveAllReactionsForEmoteAsync(IEmote emote, RequestOptions options = null)
|
||||||
=> MessageHelper.RemoveAllReactionsForEmoteAsync(this, emote, Discord, options);
|
=> MessageHelper.RemoveAllReactionsForEmoteAsync(this, emote, Discord, options);
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null)
|
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null, ReactionType type = ReactionType.Normal)
|
||||||
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options);
|
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, type, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using Model = Discord.API.Reaction;
|
using Model = Discord.API.Reaction;
|
||||||
|
|
||||||
namespace Discord.Rest
|
namespace Discord.Rest
|
||||||
@@ -9,20 +10,44 @@ namespace Discord.Rest
|
|||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEmote Emote { get; }
|
public IEmote Emote { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the number of reactions added.
|
/// Gets the number of reactions added.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Count { get; }
|
public int Count { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets whether the reactions is added by the user.
|
/// Gets whether the reaction is added by the user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Me { get; }
|
public bool Me { get; }
|
||||||
|
|
||||||
internal RestReaction(IEmote emote, int count, bool me)
|
/// <summary>
|
||||||
|
/// Gets whether the super-reaction is added by the user.
|
||||||
|
/// </summary>
|
||||||
|
public bool MeBurst { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of burst reactions added.
|
||||||
|
/// </summary>
|
||||||
|
public int BurstCount { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of normal reactions added.
|
||||||
|
/// </summary>
|
||||||
|
public int NormalCount { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IReadOnlyCollection<Color> BurstColors { get; }
|
||||||
|
|
||||||
|
internal RestReaction(IEmote emote, int count, bool me, int burst, int normal, IReadOnlyCollection<Color> colors, bool meBurst)
|
||||||
{
|
{
|
||||||
Emote = emote;
|
Emote = emote;
|
||||||
Count = count;
|
Count = count;
|
||||||
Me = me;
|
Me = me;
|
||||||
|
BurstCount = burst;
|
||||||
|
NormalCount = normal;
|
||||||
|
BurstColors = colors;
|
||||||
|
MeBurst = meBurst;
|
||||||
}
|
}
|
||||||
internal static RestReaction Create(Model model)
|
internal static RestReaction Create(Model model)
|
||||||
{
|
{
|
||||||
@@ -31,7 +56,13 @@ namespace Discord.Rest
|
|||||||
emote = new Emote(model.Emoji.Id.Value, model.Emoji.Name, model.Emoji.Animated.GetValueOrDefault());
|
emote = new Emote(model.Emoji.Id.Value, model.Emoji.Name, model.Emoji.Animated.GetValueOrDefault());
|
||||||
else
|
else
|
||||||
emote = new Emoji(model.Emoji.Name);
|
emote = new Emoji(model.Emoji.Name);
|
||||||
return new RestReaction(emote, model.Count, model.Me);
|
return new RestReaction(emote,
|
||||||
|
model.Count,
|
||||||
|
model.Me,
|
||||||
|
model.CountDetails.BurstCount,
|
||||||
|
model.CountDetails.NormalCount,
|
||||||
|
model.Colors.ToReadOnlyCollection(),
|
||||||
|
model.MeBurst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/Discord.Net.Rest/Net/Converters/ColorConverter.cs
Normal file
27
src/Discord.Net.Rest/Net/Converters/ColorConverter.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Discord.Net.Converters;
|
||||||
|
|
||||||
|
internal class ColorConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public static readonly ColorConverter Instance = new ();
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType) => true;
|
||||||
|
public override bool CanRead => true;
|
||||||
|
public override bool CanWrite => true;
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.Value is null)
|
||||||
|
return null;
|
||||||
|
return new Color(uint.Parse(reader.Value.ToString()!.TrimStart('#'), NumberStyles.HexNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
writer.WriteValue($"#{(uint)value:X}");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -93,6 +93,8 @@ namespace Discord.Net.Converters
|
|||||||
return DiscordErrorConverter.Instance;
|
return DiscordErrorConverter.Instance;
|
||||||
if (type == typeof(GuildFeatures))
|
if (type == typeof(GuildFeatures))
|
||||||
return GuildFeaturesConverter.Instance;
|
return GuildFeaturesConverter.Instance;
|
||||||
|
if(type == typeof(Color))
|
||||||
|
return ColorConverter.Instance;
|
||||||
|
|
||||||
//Entities
|
//Entities
|
||||||
var typeInfo = type.GetTypeInfo();
|
var typeInfo = type.GetTypeInfo();
|
||||||
|
|||||||
@@ -1,20 +1,33 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Discord.API.Gateway
|
namespace Discord.API.Gateway;
|
||||||
|
|
||||||
|
internal class Reaction
|
||||||
{
|
{
|
||||||
internal class Reaction
|
[JsonProperty("user_id")]
|
||||||
{
|
public ulong UserId { get; set; }
|
||||||
[JsonProperty("user_id")]
|
|
||||||
public ulong UserId { get; set; }
|
[JsonProperty("message_id")]
|
||||||
[JsonProperty("message_id")]
|
public ulong MessageId { get; set; }
|
||||||
public ulong MessageId { get; set; }
|
|
||||||
[JsonProperty("channel_id")]
|
[JsonProperty("channel_id")]
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
[JsonProperty("guild_id")]
|
|
||||||
public Optional<ulong> GuildId { get; set; }
|
[JsonProperty("guild_id")]
|
||||||
[JsonProperty("emoji")]
|
public Optional<ulong> GuildId { get; set; }
|
||||||
public Emoji Emoji { get; set; }
|
|
||||||
[JsonProperty("member")]
|
[JsonProperty("emoji")]
|
||||||
public Optional<GuildMember> Member { get; set; }
|
public Emoji Emoji { get; set; }
|
||||||
}
|
|
||||||
|
[JsonProperty("member")]
|
||||||
|
public Optional<GuildMember> Member { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("burst")]
|
||||||
|
public bool IsBurst { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("burst_colors")]
|
||||||
|
public Optional<Color[]> BurstColors { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("type")]
|
||||||
|
public ReactionType Type { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -374,8 +374,8 @@ namespace Discord.WebSocket
|
|||||||
public Task RemoveAllReactionsForEmoteAsync(IEmote emote, RequestOptions options = null)
|
public Task RemoveAllReactionsForEmoteAsync(IEmote emote, RequestOptions options = null)
|
||||||
=> MessageHelper.RemoveAllReactionsForEmoteAsync(this, emote, Discord, options);
|
=> MessageHelper.RemoveAllReactionsForEmoteAsync(this, emote, Discord, options);
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null)
|
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null, ReactionType type = ReactionType.Normal)
|
||||||
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options);
|
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, type, options);
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,113 +1,145 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Model = Discord.API.Gateway.Reaction;
|
using Model = Discord.API.Gateway.Reaction;
|
||||||
|
|
||||||
namespace Discord.WebSocket
|
namespace Discord.WebSocket;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a WebSocket-based reaction object.
|
||||||
|
/// </summary>
|
||||||
|
public class SocketReaction : IReaction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a WebSocket-based reaction object.
|
/// Gets the ID of the user who added the reaction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SocketReaction : IReaction
|
/// <remarks>
|
||||||
|
/// This property retrieves the snowflake identifier of the user responsible for this reaction. This
|
||||||
|
/// property will always contain the user identifier in event that
|
||||||
|
/// <see cref="Discord.WebSocket.SocketReaction.User" /> cannot be retrieved.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>
|
||||||
|
/// A user snowflake identifier associated with the user.
|
||||||
|
/// </returns>
|
||||||
|
public ulong UserId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user who added the reaction if possible.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// This property attempts to retrieve a WebSocket-cached user that is responsible for this reaction from
|
||||||
|
/// the client. In other words, when the user is not in the WebSocket cache, this property may not
|
||||||
|
/// contain a value, leaving the only identifiable information to be
|
||||||
|
/// <see cref="Discord.WebSocket.SocketReaction.UserId" />.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// If you wish to obtain an identifiable user object, consider utilizing
|
||||||
|
/// <see cref="Discord.Rest.DiscordRestClient" /> which will attempt to retrieve the user from REST.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>
|
||||||
|
/// A user object where possible; a value is not always returned.
|
||||||
|
/// </returns>
|
||||||
|
/// <seealso cref="Optional{T}"/>
|
||||||
|
public Optional<IUser> User { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ID of the message that has been reacted to.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A message snowflake identifier associated with the message.
|
||||||
|
/// </returns>
|
||||||
|
public ulong MessageId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message that has been reacted to if possible.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A WebSocket-based message where possible; a value is not always returned.
|
||||||
|
/// </returns>
|
||||||
|
/// <seealso cref="Optional{T}"/>
|
||||||
|
public Optional<SocketUserMessage> Message { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the channel where the reaction takes place in.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A WebSocket-based message channel.
|
||||||
|
/// </returns>
|
||||||
|
public ISocketMessageChannel Channel { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IEmote Emote { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the reaction is a super reaction.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsBurst { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IReadOnlyCollection<Color> BurstColors { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type of the reaction.
|
||||||
|
/// </summary>
|
||||||
|
public ReactionType ReactionType { get; }
|
||||||
|
|
||||||
|
internal SocketReaction(ISocketMessageChannel channel, ulong messageId, Optional<SocketUserMessage> message, ulong userId, Optional<IUser> user,
|
||||||
|
IEmote emoji, bool isBurst, IReadOnlyCollection<Color> colors, ReactionType reactionType)
|
||||||
{
|
{
|
||||||
/// <summary>
|
Channel = channel;
|
||||||
/// Gets the ID of the user who added the reaction.
|
MessageId = messageId;
|
||||||
/// </summary>
|
Message = message;
|
||||||
/// <remarks>
|
UserId = userId;
|
||||||
/// This property retrieves the snowflake identifier of the user responsible for this reaction. This
|
User = user;
|
||||||
/// property will always contain the user identifier in event that
|
Emote = emoji;
|
||||||
/// <see cref="Discord.WebSocket.SocketReaction.User" /> cannot be retrieved.
|
IsBurst = isBurst;
|
||||||
/// </remarks>
|
BurstColors = colors;
|
||||||
/// <returns>
|
ReactionType = reactionType;
|
||||||
/// A user snowflake identifier associated with the user.
|
}
|
||||||
/// </returns>
|
|
||||||
public ulong UserId { get; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the user who added the reaction if possible.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// This property attempts to retrieve a WebSocket-cached user that is responsible for this reaction from
|
|
||||||
/// the client. In other words, when the user is not in the WebSocket cache, this property may not
|
|
||||||
/// contain a value, leaving the only identifiable information to be
|
|
||||||
/// <see cref="Discord.WebSocket.SocketReaction.UserId" />.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// If you wish to obtain an identifiable user object, consider utilizing
|
|
||||||
/// <see cref="Discord.Rest.DiscordRestClient" /> which will attempt to retrieve the user from REST.
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
/// <returns>
|
|
||||||
/// A user object where possible; a value is not always returned.
|
|
||||||
/// </returns>
|
|
||||||
/// <seealso cref="Optional{T}"/>
|
|
||||||
public Optional<IUser> User { get; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the ID of the message that has been reacted to.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// A message snowflake identifier associated with the message.
|
|
||||||
/// </returns>
|
|
||||||
public ulong MessageId { get; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the message that has been reacted to if possible.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// A WebSocket-based message where possible; a value is not always returned.
|
|
||||||
/// </returns>
|
|
||||||
/// <seealso cref="Optional{T}"/>
|
|
||||||
public Optional<SocketUserMessage> Message { get; }
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the channel where the reaction takes place in.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// A WebSocket-based message channel.
|
|
||||||
/// </returns>
|
|
||||||
public ISocketMessageChannel Channel { get; }
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IEmote Emote { get; }
|
|
||||||
|
|
||||||
internal SocketReaction(ISocketMessageChannel channel, ulong messageId, Optional<SocketUserMessage> message, ulong userId, Optional<IUser> user, IEmote emoji)
|
internal static SocketReaction Create(Model model, ISocketMessageChannel channel, Optional<SocketUserMessage> message, Optional<IUser> user)
|
||||||
|
{
|
||||||
|
IEmote emote;
|
||||||
|
if (model.Emoji.Id.HasValue)
|
||||||
|
emote = new Emote(model.Emoji.Id.Value, model.Emoji.Name, model.Emoji.Animated.GetValueOrDefault());
|
||||||
|
else
|
||||||
|
emote = new Emoji(model.Emoji.Name);
|
||||||
|
return new SocketReaction(channel,
|
||||||
|
model.MessageId,
|
||||||
|
message,
|
||||||
|
model.UserId,
|
||||||
|
user,
|
||||||
|
emote,
|
||||||
|
model.IsBurst,
|
||||||
|
model.BurstColors.GetValueOrDefault(Array.Empty<Color>()).ToReadOnlyCollection(),
|
||||||
|
model.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (other == null)
|
||||||
|
return false;
|
||||||
|
if (other == this)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var otherReaction = other as SocketReaction;
|
||||||
|
if (otherReaction == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return UserId == otherReaction.UserId && MessageId == otherReaction.MessageId && Emote.Equals(otherReaction.Emote);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
{
|
{
|
||||||
Channel = channel;
|
var hashCode = UserId.GetHashCode();
|
||||||
MessageId = messageId;
|
hashCode = (hashCode * 397) ^ MessageId.GetHashCode();
|
||||||
Message = message;
|
hashCode = (hashCode * 397) ^ Emote.GetHashCode();
|
||||||
UserId = userId;
|
return hashCode;
|
||||||
User = user;
|
|
||||||
Emote = emoji;
|
|
||||||
}
|
|
||||||
internal static SocketReaction Create(Model model, ISocketMessageChannel channel, Optional<SocketUserMessage> message, Optional<IUser> user)
|
|
||||||
{
|
|
||||||
IEmote emote;
|
|
||||||
if (model.Emoji.Id.HasValue)
|
|
||||||
emote = new Emote(model.Emoji.Id.Value, model.Emoji.Name, model.Emoji.Animated.GetValueOrDefault());
|
|
||||||
else
|
|
||||||
emote = new Emoji(model.Emoji.Name);
|
|
||||||
return new SocketReaction(channel, model.MessageId, message, model.UserId, user, emote);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool Equals(object other)
|
|
||||||
{
|
|
||||||
if (other == null)
|
|
||||||
return false;
|
|
||||||
if (other == this)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var otherReaction = other as SocketReaction;
|
|
||||||
if (otherReaction == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return UserId == otherReaction.UserId && MessageId == otherReaction.MessageId && Emote.Equals(otherReaction.Emote);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
unchecked
|
|
||||||
{
|
|
||||||
var hashCode = UserId.GetHashCode();
|
|
||||||
hashCode = (hashCode * 397) ^ MessageId.GetHashCode();
|
|
||||||
hashCode = (hashCode * 397) ^ Emote.GetHashCode();
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user