示例#1
0
        private async Task _handleTooManyRequests(RateLimitInfo ratelimit)
        {
            _log(LogLevel.WARN, "Got 429 Response, this should normally not happen");
            try
            {
                if (ratelimit.RetryAfter != null)
                {
                    await Bucket.SetTimeout(TimeSpan.FromMilliseconds((int)ratelimit.RetryAfter));

                    _log(LogLevel.DEBUG,
                         $"Timeout: {TimeSpan.FromMilliseconds((int) ratelimit.RetryAfter).TotalMilliseconds}");
                }

                if (ratelimit.IsGlobal && ratelimit.RetryAfter != null && Client.GlobalTimeout == null)
                {
                    await Bucket.SetGloballyLimited(TimeSpan.FromMilliseconds((int)ratelimit.RetryAfter));

                    _log(LogLevel.DEBUG,
                         $"Global Limited: {TimeSpan.FromMilliseconds((int) ratelimit.RetryAfter).TotalMilliseconds}");
                }

                Timeout = 100;
            }
            catch (Exception)
            {
                _log(LogLevel.WARN,
                     $"Could not update Ratelimit information, retrying in {TimeSpan.FromMilliseconds(Timeout).TotalSeconds} Seconds");
                Timeout *= 2;
                await Task.Delay(Timeout);
                await _handleTooManyRequests(ratelimit);
            }
        }
示例#2
0
        private async Task _handleHeaders(RateLimitInfo ratelimit)
        {
            _log(LogLevel.DEBUG, "Updating Bucket Ratelimit information");
            try
            {
                if (ratelimit.Remaining != null)
                {
                    await Bucket.SetRemaining((int)ratelimit.Remaining);

                    _log(LogLevel.DEBUG, $"Remaining: {ratelimit.Remaining}");
                }

                if (ratelimit.Limit != null)
                {
                    await Bucket.SetLimit((int)ratelimit.Limit);

                    _log(LogLevel.DEBUG, $"Limit: {ratelimit.Limit}");
                }

                if (ratelimit.Reset != null)
                {
                    await Bucket.SetTimeout(
                        TimeSpan.FromMilliseconds(((DateTimeOffset)ratelimit.Reset - DateTimeOffset.UtcNow)
                                                  .TotalMilliseconds));

                    _log(LogLevel.DEBUG,
                         $"Reset: {TimeSpan.FromMilliseconds(((DateTimeOffset) ratelimit.Reset - DateTimeOffset.UtcNow).TotalMilliseconds)}");
                }

                _log(LogLevel.DEBUG, "Updated Bucket Ratelimit information");
                Timeout = 100;
            }
            catch (Exception)
            {
                Timeout *= 2;
                _log(LogLevel.WARN,
                     $"Could not update Ratelimit information, retrying in {TimeSpan.FromMilliseconds(Timeout).TotalSeconds} Seconds");
                await Task.Delay(Timeout);
                await _handleHeaders(ratelimit);
            }
        }
示例#3
0
        /// <summary>
        ///     Executes this Request and Updates the Ratelimit information of the Bucket.
        /// </summary>
        /// <returns></returns>
        public async Task Execute()
        {
            HttpRequestMessage request;

            if (Method.Method == "GET")
            {
                Uri uri;
                try
                {
                    uri = new UriBuilder($"{APIEndpoints.APIBaseURL}{URL}")
                    {
                        Query = Content != null?await((FormUrlEncodedContent)Content).ReadAsStringAsync() : null
                    }.Uri;
                }
                catch (Exception e)
                {
                    Error?.Invoke(this, e);
                    return;
                }

                request = new HttpRequestMessage(Method, uri);
            }
            else
            {
                request = new HttpRequestMessage(Method, URL)
                {
                    Content = Content
                };
            }

            if (Reason != null)
            {
                request.Headers.Add("X-Audit-Log-Reason", HttpUtility.UrlEncode(Reason));
            }

            HttpResponseMessage res;

            try
            {
                _log(LogLevel.DEBUG, "Sending Request...");
                res = await Client.HttpClient.SendAsync(request);

                _log(LogLevel.DEBUG, $"Received Response {res.StatusCode}");
            }
            catch (Exception e)
            {
                Error?.Invoke(this, e);
                return;
            }

            var ratelimit = new RateLimitInfo(res.Headers.ToDictionary(a => a.Key, a => a.Value.First()));

            _log(LogLevel.DEBUG,
                 $"Created Ratelimit Info:\nLag: {ratelimit.Lag.TotalSeconds} Seconds\nLimit: {ratelimit.Limit}\nRemaining: {ratelimit.Remaining}\nReset: {ratelimit.Reset}\nGlobal Ratelimited: {ratelimit.IsGlobal}\nRetry-After: {ratelimit.RetryAfter}");

            var statusCode = (int)res.StatusCode;

            string content;

            try
            {
                content = await res.Content.ReadAsStringAsync();

                _log(LogLevel.DEBUG, "Parsed Content");
            }
            catch (Exception e)
            {
                Error?.Invoke(this, e);
                return;
            }

            if (ratelimit.Limit != null && ratelimit.Remaining != null)
            {
                await _handleHeaders(ratelimit);
            }

            if (res.StatusCode == HttpStatusCode.TooManyRequests)
            {
                await _handleTooManyRequests(ratelimit);

                Bucket.Enqueue(this);
            }
            else if (statusCode >= 500 && statusCode < 600)
            {
                _internalServerError();
            }
            else if (!res.IsSuccessStatusCode)
            {
                var error = JsonConvert.DeserializeObject <DiscordAPIErrorResponse>(content);
                Error?.Invoke(this, new DiscordAPIException(statusCode, error.Code, error.Message));
            }
            else
            {
                Success?.Invoke(this, content);
            }
        }