diff --git a/src/Discord.Net.Core/Discord.Net.Core.xml b/src/Discord.Net.Core/Discord.Net.Core.xml
index 99148bace..c254ad31f 100644
--- a/src/Discord.Net.Core/Discord.Net.Core.xml
+++ b/src/Discord.Net.Core/Discord.Net.Core.xml
@@ -2504,9 +2504,8 @@
An emoji.
- Parse an from its raw format.
- The raw encoding of an emoji. For example: :heart: or ❤
- An emoji.
+ Parse an from its raw format.
+ The raw encoding of an emoji. For example: :heart: or ❤
String is not emoji or unicode!
@@ -5040,6 +5039,14 @@
Whether this button is disabled or not.
+
+
+ Turns this button into a button builder.
+
+
+ A newly created button builder with the same properties as this button.
+
+
Represents different styles to use with buttons. You can see an example of the different styles at
@@ -5746,6 +5753,14 @@
Whether this menu is disabled or not.
+
+
+ Turns this select menu into a builder.
+
+
+ A newly create builder with the same properties as this select menu.
+
+
Represents a choice for a .
@@ -11813,6 +11828,56 @@
and an optional reason.
+
+
+ Represents a generic ratelimit info.
+
+
+
+
+ Gets whether or not this ratelimit info is global.
+
+
+
+
+ Gets the number of requests that can be made.
+
+
+
+
+ Gets the number of remaining requests that can be made.
+
+
+
+
+ Gets the total time (in seconds) of when the current rate limit bucket will reset. Can have decimals to match previous millisecond ratelimit precision
+
+
+
+
+ Gets the at which the rate limit resets
+
+
+
+
+ Gets the absolute time when this ratelimit resets.
+
+
+
+
+ Gets a unique string denoting the rate limit being encountered (non-inclusive of major parameters in the route path).
+
+
+
+
+ Gets the amount of lag for the request. This is used to denote the precise time of when the ratelimit expires.
+
+
+
+
+ Gets the endpoint that this ratelimit info came from.
+
+
Represents options that should be used when sending a request.
@@ -11870,6 +11935,11 @@
hosting system is known to have a desynced clock.
+
+
+ Gets or sets the callback to execute regarding ratelimits for this request.
+
+
Initializes a new class with the default request timeout set in
diff --git a/src/Discord.Net.Core/Net/Rest/IRateLimitInfo.cs b/src/Discord.Net.Core/Net/Rest/IRateLimitInfo.cs
new file mode 100644
index 000000000..00d446b10
--- /dev/null
+++ b/src/Discord.Net.Core/Net/Rest/IRateLimitInfo.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents a generic ratelimit info.
+ ///
+ public interface IRateLimitInfo
+ {
+ ///
+ /// Gets whether or not this ratelimit info is global.
+ ///
+ bool IsGlobal { get; }
+
+ ///
+ /// Gets the number of requests that can be made.
+ ///
+ int? Limit { get; }
+
+ ///
+ /// Gets the number of remaining requests that can be made.
+ ///
+ int? Remaining { get; }
+
+ ///
+ /// Gets the total time (in seconds) of when the current rate limit bucket will reset. Can have decimals to match previous millisecond ratelimit precision
+ ///
+ int? RetryAfter { get; }
+
+ ///
+ /// Gets the at which the rate limit resets
+ ///
+ DateTimeOffset? Reset { get; }
+
+ ///
+ /// Gets the absolute time when this ratelimit resets.
+ ///
+ TimeSpan? ResetAfter { get; }
+
+ ///
+ /// Gets a unique string denoting the rate limit being encountered (non-inclusive of major parameters in the route path).
+ ///
+ string Bucket { get; }
+
+ ///
+ /// Gets the amount of lag for the request. This is used to denote the precise time of when the ratelimit expires.
+ ///
+ TimeSpan? Lag { get; }
+
+ ///
+ /// Gets the endpoint that this ratelimit info came from.
+ ///
+ string Endpoint { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/RequestOptions.cs b/src/Discord.Net.Core/RequestOptions.cs
index dbb240273..101925ab2 100644
--- a/src/Discord.Net.Core/RequestOptions.cs
+++ b/src/Discord.Net.Core/RequestOptions.cs
@@ -1,5 +1,7 @@
using Discord.Net;
+using System;
using System.Threading;
+using System.Threading.Tasks;
namespace Discord
{
@@ -57,6 +59,11 @@ namespace Discord
///
public bool? UseSystemClock { get; set; }
+ ///
+ /// Gets or sets the callback to execute regarding ratelimits for this request.
+ ///
+ public Func RatelimitCallback { get; set; }
+
internal bool IgnoreState { get; set; }
internal BucketId BucketId { get; set; }
internal bool IsClientBucket { get; set; }
@@ -71,6 +78,17 @@ namespace Discord
return options.Clone();
}
+ internal void ExecuteRatelimitCallback(IRateLimitInfo info)
+ {
+ if (RatelimitCallback != null)
+ {
+ _ = Task.Run(async () =>
+ {
+ await RatelimitCallback(info);
+ });
+ }
+ }
+
///
/// Initializes a new class with the default request timeout set in
/// .
diff --git a/src/Discord.Net.Rest/Discord.Net.Rest.xml b/src/Discord.Net.Rest/Discord.Net.Rest.xml
index 9ffed332c..92a1734af 100644
--- a/src/Discord.Net.Rest/Discord.Net.Rest.xml
+++ b/src/Discord.Net.Rest/Discord.Net.Rest.xml
@@ -149,6 +149,38 @@
Cannot read from image.
+
+
+ Represents a REST-Based ratelimit info.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Gets the login state of the client.
diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
index d986f5c37..d2a7cabee 100644
--- a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
+++ b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
@@ -65,7 +65,9 @@ namespace Discord.Net.Queue
try
{
var response = await request.SendAsync().ConfigureAwait(false);
- info = new RateLimitInfo(response.Headers);
+ info = new RateLimitInfo(response.Headers, request.Endpoint);
+
+ request.Options.ExecuteRatelimitCallback(info);
if (response.StatusCode < (HttpStatusCode)200 || response.StatusCode >= (HttpStatusCode)300)
{
diff --git a/src/Discord.Net.Rest/Net/RateLimitInfo.cs b/src/Discord.Net.Rest/Net/RateLimitInfo.cs
index 6a7df7b01..2fe845f3c 100644
--- a/src/Discord.Net.Rest/Net/RateLimitInfo.cs
+++ b/src/Discord.Net.Rest/Net/RateLimitInfo.cs
@@ -4,19 +4,42 @@ using System.Globalization;
namespace Discord.Net
{
- internal struct RateLimitInfo
+ ///
+ /// Represents a REST-Based ratelimit info.
+ ///
+ public struct RateLimitInfo : IRateLimitInfo
{
+ ///
public bool IsGlobal { get; }
+
+ ///
public int? Limit { get; }
+
+ ///
public int? Remaining { get; }
+
+ ///
public int? RetryAfter { get; }
+
+ ///
public DateTimeOffset? Reset { get; }
+
+ ///
public TimeSpan? ResetAfter { get; }
+
+ ///
public string Bucket { get; }
+
+ ///
public TimeSpan? Lag { get; }
- internal RateLimitInfo(Dictionary headers)
+ ///
+ public string Endpoint { get; }
+
+ internal RateLimitInfo(Dictionary headers, string endpoint)
{
+ Endpoint = endpoint;
+
IsGlobal = headers.TryGetValue("X-RateLimit-Global", out string temp) &&
bool.TryParse(temp, out var isGlobal) && isGlobal;
Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) &&