Browse Source

Merge branch 'feature/ratelimit-callbacks' into release/3.x

pull/1923/head
quin lynch 3 years ago
parent
commit
774e9d3c64
6 changed files with 210 additions and 6 deletions
  1. +73
    -3
      src/Discord.Net.Core/Discord.Net.Core.xml
  2. +59
    -0
      src/Discord.Net.Core/Net/Rest/IRateLimitInfo.cs
  3. +18
    -0
      src/Discord.Net.Core/RequestOptions.cs
  4. +32
    -0
      src/Discord.Net.Rest/Discord.Net.Rest.xml
  5. +3
    -1
      src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
  6. +25
    -2
      src/Discord.Net.Rest/Net/RateLimitInfo.cs

+ 73
- 3
src/Discord.Net.Core/Discord.Net.Core.xml View File

@@ -2504,9 +2504,8 @@
<param name="result">An emoji.</param>
</member>
<member name="M:Discord.Emoji.Parse(System.String)">
<summary> Parse an <see cref="T:Discord.Emoji"/> from its raw format. </summary>
<param name="text">The raw encoding of an emoji. For example: <c>:heart: or ❤</c></param>
<param name="result">An emoji.</param>
<summary> Parse an <see cref="T:Discord.Emoji"/> from its raw format.</summary>
<param name="emojiStr">The raw encoding of an emoji. For example: <c>:heart: or ❤</c></param>
<exception cref="T:System.FormatException">String is not emoji or unicode!</exception>
</member>
<member name="M:Discord.Emoji.GetHashCode">
@@ -5040,6 +5039,14 @@
Whether this button is disabled or not.
</summary>
</member>
<member name="M:Discord.ButtonComponent.ToBuilder">
<summary>
Turns this button into a button builder.
</summary>
<returns>
A newly created button builder with the same properties as this button.
</returns>
</member>
<member name="T:Discord.ButtonStyle">
<summary>
Represents different styles to use with buttons. You can see an example of the different styles at <see href="https://discord.com/developers/docs/interactions/message-components#buttons-button-styles"/>
@@ -5746,6 +5753,14 @@
Whether this menu is disabled or not.
</summary>
</member>
<member name="M:Discord.SelectMenu.ToBuilder">
<summary>
Turns this select menu into a builder.
</summary>
<returns>
A newly create builder with the same properties as this select menu.
</returns>
</member>
<member name="T:Discord.SelectMenuOption">
<summary>
Represents a choice for a <see cref="T:Discord.SelectMenu"/>.
@@ -11813,6 +11828,56 @@
and an optional reason.
</summary>
</member>
<member name="T:Discord.IRateLimitInfo">
<summary>
Represents a generic ratelimit info.
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.IsGlobal">
<summary>
Gets whether or not this ratelimit info is global.
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.Limit">
<summary>
Gets the number of requests that can be made.
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.Remaining">
<summary>
Gets the number of remaining requests that can be made.
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.RetryAfter">
<summary>
Gets the total time (in seconds) of when the current rate limit bucket will reset. Can have decimals to match previous millisecond ratelimit precision
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.Reset">
<summary>
Gets the <see cref="T:System.DateTimeOffset"/> at which the rate limit resets
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.ResetAfter">
<summary>
Gets the absolute time when this ratelimit resets.
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.Bucket">
<summary>
Gets a unique string denoting the rate limit being encountered (non-inclusive of major parameters in the route path).
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.Lag">
<summary>
Gets the amount of lag for the request. This is used to denote the precise time of when the ratelimit expires.
</summary>
</member>
<member name="P:Discord.IRateLimitInfo.Endpoint">
<summary>
Gets the endpoint that this ratelimit info came from.
</summary>
</member>
<member name="T:Discord.RequestOptions">
<summary>
Represents options that should be used when sending a request.
@@ -11870,6 +11935,11 @@
hosting system is known to have a desynced clock.
</remarks>
</member>
<member name="P:Discord.RequestOptions.RatelimitCallback">
<summary>
Gets or sets the callback to execute regarding ratelimits for this request.
</summary>
</member>
<member name="M:Discord.RequestOptions.#ctor">
<summary>
Initializes a new <see cref="T:Discord.RequestOptions" /> class with the default request timeout set in


+ 59
- 0
src/Discord.Net.Core/Net/Rest/IRateLimitInfo.cs View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// Represents a generic ratelimit info.
/// </summary>
public interface IRateLimitInfo
{
/// <summary>
/// Gets whether or not this ratelimit info is global.
/// </summary>
bool IsGlobal { get; }

/// <summary>
/// Gets the number of requests that can be made.
/// </summary>
int? Limit { get; }

/// <summary>
/// Gets the number of remaining requests that can be made.
/// </summary>
int? Remaining { get; }

/// <summary>
/// Gets the total time (in seconds) of when the current rate limit bucket will reset. Can have decimals to match previous millisecond ratelimit precision
/// </summary>
int? RetryAfter { get; }

/// <summary>
/// Gets the <see cref="DateTimeOffset"/> at which the rate limit resets
/// </summary>
DateTimeOffset? Reset { get; }

/// <summary>
/// Gets the absolute time when this ratelimit resets.
/// </summary>
TimeSpan? ResetAfter { get; }

/// <summary>
/// Gets a unique string denoting the rate limit being encountered (non-inclusive of major parameters in the route path).
/// </summary>
string Bucket { get; }

/// <summary>
/// Gets the amount of lag for the request. This is used to denote the precise time of when the ratelimit expires.
/// </summary>
TimeSpan? Lag { get; }

/// <summary>
/// Gets the endpoint that this ratelimit info came from.
/// </summary>
string Endpoint { get; }
}
}

+ 18
- 0
src/Discord.Net.Core/RequestOptions.cs View File

@@ -1,5 +1,7 @@
using Discord.Net;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Discord
{
@@ -57,6 +59,11 @@ namespace Discord
/// </remarks>
public bool? UseSystemClock { get; set; }

/// <summary>
/// Gets or sets the callback to execute regarding ratelimits for this request.
/// </summary>
public Func<IRateLimitInfo, Task> 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);
});
}
}

/// <summary>
/// Initializes a new <see cref="RequestOptions" /> class with the default request timeout set in
/// <see cref="DiscordConfig"/>.


+ 32
- 0
src/Discord.Net.Rest/Discord.Net.Rest.xml View File

@@ -149,6 +149,38 @@
<member name="M:Discord.Net.Converters.ImageConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,System.Object,Newtonsoft.Json.JsonSerializer)">
<exception cref="T:System.InvalidOperationException">Cannot read from image.</exception>
</member>
<member name="T:Discord.Net.RateLimitInfo">
<summary>
Represents a REST-Based ratelimit info.
</summary>
</member>
<member name="P:Discord.Net.RateLimitInfo.IsGlobal">
<inheritdoc/>
</member>
<member name="P:Discord.Net.RateLimitInfo.Limit">
<inheritdoc/>
</member>
<member name="P:Discord.Net.RateLimitInfo.Remaining">
<inheritdoc/>
</member>
<member name="P:Discord.Net.RateLimitInfo.RetryAfter">
<inheritdoc/>
</member>
<member name="P:Discord.Net.RateLimitInfo.Reset">
<inheritdoc/>
</member>
<member name="P:Discord.Net.RateLimitInfo.ResetAfter">
<inheritdoc/>
</member>
<member name="P:Discord.Net.RateLimitInfo.Bucket">
<inheritdoc/>
</member>
<member name="P:Discord.Net.RateLimitInfo.Lag">
<inheritdoc/>
</member>
<member name="P:Discord.Net.RateLimitInfo.Endpoint">
<inheritdoc/>
</member>
<member name="P:Discord.Rest.BaseDiscordClient.LoginState">
<summary>
Gets the login state of the client.


+ 3
- 1
src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs View File

@@ -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)
{


+ 25
- 2
src/Discord.Net.Rest/Net/RateLimitInfo.cs View File

@@ -4,19 +4,42 @@ using System.Globalization;

namespace Discord.Net
{
internal struct RateLimitInfo
/// <summary>
/// Represents a REST-Based ratelimit info.
/// </summary>
public struct RateLimitInfo : IRateLimitInfo
{
/// <inheritdoc/>
public bool IsGlobal { get; }

/// <inheritdoc/>
public int? Limit { get; }

/// <inheritdoc/>
public int? Remaining { get; }

/// <inheritdoc/>
public int? RetryAfter { get; }

/// <inheritdoc/>
public DateTimeOffset? Reset { get; }

/// <inheritdoc/>
public TimeSpan? ResetAfter { get; }

/// <inheritdoc/>
public string Bucket { get; }

/// <inheritdoc/>
public TimeSpan? Lag { get; }

internal RateLimitInfo(Dictionary<string, string> headers)
/// <inheritdoc/>
public string Endpoint { get; }

internal RateLimitInfo(Dictionary<string, string> 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) &&


Loading…
Cancel
Save