Browse Source

Remove ReactionMessage types, move reaction impl to IMessage

Removes the IReactionMessage and derived types, which was unnecessary since all classes derived from IReactionMessage were IMessage.

Moves the reaction implementation to IMessage and derived types.
pull/1368/head
Chris Johnston 6 years ago
parent
commit
118217387e
12 changed files with 160 additions and 222 deletions
  1. +85
    -0
      src/Discord.Net.Core/Entities/Messages/IMessage.cs
  2. +0
    -98
      src/Discord.Net.Core/Entities/Messages/IReactionMessage.cs
  3. +1
    -1
      src/Discord.Net.Core/Entities/Messages/ISystemMessage.cs
  4. +1
    -1
      src/Discord.Net.Core/Entities/Messages/IUserMessage.cs
  5. +36
    -0
      src/Discord.Net.Rest/Entities/Messages/RestMessage.cs
  6. +0
    -63
      src/Discord.Net.Rest/Entities/Messages/RestReactionMessage.cs
  7. +1
    -1
      src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs
  8. +1
    -1
      src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs
  9. +33
    -0
      src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs
  10. +0
    -55
      src/Discord.Net.WebSocket/Entities/Messages/SocketReactionMessage.cs
  11. +1
    -1
      src/Discord.Net.WebSocket/Entities/Messages/SocketSystemMessage.cs
  12. +1
    -1
      src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs

+ 85
- 0
src/Discord.Net.Core/Entities/Messages/IMessage.cs View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Discord
{
@@ -138,5 +139,89 @@ namespace Discord
/// A message's application, if any is associated.
/// </returns>
MessageApplication Application { get; }

/// <summary>
/// Gets all reactions included in this message.
/// </summary>
IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions { get; }

/// <summary>
/// Adds a reaction to this message.
/// </summary>
/// <example>
/// The following example adds the reaction, <c>💕</c>, to the message.
/// <code language="cs">
/// await msg.AddReactionAsync(new Emoji("\U0001f495"));
/// </code>
/// </example>
/// <param name="emote">The emoji used to react to this message.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous operation for adding a reaction to this message.
/// </returns>
/// <seealso cref="IEmote"/>
Task AddReactionAsync(IEmote emote, RequestOptions options = null);
/// <summary>
/// Removes a reaction from message.
/// </summary>
/// <example>
/// The following example removes the reaction, <c>💕</c>, added by the message author from the message.
/// <code language="cs">
/// await msg.RemoveReactionAsync(new Emoji("\U0001f495"), msg.Author);
/// </code>
/// </example>
/// <param name="emote">The emoji used to react to this message.</param>
/// <param name="user">The user that added the emoji.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous operation for removing a reaction to this message.
/// </returns>
/// <seealso cref="IEmote"/>
Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null);
/// <summary>
/// Removes a reaction from message.
/// </summary>
/// <example>
/// The following example removes the reaction, <c>💕</c>, added by the user with ID 84291986575613952 from the message.
/// <code language="cs">
/// await msg.RemoveReactionAsync(new Emoji("\U0001f495"), 84291986575613952);
/// </code>
/// </example>
/// <param name="emote">The emoji used to react to this message.</param>
/// <param name="userId">The ID of the user that added the emoji.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous operation for removing a reaction to this message.
/// </returns>
/// <seealso cref="IEmote"/>
Task RemoveReactionAsync(IEmote emote, ulong userId, RequestOptions options = null);
/// <summary>
/// Removes all reactions from this message.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous removal operation.
/// </returns>
Task RemoveAllReactionsAsync(RequestOptions options = null);

/// <summary>
/// Gets all users that reacted to a message with a given emote.
/// </summary>
/// <example>
/// The following example gets the users that have reacted with the emoji <c>💕</c> to the message.
/// <code language="cs">
/// var emoji = new Emoji("\U0001f495");
/// var reactedUsers = await message.GetReactionUsersAsync(emoji, 100).FlattenAsync();
/// </code>
/// </example>
/// <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="options">The options to be used when sending the request.</param>
/// <returns>
/// A paged collection containing a read-only collection of users that has reacted to this message.
/// Flattening the paginated response into a collection of users with
/// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> is required if you wish to access the users.
/// </returns>
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emoji, int limit, RequestOptions options = null);
}
}

+ 0
- 98
src/Discord.Net.Core/Entities/Messages/IReactionMessage.cs View File

@@ -1,98 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// Represents a message where reactions can be added or removed.
/// </summary>
public interface IReactionMessage : IMessage
{
/// <summary>
/// Gets all reactions included in this message.
/// </summary>
IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions { get; }

/// <summary>
/// Adds a reaction to this message.
/// </summary>
/// <example>
/// The following example adds the reaction, <c>💕</c>, to the message.
/// <code language="cs">
/// await msg.AddReactionAsync(new Emoji("\U0001f495"));
/// </code>
/// </example>
/// <param name="emote">The emoji used to react to this message.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous operation for adding a reaction to this message.
/// </returns>
/// <seealso cref="IEmote"/>
Task AddReactionAsync(IEmote emote, RequestOptions options = null);
/// <summary>
/// Removes a reaction from message.
/// </summary>
/// <example>
/// The following example removes the reaction, <c>💕</c>, added by the message author from the message.
/// <code language="cs">
/// await msg.RemoveReactionAsync(new Emoji("\U0001f495"), msg.Author);
/// </code>
/// </example>
/// <param name="emote">The emoji used to react to this message.</param>
/// <param name="user">The user that added the emoji.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous operation for removing a reaction to this message.
/// </returns>
/// <seealso cref="IEmote"/>
Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null);
/// <summary>
/// Removes a reaction from message.
/// </summary>
/// <example>
/// The following example removes the reaction, <c>💕</c>, added by the user with ID 84291986575613952 from the message.
/// <code language="cs">
/// await msg.RemoveReactionAsync(new Emoji("\U0001f495"), 84291986575613952);
/// </code>
/// </example>
/// <param name="emote">The emoji used to react to this message.</param>
/// <param name="userId">The ID of the user that added the emoji.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous operation for removing a reaction to this message.
/// </returns>
/// <seealso cref="IEmote"/>
Task RemoveReactionAsync(IEmote emote, ulong userId, RequestOptions options = null);
/// <summary>
/// Removes all reactions from this message.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous removal operation.
/// </returns>
Task RemoveAllReactionsAsync(RequestOptions options = null);

/// <summary>
/// Gets all users that reacted to a message with a given emote.
/// </summary>
/// <example>
/// The following example gets the users that have reacted with the emoji <c>💕</c> to the message.
/// <code language="cs">
/// var emoji = new Emoji("\U0001f495");
/// var reactedUsers = await message.GetReactionUsersAsync(emoji, 100).FlattenAsync();
/// </code>
/// </example>
/// <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="options">The options to be used when sending the request.</param>
/// <returns>
/// A paged collection containing a read-only collection of users that has reacted to this message.
/// Flattening the paginated response into a collection of users with
/// <see cref="AsyncEnumerableExtensions.FlattenAsync{T}"/> is required if you wish to access the users.
/// </returns>
IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emoji, int limit, RequestOptions options = null);
}
}

+ 1
- 1
src/Discord.Net.Core/Entities/Messages/ISystemMessage.cs View File

@@ -3,7 +3,7 @@ namespace Discord
/// <summary>
/// Represents a generic message sent by the system.
/// </summary>
public interface ISystemMessage : IReactionMessage
public interface ISystemMessage : IMessage
{
}
}

+ 1
- 1
src/Discord.Net.Core/Entities/Messages/IUserMessage.cs View File

@@ -7,7 +7,7 @@ namespace Discord
/// <summary>
/// Represents a generic message sent by a user.
/// </summary>
public interface IUserMessage : IReactionMessage
public interface IUserMessage : IMessage
{
/// <summary>
/// Modifies this message.


+ 36
- 0
src/Discord.Net.Rest/Entities/Messages/RestMessage.cs View File

@@ -13,6 +13,7 @@ namespace Discord.Rest
public abstract class RestMessage : RestEntity<ulong>, IMessage, IUpdateable
{
private long _timestampTicks;
private ImmutableArray<RestReaction> _reactions = ImmutableArray.Create<RestReaction>();

/// <inheritdoc />
public IMessageChannel Channel { get; }
@@ -106,6 +107,22 @@ namespace Discord.Rest
PartyId = model.Activity.Value.PartyId.GetValueOrDefault()
};
}

if (model.Reactions.IsSpecified)
{
var value = model.Reactions.Value;
if (value.Length > 0)
{
var reactions = ImmutableArray.CreateBuilder<RestReaction>(value.Length);
for (int i = 0; i < value.Length; i++)
reactions.Add(RestReaction.Create(value[i]));
_reactions = reactions.ToImmutable();
}
else
_reactions = ImmutableArray.Create<RestReaction>();
}
else
_reactions = ImmutableArray.Create<RestReaction>();
}

/// <inheritdoc />
@@ -135,5 +152,24 @@ namespace Discord.Rest
IReadOnlyCollection<IEmbed> IMessage.Embeds => Embeds;
/// <inheritdoc />
IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray();
/// <inheritdoc />
public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me });

/// <inheritdoc />
public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
=> MessageHelper.AddReactionAsync(this, emote, Discord, options);
/// <inheritdoc />
public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null)
=> MessageHelper.RemoveReactionAsync(this, user.Id, emote, Discord, options);
/// <inheritdoc />
public Task RemoveReactionAsync(IEmote emote, ulong userId, RequestOptions options = null)
=> MessageHelper.RemoveReactionAsync(this, userId, emote, Discord, options);
/// <inheritdoc />
public Task RemoveAllReactionsAsync(RequestOptions options = null)
=> MessageHelper.RemoveAllReactionsAsync(this, Discord, options);
/// <inheritdoc />
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null)
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options);
}
}

+ 0
- 63
src/Discord.Net.Rest/Entities/Messages/RestReactionMessage.cs View File

@@ -1,63 +0,0 @@
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
{
/// <summary>
/// Represents a REST-based mesage where reactions can be added or removed.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public abstract class RestReactionMessage : RestMessage, IReactionMessage
{
private ImmutableArray<RestReaction> _reactions = ImmutableArray.Create<RestReaction>();

/// <inheritdoc />
public IReadOnlyDictionary<IEmote, ReactionMetadata> 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<RestReaction>(value.Length);
for (int i = 0; i < value.Length; i++)
reactions.Add(RestReaction.Create(value[i]));
_reactions = reactions.ToImmutable();
}
else
_reactions = ImmutableArray.Create<RestReaction>();
}
else
_reactions = ImmutableArray.Create<RestReaction>();
}

/// <inheritdoc />
public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
=> MessageHelper.AddReactionAsync(this, emote, Discord, options);
/// <inheritdoc />
public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null)
=> MessageHelper.RemoveReactionAsync(this, user.Id, emote, Discord, options);
/// <inheritdoc />
public Task RemoveReactionAsync(IEmote emote, ulong userId, RequestOptions options = null)
=> MessageHelper.RemoveReactionAsync(this, userId, emote, Discord, options);
/// <inheritdoc />
public Task RemoveAllReactionsAsync(RequestOptions options = null)
=> MessageHelper.RemoveAllReactionsAsync(this, Discord, options);
/// <inheritdoc />
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null)
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options);
}
}

+ 1
- 1
src/Discord.Net.Rest/Entities/Messages/RestSystemMessage.cs View File

@@ -7,7 +7,7 @@ namespace Discord.Rest
/// Represents a REST-based system message.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestSystemMessage : RestReactionMessage, ISystemMessage
public class RestSystemMessage : RestMessage, ISystemMessage
{
/// <inheritdoc />
public MessageType Type { get; private set; }


+ 1
- 1
src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs View File

@@ -11,7 +11,7 @@ namespace Discord.Rest
/// Represents a REST-based message sent by a user.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestUserMessage : RestReactionMessage, IUserMessage
public class RestUserMessage : RestMessage, IUserMessage
{
private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed;
private long? _editedTimestampTicks;


+ 33
- 0
src/Discord.Net.WebSocket/Entities/Messages/SocketMessage.cs View File

@@ -14,6 +14,7 @@ namespace Discord.WebSocket
public abstract class SocketMessage : SocketEntity<ulong>, IMessage
{
private long _timestampTicks;
private readonly List<SocketReaction> _reactions = new List<SocketReaction>();

/// <summary>
/// Gets the author of this message.
@@ -89,6 +90,8 @@ namespace Discord.WebSocket
public virtual IReadOnlyCollection<SocketUser> MentionedUsers => ImmutableArray.Create<SocketUser>();
/// <inheritdoc />
public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>();
/// <inheritdoc />
public IReadOnlyDictionary<IEmote, ReactionMetadata> 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) });

/// <inheritdoc />
public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks);
@@ -169,5 +172,35 @@ namespace Discord.WebSocket
IReadOnlyCollection<ulong> IMessage.MentionedRoleIds => MentionedRoles.Select(x => x.Id).ToImmutableArray();
/// <inheritdoc />
IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray();

internal void AddReaction(SocketReaction reaction)
{
_reactions.Add(reaction);
}
internal void RemoveReaction(SocketReaction reaction)
{
if (_reactions.Contains(reaction))
_reactions.Remove(reaction);
}
internal void ClearReactions()
{
_reactions.Clear();
}

/// <inheritdoc />
public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
=> MessageHelper.AddReactionAsync(this, emote, Discord, options);
/// <inheritdoc />
public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null)
=> MessageHelper.RemoveReactionAsync(this, user.Id, emote, Discord, options);
/// <inheritdoc />
public Task RemoveReactionAsync(IEmote emote, ulong userId, RequestOptions options = null)
=> MessageHelper.RemoveReactionAsync(this, userId, emote, Discord, options);
/// <inheritdoc />
public Task RemoveAllReactionsAsync(RequestOptions options = null)
=> MessageHelper.RemoveAllReactionsAsync(this, Discord, options);
/// <inheritdoc />
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null)
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options);
}
}

+ 0
- 55
src/Discord.Net.WebSocket/Entities/Messages/SocketReactionMessage.cs View File

@@ -1,55 +0,0 @@
using Discord.Rest;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Discord.WebSocket
{
/// <summary>
/// Represents a WebSocket-based message where reactions can be added or removed.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public abstract class SocketReactionMessage : SocketMessage, IReactionMessage
{
private readonly List<SocketReaction> _reactions = new List<SocketReaction>();

internal SocketReactionMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source)
: base(discord, id, channel, author, source)
{
}

/// <inheritdoc />
public IReadOnlyDictionary<IEmote, ReactionMetadata> 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 void AddReaction(SocketReaction reaction)
{
_reactions.Add(reaction);
}
internal void RemoveReaction(SocketReaction reaction)
{
if (_reactions.Contains(reaction))
_reactions.Remove(reaction);
}
internal void ClearReactions()
{
_reactions.Clear();
}

/// <inheritdoc />
public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
=> MessageHelper.AddReactionAsync(this, emote, Discord, options);
/// <inheritdoc />
public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null)
=> MessageHelper.RemoveReactionAsync(this, user.Id, emote, Discord, options);
/// <inheritdoc />
public Task RemoveReactionAsync(IEmote emote, ulong userId, RequestOptions options = null)
=> MessageHelper.RemoveReactionAsync(this, userId, emote, Discord, options);
/// <inheritdoc />
public Task RemoveAllReactionsAsync(RequestOptions options = null)
=> MessageHelper.RemoveAllReactionsAsync(this, Discord, options);
/// <inheritdoc />
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null)
=> MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options);
}
}

+ 1
- 1
src/Discord.Net.WebSocket/Entities/Messages/SocketSystemMessage.cs View File

@@ -7,7 +7,7 @@ namespace Discord.WebSocket
/// Represents a WebSocket-based message sent by the system.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class SocketSystemMessage : SocketReactionMessage, ISystemMessage
public class SocketSystemMessage : SocketMessage, ISystemMessage
{
/// <inheritdoc />
public MessageType Type { get; private set; }


+ 1
- 1
src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs View File

@@ -13,7 +13,7 @@ namespace Discord.WebSocket
/// Represents a WebSocket-based message sent by a user.
/// </summary>
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class SocketUserMessage : SocketReactionMessage, IUserMessage
public class SocketUserMessage : SocketMessage, IUserMessage
{
private bool _isMentioningEveryone, _isTTS, _isPinned, _isSuppressed;
private long? _editedTimestampTicks;


Loading…
Cancel
Save