From 7ef48c5ce56bd9e5eb8691842adaaedf2d981a2d Mon Sep 17 00:00:00 2001 From: RogueException Date: Tue, 24 Jan 2017 11:40:08 -0400 Subject: [PATCH] Improved discord HTTP exceptions --- src/Discord.Net.Core/Net/HttpException.cs | 30 ++++++++++++++++--- .../Net/Queue/RequestQueue.cs | 4 +-- .../Net/Queue/RequestQueueBucket.cs | 20 ++++++------- src/Discord.Net.Rest/Net/RateLimitInfo.cs | 6 +++- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/Discord.Net.Core/Net/HttpException.cs b/src/Discord.Net.Core/Net/HttpException.cs index d18d81abf..4141979a0 100644 --- a/src/Discord.Net.Core/Net/HttpException.cs +++ b/src/Discord.Net.Core/Net/HttpException.cs @@ -5,14 +5,36 @@ namespace Discord.Net { public class HttpException : Exception { - public HttpStatusCode StatusCode { get; } + public HttpStatusCode HttpCode { get; } + public int? DiscordCode { get; } public string Reason { get; } - public HttpException(HttpStatusCode statusCode, string reason = null) - : base($"The server responded with error {(int)statusCode} ({statusCode}){(reason != null ? $": \"{reason}\"" : "")}") + public HttpException(HttpStatusCode httpCode, int? discordCode = null, string reason = null) + : base(CreateMessage(httpCode, discordCode, reason)) { - StatusCode = statusCode; + HttpCode = httpCode; + DiscordCode = discordCode; Reason = reason; } + + private static string CreateMessage(HttpStatusCode httpCode, int? discordCode = null, string reason = null) + { + string msg; + if (discordCode != null) + { + if (reason != null) + msg = $"The server responded with error {(int)discordCode}: {reason}"; + else + msg = $"The server responded with error {(int)discordCode}: {httpCode}"; + } + else + { + if (reason != null) + msg = $"The server responded with error {(int)httpCode}: {reason}"; + else + msg = $"The server responded with error {(int)httpCode}: {httpCode}"; + } + return msg; + } } } diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueue.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueue.cs index ef7951765..fce7e3e1b 100644 --- a/src/Discord.Net.Rest/Net/Queue/RequestQueue.cs +++ b/src/Discord.Net.Rest/Net/Queue/RequestQueue.cs @@ -91,9 +91,9 @@ namespace Discord.Net.Queue await Task.Delay(millis).ConfigureAwait(false); } } - internal void PauseGlobal(RateLimitInfo info, TimeSpan lag) + internal void PauseGlobal(RateLimitInfo info) { - _waitUntil = DateTimeOffset.UtcNow.AddMilliseconds(info.RetryAfter.Value + lag.TotalMilliseconds); + _waitUntil = DateTimeOffset.UtcNow.AddMilliseconds(info.RetryAfter.Value + (info.Lag?.TotalMilliseconds ?? 0.0)); } private RequestBucket GetOrCreateBucket(string id, RestRequest request) diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs index 5f23a626f..2cc4b8a10 100644 --- a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs +++ b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs @@ -54,12 +54,10 @@ namespace Discord.Net.Queue #if DEBUG_LIMITS Debug.WriteLine($"[{id}] Sending..."); #endif - TimeSpan lag = default(TimeSpan); RateLimitInfo info = default(RateLimitInfo); try { var response = await request.SendAsync().ConfigureAwait(false); - lag = DateTimeOffset.UtcNow - DateTimeOffset.Parse(response.Headers["Date"]); info = new RateLimitInfo(response.Headers); if (response.StatusCode < (HttpStatusCode)200 || response.StatusCode >= (HttpStatusCode)300) @@ -72,14 +70,14 @@ namespace Discord.Net.Queue #if DEBUG_LIMITS Debug.WriteLine($"[{id}] (!) 429 [Global]"); #endif - _queue.PauseGlobal(info, lag); + _queue.PauseGlobal(info); } else { #if DEBUG_LIMITS Debug.WriteLine($"[{id}] (!) 429"); #endif - UpdateRateLimit(id, request, info, lag, true); + UpdateRateLimit(id, request, info, true); } await _queue.RaiseRateLimitTriggered(Id, info).ConfigureAwait(false); continue; //Retry @@ -92,6 +90,7 @@ namespace Discord.Net.Queue continue; //Retry default: + int? code = null; string reason = null; if (response.Stream != null) { @@ -101,12 +100,13 @@ namespace Discord.Net.Queue using (var jsonReader = new JsonTextReader(reader)) { var json = JToken.Load(jsonReader); - reason = json.Value("message"); + try { code = json.Value("code"); } catch { }; + try { reason = json.Value("message"); } catch { }; } } catch { } } - throw new HttpException(response.StatusCode, reason); + throw new HttpException(response.StatusCode, code, reason); } } else @@ -142,7 +142,7 @@ namespace Discord.Net.Queue }*/ finally { - UpdateRateLimit(id, request, info, lag, false); + UpdateRateLimit(id, request, info, false); #if DEBUG_LIMITS Debug.WriteLine($"[{id}] Stop"); #endif @@ -214,7 +214,7 @@ namespace Discord.Net.Queue } } - private void UpdateRateLimit(int id, RestRequest request, RateLimitInfo info, TimeSpan lag, bool is429) + private void UpdateRateLimit(int id, RestRequest request, RateLimitInfo info, bool is429) { if (WindowCount == 0) return; @@ -250,10 +250,10 @@ namespace Discord.Net.Queue } else if (info.Reset.HasValue) { - resetTick = info.Reset.Value.AddSeconds(/*1.0 +*/ lag.TotalSeconds); + resetTick = info.Reset.Value.AddSeconds(info.Lag?.TotalSeconds ?? 1.0); int diff = (int)(resetTick.Value - DateTimeOffset.UtcNow).TotalMilliseconds; #if DEBUG_LIMITS - Debug.WriteLine($"[{id}] X-RateLimit-Reset: {info.Reset.Value.ToUnixTimeSeconds()} ({diff} ms, {lag.TotalMilliseconds} ms lag)"); + Debug.WriteLine($"[{id}] X-RateLimit-Reset: {info.Reset.Value.ToUnixTimeSeconds()} ({diff} ms, {info.Lag?.TotalMilliseconds} ms lag)"); #endif } else if (request.Options.IsClientBucket && request.Options.BucketId != null) diff --git a/src/Discord.Net.Rest/Net/RateLimitInfo.cs b/src/Discord.Net.Rest/Net/RateLimitInfo.cs index 5e87f664d..d8d168aec 100644 --- a/src/Discord.Net.Rest/Net/RateLimitInfo.cs +++ b/src/Discord.Net.Rest/Net/RateLimitInfo.cs @@ -10,6 +10,7 @@ namespace Discord.Net public int? Remaining { get; } public int? RetryAfter { get; } public DateTimeOffset? Reset { get; } + public TimeSpan? Lag { get; } internal RateLimitInfo(Dictionary headers) { @@ -17,8 +18,11 @@ namespace Discord.Net IsGlobal = headers.TryGetValue("X-RateLimit-Global", out temp) ? bool.Parse(temp) : false; Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) ? int.Parse(temp) : (int?)null; Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) ? int.Parse(temp) : (int?)null; - Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) ? DateTimeUtils.FromUnixSeconds(int.Parse(temp)) : (DateTimeOffset?)null; + Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) ? + DateTimeUtils.FromUnixSeconds(int.Parse(temp)) : (DateTimeOffset?)null; RetryAfter = headers.TryGetValue("Retry-After", out temp) ? int.Parse(temp) : (int?)null; + Lag = headers.TryGetValue("Date", out temp) ? + DateTimeOffset.UtcNow - DateTimeOffset.Parse(temp) : (TimeSpan?)null; } } }