mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-14 18:43:31 +01:00
refactor: use eslint-config-neon for packages. (#8579)
Co-authored-by: Noel <buechler.noel@outlook.com>
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
import { setTimeout, clearTimeout } from 'node:timers';
|
||||
import { setTimeout as sleep } from 'node:timers/promises';
|
||||
import { AsyncQueue } from '@sapphire/async-queue';
|
||||
import { request, type Dispatcher } from 'undici';
|
||||
import type { IHandler } from './IHandler';
|
||||
import type { RateLimitData, RequestOptions } from '../REST';
|
||||
import type { HandlerRequestData, RequestManager, RouteData } from '../RequestManager';
|
||||
import { DiscordAPIError, DiscordErrorData, OAuthErrorData } from '../errors/DiscordAPIError';
|
||||
import { HTTPError } from '../errors/HTTPError';
|
||||
import { RateLimitError } from '../errors/RateLimitError';
|
||||
import { RESTEvents } from '../utils/constants';
|
||||
import { hasSublimit, parseHeader, parseResponse } from '../utils/utils';
|
||||
import { DiscordAPIError, type DiscordErrorData, type OAuthErrorData } from '../errors/DiscordAPIError.js';
|
||||
import { HTTPError } from '../errors/HTTPError.js';
|
||||
import { RateLimitError } from '../errors/RateLimitError.js';
|
||||
import { RESTEvents } from '../utils/constants.js';
|
||||
import { hasSublimit, parseHeader, parseResponse } from '../utils/utils.js';
|
||||
import type { IHandler } from './IHandler.js';
|
||||
|
||||
/**
|
||||
* Invalid request limiting is done on a per-IP basis, not a per-token basis.
|
||||
@@ -47,7 +48,7 @@ export class SequentialHandler implements IHandler {
|
||||
/**
|
||||
* The total number of requests that can be made before we are rate limited
|
||||
*/
|
||||
private limit = Infinity;
|
||||
private limit = Number.POSITIVE_INFINITY;
|
||||
|
||||
/**
|
||||
* The interface used to sequence async requests sequentially
|
||||
@@ -65,7 +66,7 @@ export class SequentialHandler implements IHandler {
|
||||
* A promise wrapper for when the sublimited queue is finished being processed or null when not being processed
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
|
||||
#sublimitPromise: { promise: Promise<void>; resolve: () => void } | null = null;
|
||||
#sublimitPromise: { promise: Promise<void>; resolve(): void } | null = null;
|
||||
|
||||
/**
|
||||
* Whether the sublimit queue needs to be shifted in the finally block
|
||||
@@ -176,6 +177,7 @@ export class SequentialHandler implements IHandler {
|
||||
queue = this.#sublimitedQueue!;
|
||||
queueType = QueueType.Sublimit;
|
||||
}
|
||||
|
||||
// Wait for any previous requests to be completed before this one is run
|
||||
await queue.wait();
|
||||
// This set handles retroactively sublimiting requests
|
||||
@@ -194,6 +196,7 @@ export class SequentialHandler implements IHandler {
|
||||
await this.#sublimitPromise.promise;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Make the request, and return the results
|
||||
return await this.runRequest(routeId, url, options, requestData);
|
||||
@@ -204,6 +207,7 @@ export class SequentialHandler implements IHandler {
|
||||
this.#shiftSublimit = false;
|
||||
this.#sublimitedQueue?.shift();
|
||||
}
|
||||
|
||||
// If this request is the last request in a sublimit
|
||||
if (this.#sublimitedQueue?.remaining === 0) {
|
||||
this.#sublimitPromise?.resolve();
|
||||
@@ -247,6 +251,7 @@ export class SequentialHandler implements IHandler {
|
||||
// The global delay function clears the global delay state when it is resolved
|
||||
this.manager.globalDelay = this.globalDelayFor(timeout);
|
||||
}
|
||||
|
||||
delay = this.manager.globalDelay;
|
||||
} else {
|
||||
// Set RateLimitData based on the route-specific limit
|
||||
@@ -254,6 +259,7 @@ export class SequentialHandler implements IHandler {
|
||||
timeout = this.timeToReset;
|
||||
delay = sleep(timeout);
|
||||
}
|
||||
|
||||
const rateLimitData: RateLimitData = {
|
||||
timeToReset: timeout,
|
||||
limit,
|
||||
@@ -274,14 +280,17 @@ export class SequentialHandler implements IHandler {
|
||||
} else {
|
||||
this.debug(`Waiting ${timeout}ms for rate limit to pass`);
|
||||
}
|
||||
|
||||
// Wait the remaining time left before the rate limit resets
|
||||
await delay;
|
||||
}
|
||||
|
||||
// As the request goes out, update the global usage information
|
||||
if (!this.manager.globalReset || this.manager.globalReset < Date.now()) {
|
||||
this.manager.globalReset = Date.now() + 1000;
|
||||
this.manager.globalReset = Date.now() + 1_000;
|
||||
this.manager.globalRemaining = this.manager.options.globalRequestsPerSecond;
|
||||
}
|
||||
|
||||
this.manager.globalRemaining--;
|
||||
|
||||
const method = options.method ?? 'get';
|
||||
@@ -295,6 +304,7 @@ export class SequentialHandler implements IHandler {
|
||||
} catch (error: unknown) {
|
||||
// Retry the specified number of times for possible timed out requests
|
||||
if (error instanceof Error && error.name === 'AbortError' && retries !== this.manager.options.retries) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
return await this.runRequest(routeId, url, options, requestData, ++retries);
|
||||
}
|
||||
|
||||
@@ -328,14 +338,14 @@ export class SequentialHandler implements IHandler {
|
||||
const retry = parseHeader(res.headers['retry-after']);
|
||||
|
||||
// Update the total number of requests that can be made before the rate limit resets
|
||||
this.limit = limit ? Number(limit) : Infinity;
|
||||
this.limit = limit ? Number(limit) : Number.POSITIVE_INFINITY;
|
||||
// Update the number of remaining requests that can be made before the rate limit resets
|
||||
this.remaining = remaining ? Number(remaining) : 1;
|
||||
// Update the time when this rate limit resets (reset-after is in seconds)
|
||||
this.reset = reset ? Number(reset) * 1000 + Date.now() + this.manager.options.offset : Date.now();
|
||||
this.reset = reset ? Number(reset) * 1_000 + Date.now() + this.manager.options.offset : Date.now();
|
||||
|
||||
// Amount of time in milliseconds until we should retry if rate limited (globally or otherwise)
|
||||
if (retry) retryAfter = Number(retry) * 1000 + this.manager.options.offset;
|
||||
if (retry) retryAfter = Number(retry) * 1_000 + this.manager.options.offset;
|
||||
|
||||
// Handle buckets via the hash header retroactively
|
||||
if (hash && hash !== this.hash) {
|
||||
@@ -373,9 +383,10 @@ export class SequentialHandler implements IHandler {
|
||||
// Count the invalid requests
|
||||
if (status === 401 || status === 403 || status === 429) {
|
||||
if (!invalidCountResetTime || invalidCountResetTime < Date.now()) {
|
||||
invalidCountResetTime = Date.now() + 1000 * 60 * 10;
|
||||
invalidCountResetTime = Date.now() + 1_000 * 60 * 10;
|
||||
invalidCount = 0;
|
||||
}
|
||||
|
||||
invalidCount++;
|
||||
|
||||
const emitInvalid =
|
||||
@@ -407,6 +418,7 @@ export class SequentialHandler implements IHandler {
|
||||
limit = this.limit;
|
||||
timeout = this.timeToReset;
|
||||
}
|
||||
|
||||
await this.onRateLimit({
|
||||
timeToReset: timeout,
|
||||
limit,
|
||||
@@ -440,10 +452,12 @@ export class SequentialHandler implements IHandler {
|
||||
void this.#sublimitedQueue.wait();
|
||||
this.#asyncQueue.shift();
|
||||
}
|
||||
|
||||
this.#sublimitPromise?.resolve();
|
||||
this.#sublimitPromise = null;
|
||||
await sleep(sublimitTimeout, undefined, { ref: false });
|
||||
let resolve: () => void;
|
||||
// eslint-disable-next-line promise/param-names, no-promise-executor-return
|
||||
const promise = new Promise<void>((res) => (resolve = res));
|
||||
this.#sublimitPromise = { promise, resolve: resolve! };
|
||||
if (firstSublimit) {
|
||||
@@ -452,13 +466,16 @@ export class SequentialHandler implements IHandler {
|
||||
this.#shiftSublimit = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Since this is not a server side issue, the next request should pass, so we don't bump the retries counter
|
||||
return this.runRequest(routeId, url, options, requestData, retries);
|
||||
} else if (status >= 500 && status < 600) {
|
||||
// Retry the specified number of times for possible server side issues
|
||||
if (retries !== this.manager.options.retries) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
return this.runRequest(routeId, url, options, requestData, ++retries);
|
||||
}
|
||||
|
||||
// We are out of retries, throw an error
|
||||
throw new HTTPError(res.constructor.name, status, method, url, requestData);
|
||||
} else {
|
||||
@@ -468,11 +485,13 @@ export class SequentialHandler implements IHandler {
|
||||
if (status === 401 && requestData.auth) {
|
||||
this.manager.setToken(null!);
|
||||
}
|
||||
|
||||
// The request will not succeed for some reason, parse the error returned from the api
|
||||
const data = (await parseResponse(res)) as DiscordErrorData | OAuthErrorData;
|
||||
// throw the API error
|
||||
throw new DiscordAPIError(data, 'code' in data ? data.code : data.error, status, method, url, requestData);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user