* Reimplement messags bulk deleted event RogueException/Discord.Net#1120 * Update remark * Backwards compatability with config optiontags/2.1.0
@@ -1,4 +1,5 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
@@ -128,6 +129,38 @@ namespace Discord.WebSocket | |||||
remove { _messageDeletedEvent.Remove(value); } | remove { _messageDeletedEvent.Remove(value); } | ||||
} | } | ||||
internal readonly AsyncEvent<Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent<Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task>>(); | internal readonly AsyncEvent<Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent<Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task>>(); | ||||
/// <summary> Fired when multiple messages are bulk deleted. </summary> | |||||
/// <remarks> | |||||
/// <note> | |||||
/// The <see cref="MessageDeleted"/> event will not be fired for individual messages contained in this event. | |||||
/// </note> | |||||
/// <para> | |||||
/// This event is fired when multiple messages are bulk deleted. The event handler must return a | |||||
/// <see cref="Task"/> and accept an <see cref="IReadOnlyCollection{Cacheable{TEntity,TId}}"/> and | |||||
/// <see cref="ISocketMessageChannel"/> as its parameters. | |||||
/// </para> | |||||
/// <para> | |||||
/// <note type="important"> | |||||
/// It is not possible to retrieve the message via | |||||
/// <see cref="Cacheable{TEntity,TId}.DownloadAsync"/>; the message cannot be retrieved by Discord | |||||
/// after the message has been deleted. | |||||
/// </note> | |||||
/// If caching is enabled via <see cref="DiscordSocketConfig"/>, the | |||||
/// <see cref="Cacheable{TEntity,TId}"/> entity will contain the deleted message; otherwise, in event | |||||
/// that the message cannot be retrieved, the snowflake ID of the message is preserved in the | |||||
/// <see cref="ulong"/>. | |||||
/// </para> | |||||
/// <para> | |||||
/// The source channel of the removed message will be passed into the | |||||
/// <see cref="ISocketMessageChannel"/> parameter. | |||||
/// </para> | |||||
/// </remarks> | |||||
public event Func<IReadOnlyCollection<Cacheable<IMessage, ulong>>, ISocketMessageChannel, Task> MessagesBulkDeleted | |||||
{ | |||||
add { _messagesBulkDeletedEvent.Add(value); } | |||||
remove { _messagesBulkDeletedEvent.Remove(value); } | |||||
} | |||||
internal readonly AsyncEvent<Func<IReadOnlyCollection<Cacheable<IMessage, ulong>>, ISocketMessageChannel, Task>> _messagesBulkDeletedEvent = new AsyncEvent<Func<IReadOnlyCollection<Cacheable<IMessage, ulong>>, ISocketMessageChannel, Task>>(); | |||||
/// <summary> Fired when a message is updated. </summary> | /// <summary> Fired when a message is updated. </summary> | ||||
/// <remarks> | /// <remarks> | ||||
/// <para> | /// <para> | ||||
@@ -302,6 +302,7 @@ namespace Discord.WebSocket | |||||
client.MessageReceived += (msg) => _messageReceivedEvent.InvokeAsync(msg); | client.MessageReceived += (msg) => _messageReceivedEvent.InvokeAsync(msg); | ||||
client.MessageDeleted += (cache, channel) => _messageDeletedEvent.InvokeAsync(cache, channel); | client.MessageDeleted += (cache, channel) => _messageDeletedEvent.InvokeAsync(cache, channel); | ||||
client.MessagesBulkDeleted += (cache, channel) => _messagesBulkDeletedEvent.InvokeAsync(cache, channel); | |||||
client.MessageUpdated += (oldMsg, newMsg, channel) => _messageUpdatedEvent.InvokeAsync(oldMsg, newMsg, channel); | client.MessageUpdated += (oldMsg, newMsg, channel) => _messageUpdatedEvent.InvokeAsync(oldMsg, newMsg, channel); | ||||
client.ReactionAdded += (cache, channel, reaction) => _reactionAddedEvent.InvokeAsync(cache, channel, reaction); | client.ReactionAdded += (cache, channel, reaction) => _reactionAddedEvent.InvokeAsync(cache, channel, reaction); | ||||
client.ReactionRemoved += (cache, channel, reaction) => _reactionRemovedEvent.InvokeAsync(cache, channel, reaction); | client.ReactionRemoved += (cache, channel, reaction) => _reactionRemovedEvent.InvokeAsync(cache, channel, reaction); | ||||
@@ -66,6 +66,7 @@ namespace Discord.WebSocket | |||||
internal WebSocketProvider WebSocketProvider { get; private set; } | internal WebSocketProvider WebSocketProvider { get; private set; } | ||||
internal bool AlwaysDownloadUsers { get; private set; } | internal bool AlwaysDownloadUsers { get; private set; } | ||||
internal int? HandlerTimeout { get; private set; } | internal int? HandlerTimeout { get; private set; } | ||||
internal bool UseMessagesBulkDeletedOnly { get; private set; } | |||||
internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; | internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; | ||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
@@ -128,6 +129,7 @@ namespace Discord.WebSocket | |||||
WebSocketProvider = config.WebSocketProvider; | WebSocketProvider = config.WebSocketProvider; | ||||
AlwaysDownloadUsers = config.AlwaysDownloadUsers; | AlwaysDownloadUsers = config.AlwaysDownloadUsers; | ||||
HandlerTimeout = config.HandlerTimeout; | HandlerTimeout = config.HandlerTimeout; | ||||
UseMessagesBulkDeletedOnly = config.UseMessagesBulkDeletedOnly; | |||||
State = new ClientState(0, 0); | State = new ClientState(0, 0); | ||||
Rest = new DiscordSocketRestClient(config, ApiClient); | Rest = new DiscordSocketRestClient(config, ApiClient); | ||||
_heartbeatTimes = new ConcurrentQueue<long>(); | _heartbeatTimes = new ConcurrentQueue<long>(); | ||||
@@ -1365,13 +1367,19 @@ namespace Discord.WebSocket | |||||
return; | return; | ||||
} | } | ||||
var cacheableList = ImmutableArray<Cacheable<IMessage, ulong>>.Empty; | |||||
foreach (ulong id in data.Ids) | foreach (ulong id in data.Ids) | ||||
{ | { | ||||
var msg = SocketChannelHelper.RemoveMessage(channel, this, id); | var msg = SocketChannelHelper.RemoveMessage(channel, this, id); | ||||
bool isCached = msg != null; | bool isCached = msg != null; | ||||
var cacheable = new Cacheable<IMessage, ulong>(msg, id, isCached, async () => await channel.GetMessageAsync(id).ConfigureAwait(false)); | var cacheable = new Cacheable<IMessage, ulong>(msg, id, isCached, async () => await channel.GetMessageAsync(id).ConfigureAwait(false)); | ||||
await TimedInvokeAsync(_messageDeletedEvent, nameof(MessageDeleted), cacheable, channel).ConfigureAwait(false); | |||||
cacheableList = cacheableList.Add(cacheable); | |||||
if (!UseMessagesBulkDeletedOnly) | |||||
await TimedInvokeAsync(_messageDeletedEvent, nameof(MessageDeleted), cacheable, channel).ConfigureAwait(false); | |||||
} | } | ||||
await TimedInvokeAsync(_messagesBulkDeletedEvent, nameof(MessagesBulkDeleted), cacheableList, channel).ConfigureAwait(false); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -107,6 +107,11 @@ namespace Discord.WebSocket | |||||
public int? HandlerTimeout { get; set; } = 3000; | public int? HandlerTimeout { get; set; } = 3000; | ||||
/// <summary> | /// <summary> | ||||
/// Gets or sets whether or not <see cref="Discord.WebSocket.BaseSocketClient.MessageDeleted"/> is fired for each message on bulk delete. | |||||
/// </summary> | |||||
public bool UseMessagesBulkDeletedOnly { get; set; } = false; | |||||
/// <summary> | |||||
/// Initializes a default configuration. | /// Initializes a default configuration. | ||||
/// </summary> | /// </summary> | ||||
public DiscordSocketConfig() | public DiscordSocketConfig() | ||||