private async Task<RatelimitBucket> GetBucketFromEndpointAsync( string endpoint, CancellationToken token = default) { _logger.Log(LogLevel.Debug, "Retrieving rate-limit bucket for [{Endpoint}]", endpoint); if (_ratelimits.TryGetValue(endpoint, out var bucket) && !bucket.HasExpired && bucket.Remaining <= 0) { _logger.Log(LogLevel.Warning, "Pre-emptive rate-limit bucket hit for [{Endpoint}]: [{Amount}/{Limit}]", endpoint, bucket.Limit - bucket.Remaining, bucket.Limit); if (!_configuration.ThrowOnRateLimits) { await Task.Delay(bucket.ExpiresIn, token).ConfigureAwait(false); } else { throw new PreemptiveRateLimitException(bucket.ExpiresIn); } } else if (bucket == null) { bucket = new RatelimitBucket(); _ratelimits.TryRemove(endpoint, out _); _ratelimits.TryAdd(endpoint, bucket); } return bucket; }
private void UpdateBucket( string endpoint, RatelimitBucket bucket, HttpResponseMessage response) { bucket.Limit = response.Headers.TryGetValues("X-RateLimit-Limit", out var limitHeaders) ? int.Parse(limitHeaders.First()) : 1200; bucket.Remaining = response.Headers.TryGetValues("X-RateLimit-Remaining", out var remainingHeaders) ? int.Parse(remainingHeaders.First()) : bucket.Remaining - 1; if (bucket.HasExpired) { bucket.CreatedAt = DateTimeOffset.Now; } _logger.Log(LogLevel.Debug, "Rate-limit bucket passed for [{Endpoint}]: [{Amount}/{Limit}] (Expires In {Timespan})", endpoint, bucket.Limit - bucket.Remaining, bucket.Limit, bucket.ExpiresIn.ToString("g")); }