Conflicts: src/Discord.Net.WebSocket/DiscordSocketClient.cstags/1.0-rc
| @@ -0,0 +1,60 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord | |||||
| { | |||||
| /// <summary> | |||||
| /// Contains an entity that may be cached. | |||||
| /// </summary> | |||||
| /// <typeparam name="TEntity">The type of entity that is cached</typeparam> | |||||
| /// <typeparam name="TId">The type of this entity's ID</typeparam> | |||||
| public struct Cacheable<TEntity, TId> | |||||
| where TEntity : IEntity<TId> | |||||
| where TId : IEquatable<TId> | |||||
| { | |||||
| /// <summary> | |||||
| /// Is this entity cached? | |||||
| /// </summary> | |||||
| public bool HasValue { get; } | |||||
| /// <summary> | |||||
| /// The ID of this entity. | |||||
| /// </summary> | |||||
| public TId Id { get; } | |||||
| /// <summary> | |||||
| /// The entity, if it could be pulled from cache. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// This value is not guaranteed to be set; in cases where the entity cannot be pulled from cache, it is null. | |||||
| /// </remarks> | |||||
| public TEntity Value { get; } | |||||
| private Func<Task<TEntity>> DownloadFunc { get; } | |||||
| internal Cacheable(TEntity value, TId id, bool hasValue , Func<Task<TEntity>> downloadFunc) | |||||
| { | |||||
| Value = value; | |||||
| Id = id; | |||||
| HasValue = hasValue; | |||||
| DownloadFunc = downloadFunc; | |||||
| } | |||||
| /// <summary> | |||||
| /// Downloads this entity to cache. | |||||
| /// </summary> | |||||
| /// <returns>An awaitable Task containing the downloaded entity.</returns> | |||||
| /// <exception cref="Discord.Net.HttpException">Thrown when used from a user account.</exception> | |||||
| /// <exception cref="NullReferenceException">Thrown when the message is deleted.</exception> | |||||
| public async Task<TEntity> DownloadAsync() | |||||
| { | |||||
| return await DownloadFunc(); | |||||
| } | |||||
| /// <summary> | |||||
| /// Returns the cached entity if it exists; otherwise downloads it. | |||||
| /// </summary> | |||||
| /// <returns>An awaitable Task containing a cached or downloaded entity.</returns> | |||||
| /// <exception cref="Discord.Net.HttpException">Thrown when used from a user account.</exception> | |||||
| /// <exception cref="NullReferenceException">Thrown when the message is deleted and is not in cache.</exception> | |||||
| public async Task<TEntity> GetOrDownloadAsync() => HasValue ? Value : await DownloadAsync(); | |||||
| } | |||||
| } | |||||
| @@ -1,5 +1,6 @@ | |||||
| using System; | using System; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Discord.Net; | |||||
| namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
| { | { | ||||
| @@ -33,36 +34,36 @@ namespace Discord.WebSocket | |||||
| remove { _messageReceivedEvent.Remove(value); } | remove { _messageReceivedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<SocketMessage, Task>> _messageReceivedEvent = new AsyncEvent<Func<SocketMessage, Task>>(); | private readonly AsyncEvent<Func<SocketMessage, Task>> _messageReceivedEvent = new AsyncEvent<Func<SocketMessage, Task>>(); | ||||
| public event Func<ulong, Optional<SocketMessage>, Task> MessageDeleted | |||||
| public event Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task> MessageDeleted | |||||
| { | { | ||||
| add { _messageDeletedEvent.Add(value); } | add { _messageDeletedEvent.Add(value); } | ||||
| remove { _messageDeletedEvent.Remove(value); } | remove { _messageDeletedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<ulong, Optional<SocketMessage>, Task>> _messageDeletedEvent = new AsyncEvent<Func<ulong, Optional<SocketMessage>, Task>>(); | |||||
| public event Func<Optional<SocketMessage>, SocketMessage, Task> MessageUpdated | |||||
| private readonly AsyncEvent<Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent<Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task>>(); | |||||
| public event Func<Cacheable<IMessage, ulong>, SocketMessage, ISocketMessageChannel, Task> MessageUpdated | |||||
| { | { | ||||
| add { _messageUpdatedEvent.Add(value); } | add { _messageUpdatedEvent.Add(value); } | ||||
| remove { _messageUpdatedEvent.Remove(value); } | remove { _messageUpdatedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<Optional<SocketMessage>, SocketMessage, Task>> _messageUpdatedEvent = new AsyncEvent<Func<Optional<SocketMessage>, SocketMessage, Task>>(); | |||||
| public event Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task> ReactionAdded | |||||
| private readonly AsyncEvent<Func<Cacheable<IMessage, ulong>, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent<Func<Cacheable<IMessage, ulong>, SocketMessage, ISocketMessageChannel, Task>>(); | |||||
| public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionAdded | |||||
| { | { | ||||
| add { _reactionAddedEvent.Add(value); } | add { _reactionAddedEvent.Add(value); } | ||||
| remove { _reactionAddedEvent.Remove(value); } | remove { _reactionAddedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent<Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task>>(); | |||||
| public event Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task> ReactionRemoved | |||||
| private readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | |||||
| public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved | |||||
| { | { | ||||
| add { _reactionRemovedEvent.Add(value); } | add { _reactionRemovedEvent.Add(value); } | ||||
| remove { _reactionRemovedEvent.Remove(value); } | remove { _reactionRemovedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent<Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task>>(); | |||||
| public event Func<ulong, Optional<SocketUserMessage>, Task> ReactionsCleared | |||||
| private readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | |||||
| public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task> ReactionsCleared | |||||
| { | { | ||||
| add { _reactionsClearedEvent.Add(value); } | add { _reactionsClearedEvent.Add(value); } | ||||
| remove { _reactionsClearedEvent.Remove(value); } | remove { _reactionsClearedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<ulong, Optional<SocketUserMessage>, Task>> _reactionsClearedEvent = new AsyncEvent<Func<ulong, Optional<SocketUserMessage>, Task>>(); | |||||
| private readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task>>(); | |||||
| //Roles | //Roles | ||||
| public event Func<SocketRole, Task> RoleCreated | public event Func<SocketRole, Task> RoleCreated | ||||
| @@ -275,11 +275,11 @@ namespace Discord.WebSocket | |||||
| client.ChannelUpdated += (oldChannel, newChannel) => _channelUpdatedEvent.InvokeAsync(oldChannel, newChannel); | client.ChannelUpdated += (oldChannel, newChannel) => _channelUpdatedEvent.InvokeAsync(oldChannel, newChannel); | ||||
| client.MessageReceived += (msg) => _messageReceivedEvent.InvokeAsync(msg); | client.MessageReceived += (msg) => _messageReceivedEvent.InvokeAsync(msg); | ||||
| client.MessageDeleted += (id, msg) => _messageDeletedEvent.InvokeAsync(id, msg); | |||||
| client.MessageUpdated += (oldMsg, newMsg) => _messageUpdatedEvent.InvokeAsync(oldMsg, newMsg); | |||||
| client.ReactionAdded += (id, msg, reaction) => _reactionAddedEvent.InvokeAsync(id, msg, reaction); | |||||
| client.ReactionRemoved += (id, msg, reaction) => _reactionRemovedEvent.InvokeAsync(id, msg, reaction); | |||||
| client.ReactionsCleared += (id, msg) => _reactionsClearedEvent.InvokeAsync(id, msg); | |||||
| client.MessageDeleted += (cache, channel) => _messageDeletedEvent.InvokeAsync(cache, channel); | |||||
| client.MessageUpdated += (oldMsg, newMsg, channel) => _messageUpdatedEvent.InvokeAsync(oldMsg, newMsg, channel); | |||||
| 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.RoleCreated += (role) => _roleCreatedEvent.InvokeAsync(role); | client.RoleCreated += (role) => _roleCreatedEvent.InvokeAsync(role); | ||||
| client.RoleDeleted += (role) => _roleDeletedEvent.InvokeAsync(role); | client.RoleDeleted += (role) => _roleDeletedEvent.InvokeAsync(role); | ||||
| @@ -59,36 +59,36 @@ namespace Discord.WebSocket | |||||
| remove { _messageReceivedEvent.Remove(value); } | remove { _messageReceivedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<SocketMessage, Task>> _messageReceivedEvent = new AsyncEvent<Func<SocketMessage, Task>>(); | private readonly AsyncEvent<Func<SocketMessage, Task>> _messageReceivedEvent = new AsyncEvent<Func<SocketMessage, Task>>(); | ||||
| public event Func<ulong, Optional<SocketMessage>, Task> MessageDeleted | |||||
| public event Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task> MessageDeleted | |||||
| { | { | ||||
| add { _messageDeletedEvent.Add(value); } | add { _messageDeletedEvent.Add(value); } | ||||
| remove { _messageDeletedEvent.Remove(value); } | remove { _messageDeletedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<ulong, Optional<SocketMessage>, Task>> _messageDeletedEvent = new AsyncEvent<Func<ulong, Optional<SocketMessage>, Task>>(); | |||||
| public event Func<Optional<SocketMessage>, SocketMessage, Task> MessageUpdated | |||||
| private readonly AsyncEvent<Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent<Func<Cacheable<IMessage, ulong>, ISocketMessageChannel, Task>>(); | |||||
| public event Func<Cacheable<IMessage, ulong>, SocketMessage, ISocketMessageChannel, Task> MessageUpdated | |||||
| { | { | ||||
| add { _messageUpdatedEvent.Add(value); } | add { _messageUpdatedEvent.Add(value); } | ||||
| remove { _messageUpdatedEvent.Remove(value); } | remove { _messageUpdatedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<Optional<SocketMessage>, SocketMessage, Task>> _messageUpdatedEvent = new AsyncEvent<Func<Optional<SocketMessage>, SocketMessage, Task>>(); | |||||
| public event Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task> ReactionAdded | |||||
| private readonly AsyncEvent<Func<Cacheable<IMessage, ulong>, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent<Func<Cacheable<IMessage, ulong>, SocketMessage, ISocketMessageChannel, Task>>(); | |||||
| public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionAdded | |||||
| { | { | ||||
| add { _reactionAddedEvent.Add(value); } | add { _reactionAddedEvent.Add(value); } | ||||
| remove { _reactionAddedEvent.Remove(value); } | remove { _reactionAddedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent<Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task>>(); | |||||
| public event Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task> ReactionRemoved | |||||
| private readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | |||||
| public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved | |||||
| { | { | ||||
| add { _reactionRemovedEvent.Add(value); } | add { _reactionRemovedEvent.Add(value); } | ||||
| remove { _reactionRemovedEvent.Remove(value); } | remove { _reactionRemovedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent<Func<ulong, Optional<SocketUserMessage>, SocketReaction, Task>>(); | |||||
| public event Func<ulong, Optional<SocketUserMessage>, Task> ReactionsCleared | |||||
| private readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, SocketReaction, Task>>(); | |||||
| public event Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task> ReactionsCleared | |||||
| { | { | ||||
| add { _reactionsClearedEvent.Add(value); } | add { _reactionsClearedEvent.Add(value); } | ||||
| remove { _reactionsClearedEvent.Remove(value); } | remove { _reactionsClearedEvent.Remove(value); } | ||||
| } | } | ||||
| private readonly AsyncEvent<Func<ulong, Optional<SocketUserMessage>, Task>> _reactionsClearedEvent = new AsyncEvent<Func<ulong, Optional<SocketUserMessage>, Task>>(); | |||||
| private readonly AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent<Func<Cacheable<IUserMessage, ulong>, ISocketMessageChannel, Task>>(); | |||||
| //Roles | //Roles | ||||
| public event Func<SocketRole, Task> RoleCreated | public event Func<SocketRole, Task> RoleCreated | ||||
| @@ -116,37 +116,37 @@ namespace Discord.WebSocket | |||||
| add { _joinedGuildEvent.Add(value); } | add { _joinedGuildEvent.Add(value); } | ||||
| remove { _joinedGuildEvent.Remove(value); } | remove { _joinedGuildEvent.Remove(value); } | ||||
| } | } | ||||
| private AsyncEvent<Func<SocketGuild, Task>> _joinedGuildEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| private readonly AsyncEvent<Func<SocketGuild, Task>> _joinedGuildEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| public event Func<SocketGuild, Task> LeftGuild | public event Func<SocketGuild, Task> LeftGuild | ||||
| { | { | ||||
| add { _leftGuildEvent.Add(value); } | add { _leftGuildEvent.Add(value); } | ||||
| remove { _leftGuildEvent.Remove(value); } | remove { _leftGuildEvent.Remove(value); } | ||||
| } | } | ||||
| private AsyncEvent<Func<SocketGuild, Task>> _leftGuildEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| private readonly AsyncEvent<Func<SocketGuild, Task>> _leftGuildEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| public event Func<SocketGuild, Task> GuildAvailable | public event Func<SocketGuild, Task> GuildAvailable | ||||
| { | { | ||||
| add { _guildAvailableEvent.Add(value); } | add { _guildAvailableEvent.Add(value); } | ||||
| remove { _guildAvailableEvent.Remove(value); } | remove { _guildAvailableEvent.Remove(value); } | ||||
| } | } | ||||
| private AsyncEvent<Func<SocketGuild, Task>> _guildAvailableEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| private readonly AsyncEvent<Func<SocketGuild, Task>> _guildAvailableEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| public event Func<SocketGuild, Task> GuildUnavailable | public event Func<SocketGuild, Task> GuildUnavailable | ||||
| { | { | ||||
| add { _guildUnavailableEvent.Add(value); } | add { _guildUnavailableEvent.Add(value); } | ||||
| remove { _guildUnavailableEvent.Remove(value); } | remove { _guildUnavailableEvent.Remove(value); } | ||||
| } | } | ||||
| private AsyncEvent<Func<SocketGuild, Task>> _guildUnavailableEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| private readonly AsyncEvent<Func<SocketGuild, Task>> _guildUnavailableEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| public event Func<SocketGuild, Task> GuildMembersDownloaded | public event Func<SocketGuild, Task> GuildMembersDownloaded | ||||
| { | { | ||||
| add { _guildMembersDownloadedEvent.Add(value); } | add { _guildMembersDownloadedEvent.Add(value); } | ||||
| remove { _guildMembersDownloadedEvent.Remove(value); } | remove { _guildMembersDownloadedEvent.Remove(value); } | ||||
| } | } | ||||
| private AsyncEvent<Func<SocketGuild, Task>> _guildMembersDownloadedEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| private readonly AsyncEvent<Func<SocketGuild, Task>> _guildMembersDownloadedEvent = new AsyncEvent<Func<SocketGuild, Task>>(); | |||||
| public event Func<SocketGuild, SocketGuild, Task> GuildUpdated | public event Func<SocketGuild, SocketGuild, Task> GuildUpdated | ||||
| { | { | ||||
| add { _guildUpdatedEvent.Add(value); } | add { _guildUpdatedEvent.Add(value); } | ||||
| remove { _guildUpdatedEvent.Remove(value); } | remove { _guildUpdatedEvent.Remove(value); } | ||||
| } | } | ||||
| private AsyncEvent<Func<SocketGuild, SocketGuild, Task>> _guildUpdatedEvent = new AsyncEvent<Func<SocketGuild, SocketGuild, Task>>(); | |||||
| private readonly AsyncEvent<Func<SocketGuild, SocketGuild, Task>> _guildUpdatedEvent = new AsyncEvent<Func<SocketGuild, SocketGuild, Task>>(); | |||||
| //Users | //Users | ||||
| public event Func<SocketGuildUser, Task> UserJoined | public event Func<SocketGuildUser, Task> UserJoined | ||||
| @@ -1101,13 +1101,8 @@ namespace Discord.WebSocket | |||||
| return; | return; | ||||
| } | } | ||||
| SocketUser author; | |||||
| if (guild != null) | |||||
| author = guild.GetUser(data.Author.Value.Id); | |||||
| else | |||||
| author = (channel as SocketChannel).GetUser(data.Author.Value.Id); | |||||
| if (author == null) | |||||
| author = SocketSimpleUser.Create(this, State, data.Author.Value); | |||||
| var author = (guild != null ? guild.GetUser(data.Author.Value.Id) : (channel as SocketChannel).GetUser(data.Author.Value.Id)) ?? | |||||
| SocketSimpleUser.Create(this, State, data.Author.Value); | |||||
| if (author != null) | if (author != null) | ||||
| { | { | ||||
| @@ -1138,14 +1133,15 @@ namespace Discord.WebSocket | |||||
| { | { | ||||
| var guild = (channel as SocketGuildChannel)?.Guild; | var guild = (channel as SocketGuildChannel)?.Guild; | ||||
| if (guild != null && !guild.IsSynced) | if (guild != null && !guild.IsSynced) | ||||
| { | |||||
| { | |||||
| await _gatewayLogger.DebugAsync("Ignored MESSAGE_UPDATE, guild is not synced yet.").ConfigureAwait(false); | await _gatewayLogger.DebugAsync("Ignored MESSAGE_UPDATE, guild is not synced yet.").ConfigureAwait(false); | ||||
| return; | return; | ||||
| } | } | ||||
| SocketMessage before = null, after = null; | SocketMessage before = null, after = null; | ||||
| SocketMessage cachedMsg = channel.GetCachedMessage(data.Id); | SocketMessage cachedMsg = channel.GetCachedMessage(data.Id); | ||||
| if (cachedMsg != null) | |||||
| bool isCached = cachedMsg != null; | |||||
| if (isCached) | |||||
| { | { | ||||
| before = cachedMsg.Clone(); | before = cachedMsg.Clone(); | ||||
| cachedMsg.Update(State, data); | cachedMsg.Update(State, data); | ||||
| @@ -1164,10 +1160,9 @@ namespace Discord.WebSocket | |||||
| after = SocketMessage.Create(this, State, author, channel, data); | after = SocketMessage.Create(this, State, author, channel, data); | ||||
| } | } | ||||
| if (before != null) | |||||
| await _messageUpdatedEvent.InvokeAsync(before, after).ConfigureAwait(false); | |||||
| else | |||||
| await _messageUpdatedEvent.InvokeAsync(Optional.Create<SocketMessage>(), after).ConfigureAwait(false); | |||||
| var cacheableBefore = new Cacheable<IMessage, ulong>(before, data.Id, isCached , async () => await channel.GetMessageAsync(data.Id)); | |||||
| await _messageUpdatedEvent.InvokeAsync(cacheableBefore, after, channel).ConfigureAwait(false); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -1179,22 +1174,22 @@ namespace Discord.WebSocket | |||||
| case "MESSAGE_DELETE": | case "MESSAGE_DELETE": | ||||
| { | { | ||||
| await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_DELETE)").ConfigureAwait(false); | await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_DELETE)").ConfigureAwait(false); | ||||
| var data = (payload as JToken).ToObject<API.Message>(_serializer); | var data = (payload as JToken).ToObject<API.Message>(_serializer); | ||||
| var channel = State.GetChannel(data.ChannelId) as ISocketMessageChannel; | var channel = State.GetChannel(data.ChannelId) as ISocketMessageChannel; | ||||
| if (channel != null) | if (channel != null) | ||||
| { | { | ||||
| if (!((channel as SocketGuildChannel)?.Guild.IsSynced ?? true)) | if (!((channel as SocketGuildChannel)?.Guild.IsSynced ?? true)) | ||||
| { | |||||
| { | |||||
| await _gatewayLogger.DebugAsync("Ignored MESSAGE_DELETE, guild is not synced yet.").ConfigureAwait(false); | await _gatewayLogger.DebugAsync("Ignored MESSAGE_DELETE, guild is not synced yet.").ConfigureAwait(false); | ||||
| return; | return; | ||||
| } | } | ||||
| var msg = SocketChannelHelper.RemoveMessage(channel, this, data.Id); | var msg = SocketChannelHelper.RemoveMessage(channel, this, data.Id); | ||||
| if (msg != null) | |||||
| await _messageDeletedEvent.InvokeAsync(data.Id, msg).ConfigureAwait(false); | |||||
| else | |||||
| await _messageDeletedEvent.InvokeAsync(data.Id, Optional.Create<SocketMessage>()).ConfigureAwait(false); | |||||
| bool isCached = msg != null; | |||||
| var cacheable = new Cacheable<IMessage, ulong>(msg, data.Id, isCached, async () => await channel.GetMessageAsync(data.Id)); | |||||
| await _messageDeletedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -1212,15 +1207,14 @@ namespace Discord.WebSocket | |||||
| if (channel != null) | if (channel != null) | ||||
| { | { | ||||
| SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; | SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; | ||||
| bool isCached = cachedMsg != null; | |||||
| var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); | var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); | ||||
| SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); | SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); | ||||
| if (cachedMsg != null) | |||||
| { | |||||
| cachedMsg.AddReaction(reaction); | |||||
| await _reactionAddedEvent.InvokeAsync(data.MessageId, cachedMsg, reaction).ConfigureAwait(false); | |||||
| return; | |||||
| } | |||||
| await _reactionAddedEvent.InvokeAsync(data.MessageId, Optional.Create<SocketUserMessage>(), reaction).ConfigureAwait(false); | |||||
| var cacheable = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); | |||||
| cachedMsg?.AddReaction(reaction); | |||||
| await _reactionAddedEvent.InvokeAsync(cacheable, channel, reaction).ConfigureAwait(false); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -1238,15 +1232,14 @@ namespace Discord.WebSocket | |||||
| if (channel != null) | if (channel != null) | ||||
| { | { | ||||
| SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; | SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; | ||||
| bool isCached = cachedMsg != null; | |||||
| var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); | var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); | ||||
| SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); | SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); | ||||
| if (cachedMsg != null) | |||||
| { | |||||
| cachedMsg.RemoveReaction(reaction); | |||||
| await _reactionRemovedEvent.InvokeAsync(data.MessageId, cachedMsg, reaction).ConfigureAwait(false); | |||||
| return; | |||||
| } | |||||
| await _reactionRemovedEvent.InvokeAsync(data.MessageId, Optional.Create<SocketUserMessage>(), reaction).ConfigureAwait(false); | |||||
| var cacheable = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); | |||||
| cachedMsg?.RemoveReaction(reaction); | |||||
| await _reactionRemovedEvent.InvokeAsync(cacheable, channel, reaction).ConfigureAwait(false); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -1264,20 +1257,18 @@ namespace Discord.WebSocket | |||||
| if (channel != null) | if (channel != null) | ||||
| { | { | ||||
| SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; | SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; | ||||
| if (cachedMsg != null) | |||||
| { | |||||
| cachedMsg.ClearReactions(); | |||||
| await _reactionsClearedEvent.InvokeAsync(data.MessageId, cachedMsg).ConfigureAwait(false); | |||||
| return; | |||||
| } | |||||
| await _reactionsClearedEvent.InvokeAsync(data.MessageId, Optional.Create<SocketUserMessage>()); | |||||
| bool isCached = cachedMsg != null; | |||||
| var cacheable = new Cacheable<IUserMessage, ulong>(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); | |||||
| cachedMsg?.ClearReactions(); | |||||
| await _reactionsClearedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| await _gatewayLogger.WarningAsync("MESSAGE_REACTION_REMOVE_ALL referenced an unknown channel.").ConfigureAwait(false); | await _gatewayLogger.WarningAsync("MESSAGE_REACTION_REMOVE_ALL referenced an unknown channel.").ConfigureAwait(false); | ||||
| return; | return; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case "MESSAGE_DELETE_BULK": | case "MESSAGE_DELETE_BULK": | ||||
| @@ -1297,10 +1288,9 @@ namespace Discord.WebSocket | |||||
| foreach (var id in data.Ids) | foreach (var id in data.Ids) | ||||
| { | { | ||||
| var msg = SocketChannelHelper.RemoveMessage(channel, this, id); | var msg = SocketChannelHelper.RemoveMessage(channel, this, id); | ||||
| if (msg != null) | |||||
| await _messageDeletedEvent.InvokeAsync(id, msg).ConfigureAwait(false); | |||||
| else | |||||
| await _messageDeletedEvent.InvokeAsync(id, Optional.Create<SocketMessage>()).ConfigureAwait(false); | |||||
| bool isCached = msg != null; | |||||
| var cacheable = new Cacheable<IMessage, ulong>(msg, id, isCached, async () => await channel.GetMessageAsync(id)); | |||||
| await _messageDeletedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); | |||||
| } | } | ||||
| } | } | ||||
| else | else | ||||