fix: Gateway events for DMs (#1854)
* Fix MessageUpdate when there's no channel cached * Fix message events * Fix cacheable type * Fix examples * Revert MessageUpdated
This commit is contained in:
@@ -71,7 +71,6 @@ namespace Discord.WebSocket
|
||||
internal WebSocketProvider WebSocketProvider { get; private set; }
|
||||
internal bool AlwaysDownloadUsers { get; private set; }
|
||||
internal int? HandlerTimeout { get; private set; }
|
||||
internal bool? ExclusiveBulkDelete { get; private set; }
|
||||
|
||||
internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient;
|
||||
/// <inheritdoc />
|
||||
@@ -132,7 +131,6 @@ namespace Discord.WebSocket
|
||||
WebSocketProvider = config.WebSocketProvider;
|
||||
AlwaysDownloadUsers = config.AlwaysDownloadUsers;
|
||||
HandlerTimeout = config.HandlerTimeout;
|
||||
ExclusiveBulkDelete = config.ExclusiveBulkDelete;
|
||||
State = new ClientState(0, 0);
|
||||
Rest = new DiscordSocketRestClient(config, ApiClient);
|
||||
_heartbeatTimes = new ConcurrentQueue<long>();
|
||||
@@ -296,6 +294,44 @@ namespace Discord.WebSocket
|
||||
public override SocketChannel GetChannel(ulong id)
|
||||
=> State.GetChannel(id);
|
||||
/// <summary>
|
||||
/// Gets a generic channel from the cache or does a rest request if unavailable.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code language="cs" title="Example method">
|
||||
/// var channel = await _client.GetChannelAsync(381889909113225237);
|
||||
/// if (channel != null && channel is IMessageChannel msgChannel)
|
||||
/// {
|
||||
/// await msgChannel.SendMessageAsync($"{msgChannel} is created at {msgChannel.CreatedAt}");
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="id">The snowflake identifier of the channel (e.g. `381889909113225237`).</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains the channel associated
|
||||
/// with the snowflake identifier; <c>null</c> when the channel cannot be found.
|
||||
/// </returns>
|
||||
public async ValueTask<IChannel> GetChannelAsync(ulong id, RequestOptions options = null)
|
||||
=> GetChannel(id) ?? (IChannel)await ClientHelper.GetChannelAsync(this, id, options).ConfigureAwait(false);
|
||||
/// <summary>
|
||||
/// Gets a user from the cache or does a rest request if unavailable.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code language="cs" title="Example method">
|
||||
/// var user = await _client.GetUserAsync(168693960628371456);
|
||||
/// if (user != null)
|
||||
/// Console.WriteLine($"{user} is created at {user.CreatedAt}.";
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <param name="id">The snowflake identifier of the user (e.g. `168693960628371456`).</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous get operation. The task result contains the user associated with
|
||||
/// the snowflake identifier; <c>null</c> if the user is not found.
|
||||
/// </returns>
|
||||
public async ValueTask<IUser> GetUserAsync(ulong id, RequestOptions options = null)
|
||||
=> await ClientHelper.GetUserAsync(this, id, options).ConfigureAwait(false);
|
||||
/// <summary>
|
||||
/// Clears all cached channels from the client.
|
||||
/// </summary>
|
||||
public void PurgeChannelCache() => State.PurgeAllChannels();
|
||||
@@ -1227,7 +1263,7 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_CREATE)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<API.Message>(_serializer);
|
||||
var channel = State.GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (guild != null && !guild.IsSynced)
|
||||
@@ -1291,52 +1327,77 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_UPDATE)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<API.Message>(_serializer);
|
||||
if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel)
|
||||
{
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (guild != null && !guild.IsSynced)
|
||||
{
|
||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
SocketMessage before = null, after = null;
|
||||
SocketMessage cachedMsg = channel.GetCachedMessage(data.Id);
|
||||
bool isCached = cachedMsg != null;
|
||||
if (isCached)
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (guild != null && !guild.IsSynced)
|
||||
{
|
||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (channel == null)
|
||||
{
|
||||
if (!data.GuildId.IsSpecified) // assume it is a DM
|
||||
{
|
||||
before = cachedMsg.Clone();
|
||||
cachedMsg.Update(State, data);
|
||||
after = cachedMsg;
|
||||
channel = CreateDMChannel(data.ChannelId, data.Author.Value, State);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Edited message isnt in cache, create a detached one
|
||||
SocketUser author;
|
||||
if (data.Author.IsSpecified)
|
||||
{
|
||||
if (guild != null)
|
||||
author = guild.GetUser(data.Author.Value.Id);
|
||||
else
|
||||
author = (channel as SocketChannel).GetUser(data.Author.Value.Id);
|
||||
if (author == null)
|
||||
author = SocketUnknownUser.Create(this, State, data.Author.Value);
|
||||
}
|
||||
else
|
||||
// Message author wasn't specified in the payload, so create a completely anonymous unknown user
|
||||
author = new SocketUnknownUser(this, id: 0);
|
||||
|
||||
after = SocketMessage.Create(this, State, author, channel, data);
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var cacheableBefore = new Cacheable<IMessage, ulong>(before, data.Id, isCached, async () => await channel.GetMessageAsync(data.Id).ConfigureAwait(false));
|
||||
}
|
||||
|
||||
await TimedInvokeAsync(_messageUpdatedEvent, nameof(MessageUpdated), cacheableBefore, after, channel).ConfigureAwait(false);
|
||||
SocketMessage before = null, after = null;
|
||||
SocketMessage cachedMsg = channel.GetCachedMessage(data.Id);
|
||||
bool isCached = cachedMsg != null;
|
||||
if (isCached)
|
||||
{
|
||||
before = cachedMsg.Clone();
|
||||
cachedMsg.Update(State, data);
|
||||
after = cachedMsg;
|
||||
}
|
||||
else
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
return;
|
||||
//Edited message isnt in cache, create a detached one
|
||||
SocketUser author;
|
||||
if (guild != null)
|
||||
{
|
||||
if (data.WebhookId.IsSpecified)
|
||||
author = SocketWebhookUser.Create(guild, State, data.Author.Value, data.WebhookId.Value);
|
||||
else
|
||||
author = guild.GetUser(data.Author.Value.Id);
|
||||
}
|
||||
else
|
||||
author = (channel as SocketChannel).GetUser(data.Author.Value.Id);
|
||||
|
||||
if (author == null)
|
||||
{
|
||||
if (guild != null)
|
||||
{
|
||||
if (data.Member.IsSpecified) // member isn't always included, but use it when we can
|
||||
{
|
||||
data.Member.Value.User = data.Author.Value;
|
||||
author = guild.AddOrUpdateUser(data.Member.Value);
|
||||
}
|
||||
else
|
||||
author = guild.AddOrUpdateUser(data.Author.Value); // user has no guild-specific data
|
||||
}
|
||||
else if (channel is SocketGroupChannel groupChannel)
|
||||
author = groupChannel.GetOrAddUser(data.Author.Value);
|
||||
else
|
||||
{
|
||||
await UnknownChannelUserAsync(type, data.Author.Value.Id, channel.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
after = SocketMessage.Create(this, State, author, channel, data);
|
||||
}
|
||||
var cacheableBefore = new Cacheable<IMessage, ulong>(before, data.Id, isCached, async () => await channel.GetMessageAsync(data.Id).ConfigureAwait(false));
|
||||
|
||||
await TimedInvokeAsync(_messageUpdatedEvent, nameof(MessageUpdated), cacheableBefore, after, channel).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_DELETE":
|
||||
@@ -1344,26 +1405,22 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_DELETE)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<API.Message>(_serializer);
|
||||
if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel)
|
||||
{
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (!(guild?.IsSynced ?? true))
|
||||
{
|
||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
var msg = SocketChannelHelper.RemoveMessage(channel, this, data.Id);
|
||||
bool isCached = msg != null;
|
||||
var cacheable = new Cacheable<IMessage, ulong>(msg, data.Id, isCached, async () => await channel.GetMessageAsync(data.Id).ConfigureAwait(false));
|
||||
|
||||
await TimedInvokeAsync(_messageDeletedEvent, nameof(MessageDeleted), cacheable, channel).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (!(guild?.IsSynced ?? true))
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
SocketMessage msg = null;
|
||||
if (channel != null)
|
||||
msg = SocketChannelHelper.RemoveMessage(channel, this, data.Id);
|
||||
var cacheableMsg = new Cacheable<IMessage, ulong>(msg, data.Id, msg != null, () => Task.FromResult((IMessage)null));
|
||||
var cacheableChannel = new Cacheable<IMessageChannel, ulong>(channel, data.ChannelId, channel != null, async () => await GetChannelAsync(data.ChannelId).ConfigureAwait(false) as IMessageChannel);
|
||||
|
||||
await TimedInvokeAsync(_messageDeletedEvent, nameof(MessageDeleted), cacheableMsg, cacheableChannel).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_REACTION_ADD":
|
||||
@@ -1371,40 +1428,43 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_REACTION_ADD)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<API.Gateway.Reaction>(_serializer);
|
||||
if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel)
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
var cachedMsg = channel?.GetCachedMessage(data.MessageId) as SocketUserMessage;
|
||||
bool isMsgCached = cachedMsg != null;
|
||||
IUser user = null;
|
||||
if (channel != null)
|
||||
user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly).ConfigureAwait(false);
|
||||
|
||||
var optionalMsg = !isMsgCached
|
||||
? Optional.Create<SocketUserMessage>()
|
||||
: Optional.Create(cachedMsg);
|
||||
|
||||
if (data.Member.IsSpecified)
|
||||
{
|
||||
var cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage;
|
||||
bool isCached = cachedMsg != null;
|
||||
var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly).ConfigureAwait(false);
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
|
||||
var optionalMsg = !isCached
|
||||
? Optional.Create<SocketUserMessage>()
|
||||
: Optional.Create(cachedMsg);
|
||||
|
||||
if (data.Member.IsSpecified)
|
||||
{
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
|
||||
if (guild != null)
|
||||
user = guild.AddOrUpdateUser(data.Member.Value);
|
||||
}
|
||||
|
||||
var optionalUser = user is null
|
||||
? Optional.Create<IUser>()
|
||||
: Optional.Create(user);
|
||||
|
||||
var reaction = SocketReaction.Create(data, channel, optionalMsg, optionalUser);
|
||||
var cacheable = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId).ConfigureAwait(false) as IUserMessage);
|
||||
|
||||
cachedMsg?.AddReaction(reaction);
|
||||
|
||||
await TimedInvokeAsync(_reactionAddedEvent, nameof(ReactionAdded), cacheable, channel, reaction).ConfigureAwait(false);
|
||||
if (guild != null)
|
||||
user = guild.AddOrUpdateUser(data.Member.Value);
|
||||
}
|
||||
else
|
||||
user = GetUser(data.UserId);
|
||||
|
||||
var optionalUser = user is null
|
||||
? Optional.Create<IUser>()
|
||||
: Optional.Create(user);
|
||||
|
||||
var cacheableChannel = new Cacheable<IMessageChannel, ulong>(channel, data.ChannelId, channel != null, async () => await GetChannelAsync(data.ChannelId).ConfigureAwait(false) as IMessageChannel);
|
||||
var cacheableMsg = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isMsgCached, async () =>
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var channelObj = await cacheableChannel.GetOrDownloadAsync().ConfigureAwait(false);
|
||||
return await channelObj.GetMessageAsync(data.MessageId).ConfigureAwait(false) as IUserMessage;
|
||||
});
|
||||
var reaction = SocketReaction.Create(data, channel, optionalMsg, optionalUser);
|
||||
|
||||
cachedMsg?.AddReaction(reaction);
|
||||
|
||||
await TimedInvokeAsync(_reactionAddedEvent, nameof(ReactionAdded), cacheableMsg, cacheableChannel, reaction).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_REACTION_REMOVE":
|
||||
@@ -1412,32 +1472,35 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_REACTION_REMOVE)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<API.Gateway.Reaction>(_serializer);
|
||||
if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel)
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
var cachedMsg = channel?.GetCachedMessage(data.MessageId) as SocketUserMessage;
|
||||
bool isMsgCached = cachedMsg != null;
|
||||
IUser user = null;
|
||||
if (channel != null)
|
||||
user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly).ConfigureAwait(false);
|
||||
else if (!data.GuildId.IsSpecified)
|
||||
user = GetUser(data.UserId);
|
||||
|
||||
var optionalMsg = !isMsgCached
|
||||
? Optional.Create<SocketUserMessage>()
|
||||
: Optional.Create(cachedMsg);
|
||||
|
||||
var optionalUser = user is null
|
||||
? Optional.Create<IUser>()
|
||||
: Optional.Create(user);
|
||||
|
||||
var cacheableChannel = new Cacheable<IMessageChannel, ulong>(channel, data.ChannelId, channel != null, async () => await GetChannelAsync(data.ChannelId).ConfigureAwait(false) as IMessageChannel);
|
||||
var cacheableMsg = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isMsgCached, async () =>
|
||||
{
|
||||
var cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage;
|
||||
bool isCached = cachedMsg != null;
|
||||
var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly).ConfigureAwait(false);
|
||||
var channelObj = await cacheableChannel.GetOrDownloadAsync().ConfigureAwait(false);
|
||||
return await channelObj.GetMessageAsync(data.MessageId).ConfigureAwait(false) as IUserMessage;
|
||||
});
|
||||
var reaction = SocketReaction.Create(data, channel, optionalMsg, optionalUser);
|
||||
|
||||
var optionalMsg = !isCached
|
||||
? Optional.Create<SocketUserMessage>()
|
||||
: Optional.Create(cachedMsg);
|
||||
cachedMsg?.RemoveReaction(reaction);
|
||||
|
||||
var optionalUser = user is null
|
||||
? Optional.Create<IUser>()
|
||||
: Optional.Create(user);
|
||||
|
||||
var reaction = SocketReaction.Create(data, channel, optionalMsg, optionalUser);
|
||||
var cacheable = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId).ConfigureAwait(false) as IUserMessage);
|
||||
|
||||
cachedMsg?.RemoveReaction(reaction);
|
||||
|
||||
await TimedInvokeAsync(_reactionRemovedEvent, nameof(ReactionRemoved), cacheable, channel, reaction).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
await TimedInvokeAsync(_reactionRemovedEvent, nameof(ReactionRemoved), cacheableMsg, cacheableChannel, reaction).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_REACTION_REMOVE_ALL":
|
||||
@@ -1445,21 +1508,20 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_REACTION_REMOVE_ALL)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<RemoveAllReactionsEvent>(_serializer);
|
||||
if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel)
|
||||
{
|
||||
var cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage;
|
||||
bool isCached = cachedMsg != null;
|
||||
var cacheable = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isCached, async () => (await channel.GetMessageAsync(data.MessageId).ConfigureAwait(false)) as IUserMessage);
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
cachedMsg?.ClearReactions();
|
||||
|
||||
await TimedInvokeAsync(_reactionsClearedEvent, nameof(ReactionsCleared), cacheable, channel).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
var cacheableChannel = new Cacheable<IMessageChannel, ulong>(channel, data.ChannelId, channel != null, async () => await GetChannelAsync(data.ChannelId).ConfigureAwait(false) as IMessageChannel);
|
||||
var cachedMsg = channel?.GetCachedMessage(data.MessageId) as SocketUserMessage;
|
||||
bool isMsgCached = cachedMsg != null;
|
||||
var cacheableMsg = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isMsgCached, async () =>
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var channelObj = await cacheableChannel.GetOrDownloadAsync().ConfigureAwait(false);
|
||||
return await channelObj.GetMessageAsync(data.MessageId).ConfigureAwait(false) as IUserMessage;
|
||||
});
|
||||
|
||||
cachedMsg?.ClearReactions();
|
||||
|
||||
await TimedInvokeAsync(_reactionsClearedEvent, nameof(ReactionsCleared), cacheableMsg, cacheableChannel).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_REACTION_REMOVE_EMOJI":
|
||||
@@ -1467,70 +1529,55 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_REACTION_REMOVE_EMOJI)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<API.Gateway.RemoveAllReactionsForEmoteEvent>(_serializer);
|
||||
if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel)
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
var cachedMsg = channel?.GetCachedMessage(data.MessageId) as SocketUserMessage;
|
||||
bool isMsgCached = cachedMsg != null;
|
||||
|
||||
var optionalMsg = !isMsgCached
|
||||
? Optional.Create<SocketUserMessage>()
|
||||
: Optional.Create(cachedMsg);
|
||||
|
||||
var cacheableChannel = new Cacheable<IMessageChannel, ulong>(channel, data.ChannelId, channel != null, async () => await GetChannelAsync(data.ChannelId).ConfigureAwait(false) as IMessageChannel);
|
||||
var cacheableMsg = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isMsgCached, async () =>
|
||||
{
|
||||
var cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage;
|
||||
bool isCached = cachedMsg != null;
|
||||
var channelObj = await cacheableChannel.GetOrDownloadAsync().ConfigureAwait(false);
|
||||
return await channelObj.GetMessageAsync(data.MessageId).ConfigureAwait(false) as IUserMessage;
|
||||
});
|
||||
var emote = data.Emoji.ToIEmote();
|
||||
|
||||
var optionalMsg = !isCached
|
||||
? Optional.Create<SocketUserMessage>()
|
||||
: Optional.Create(cachedMsg);
|
||||
cachedMsg?.RemoveReactionsForEmote(emote);
|
||||
|
||||
var cacheable = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId).ConfigureAwait(false) as IUserMessage);
|
||||
var emote = data.Emoji.ToIEmote();
|
||||
|
||||
cachedMsg?.RemoveReactionsForEmote(emote);
|
||||
|
||||
await TimedInvokeAsync(_reactionsRemovedForEmoteEvent, nameof(ReactionsRemovedForEmote), cacheable, channel, emote).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
await TimedInvokeAsync(_reactionsRemovedForEmoteEvent, nameof(ReactionsRemovedForEmote), cacheableMsg, cacheableChannel, emote).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_DELETE_BULK":
|
||||
{
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_DELETE_BULK)").ConfigureAwait(false);
|
||||
|
||||
if (!ExclusiveBulkDelete.HasValue)
|
||||
{
|
||||
await _gatewayLogger.WarningAsync("A bulk delete event has been received, but the event handling behavior has not been set. " +
|
||||
"To suppress this message, set the ExclusiveBulkDelete configuration property. " +
|
||||
"This message will appear only once.");
|
||||
ExclusiveBulkDelete = false;
|
||||
}
|
||||
|
||||
var data = (payload as JToken).ToObject<MessageDeleteBulkEvent>(_serializer);
|
||||
if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel)
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (!(guild?.IsSynced ?? true))
|
||||
{
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (!(guild?.IsSynced ?? true))
|
||||
{
|
||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var cacheableList = new List<Cacheable<IMessage, ulong>>(data.Ids.Length);
|
||||
foreach (ulong id in data.Ids)
|
||||
{
|
||||
var msg = SocketChannelHelper.RemoveMessage(channel, this, id);
|
||||
bool isCached = msg != null;
|
||||
var cacheable = new Cacheable<IMessage, ulong>(msg, id, isCached, async () => await channel.GetMessageAsync(id).ConfigureAwait(false));
|
||||
cacheableList.Add(cacheable);
|
||||
|
||||
if (!ExclusiveBulkDelete ?? false) // this shouldn't happen, but we'll play it safe anyways
|
||||
await TimedInvokeAsync(_messageDeletedEvent, nameof(MessageDeleted), cacheable, channel).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await TimedInvokeAsync(_messagesBulkDeletedEvent, nameof(MessagesBulkDeleted), cacheableList, channel).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false);
|
||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var cacheableChannel = new Cacheable<IMessageChannel, ulong>(channel, data.ChannelId, channel != null, async () => await GetChannelAsync(data.ChannelId).ConfigureAwait(false) as IMessageChannel);
|
||||
var cacheableList = new List<Cacheable<IMessage, ulong>>(data.Ids.Length);
|
||||
foreach (ulong id in data.Ids)
|
||||
{
|
||||
SocketMessage msg = null;
|
||||
if (channel != null)
|
||||
msg = SocketChannelHelper.RemoveMessage(channel, this, id);
|
||||
bool isMsgCached = msg != null;
|
||||
var cacheableMsg = new Cacheable<IMessage, ulong>(msg, id, isMsgCached, () => Task.FromResult((IMessage)null));
|
||||
cacheableList.Add(cacheableMsg);
|
||||
}
|
||||
|
||||
await TimedInvokeAsync(_messagesBulkDeletedEvent, nameof(MessagesBulkDeleted), cacheableList, cacheableChannel).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1599,24 +1646,26 @@ namespace Discord.WebSocket
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (TYPING_START)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<TypingStartEvent>(_serializer);
|
||||
if (State.GetChannel(data.ChannelId) is ISocketMessageChannel channel)
|
||||
{
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (!(guild?.IsSynced ?? true))
|
||||
{
|
||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var channel = GetChannel(data.ChannelId) as ISocketMessageChannel;
|
||||
|
||||
var user = (channel as SocketChannel).GetUser(data.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
if (guild != null)
|
||||
user = guild.AddOrUpdateUser(data.Member);
|
||||
}
|
||||
if (user != null)
|
||||
await TimedInvokeAsync(_userIsTypingEvent, nameof(UserIsTyping), user, channel).ConfigureAwait(false);
|
||||
var guild = (channel as SocketGuildChannel)?.Guild;
|
||||
if (!(guild?.IsSynced ?? true))
|
||||
{
|
||||
await UnsyncedGuildAsync(type, guild.Id).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var cacheableChannel = new Cacheable<IMessageChannel, ulong>(channel, data.ChannelId, channel != null, async () => await GetChannelAsync(data.ChannelId).ConfigureAwait(false) as IMessageChannel);
|
||||
|
||||
var user = (channel as SocketChannel)?.GetUser(data.UserId);
|
||||
if (user == null)
|
||||
{
|
||||
if (guild != null)
|
||||
user = guild.AddOrUpdateUser(data.Member);
|
||||
}
|
||||
var cacheableUser = new Cacheable<IUser, ulong>(user, data.UserId, user != null, async () => await GetUserAsync(data.UserId).ConfigureAwait(false));
|
||||
|
||||
await TimedInvokeAsync(_userIsTypingEvent, nameof(UserIsTyping), cacheableUser, cacheableChannel).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1688,7 +1737,7 @@ namespace Discord.WebSocket
|
||||
}
|
||||
else
|
||||
{
|
||||
var groupChannel = State.GetChannel(data.ChannelId.Value) as SocketGroupChannel;
|
||||
var groupChannel = GetChannel(data.ChannelId.Value) as SocketGroupChannel;
|
||||
if (groupChannel == null)
|
||||
{
|
||||
await UnknownChannelAsync(type, data.ChannelId.Value).ConfigureAwait(false);
|
||||
@@ -2113,8 +2162,8 @@ namespace Discord.WebSocket
|
||||
=> await GetApplicationInfoAsync().ConfigureAwait(false);
|
||||
|
||||
/// <inheritdoc />
|
||||
Task<IChannel> IDiscordClient.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options)
|
||||
=> Task.FromResult<IChannel>(GetChannel(id));
|
||||
async Task<IChannel> IDiscordClient.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options)
|
||||
=> mode == CacheMode.AllowDownload ? await GetChannelAsync(id, options).ConfigureAwait(false) : GetChannel(id);
|
||||
/// <inheritdoc />
|
||||
Task<IReadOnlyCollection<IPrivateChannel>> IDiscordClient.GetPrivateChannelsAsync(CacheMode mode, RequestOptions options)
|
||||
=> Task.FromResult<IReadOnlyCollection<IPrivateChannel>>(PrivateChannels);
|
||||
@@ -2144,8 +2193,8 @@ namespace Discord.WebSocket
|
||||
=> await CreateGuildAsync(name, region, jpegIcon).ConfigureAwait(false);
|
||||
|
||||
/// <inheritdoc />
|
||||
Task<IUser> IDiscordClient.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
|
||||
=> Task.FromResult<IUser>(GetUser(id));
|
||||
async Task<IUser> IDiscordClient.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
|
||||
=> mode == CacheMode.AllowDownload ? await GetUserAsync(id, options).ConfigureAwait(false) : GetUser(id);
|
||||
/// <inheritdoc />
|
||||
Task<IUser> IDiscordClient.GetUserAsync(string username, string discriminator, RequestOptions options)
|
||||
=> Task.FromResult<IUser>(GetUser(username, discriminator));
|
||||
|
||||
Reference in New Issue
Block a user