| @@ -61,6 +61,9 @@ namespace Discord.Collections | |||
| protected TValue Get(string key) | |||
| { | |||
| if (key == null) | |||
| return null; | |||
| TValue result; | |||
| if (!_dictionary.TryGetValue(key, out result)) | |||
| return null; | |||
| @@ -1,7 +1,6 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Threading.Tasks; | |||
| namespace Discord.Collections | |||
| { | |||
| @@ -15,7 +14,8 @@ namespace Discord.Collections | |||
| protected override void OnCreated(Channel item) | |||
| { | |||
| item.Server.AddChannel(item.Id); | |||
| if (item.ServerId != null) | |||
| item.Server.AddChannel(item.Id); | |||
| if (item.RecipientId != null) | |||
| { | |||
| var user = item.Recipient; | |||
| @@ -27,8 +27,8 @@ namespace Discord.Collections | |||
| } | |||
| protected override void OnRemoved(Channel item) | |||
| { | |||
| item.Server.RemoveChannel(item.Id); | |||
| if (item.ServerId != null) | |||
| item.Server.RemoveChannel(item.Id); | |||
| if (item.RecipientId != null) | |||
| { | |||
| var user = item.Recipient; | |||
| @@ -376,7 +376,7 @@ namespace Discord | |||
| case "PRESENCE_UPDATE": | |||
| { | |||
| var data = e.Payload.ToObject<Events.PresenceUpdate>(_serializer); | |||
| var member = _members[data.UserId, data.GuildId]; | |||
| var member = _members[data.User.Id, data.GuildId]; | |||
| /*if (_config.TrackActivity) | |||
| { | |||
| var user = _users[data.User.Id]; | |||
| @@ -539,8 +539,8 @@ namespace Discord | |||
| } | |||
| /// <summary> Disconnects from the Discord server, canceling any pending requests. </summary> | |||
| public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user.")); | |||
| protected async Task DisconnectInternal(Exception ex, bool isUnexpected = true) | |||
| public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false); | |||
| protected async Task DisconnectInternal(Exception ex, bool isUnexpected = true, bool skipAwait = false) | |||
| { | |||
| int oldState; | |||
| bool hasWriterLock; | |||
| @@ -563,9 +563,12 @@ namespace Discord | |||
| _cancelToken.Cancel(); | |||
| } | |||
| Task task = _runTask; | |||
| if (task != null) | |||
| await task.ConfigureAwait(false); | |||
| if (!skipAwait) | |||
| { | |||
| Task task = _runTask; | |||
| if (task != null) | |||
| await task.ConfigureAwait(false); | |||
| } | |||
| if (hasWriterLock) | |||
| { | |||
| @@ -587,7 +590,7 @@ namespace Discord | |||
| { | |||
| await task.ConfigureAwait(false); | |||
| } | |||
| catch (Exception ex) { await DisconnectInternal(ex).ConfigureAwait(false); } | |||
| catch (Exception ex) { await DisconnectInternal(ex, skipAwait: true).ConfigureAwait(false); } | |||
| await Cleanup().ConfigureAwait(false); | |||
| _runTask = null; | |||
| @@ -129,8 +129,8 @@ namespace Discord | |||
| var members = _client.Members; | |||
| foreach (var subModel in model.Members) | |||
| { | |||
| var user = users.GetOrAdd(subModel.UserId); | |||
| var member = members.GetOrAdd(subModel.UserId, Id); | |||
| var user = users.GetOrAdd(subModel.User.Id); | |||
| var member = members.GetOrAdd(subModel.User.Id, Id); | |||
| user.Update(subModel.User); | |||
| member.Update(subModel); | |||
| } | |||
| @@ -141,7 +141,7 @@ namespace Discord | |||
| } | |||
| foreach (var subModel in model.Presences) | |||
| { | |||
| var member = members.GetOrAdd(subModel.UserId, Id); | |||
| var member = members.GetOrAdd(subModel.User.Id, Id); | |||
| member.Update(subModel); | |||
| } | |||
| } | |||
| @@ -11,12 +11,12 @@ namespace Discord.Net.WebSockets | |||
| { | |||
| internal static class Commands | |||
| { | |||
| public sealed class KeepAlive : WebSocketMessage<int> | |||
| public sealed class KeepAlive : WebSocketMessage<ulong> | |||
| { | |||
| public KeepAlive() : base(1, GetTimestamp()) { } | |||
| private static DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); | |||
| private static int GetTimestamp() | |||
| => (int)(DateTime.UtcNow - epoch).TotalMilliseconds; | |||
| private static ulong GetTimestamp() | |||
| => (ulong)(DateTime.UtcNow - epoch).TotalMilliseconds; | |||
| } | |||
| public sealed class Login : WebSocketMessage<Login.Data> | |||
| { | |||
| @@ -24,11 +24,7 @@ namespace Discord.Net.WebSockets | |||
| Commands.Login msg = new Commands.Login(); | |||
| msg.Payload.Token = token; | |||
| //msg.Payload.Properties["$os"] = ""; | |||
| //msg.Payload.Properties["$browser"] = ""; | |||
| msg.Payload.Properties["$device"] = "Discord.Net"; | |||
| //msg.Payload.Properties["$referrer"] = ""; | |||
| //msg.Payload.Properties["$referring_domain"] = ""; | |||
| QueueMessage(msg); | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| using Discord.Helpers; | |||
| using Newtonsoft.Json; | |||
| using System; | |||
| using System.Linq; | |||
| using System.Runtime.ExceptionServices; | |||
| using System.Text; | |||
| using System.Threading; | |||
| @@ -96,8 +97,8 @@ namespace Discord.Net.WebSockets | |||
| public Task Reconnect() | |||
| => Connect(_host); | |||
| public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user.")); | |||
| protected async Task DisconnectInternal(Exception ex, bool isUnexpected = true) | |||
| public Task Disconnect() => DisconnectInternal(new Exception("Disconnect was requested by user."), isUnexpected: false); | |||
| protected async Task DisconnectInternal(Exception ex, bool isUnexpected = true, bool skipAwait = false) | |||
| { | |||
| int oldState; | |||
| bool hasWriterLock; | |||
| @@ -120,9 +121,12 @@ namespace Discord.Net.WebSockets | |||
| _cancelToken.Cancel(); | |||
| } | |||
| Task task = _runTask; | |||
| if (task != null) | |||
| await task.ConfigureAwait(false); | |||
| if (!skipAwait) | |||
| { | |||
| Task task = _runTask; | |||
| if (task != null) | |||
| await task.ConfigureAwait(false); | |||
| } | |||
| if (hasWriterLock) | |||
| { | |||
| @@ -133,12 +137,13 @@ namespace Discord.Net.WebSockets | |||
| protected virtual async Task RunTasks() | |||
| { | |||
| Task[] tasks = Run(); | |||
| Task task = Task.WhenAll(Run()); | |||
| try | |||
| { | |||
| await Task.WhenAll(tasks).ConfigureAwait(false); | |||
| await task.ConfigureAwait(false); | |||
| } | |||
| catch (Exception ex) { await DisconnectInternal(ex).ConfigureAwait(false); } | |||
| catch (Exception ex) { await DisconnectInternal(ex, skipAwait: true).ConfigureAwait(false); } | |||
| bool wasUnexpected = _wasDisconnectUnexpected; | |||
| _wasDisconnectUnexpected = false; | |||
| @@ -147,7 +152,13 @@ namespace Discord.Net.WebSockets | |||
| await Cleanup().ConfigureAwait(false); | |||
| _runTask = null; | |||
| } | |||
| protected virtual Task[] Run() { return _engine.RunTasks(_cancelToken.Token); } | |||
| protected virtual Task[] Run() | |||
| { | |||
| var cancelToken = _cancelToken.Token; | |||
| return _engine.RunTasks(cancelToken) | |||
| .Concat(new Task[] { HeartbeatAsync(cancelToken) }) | |||
| .ToArray(); | |||
| } | |||
| protected virtual Task Cleanup() { return TaskHelper.CompletedTask; } | |||
| protected abstract Task ProcessMessage(string json); | |||