feature: Add support for setting X-RateLimit-Precision (#1354)
* support X-RateLimit-Reset sending integer or float values This changes the way that the X-RateLimit-Request header is parsed, so that it will work with both integer seconds and float values with seconds and milliseconds * Add RateLimitPrecision enum, set X-RateLimit-Precision Adds the RateLimitPrecision enum, with Second and Millisecond values. (Do we want to use an extension method to convert it into a string, or is ToString().ToLower() fine?) Adds RateLimitPrecision as a parameter to DiscordRestApiClient, and to DiscordConfig so that it can set the X-RateLimit-Precision header.
This commit is contained in:
committed by
Christopher F
parent
07f4d5f353
commit
9482204bcf
@@ -36,7 +36,7 @@ namespace Discord
|
|||||||
typeof(DiscordConfig).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ??
|
typeof(DiscordConfig).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ??
|
||||||
typeof(DiscordConfig).GetTypeInfo().Assembly.GetName().Version.ToString(3) ??
|
typeof(DiscordConfig).GetTypeInfo().Assembly.GetName().Version.ToString(3) ??
|
||||||
"Unknown";
|
"Unknown";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user agent that Discord.Net uses in its clients.
|
/// Gets the user agent that Discord.Net uses in its clients.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -123,7 +123,7 @@ namespace Discord
|
|||||||
/// The currently set <see cref="RetryMode"/>.
|
/// The currently set <see cref="RetryMode"/>.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public RetryMode DefaultRetryMode { get; set; } = RetryMode.AlwaysRetry;
|
public RetryMode DefaultRetryMode { get; set; } = RetryMode.AlwaysRetry;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the minimum log level severity that will be sent to the Log event.
|
/// Gets or sets the minimum log level severity that will be sent to the Log event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -140,5 +140,17 @@ namespace Discord
|
|||||||
/// the API version it uses on startup.
|
/// the API version it uses on startup.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
internal bool DisplayInitialLog { get; set; } = true;
|
internal bool DisplayInitialLog { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the level of precision of the rate limit reset response.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If set to <see cref="RateLimitPrecision.Second"/>, this value will be rounded up to the
|
||||||
|
/// nearest second.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>
|
||||||
|
/// The currently set <see cref="RateLimitPrecision"/>.
|
||||||
|
/// </returns>
|
||||||
|
public RateLimitPrecision RateLimitPrecision { get; set; } = RateLimitPrecision.Second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/Discord.Net.Core/RateLimitPrecision.cs
Normal file
18
src/Discord.Net.Core/RateLimitPrecision.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Discord
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the level of precision to request in the rate limit
|
||||||
|
/// response header.
|
||||||
|
/// </summary>
|
||||||
|
public enum RateLimitPrecision
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies precision rounded up to the nearest whole second
|
||||||
|
/// </summary>
|
||||||
|
Second,
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies precision rounded to the nearest millisecond.
|
||||||
|
/// </summary>
|
||||||
|
Millisecond
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,17 +45,19 @@ namespace Discord.API
|
|||||||
internal string AuthToken { get; private set; }
|
internal string AuthToken { get; private set; }
|
||||||
internal IRestClient RestClient { get; private set; }
|
internal IRestClient RestClient { get; private set; }
|
||||||
internal ulong? CurrentUserId { get; set; }
|
internal ulong? CurrentUserId { get; set; }
|
||||||
|
public RateLimitPrecision RateLimitPrecision { get; private set; }
|
||||||
|
|
||||||
internal JsonSerializer Serializer => _serializer;
|
internal JsonSerializer Serializer => _serializer;
|
||||||
|
|
||||||
/// <exception cref="ArgumentException">Unknown OAuth token type.</exception>
|
/// <exception cref="ArgumentException">Unknown OAuth token type.</exception>
|
||||||
public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, RetryMode defaultRetryMode = RetryMode.AlwaysRetry,
|
public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, RetryMode defaultRetryMode = RetryMode.AlwaysRetry,
|
||||||
JsonSerializer serializer = null)
|
JsonSerializer serializer = null, RateLimitPrecision rateLimitPrecision = RateLimitPrecision.Second)
|
||||||
{
|
{
|
||||||
_restClientProvider = restClientProvider;
|
_restClientProvider = restClientProvider;
|
||||||
UserAgent = userAgent;
|
UserAgent = userAgent;
|
||||||
DefaultRetryMode = defaultRetryMode;
|
DefaultRetryMode = defaultRetryMode;
|
||||||
_serializer = serializer ?? new JsonSerializer { ContractResolver = new DiscordContractResolver() };
|
_serializer = serializer ?? new JsonSerializer { ContractResolver = new DiscordContractResolver() };
|
||||||
|
RateLimitPrecision = rateLimitPrecision;
|
||||||
|
|
||||||
RequestQueue = new RequestQueue();
|
RequestQueue = new RequestQueue();
|
||||||
_stateLock = new SemaphoreSlim(1, 1);
|
_stateLock = new SemaphoreSlim(1, 1);
|
||||||
@@ -71,6 +73,7 @@ namespace Discord.API
|
|||||||
RestClient.SetHeader("accept", "*/*");
|
RestClient.SetHeader("accept", "*/*");
|
||||||
RestClient.SetHeader("user-agent", UserAgent);
|
RestClient.SetHeader("user-agent", UserAgent);
|
||||||
RestClient.SetHeader("authorization", GetPrefixedToken(AuthTokenType, AuthToken));
|
RestClient.SetHeader("authorization", GetPrefixedToken(AuthTokenType, AuthToken));
|
||||||
|
RestClient.SetHeader("X-RateLimit-Precision", RateLimitPrecision.ToString().ToLower());
|
||||||
}
|
}
|
||||||
/// <exception cref="ArgumentException">Unknown OAuth token type.</exception>
|
/// <exception cref="ArgumentException">Unknown OAuth token type.</exception>
|
||||||
internal static string GetPrefixedToken(TokenType tokenType, string token)
|
internal static string GetPrefixedToken(TokenType tokenType, string token)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Discord.Net
|
|||||||
Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) &&
|
Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) &&
|
||||||
int.TryParse(temp, out var remaining) ? remaining : (int?)null;
|
int.TryParse(temp, out var remaining) ? remaining : (int?)null;
|
||||||
Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) &&
|
Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) &&
|
||||||
int.TryParse(temp, out var reset) ? DateTimeOffset.FromUnixTimeSeconds(reset) : (DateTimeOffset?)null;
|
float.TryParse(temp, out var reset) ? DateTimeOffset.FromUnixTimeMilliseconds((long)(reset * 1000)) : (DateTimeOffset?)null;
|
||||||
RetryAfter = headers.TryGetValue("Retry-After", out temp) &&
|
RetryAfter = headers.TryGetValue("Retry-After", out temp) &&
|
||||||
int.TryParse(temp, out var retryAfter) ? retryAfter : (int?)null;
|
int.TryParse(temp, out var retryAfter) ? retryAfter : (int?)null;
|
||||||
Lag = headers.TryGetValue("Date", out temp) &&
|
Lag = headers.TryGetValue("Date", out temp) &&
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ namespace Discord.WebSocket
|
|||||||
internal BaseSocketClient(DiscordSocketConfig config, DiscordRestApiClient client)
|
internal BaseSocketClient(DiscordSocketConfig config, DiscordRestApiClient client)
|
||||||
: base(config, client) => BaseConfig = config;
|
: base(config, client) => BaseConfig = config;
|
||||||
private static DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config)
|
private static DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config)
|
||||||
=> new DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent);
|
=> new DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent,
|
||||||
|
rateLimitPrecision: config.RateLimitPrecision);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Discord application information for the logged-in user.
|
/// Gets a Discord application information for the logged-in user.
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ namespace Discord.WebSocket
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static API.DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config)
|
private static API.DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config)
|
||||||
=> new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent);
|
=> new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent,
|
||||||
|
rateLimitPrecision: config.RateLimitPrecision);
|
||||||
|
|
||||||
internal override async Task OnLoginAsync(TokenType tokenType, string token)
|
internal override async Task OnLoginAsync(TokenType tokenType, string token)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,8 +38,9 @@ namespace Discord.API
|
|||||||
public ConnectionState ConnectionState { get; private set; }
|
public ConnectionState ConnectionState { get; private set; }
|
||||||
|
|
||||||
public DiscordSocketApiClient(RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, string userAgent,
|
public DiscordSocketApiClient(RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, string userAgent,
|
||||||
string url = null, RetryMode defaultRetryMode = RetryMode.AlwaysRetry, JsonSerializer serializer = null)
|
string url = null, RetryMode defaultRetryMode = RetryMode.AlwaysRetry, JsonSerializer serializer = null,
|
||||||
: base(restClientProvider, userAgent, defaultRetryMode, serializer)
|
RateLimitPrecision rateLimitPrecision = RateLimitPrecision.Second)
|
||||||
|
: base(restClientProvider, userAgent, defaultRetryMode, serializer, rateLimitPrecision)
|
||||||
{
|
{
|
||||||
_gatewayUrl = url;
|
_gatewayUrl = url;
|
||||||
if (url != null)
|
if (url != null)
|
||||||
|
|||||||
@@ -176,7 +176,8 @@ namespace Discord.WebSocket
|
|||||||
_largeGuilds = new ConcurrentQueue<ulong>();
|
_largeGuilds = new ConcurrentQueue<ulong>();
|
||||||
}
|
}
|
||||||
private static API.DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config)
|
private static API.DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config)
|
||||||
=> new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config.GatewayHost);
|
=> new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config.GatewayHost,
|
||||||
|
rateLimitPrecision: config.RateLimitPrecision);
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
internal override void Dispose(bool disposing)
|
internal override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user