From 05fcd5f07637823a073a7a731083e0ff5af13fa0 Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Tue, 29 Nov 2016 00:37:45 +0100 Subject: [PATCH 01/11] First commit --- src/Discord.Net.Core/Utils/Cache.cs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/Discord.Net.Core/Utils/Cache.cs diff --git a/src/Discord.Net.Core/Utils/Cache.cs b/src/Discord.Net.Core/Utils/Cache.cs new file mode 100644 index 000000000..f61c41793 --- /dev/null +++ b/src/Discord.Net.Core/Utils/Cache.cs @@ -0,0 +1,23 @@ +using System; +using System.Reflection; +using System.Threading.Tasks; +using TId = Discord.IEntity; + + +namespace Discord +{ + public abstract class Cache where T : IEntity + { + public bool IsCached => Value != null; + public TId Id { get; } + public T Value { get; } + + protected Cache(TId id) + { + Id = id; + } + + public async Task DownloadAsync() => typeof(T).GetRuntimeMethod("DownloadAsync",{ulong id}); + public async Task GetOrDownloadAsync() => IsCached ? Value : await DownloadAsync(); + } +} \ No newline at end of file From 959d49a26f8ad7c181373e1efbbb6574ac4837d5 Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Thu, 1 Dec 2016 11:35:45 +0100 Subject: [PATCH 02/11] renamed Cache to Cached, and refactored many events to use Cached --- src/Discord.Net.Core/Utils/Cache.cs | 23 ---- src/Discord.Net.Core/Utils/Cached.cs | 33 ++++++ .../DiscordSocketClient.Events.cs | 32 +++--- .../DiscordSocketClient.cs | 103 ++++++------------ 4 files changed, 85 insertions(+), 106 deletions(-) delete mode 100644 src/Discord.Net.Core/Utils/Cache.cs create mode 100644 src/Discord.Net.Core/Utils/Cached.cs diff --git a/src/Discord.Net.Core/Utils/Cache.cs b/src/Discord.Net.Core/Utils/Cache.cs deleted file mode 100644 index f61c41793..000000000 --- a/src/Discord.Net.Core/Utils/Cache.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Reflection; -using System.Threading.Tasks; -using TId = Discord.IEntity; - - -namespace Discord -{ - public abstract class Cache where T : IEntity - { - public bool IsCached => Value != null; - public TId Id { get; } - public T Value { get; } - - protected Cache(TId id) - { - Id = id; - } - - public async Task DownloadAsync() => typeof(T).GetRuntimeMethod("DownloadAsync",{ulong id}); - public async Task GetOrDownloadAsync() => IsCached ? Value : await DownloadAsync(); - } -} \ No newline at end of file diff --git a/src/Discord.Net.Core/Utils/Cached.cs b/src/Discord.Net.Core/Utils/Cached.cs new file mode 100644 index 000000000..99c7794f7 --- /dev/null +++ b/src/Discord.Net.Core/Utils/Cached.cs @@ -0,0 +1,33 @@ +using Discord.WebSocket; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Discord +{ + public struct Cached where T : IMessage + { + public bool IsCached => !EqualityComparer.Default.Equals(Value, default(T)); + public bool IsDownloadable { get; } + public ulong Id { get; } + public T Value { get; } + public ISocketMessageChannel Channel { get; } + + public Cached(ulong id, T value, ISocketMessageChannel channel, bool isDownloadable = true) + { + Id = id; + Value = value; + Channel = channel; + IsDownloadable = isDownloadable; + } + + public async Task DownloadAsync() + { + if (IsDownloadable) + return (T) await Channel.GetMessageAsync(Id); + throw new InvalidOperationException("This message cannot be downloaded."); + } + + public async Task GetOrDownloadAsync() => IsCached ? Value : await DownloadAsync(); + } +} diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs index 2f952bdaa..48f945b0c 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs @@ -59,36 +59,36 @@ namespace Discord.WebSocket remove { _messageReceivedEvent.Remove(value); } } private readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); - public event Func, Task> MessageDeleted + public event Func, Task> MessageDeleted { add { _messageDeletedEvent.Add(value); } remove { _messageDeletedEvent.Remove(value); } } - private readonly AsyncEvent, Task>> _messageDeletedEvent = new AsyncEvent, Task>>(); - public event Func, SocketMessage, Task> MessageUpdated + private readonly AsyncEvent, Task>> _messageDeletedEvent = new AsyncEvent, Task>>(); + public event Func, SocketMessage, Task> MessageUpdated { add { _messageUpdatedEvent.Add(value); } remove { _messageUpdatedEvent.Remove(value); } } - private readonly AsyncEvent, SocketMessage, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, Task>>(); - public event Func, SocketReaction, Task> ReactionAdded + private readonly AsyncEvent, SocketMessage, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, Task>>(); + public event Func, SocketReaction, Task> ReactionAdded { add { _reactionAddedEvent.Add(value); } remove { _reactionAddedEvent.Remove(value); } } - private readonly AsyncEvent, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, SocketReaction, Task>>(); - public event Func, SocketReaction, Task> ReactionRemoved + private readonly AsyncEvent, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, SocketReaction, Task>>(); + public event Func, SocketReaction, Task> ReactionRemoved { add { _reactionRemovedEvent.Add(value); } remove { _reactionRemovedEvent.Remove(value); } } - private readonly AsyncEvent, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, SocketReaction, Task>>(); - public event Func, Task> ReactionsCleared + private readonly AsyncEvent, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, SocketReaction, Task>>(); + public event Func, Task> ReactionsCleared { add { _reactionsClearedEvent.Add(value); } remove { _reactionsClearedEvent.Remove(value); } } - private readonly AsyncEvent, Task>> _reactionsClearedEvent = new AsyncEvent, Task>>(); + private readonly AsyncEvent, Task>> _reactionsClearedEvent = new AsyncEvent, Task>>(); //Roles public event Func RoleCreated @@ -116,37 +116,37 @@ namespace Discord.WebSocket add { _joinedGuildEvent.Add(value); } remove { _joinedGuildEvent.Remove(value); } } - private AsyncEvent> _joinedGuildEvent = new AsyncEvent>(); + private readonly AsyncEvent> _joinedGuildEvent = new AsyncEvent>(); public event Func LeftGuild { add { _leftGuildEvent.Add(value); } remove { _leftGuildEvent.Remove(value); } } - private AsyncEvent> _leftGuildEvent = new AsyncEvent>(); + private readonly AsyncEvent> _leftGuildEvent = new AsyncEvent>(); public event Func GuildAvailable { add { _guildAvailableEvent.Add(value); } remove { _guildAvailableEvent.Remove(value); } } - private AsyncEvent> _guildAvailableEvent = new AsyncEvent>(); + private readonly AsyncEvent> _guildAvailableEvent = new AsyncEvent>(); public event Func GuildUnavailable { add { _guildUnavailableEvent.Add(value); } remove { _guildUnavailableEvent.Remove(value); } } - private AsyncEvent> _guildUnavailableEvent = new AsyncEvent>(); + private readonly AsyncEvent> _guildUnavailableEvent = new AsyncEvent>(); public event Func GuildMembersDownloaded { add { _guildMembersDownloadedEvent.Add(value); } remove { _guildMembersDownloadedEvent.Remove(value); } } - private AsyncEvent> _guildMembersDownloadedEvent = new AsyncEvent>(); + private readonly AsyncEvent> _guildMembersDownloadedEvent = new AsyncEvent>(); public event Func GuildUpdated { add { _guildUpdatedEvent.Add(value); } remove { _guildUpdatedEvent.Remove(value); } } - private AsyncEvent> _guildUpdatedEvent = new AsyncEvent>(); + private readonly AsyncEvent> _guildUpdatedEvent = new AsyncEvent>(); //Users public event Func UserJoined diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 0641672d2..2d510790f 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -108,11 +108,11 @@ namespace Discord.WebSocket { if (ex != null) { - await _gatewayLogger.WarningAsync($"Connection Closed", ex).ConfigureAwait(false); + await _gatewayLogger.WarningAsync("Connection Closed", ex).ConfigureAwait(false); await StartReconnectAsync(ex).ConfigureAwait(false); } else - await _gatewayLogger.WarningAsync($"Connection Closed").ConfigureAwait(false); + await _gatewayLogger.WarningAsync("Connection Closed").ConfigureAwait(false); }; LeftGuild += async g => await _gatewayLogger.InfoAsync($"Left {g.Name}").ConfigureAwait(false); @@ -408,7 +408,7 @@ namespace Discord.WebSocket /// public SocketUser GetUser(string username, string discriminator) { - return State.Users.Where(x => x.Discriminator == discriminator && x.Username == username).FirstOrDefault(); + return State.Users.FirstOrDefault(x => x.Discriminator == discriminator && x.Username == username); } internal SocketGlobalUser GetOrCreateUser(ClientState state, Discord.API.User model) { @@ -770,7 +770,7 @@ namespace Discord.WebSocket if (data.Unavailable == true) { type = "GUILD_UNAVAILABLE"; - await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_UNAVAILABLE)").ConfigureAwait(false); + await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_UNAVAILABLE)").ConfigureAwait(false); var guild = State.GetGuild(data.Id); if (guild != null) @@ -780,13 +780,13 @@ namespace Discord.WebSocket } else { - await _gatewayLogger.WarningAsync($"GUILD_UNAVAILABLE referenced an unknown guild.").ConfigureAwait(false); + await _gatewayLogger.WarningAsync("GUILD_UNAVAILABLE referenced an unknown guild.").ConfigureAwait(false); return; } } else { - await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_DELETE)").ConfigureAwait(false); + await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_DELETE)").ConfigureAwait(false); _downloadUsersFor.TryRemove(data.Id); var guild = RemoveGuild(data.Id); @@ -797,7 +797,7 @@ namespace Discord.WebSocket } else { - await _gatewayLogger.WarningAsync($"GUILD_DELETE referenced an unknown guild.").ConfigureAwait(false); + await _gatewayLogger.WarningAsync("GUILD_DELETE referenced an unknown guild.").ConfigureAwait(false); return; } } @@ -810,7 +810,7 @@ namespace Discord.WebSocket await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_CREATE)").ConfigureAwait(false); var data = (payload as JToken).ToObject(_serializer); - SocketChannel channel = null; + SocketChannel channel; if (data.GuildId.IsSpecified) { var guild = State.GetGuild(data.GuildId.Value); @@ -867,7 +867,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_DELETE)").ConfigureAwait(false); - SocketChannel channel = null; + SocketChannel channel; var data = (payload as JToken).ToObject(_serializer); if (data.GuildId.IsSpecified) { @@ -1205,9 +1205,8 @@ namespace Discord.WebSocket return; } - SocketUser user = State.GetUser(data.User.Id); - if (user == null) - user = SocketSimpleUser.Create(this, State, data.User); + SocketUser user = State.GetUser(data.User.Id) ?? + (SocketUser) SocketSimpleUser.Create(this, State, data.User); await _userUnbannedEvent.InvokeAsync(user, guild).ConfigureAwait(false); } else @@ -1234,13 +1233,8 @@ namespace Discord.WebSocket 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) { @@ -1287,25 +1281,17 @@ namespace Discord.WebSocket else if (data.Author.IsSpecified) { //Edited message isnt in cache, create a detached one - 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); after = SocketMessage.Create(this, State, author, channel, data); } - if (before != null) - await _messageUpdatedEvent.InvokeAsync(before, after).ConfigureAwait(false); - else - await _messageUpdatedEvent.InvokeAsync(Optional.Create(), after).ConfigureAwait(false); + var cached = new Cached(data.Id, before, channel); + await _messageUpdatedEvent.InvokeAsync(cached, after).ConfigureAwait(false); } else { await _gatewayLogger.WarningAsync("MESSAGE_UPDATE referenced an unknown channel.").ConfigureAwait(false); - return; } } break; @@ -1324,15 +1310,13 @@ namespace Discord.WebSocket } 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()).ConfigureAwait(false); + var cached = new Cached(data.Id, msg, channel, isDownloadable: false); + + await _messageDeletedEvent.InvokeAsync(cached).ConfigureAwait(false); } else { await _gatewayLogger.WarningAsync("MESSAGE_DELETE referenced an unknown channel.").ConfigureAwait(false); - return; } } break; @@ -1347,19 +1331,15 @@ namespace Discord.WebSocket SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); + var cached = new Cached(data.MessageId, cachedMsg, channel); - if (cachedMsg != null) - { - cachedMsg.AddReaction(reaction); - await _reactionAddedEvent.InvokeAsync(data.MessageId, cachedMsg, reaction).ConfigureAwait(false); - return; - } - await _reactionAddedEvent.InvokeAsync(data.MessageId, Optional.Create(), reaction).ConfigureAwait(false); + cachedMsg?.AddReaction(reaction); + + await _reactionAddedEvent.InvokeAsync(cached, reaction).ConfigureAwait(false); } else { await _gatewayLogger.WarningAsync("MESSAGE_REACTION_ADD referenced an unknown channel.").ConfigureAwait(false); - return; } break; } @@ -1374,18 +1354,15 @@ namespace Discord.WebSocket SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); 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(), reaction).ConfigureAwait(false); + var cached = new Cached(data.MessageId, cachedMsg, channel); + + cachedMsg?.RemoveReaction(reaction); + + await _reactionRemovedEvent.InvokeAsync(cached, reaction).ConfigureAwait(false); } else { await _gatewayLogger.WarningAsync("MESSAGE_REACTION_REMOVE referenced an unknown channel.").ConfigureAwait(false); - return; } break; } @@ -1398,20 +1375,16 @@ namespace Discord.WebSocket if (channel != null) { 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()); + var cached = new Cached(data.MessageId, cachedMsg, channel); + + cachedMsg?.ClearReactions(); + + await _reactionsClearedEvent.InvokeAsync(cached); } else { await _gatewayLogger.WarningAsync("MESSAGE_REACTION_REMOVE_ALL referenced an unknown channel.").ConfigureAwait(false); - return; } - break; } case "MESSAGE_DELETE_BULK": @@ -1431,16 +1404,13 @@ namespace Discord.WebSocket foreach (var id in data.Ids) { var msg = SocketChannelHelper.RemoveMessage(channel, this, id); - if (msg != null) - await _messageDeletedEvent.InvokeAsync(id, msg).ConfigureAwait(false); - else - await _messageDeletedEvent.InvokeAsync(id, Optional.Create()).ConfigureAwait(false); + var cached = new Cached(id, msg, channel, false); + await _messageDeletedEvent.InvokeAsync(cached).ConfigureAwait(false); } } else { await _gatewayLogger.WarningAsync("MESSAGE_DELETE_BULK referenced an unknown channel.").ConfigureAwait(false); - return; } } break; @@ -1678,7 +1648,6 @@ namespace Discord.WebSocket catch (Exception ex) { await _gatewayLogger.ErrorAsync($"Error handling {opCode}{(type != null ? $" ({type})" : "")}", ex).ConfigureAwait(false); - return; } } From 8435186d79522377947f722912f540aae9e2654c Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Thu, 1 Dec 2016 18:37:53 +0100 Subject: [PATCH 03/11] returns. --- src/Discord.Net.WebSocket/DiscordSocketClient.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 2d510790f..f28d7961d 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -1292,6 +1292,7 @@ namespace Discord.WebSocket else { await _gatewayLogger.WarningAsync("MESSAGE_UPDATE referenced an unknown channel.").ConfigureAwait(false); + return; } } break; @@ -1340,6 +1341,7 @@ namespace Discord.WebSocket else { await _gatewayLogger.WarningAsync("MESSAGE_REACTION_ADD referenced an unknown channel.").ConfigureAwait(false); + return; } break; } @@ -1384,6 +1386,7 @@ namespace Discord.WebSocket else { await _gatewayLogger.WarningAsync("MESSAGE_REACTION_REMOVE_ALL referenced an unknown channel.").ConfigureAwait(false); + return; } break; } @@ -1648,6 +1651,7 @@ namespace Discord.WebSocket catch (Exception ex) { await _gatewayLogger.ErrorAsync($"Error handling {opCode}{(type != null ? $" ({type})" : "")}", ex).ConfigureAwait(false); + return; } } From 705d71875c69d68756e81ca6c8964ccf1fb81a47 Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Fri, 16 Dec 2016 23:50:27 +0100 Subject: [PATCH 04/11] Simplified PR, renamed Cached to Cacheable. --- src/Discord.Net.Core/Utils/Cacheable.cs | 30 +++++++++++++ src/Discord.Net.Core/Utils/Cached.cs | 33 -------------- .../DiscordSocketClient.Events.cs | 20 ++++----- .../DiscordSocketClient.cs | 44 ++++++++++++------- 4 files changed, 67 insertions(+), 60 deletions(-) create mode 100644 src/Discord.Net.Core/Utils/Cacheable.cs delete mode 100644 src/Discord.Net.Core/Utils/Cached.cs diff --git a/src/Discord.Net.Core/Utils/Cacheable.cs b/src/Discord.Net.Core/Utils/Cacheable.cs new file mode 100644 index 000000000..b85536434 --- /dev/null +++ b/src/Discord.Net.Core/Utils/Cacheable.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Discord +{ + public struct Cacheable + where TEntity : IEntity + where TId : IEquatable + { + public bool HasValue => !EqualityComparer.Default.Equals(Value, default(TEntity)); + public ulong Id { get; } + public TEntity Value { get; } + private Func> DownloadFunc { get; } + + internal Cacheable(TEntity value, ulong id, Func> downloadFunc) + { + Value = value; + Id = id; + DownloadFunc = downloadFunc; + } + + public async Task DownloadAsync() + { + return await DownloadFunc(); + } + + public async Task GetOrDownloadAsync() => HasValue ? Value : await DownloadAsync(); + } +} \ No newline at end of file diff --git a/src/Discord.Net.Core/Utils/Cached.cs b/src/Discord.Net.Core/Utils/Cached.cs deleted file mode 100644 index 99c7794f7..000000000 --- a/src/Discord.Net.Core/Utils/Cached.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Discord.WebSocket; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Discord -{ - public struct Cached where T : IMessage - { - public bool IsCached => !EqualityComparer.Default.Equals(Value, default(T)); - public bool IsDownloadable { get; } - public ulong Id { get; } - public T Value { get; } - public ISocketMessageChannel Channel { get; } - - public Cached(ulong id, T value, ISocketMessageChannel channel, bool isDownloadable = true) - { - Id = id; - Value = value; - Channel = channel; - IsDownloadable = isDownloadable; - } - - public async Task DownloadAsync() - { - if (IsDownloadable) - return (T) await Channel.GetMessageAsync(Id); - throw new InvalidOperationException("This message cannot be downloaded."); - } - - public async Task GetOrDownloadAsync() => IsCached ? Value : await DownloadAsync(); - } -} diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs index 48f945b0c..63083bbb5 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs @@ -59,36 +59,36 @@ namespace Discord.WebSocket remove { _messageReceivedEvent.Remove(value); } } private readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); - public event Func, Task> MessageDeleted + public event Func, ISocketMessageChannel, Task> MessageDeleted { add { _messageDeletedEvent.Add(value); } remove { _messageDeletedEvent.Remove(value); } } - private readonly AsyncEvent, Task>> _messageDeletedEvent = new AsyncEvent, Task>>(); - public event Func, SocketMessage, Task> MessageUpdated + private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); + public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated { add { _messageUpdatedEvent.Add(value); } remove { _messageUpdatedEvent.Remove(value); } } - private readonly AsyncEvent, SocketMessage, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, Task>>(); - public event Func, SocketReaction, Task> ReactionAdded + private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded { add { _reactionAddedEvent.Add(value); } remove { _reactionAddedEvent.Remove(value); } } - private readonly AsyncEvent, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, SocketReaction, Task>>(); - public event Func, SocketReaction, Task> ReactionRemoved + private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved { add { _reactionRemovedEvent.Add(value); } remove { _reactionRemovedEvent.Remove(value); } } - private readonly AsyncEvent, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, SocketReaction, Task>>(); - public event Func, Task> ReactionsCleared + private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + public event Func, ISocketMessageChannel, Task> ReactionsCleared { add { _reactionsClearedEvent.Add(value); } remove { _reactionsClearedEvent.Remove(value); } } - private readonly AsyncEvent, Task>> _reactionsClearedEvent = new AsyncEvent, Task>>(); + private readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); //Roles public event Func RoleCreated diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index f28d7961d..54ffb348e 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -1265,7 +1265,7 @@ namespace Discord.WebSocket { var guild = (channel as SocketGuildChannel)?.Guild; if (guild != null && !guild.IsSynced) - { + { await _gatewayLogger.DebugAsync("Ignored MESSAGE_UPDATE, guild is not synced yet.").ConfigureAwait(false); return; } @@ -1281,13 +1281,20 @@ namespace Discord.WebSocket else if (data.Author.IsSpecified) { //Edited message isnt in cache, create a detached one - 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); + 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); after = SocketMessage.Create(this, State, author, channel, data); } - var cached = new Cached(data.Id, before, channel); - await _messageUpdatedEvent.InvokeAsync(cached, after).ConfigureAwait(false); + if (before != null) + await _messageUpdatedEvent.InvokeAsync(before, after, channel).ConfigureAwait(false); + else + await _messageUpdatedEvent.InvokeAsync(Optional.Create(), after, channel).ConfigureAwait(false); } else { @@ -1299,25 +1306,26 @@ namespace Discord.WebSocket case "MESSAGE_DELETE": { await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_DELETE)").ConfigureAwait(false); - + var data = (payload as JToken).ToObject(_serializer); var channel = State.GetChannel(data.ChannelId) as ISocketMessageChannel; if (channel != null) { if (!((channel as SocketGuildChannel)?.Guild.IsSynced ?? true)) - { + { await _gatewayLogger.DebugAsync("Ignored MESSAGE_DELETE, guild is not synced yet.").ConfigureAwait(false); return; } var msg = SocketChannelHelper.RemoveMessage(channel, this, data.Id); - var cached = new Cached(data.Id, msg, channel, isDownloadable: false); + var cacheable = new Cacheable(msg, data.Id, async () => await channel.GetMessageAsync(data.Id) as SocketUserMessage); - await _messageDeletedEvent.InvokeAsync(cached).ConfigureAwait(false); + await _messageDeletedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); } else { await _gatewayLogger.WarningAsync("MESSAGE_DELETE referenced an unknown channel.").ConfigureAwait(false); + return; } } break; @@ -1332,11 +1340,11 @@ namespace Discord.WebSocket SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); - var cached = new Cached(data.MessageId, cachedMsg, channel); + var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as SocketUserMessage); cachedMsg?.AddReaction(reaction); - await _reactionAddedEvent.InvokeAsync(cached, reaction).ConfigureAwait(false); + await _reactionAddedEvent.InvokeAsync(cacheable, channel, reaction).ConfigureAwait(false); } else { @@ -1356,15 +1364,16 @@ namespace Discord.WebSocket SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); - var cached = new Cached(data.MessageId, cachedMsg, channel); + var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as SocketUserMessage); cachedMsg?.RemoveReaction(reaction); - await _reactionRemovedEvent.InvokeAsync(cached, reaction).ConfigureAwait(false); + await _reactionRemovedEvent.InvokeAsync(cacheable, channel, reaction).ConfigureAwait(false); } else { await _gatewayLogger.WarningAsync("MESSAGE_REACTION_REMOVE referenced an unknown channel.").ConfigureAwait(false); + return; } break; } @@ -1377,11 +1386,11 @@ namespace Discord.WebSocket if (channel != null) { SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; - var cached = new Cached(data.MessageId, cachedMsg, channel); + var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as SocketUserMessage); cachedMsg?.ClearReactions(); - await _reactionsClearedEvent.InvokeAsync(cached); + await _reactionsClearedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); } else { @@ -1407,13 +1416,14 @@ namespace Discord.WebSocket foreach (var id in data.Ids) { var msg = SocketChannelHelper.RemoveMessage(channel, this, id); - var cached = new Cached(id, msg, channel, false); - await _messageDeletedEvent.InvokeAsync(cached).ConfigureAwait(false); + var cacheable = new Cacheable(msg, id, async () => await channel.GetMessageAsync(id) as SocketMessage); + await _messageDeletedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); } } else { await _gatewayLogger.WarningAsync("MESSAGE_DELETE_BULK referenced an unknown channel.").ConfigureAwait(false); + return; } } break; From daf0ac9347ff49026c3593791119f8c9b18fbe51 Mon Sep 17 00:00:00 2001 From: Christopher F Date: Wed, 21 Dec 2016 20:52:07 -0500 Subject: [PATCH 05/11] Added docstrings for Cacheable --- src/Discord.Net.Core/Utils/Cacheable.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/Discord.Net.Core/Utils/Cacheable.cs b/src/Discord.Net.Core/Utils/Cacheable.cs index b85536434..ff63e4c69 100644 --- a/src/Discord.Net.Core/Utils/Cacheable.cs +++ b/src/Discord.Net.Core/Utils/Cacheable.cs @@ -4,12 +4,29 @@ using System.Threading.Tasks; namespace Discord { + /// + /// Contains an entity that may be cached. + /// + /// The type of entity that is cached + /// The type of this entity's ID public struct Cacheable where TEntity : IEntity where TId : IEquatable { + /// + /// Is this entity cached? + /// public bool HasValue => !EqualityComparer.Default.Equals(Value, default(TEntity)); + /// + /// The ID of this entity. + /// public ulong Id { get; } + /// + /// The entity, if it could be pulled from cache. + /// + /// + /// This value is not guaranteed to be set; in cases where the entity cannot be pulled from cache, it is null. + /// public TEntity Value { get; } private Func> DownloadFunc { get; } @@ -20,11 +37,19 @@ namespace Discord DownloadFunc = downloadFunc; } + /// + /// Downloads this entity to cache. + /// + /// An awaitable Task containing the downloaded entity. public async Task DownloadAsync() { return await DownloadFunc(); } + /// + /// Returns the cached entity if it exists; otherwise downloads it. + /// + /// An awaitable Task containing a cached or downloaded entity. public async Task GetOrDownloadAsync() => HasValue ? Value : await DownloadAsync(); } } \ No newline at end of file From 2a1314da25dd0eede993a7fdf7fb85a032315d18 Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Thu, 22 Dec 2016 03:41:23 +0100 Subject: [PATCH 06/11] Cleanup. --- .../DiscordSocketClient.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 54ffb348e..164fdeb07 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -108,11 +108,11 @@ namespace Discord.WebSocket { if (ex != null) { - await _gatewayLogger.WarningAsync("Connection Closed", ex).ConfigureAwait(false); + await _gatewayLogger.WarningAsync($"Connection Closed", ex).ConfigureAwait(false); await StartReconnectAsync(ex).ConfigureAwait(false); } else - await _gatewayLogger.WarningAsync("Connection Closed").ConfigureAwait(false); + await _gatewayLogger.WarningAsync($"Connection Closed").ConfigureAwait(false); }; LeftGuild += async g => await _gatewayLogger.InfoAsync($"Left {g.Name}").ConfigureAwait(false); @@ -408,7 +408,7 @@ namespace Discord.WebSocket /// public SocketUser GetUser(string username, string discriminator) { - return State.Users.FirstOrDefault(x => x.Discriminator == discriminator && x.Username == username); + return State.Users.Where(x => x.Discriminator == discriminator && x.Username == username).FirstOrDefault(); } internal SocketGlobalUser GetOrCreateUser(ClientState state, Discord.API.User model) { @@ -485,25 +485,25 @@ namespace Discord.WebSocket } } - public async Task SetStatusAsync(UserStatus status) + public async Task SetStatus(UserStatus status) { Status = status; if (status == UserStatus.AFK) _statusSince = DateTimeOffset.UtcNow; else _statusSince = null; - await SendStatusAsync().ConfigureAwait(false); + await SendStatus().ConfigureAwait(false); } - public async Task SetGameAsync(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) + public async Task SetGame(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) { if (name != null) Game = new Game(name, streamUrl, streamType); else Game = null; CurrentUser.Presence = new SocketPresence(Status, Game); - await SendStatusAsync().ConfigureAwait(false); + await SendStatus().ConfigureAwait(false); } - private async Task SendStatusAsync() + private async Task SendStatus() { var game = Game; var status = Status; @@ -770,7 +770,7 @@ namespace Discord.WebSocket if (data.Unavailable == true) { type = "GUILD_UNAVAILABLE"; - await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_UNAVAILABLE)").ConfigureAwait(false); + await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_UNAVAILABLE)").ConfigureAwait(false); var guild = State.GetGuild(data.Id); if (guild != null) @@ -780,13 +780,13 @@ namespace Discord.WebSocket } else { - await _gatewayLogger.WarningAsync("GUILD_UNAVAILABLE referenced an unknown guild.").ConfigureAwait(false); + await _gatewayLogger.WarningAsync($"GUILD_UNAVAILABLE referenced an unknown guild.").ConfigureAwait(false); return; } } else { - await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_DELETE)").ConfigureAwait(false); + await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_DELETE)").ConfigureAwait(false); _downloadUsersFor.TryRemove(data.Id); var guild = RemoveGuild(data.Id); @@ -797,7 +797,7 @@ namespace Discord.WebSocket } else { - await _gatewayLogger.WarningAsync("GUILD_DELETE referenced an unknown guild.").ConfigureAwait(false); + await _gatewayLogger.WarningAsync($"GUILD_DELETE referenced an unknown guild.").ConfigureAwait(false); return; } } @@ -810,7 +810,7 @@ namespace Discord.WebSocket await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_CREATE)").ConfigureAwait(false); var data = (payload as JToken).ToObject(_serializer); - SocketChannel channel; + SocketChannel channel = null; if (data.GuildId.IsSpecified) { var guild = State.GetGuild(data.GuildId.Value); @@ -867,7 +867,7 @@ namespace Discord.WebSocket { await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_DELETE)").ConfigureAwait(false); - SocketChannel channel; + SocketChannel channel = null; var data = (payload as JToken).ToObject(_serializer); if (data.GuildId.IsSpecified) { From 2d67cf36ae01e8fe9bf8badf2ecca3d8e60dcd07 Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Sat, 24 Dec 2016 02:25:37 +0100 Subject: [PATCH 07/11] Changed Id from a ulong to generic TId, as per discussion. --- src/Discord.Net.Core/Utils/Cacheable.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Discord.Net.Core/Utils/Cacheable.cs b/src/Discord.Net.Core/Utils/Cacheable.cs index ff63e4c69..48af580d9 100644 --- a/src/Discord.Net.Core/Utils/Cacheable.cs +++ b/src/Discord.Net.Core/Utils/Cacheable.cs @@ -20,7 +20,7 @@ namespace Discord /// /// The ID of this entity. /// - public ulong Id { get; } + public TId Id { get; } /// /// The entity, if it could be pulled from cache. /// @@ -30,7 +30,7 @@ namespace Discord public TEntity Value { get; } private Func> DownloadFunc { get; } - internal Cacheable(TEntity value, ulong id, Func> downloadFunc) + internal Cacheable(TEntity value, TId id, Func> downloadFunc) { Value = value; Id = id; From 4b13e3fb00c958fdecc288ed414dd121117a176f Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Sun, 25 Dec 2016 14:30:20 +0100 Subject: [PATCH 08/11] Changed MessageUpdated to use Cacheable as well, after discussion with Volt. --- src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs | 4 ++-- src/Discord.Net.WebSocket/DiscordSocketClient.cs | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs index 63083bbb5..03edeb7c0 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs @@ -65,12 +65,12 @@ namespace Discord.WebSocket remove { _messageDeletedEvent.Remove(value); } } private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); - public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated + public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated { add { _messageUpdatedEvent.Add(value); } remove { _messageUpdatedEvent.Remove(value); } } - private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); + private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded { add { _reactionAddedEvent.Add(value); } diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 164fdeb07..3e3128354 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -1291,10 +1291,9 @@ namespace Discord.WebSocket after = SocketMessage.Create(this, State, author, channel, data); } - if (before != null) - await _messageUpdatedEvent.InvokeAsync(before, after, channel).ConfigureAwait(false); - else - await _messageUpdatedEvent.InvokeAsync(Optional.Create(), after, channel).ConfigureAwait(false); + var cacheableBefore = new Cacheable(before, data.Id, async () => await channel.GetMessageAsync(data.Id) as SocketMessage); + + await _messageUpdatedEvent.InvokeAsync(cacheableBefore, after, channel).ConfigureAwait(false); } else { From 25547407c8e2f5214600d16e8d200d2f5cbac1e3 Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Thu, 2 Feb 2017 14:41:27 +0100 Subject: [PATCH 09/11] Now this should be ready to, I am the worst at git. --- .../DiscordShardedClient.Events.cs | 20 +++++++++---------- .../DiscordShardedClient.cs | 10 +++++----- .../DiscordSocketClient.cs | 15 +++++++------- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs index 449d30599..f06bad926 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs @@ -33,36 +33,36 @@ namespace Discord.WebSocket remove { _messageReceivedEvent.Remove(value); } } private readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); - public event Func, Task> MessageDeleted + public event Func, ISocketMessageChannel, Task> MessageDeleted { add { _messageDeletedEvent.Add(value); } remove { _messageDeletedEvent.Remove(value); } } - private readonly AsyncEvent, Task>> _messageDeletedEvent = new AsyncEvent, Task>>(); - public event Func, SocketMessage, Task> MessageUpdated + private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); + public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated { add { _messageUpdatedEvent.Add(value); } remove { _messageUpdatedEvent.Remove(value); } } - private readonly AsyncEvent, SocketMessage, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, Task>>(); - public event Func, SocketReaction, Task> ReactionAdded + private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded { add { _reactionAddedEvent.Add(value); } remove { _reactionAddedEvent.Remove(value); } } - private readonly AsyncEvent, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, SocketReaction, Task>>(); - public event Func, SocketReaction, Task> ReactionRemoved + private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved { add { _reactionRemovedEvent.Add(value); } remove { _reactionRemovedEvent.Remove(value); } } - private readonly AsyncEvent, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, SocketReaction, Task>>(); - public event Func, Task> ReactionsCleared + private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + public event Func, ISocketMessageChannel, Task> ReactionsCleared { add { _reactionsClearedEvent.Add(value); } remove { _reactionsClearedEvent.Remove(value); } } - private readonly AsyncEvent, Task>> _reactionsClearedEvent = new AsyncEvent, Task>>(); + private readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); //Roles public event Func RoleCreated diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.cs index 832e35578..92e016d6e 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.cs @@ -303,11 +303,11 @@ namespace Discord.WebSocket client.ChannelUpdated += (oldChannel, newChannel) => _channelUpdatedEvent.InvokeAsync(oldChannel, newChannel); 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.RoleDeleted += (role) => _roleDeletedEvent.InvokeAsync(role); diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 3e3128354..a40ec04e8 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -485,25 +485,25 @@ namespace Discord.WebSocket } } - public async Task SetStatus(UserStatus status) + public async Task SetStatusAsync(UserStatus status) { Status = status; if (status == UserStatus.AFK) _statusSince = DateTimeOffset.UtcNow; else _statusSince = null; - await SendStatus().ConfigureAwait(false); + await SendStatusAsync().ConfigureAwait(false); } - public async Task SetGame(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) + public async Task SetGameAsync(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) { if (name != null) Game = new Game(name, streamUrl, streamType); else Game = null; CurrentUser.Presence = new SocketPresence(Status, Game); - await SendStatus().ConfigureAwait(false); + await SendStatusAsync().ConfigureAwait(false); } - private async Task SendStatus() + private async Task SendStatusAsync() { var game = Game; var status = Status; @@ -1205,8 +1205,9 @@ namespace Discord.WebSocket return; } - SocketUser user = State.GetUser(data.User.Id) ?? - (SocketUser) SocketSimpleUser.Create(this, State, data.User); + SocketUser user = State.GetUser(data.User.Id); + if (user == null) + user = SocketSimpleUser.Create(this, State, data.User); await _userUnbannedEvent.InvokeAsync(user, guild).ConfigureAwait(false); } else From d8682a82b2b0325425d34ef8b92ca19e64b7cb31 Mon Sep 17 00:00:00 2001 From: Sindre Langhus Date: Fri, 3 Feb 2017 15:04:54 +0100 Subject: [PATCH 10/11] Change all signatures in the SocketClients to interfaces. --- src/Discord.Net.Core/Utils/Cacheable.cs | 4 ++++ .../DiscordShardedClient.Events.cs | 21 ++++++++++--------- .../DiscordSocketClient.Events.cs | 20 +++++++++--------- .../DiscordSocketClient.cs | 12 +++++------ 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Discord.Net.Core/Utils/Cacheable.cs b/src/Discord.Net.Core/Utils/Cacheable.cs index 48af580d9..da6c660b8 100644 --- a/src/Discord.Net.Core/Utils/Cacheable.cs +++ b/src/Discord.Net.Core/Utils/Cacheable.cs @@ -41,6 +41,8 @@ namespace Discord /// Downloads this entity to cache. /// /// An awaitable Task containing the downloaded entity. + /// Thrown when used from a user account. + /// Thrown when the message is deleted. public async Task DownloadAsync() { return await DownloadFunc(); @@ -50,6 +52,8 @@ namespace Discord /// Returns the cached entity if it exists; otherwise downloads it. /// /// An awaitable Task containing a cached or downloaded entity. + /// Thrown when used from a user account. + /// Thrown when the message is deleted and is not in cache. public async Task GetOrDownloadAsync() => HasValue ? Value : await DownloadAsync(); } } \ No newline at end of file diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs index f06bad926..874062c56 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.Events.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Discord.Net; namespace Discord.WebSocket { @@ -33,36 +34,36 @@ namespace Discord.WebSocket remove { _messageReceivedEvent.Remove(value); } } private readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); - public event Func, ISocketMessageChannel, Task> MessageDeleted + public event Func, ISocketMessageChannel, Task> MessageDeleted { add { _messageDeletedEvent.Add(value); } remove { _messageDeletedEvent.Remove(value); } } - private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); - public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated + private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); + public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated { add { _messageUpdatedEvent.Add(value); } remove { _messageUpdatedEvent.Remove(value); } } - private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); - public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded + private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded { add { _reactionAddedEvent.Add(value); } remove { _reactionAddedEvent.Remove(value); } } - private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); - public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved + private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved { add { _reactionRemovedEvent.Add(value); } remove { _reactionRemovedEvent.Remove(value); } } - private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); - public event Func, ISocketMessageChannel, Task> ReactionsCleared + private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + public event Func, ISocketMessageChannel, Task> ReactionsCleared { add { _reactionsClearedEvent.Add(value); } remove { _reactionsClearedEvent.Remove(value); } } - private readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); + private readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); //Roles public event Func RoleCreated diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs index 03edeb7c0..313e661f3 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs @@ -59,36 +59,36 @@ namespace Discord.WebSocket remove { _messageReceivedEvent.Remove(value); } } private readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); - public event Func, ISocketMessageChannel, Task> MessageDeleted + public event Func, ISocketMessageChannel, Task> MessageDeleted { add { _messageDeletedEvent.Add(value); } remove { _messageDeletedEvent.Remove(value); } } - private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); - public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated + private readonly AsyncEvent, ISocketMessageChannel, Task>> _messageDeletedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); + public event Func, SocketMessage, ISocketMessageChannel, Task> MessageUpdated { add { _messageUpdatedEvent.Add(value); } remove { _messageUpdatedEvent.Remove(value); } } - private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); - public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded + private readonly AsyncEvent, SocketMessage, ISocketMessageChannel, Task>> _messageUpdatedEvent = new AsyncEvent, SocketMessage, ISocketMessageChannel, Task>>(); + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionAdded { add { _reactionAddedEvent.Add(value); } remove { _reactionAddedEvent.Remove(value); } } - private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); - public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved + private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionAddedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + public event Func, ISocketMessageChannel, SocketReaction, Task> ReactionRemoved { add { _reactionRemovedEvent.Add(value); } remove { _reactionRemovedEvent.Remove(value); } } - private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); - public event Func, ISocketMessageChannel, Task> ReactionsCleared + private readonly AsyncEvent, ISocketMessageChannel, SocketReaction, Task>> _reactionRemovedEvent = new AsyncEvent, ISocketMessageChannel, SocketReaction, Task>>(); + public event Func, ISocketMessageChannel, Task> ReactionsCleared { add { _reactionsClearedEvent.Add(value); } remove { _reactionsClearedEvent.Remove(value); } } - private readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); + private readonly AsyncEvent, ISocketMessageChannel, Task>> _reactionsClearedEvent = new AsyncEvent, ISocketMessageChannel, Task>>(); //Roles public event Func RoleCreated diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index a40ec04e8..60ebeb535 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -1292,7 +1292,7 @@ namespace Discord.WebSocket after = SocketMessage.Create(this, State, author, channel, data); } - var cacheableBefore = new Cacheable(before, data.Id, async () => await channel.GetMessageAsync(data.Id) as SocketMessage); + var cacheableBefore = new Cacheable(before, data.Id, async () => await channel.GetMessageAsync(data.Id)); await _messageUpdatedEvent.InvokeAsync(cacheableBefore, after, channel).ConfigureAwait(false); } @@ -1318,7 +1318,7 @@ namespace Discord.WebSocket } var msg = SocketChannelHelper.RemoveMessage(channel, this, data.Id); - var cacheable = new Cacheable(msg, data.Id, async () => await channel.GetMessageAsync(data.Id) as SocketUserMessage); + var cacheable = new Cacheable(msg, data.Id, async () => await channel.GetMessageAsync(data.Id)); await _messageDeletedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); } @@ -1340,7 +1340,7 @@ namespace Discord.WebSocket SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); - var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as SocketUserMessage); + var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); cachedMsg?.AddReaction(reaction); @@ -1364,7 +1364,7 @@ namespace Discord.WebSocket SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); - var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as SocketUserMessage); + var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); cachedMsg?.RemoveReaction(reaction); @@ -1386,7 +1386,7 @@ namespace Discord.WebSocket if (channel != null) { SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; - var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as SocketUserMessage); + var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); cachedMsg?.ClearReactions(); @@ -1416,7 +1416,7 @@ namespace Discord.WebSocket foreach (var id in data.Ids) { var msg = SocketChannelHelper.RemoveMessage(channel, this, id); - var cacheable = new Cacheable(msg, id, async () => await channel.GetMessageAsync(id) as SocketMessage); + var cacheable = new Cacheable(msg, id, async () => await channel.GetMessageAsync(id)); await _messageDeletedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); } } From ab60f635116e509df54f7d76253c6edc2e556f7b Mon Sep 17 00:00:00 2001 From: "Sindre G. Langhus" Date: Tue, 21 Feb 2017 22:11:48 +0900 Subject: [PATCH 11/11] Changes HasValue in Cachable to constructor argument --- src/Discord.Net.Core/Utils/Cacheable.cs | 5 +++-- .../DiscordSocketClient.cs | 20 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Discord.Net.Core/Utils/Cacheable.cs b/src/Discord.Net.Core/Utils/Cacheable.cs index da6c660b8..10b61be90 100644 --- a/src/Discord.Net.Core/Utils/Cacheable.cs +++ b/src/Discord.Net.Core/Utils/Cacheable.cs @@ -16,7 +16,7 @@ namespace Discord /// /// Is this entity cached? /// - public bool HasValue => !EqualityComparer.Default.Equals(Value, default(TEntity)); + public bool HasValue { get; } /// /// The ID of this entity. /// @@ -30,10 +30,11 @@ namespace Discord public TEntity Value { get; } private Func> DownloadFunc { get; } - internal Cacheable(TEntity value, TId id, Func> downloadFunc) + internal Cacheable(TEntity value, TId id, bool hasValue , Func> downloadFunc) { Value = value; Id = id; + HasValue = hasValue; DownloadFunc = downloadFunc; } diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 60ebeb535..891db6307 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -1273,7 +1273,8 @@ namespace Discord.WebSocket SocketMessage before = null, after = null; SocketMessage cachedMsg = channel.GetCachedMessage(data.Id); - if (cachedMsg != null) + bool isCached = cachedMsg != null; + if (isCached) { before = cachedMsg.Clone(); cachedMsg.Update(State, data); @@ -1292,7 +1293,7 @@ namespace Discord.WebSocket after = SocketMessage.Create(this, State, author, channel, data); } - var cacheableBefore = new Cacheable(before, data.Id, async () => await channel.GetMessageAsync(data.Id)); + var cacheableBefore = new Cacheable(before, data.Id, isCached , async () => await channel.GetMessageAsync(data.Id)); await _messageUpdatedEvent.InvokeAsync(cacheableBefore, after, channel).ConfigureAwait(false); } @@ -1318,7 +1319,8 @@ namespace Discord.WebSocket } var msg = SocketChannelHelper.RemoveMessage(channel, this, data.Id); - var cacheable = new Cacheable(msg, data.Id, async () => await channel.GetMessageAsync(data.Id)); + bool isCached = msg != null; + var cacheable = new Cacheable(msg, data.Id, isCached, async () => await channel.GetMessageAsync(data.Id)); await _messageDeletedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); } @@ -1338,9 +1340,10 @@ namespace Discord.WebSocket if (channel != null) { SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; + bool isCached = cachedMsg != null; var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); - var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); + var cacheable = new Cacheable(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); cachedMsg?.AddReaction(reaction); @@ -1362,9 +1365,10 @@ namespace Discord.WebSocket if (channel != null) { SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; + bool isCached = cachedMsg != null; var user = await channel.GetUserAsync(data.UserId, CacheMode.CacheOnly); SocketReaction reaction = SocketReaction.Create(data, channel, cachedMsg, Optional.Create(user)); - var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); + var cacheable = new Cacheable(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); cachedMsg?.RemoveReaction(reaction); @@ -1386,7 +1390,8 @@ namespace Discord.WebSocket if (channel != null) { SocketUserMessage cachedMsg = channel.GetCachedMessage(data.MessageId) as SocketUserMessage; - var cacheable = new Cacheable(cachedMsg, data.MessageId, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); + bool isCached = cachedMsg != null; + var cacheable = new Cacheable(cachedMsg, data.MessageId, isCached, async () => await channel.GetMessageAsync(data.MessageId) as IUserMessage); cachedMsg?.ClearReactions(); @@ -1416,7 +1421,8 @@ namespace Discord.WebSocket foreach (var id in data.Ids) { var msg = SocketChannelHelper.RemoveMessage(channel, this, id); - var cacheable = new Cacheable(msg, id, async () => await channel.GetMessageAsync(id)); + bool isCached = msg != null; + var cacheable = new Cacheable(msg, id, isCached, async () => await channel.GetMessageAsync(id)); await _messageDeletedEvent.InvokeAsync(cacheable, channel).ConfigureAwait(false); } }