| @@ -216,6 +216,16 @@ namespace Discord | |||
| /// </returns> | |||
| Task RemoveAllReactionsAsync(RequestOptions options = null); | |||
| /// <summary> | |||
| /// Removes all reactions of a given emote in the message. | |||
| /// </summary> | |||
| /// <param name="emote">The emote to clear.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asyncronous removal operation. | |||
| /// </returns> | |||
| Task RemoveEmojiReactionsAsync(IEmote emote, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Gets all users that reacted to a message with a given emote. | |||
| /// </summary> | |||
| @@ -665,6 +665,19 @@ namespace Discord.API | |||
| await SendAsync("DELETE", () => $"channels/{channelId}/messages/{messageId}/reactions", ids, options: options).ConfigureAwait(false); | |||
| } | |||
| public async Task RemoveEmojiReactionsAsync(ulong channelId, ulong messageId, string emoji, RequestOptions options = null) | |||
| { | |||
| Preconditions.NotEqual(channelId, 0, nameof(channelId)); | |||
| Preconditions.NotEqual(messageId, 0, nameof(messageId)); | |||
| options = RequestOptions.CreateOrClone(options); | |||
| var ids = new BucketIds(channelId: channelId); | |||
| await SendAsync("DELETE", () => $"channels/{channelId}/messages/{messageId}/reactions/{emoji}", ids, options: options); | |||
| } | |||
| public async Task<IReadOnlyCollection<User>> GetReactionUsersAsync(ulong channelId, ulong messageId, string emoji, GetReactionUsersParams args, RequestOptions options = null) | |||
| { | |||
| Preconditions.NotEqual(channelId, 0, nameof(channelId)); | |||
| @@ -71,6 +71,11 @@ namespace Discord.Rest | |||
| await client.ApiClient.RemoveAllReactionsAsync(msg.Channel.Id, msg.Id, options).ConfigureAwait(false); | |||
| } | |||
| public static async Task RemoveEmojiReactionsAsync(IMessage msg, IEmote emote, BaseDiscordClient client, RequestOptions options) | |||
| { | |||
| await client.ApiClient.RemoveEmojiReactionsAsync(msg.Channel.Id, msg.Id, emote is Emote e ? $"{e.Name}:{e.Id}" : emote.Name, options).ConfigureAwait(false); | |||
| } | |||
| public static IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IMessage msg, IEmote emote, | |||
| int? limit, BaseDiscordClient client, RequestOptions options) | |||
| { | |||
| @@ -182,6 +182,9 @@ namespace Discord.Rest | |||
| public Task RemoveAllReactionsAsync(RequestOptions options = null) | |||
| => MessageHelper.RemoveAllReactionsAsync(this, Discord, options); | |||
| /// <inheritdoc /> | |||
| public Task RemoveEmojiReactionsAsync(IEmote emote, RequestOptions options = null) | |||
| => MessageHelper.RemoveEmojiReactionsAsync(this, emote, Discord, options); | |||
| /// <inheritdoc /> | |||
| public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null) | |||
| => MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options); | |||
| } | |||
| @@ -236,11 +236,11 @@ namespace Discord.WebSocket | |||
| internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task>>(); | |||
| /// <summary> Fired when all reactions of a specific reaction are removed.</summary> | |||
| public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionsClearedEmoji { | |||
| add { _reactionsClearedEmojiEvent.Add(value); } | |||
| remove { _reactionsClearedEmojiEvent.Remove(value); } | |||
| public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> RemovedEmojiReactions { | |||
| add { _removedEmojiReactionsEvent.Add(value); } | |||
| remove { _removedEmojiReactionsEvent.Remove(value); } | |||
| } | |||
| internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionsClearedEmojiEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | |||
| internal readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _removedEmojiReactionsEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | |||
| //Roles | |||
| @@ -313,7 +313,7 @@ namespace Discord.WebSocket | |||
| client.ReactionAdded += (cache, channel, reaction) => _reactionAddedEvent.InvokeAsync(cache, channel, reaction); | |||
| client.ReactionRemoved += (cache, channel, reaction) => _reactionRemovedEvent.InvokeAsync(cache, channel, reaction); | |||
| client.ReactionsCleared += (cache, channel) => _reactionsClearedEvent.InvokeAsync(cache, channel); | |||
| client.ReactionsClearedEmoji += (cache, channel, reaction) => _reactionsClearedEmojiEvent.InvokeAsync(cache, channel, reaction); | |||
| client.RemovedEmojiReactions += (cache, channel, reaction) => _removedEmojiReactionsEvent.InvokeAsync(cache, channel, reaction); | |||
| client.RoleCreated += (role) => _roleCreatedEvent.InvokeAsync(role); | |||
| client.RoleDeleted += (role) => _roleDeletedEvent.InvokeAsync(role); | |||
| @@ -1401,7 +1401,7 @@ namespace Discord.WebSocket | |||
| cachedMsg?.ClearReactionsEmoji(reaction); | |||
| await TimedInvokeAsync(_reactionsClearedEmojiEvent, nameof(ReactionsClearedEmoji), cacheable, channel, reaction).ConfigureAwait(false); | |||
| await TimedInvokeAsync(_removedEmojiReactionsEvent, nameof(RemovedEmojiReactions), cacheable, channel, reaction).ConfigureAwait(false); | |||
| } | |||
| else | |||
| { | |||
| @@ -7,29 +7,65 @@ using Model = Discord.API.InviteEvent; | |||
| namespace Discord.WebSocket | |||
| { | |||
| /// <summary> | |||
| /// Represents a WebSocket-based invite. | |||
| /// </summary> | |||
| public class SocketInvite : SocketEntity<string> | |||
| { | |||
| /// <summary> | |||
| /// Gets the channel in which this invite was created. | |||
| /// </summary> | |||
| public ISocketMessageChannel Channel { get; private set; } | |||
| /// <summary> | |||
| /// Gets the channel ID in which this invite was created. | |||
| /// </summary> | |||
| public ulong ChannelId { get; private set; } | |||
| /// <summary> | |||
| /// Gets the guild in which this invite was created. | |||
| /// </summary> | |||
| public IGuild Guild { get; private set; } | |||
| /// <summary> | |||
| /// Gets the guild ID in which this invite was created. | |||
| /// </summary> | |||
| public ulong GuildId { get; private set; } | |||
| /// <summary> | |||
| /// Gets the unique identifier for this invite. | |||
| /// </summary> | |||
| public string Code { get; private set; } | |||
| public SocketUser Inviter { get; private set; } | |||
| /// <summary> | |||
| /// Gets the user who created this invite. | |||
| /// </summary> | |||
| public Optional<SocketUser> Inviter { get; private set; } | |||
| public DateTimeOffset CreatedAt { get; private set; } | |||
| /// <summary> | |||
| /// Gets when this invite was created. | |||
| /// </summary> | |||
| public Optional<DateTimeOffset> CreatedAt { get; private set; } | |||
| public int MaxAge { get; private set; } | |||
| /// <summary> | |||
| /// Gets the time (in seconds) until the invite expires. | |||
| /// </summary> | |||
| public Optional<int> MaxAge { get; private set; } | |||
| public int MaxUses { get; private set; } | |||
| /// <summary> | |||
| /// Gets the max number of uses this invite may have. | |||
| /// </summary> | |||
| public Optional<int> MaxUses { get; private set; } | |||
| public int Uses { get; set; } | |||
| /// <summary> | |||
| /// Gets the number of times this invite has been used. | |||
| /// </summary> | |||
| public Optional<int> Uses { get; set; } | |||
| public bool Temporary { get; private set; } | |||
| /// <summary> | |||
| /// Gets a value that indicates whether the invite is a temporary one. | |||
| /// </summary> | |||
| public Optional<bool> IsTemporary { get; private set; } | |||
| internal SocketInvite(DiscordSocketClient discord, Model model) | |||
| : base(discord, model.Code) | |||
| @@ -62,7 +98,7 @@ namespace Discord.WebSocket | |||
| MaxAge = model.MaxAge.Value; | |||
| MaxUses = model.MaxUses.Value; | |||
| Uses = model.Uses.Value; | |||
| Temporary = model.Temporary; | |||
| IsTemporary = model.Temporary; | |||
| } | |||
| internal void Update(string code, IGuild guild, ISocketMessageChannel channel) | |||
| @@ -215,6 +215,9 @@ namespace Discord.WebSocket | |||
| public Task RemoveAllReactionsAsync(RequestOptions options = null) | |||
| => MessageHelper.RemoveAllReactionsAsync(this, Discord, options); | |||
| /// <inheritdoc /> | |||
| public Task RemoveEmojiReactionsAsync(IEmote emote, RequestOptions options = null) | |||
| => MessageHelper.RemoveEmojiReactionsAsync(this, emote, Discord, options); | |||
| /// <inheritdoc /> | |||
| public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null) | |||
| => MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options); | |||
| } | |||