diff --git a/src/Discord.Net.Core/Discord.Net.Core.xml b/src/Discord.Net.Core/Discord.Net.Core.xml index 24ced574c..fa2c894cb 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! @@ -5029,6 +5028,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 @@ -5735,6 +5742,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 . @@ -11802,6 +11817,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. @@ -11859,6 +11924,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 6e4d93991..db5b2d29b 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) &&