From fad217e8bc1eb7596e91d3a0e95bfc824baedd8e Mon Sep 17 00:00:00 2001
From: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Date: Sat, 12 Feb 2022 06:51:36 -0400
Subject: [PATCH] Fix crosspost ratelimits (#2100)
---
src/Discord.Net.Rest/API/Common/Ratelimit.cs | 21 ++++++++++++++++
src/Discord.Net.Rest/Net/DefaultRestClient.cs | 2 +-
.../Net/Queue/RequestQueueBucket.cs | 1 +
src/Discord.Net.Rest/Net/RateLimitInfo.cs | 24 ++++++++++++++++++-
4 files changed, 46 insertions(+), 2 deletions(-)
create mode 100644 src/Discord.Net.Rest/API/Common/Ratelimit.cs
diff --git a/src/Discord.Net.Rest/API/Common/Ratelimit.cs b/src/Discord.Net.Rest/API/Common/Ratelimit.cs
new file mode 100644
index 000000000..a7320cbe1
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/Ratelimit.cs
@@ -0,0 +1,21 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API
+{
+ internal class Ratelimit
+ {
+ [JsonProperty("global")]
+ public bool Global { get; set; }
+
+ [JsonProperty("message")]
+ public string Message { get; set; }
+
+ [JsonProperty("retry_after")]
+ public double RetryAfter { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/Net/DefaultRestClient.cs b/src/Discord.Net.Rest/Net/DefaultRestClient.cs
index ce32b085b..721c7009d 100644
--- a/src/Discord.Net.Rest/Net/DefaultRestClient.cs
+++ b/src/Discord.Net.Rest/Net/DefaultRestClient.cs
@@ -149,7 +149,7 @@ namespace Discord.Net.Rest
HttpResponseMessage response = await _client.SendAsync(request, cancelToken).ConfigureAwait(false);
var headers = response.Headers.ToDictionary(x => x.Key, x => x.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
- var stream = !headerOnly ? await response.Content.ReadAsStreamAsync().ConfigureAwait(false) : null;
+ var stream = (!headerOnly || !response.IsSuccessStatusCode) ? await response.Content.ReadAsStreamAsync().ConfigureAwait(false) : null;
return new RestResponse(response.StatusCode, headers, stream);
}
diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
index 408c8bbdb..8130e6fac 100644
--- a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
+++ b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
@@ -75,6 +75,7 @@ namespace Discord.Net.Queue
switch (response.StatusCode)
{
case (HttpStatusCode)429:
+ info.ReadRatelimitPayload(response.Stream);
if (info.IsGlobal)
{
#if DEBUG_LIMITS
diff --git a/src/Discord.Net.Rest/Net/RateLimitInfo.cs b/src/Discord.Net.Rest/Net/RateLimitInfo.cs
index c08f30c7b..253343311 100644
--- a/src/Discord.Net.Rest/Net/RateLimitInfo.cs
+++ b/src/Discord.Net.Rest/Net/RateLimitInfo.cs
@@ -1,6 +1,10 @@
+using Discord.API;
+using Discord.Net.Rest;
+using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
namespace Discord.Net
{
@@ -25,7 +29,7 @@ namespace Discord.Net
public DateTimeOffset? Reset { get; }
///
- public TimeSpan? ResetAfter { get; }
+ public TimeSpan? ResetAfter { get; private set; }
///
public string Bucket { get; }
@@ -56,5 +60,23 @@ namespace Discord.Net
Lag = headers.TryGetValue("Date", out temp) &&
DateTimeOffset.TryParse(temp, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date) ? DateTimeOffset.UtcNow - date : (TimeSpan?)null;
}
+
+ internal void ReadRatelimitPayload(Stream response)
+ {
+ try
+ {
+ if (response != null && response.Length != 0)
+ {
+ using (TextReader text = new StreamReader(response))
+ using (JsonReader reader = new JsonTextReader(text))
+ {
+ var ratelimit = Discord.Rest.DiscordRestClient.Serializer.Deserialize(reader);
+
+ ResetAfter = TimeSpan.FromSeconds(ratelimit.RetryAfter);
+ }
+ }
+ }
+ catch { }
+ }
}
}