1 line
101 KiB
Plaintext
1 line
101 KiB
Plaintext
{"version":3,"sources":["../src/environment.ts","../src/lib/utils/constants.ts","../src/lib/errors/RateLimitError.ts","../src/lib/utils/types.ts","../src/lib/utils/utils.ts","../src/lib/CDN.ts","../src/lib/errors/DiscordAPIError.ts","../src/lib/errors/HTTPError.ts","../src/lib/REST.ts","../src/lib/handlers/Shared.ts","../src/lib/handlers/BurstHandler.ts","../src/lib/handlers/SequentialHandler.ts","../src/shared.ts","../src/web.ts"],"sourcesContent":["import type { RESTOptions } from './shared.js';\n\nlet defaultStrategy: RESTOptions['makeRequest'];\n\nexport function setDefaultStrategy(newStrategy: RESTOptions['makeRequest']) {\n\tdefaultStrategy = newStrategy;\n}\n\nexport function getDefaultStrategy() {\n\treturn defaultStrategy;\n}\n","import { getUserAgentAppendix } from '@discordjs/util';\nimport { APIVersion } from 'discord-api-types/v10';\nimport { getDefaultStrategy } from '../../environment.js';\nimport type { RESTOptions, ResponseLike } from './types.js';\n\nexport const DefaultUserAgent =\n\t`DiscordBot (https://discord.js.org, 2.2.0)` as `DiscordBot (https://discord.js.org, ${string})`;\n\n/**\n * The default string to append onto the user agent.\n */\nexport const DefaultUserAgentAppendix = getUserAgentAppendix();\n\nexport const DefaultRestOptions = {\n\tagent: null,\n\tapi: 'https://discord.com/api',\n\tauthPrefix: 'Bot',\n\tcdn: 'https://cdn.discordapp.com',\n\theaders: {},\n\tinvalidRequestWarningInterval: 0,\n\tglobalRequestsPerSecond: 50,\n\toffset: 50,\n\trejectOnRateLimit: null,\n\tretries: 3,\n\ttimeout: 15_000,\n\tuserAgentAppendix: DefaultUserAgentAppendix,\n\tversion: APIVersion,\n\thashSweepInterval: 14_400_000, // 4 Hours\n\thashLifetime: 86_400_000, // 24 Hours\n\thandlerSweepInterval: 3_600_000, // 1 Hour\n\tasync makeRequest(...args): Promise<ResponseLike> {\n\t\treturn getDefaultStrategy()(...args);\n\t},\n} as const satisfies Required<RESTOptions>;\n\n/**\n * The events that the REST manager emits\n */\nexport enum RESTEvents {\n\tDebug = 'restDebug',\n\tHandlerSweep = 'handlerSweep',\n\tHashSweep = 'hashSweep',\n\tInvalidRequestWarning = 'invalidRequestWarning',\n\tRateLimited = 'rateLimited',\n\tResponse = 'response',\n}\n\nexport const ALLOWED_EXTENSIONS = ['webp', 'png', 'jpg', 'jpeg', 'gif'] as const satisfies readonly string[];\nexport const ALLOWED_STICKER_EXTENSIONS = ['png', 'json', 'gif'] as const satisfies readonly string[];\nexport const ALLOWED_SIZES = [16, 32, 64, 128, 256, 512, 1_024, 2_048, 4_096] as const satisfies readonly number[];\n\nexport type ImageExtension = (typeof ALLOWED_EXTENSIONS)[number];\nexport type StickerExtension = (typeof ALLOWED_STICKER_EXTENSIONS)[number];\nexport type ImageSize = (typeof ALLOWED_SIZES)[number];\n\nexport const OverwrittenMimeTypes = {\n\t// https://github.com/discordjs/discord.js/issues/8557\n\t'image/apng': 'image/png',\n} as const satisfies Readonly<Record<string, string>>;\n\nexport const BurstHandlerMajorIdKey = 'burst';\n\n/**\n * Prefix for deprecation warnings.\n *\n * @internal\n */\nexport const DEPRECATION_WARNING_PREFIX = 'DeprecationWarning' as const;\n","import type { RateLimitData } from '../utils/types.js';\n\nexport class RateLimitError extends Error implements RateLimitData {\n\tpublic timeToReset: number;\n\n\tpublic limit: number;\n\n\tpublic method: string;\n\n\tpublic hash: string;\n\n\tpublic url: string;\n\n\tpublic route: string;\n\n\tpublic majorParameter: string;\n\n\tpublic global: boolean;\n\n\tpublic retryAfter: number;\n\n\tpublic sublimitTimeout: number;\n\n\tpublic scope: RateLimitData['scope'];\n\n\tpublic constructor({\n\t\ttimeToReset,\n\t\tlimit,\n\t\tmethod,\n\t\thash,\n\t\turl,\n\t\troute,\n\t\tmajorParameter,\n\t\tglobal,\n\t\tretryAfter,\n\t\tsublimitTimeout,\n\t\tscope,\n\t}: RateLimitData) {\n\t\tsuper();\n\t\tthis.timeToReset = timeToReset;\n\t\tthis.limit = limit;\n\t\tthis.method = method;\n\t\tthis.hash = hash;\n\t\tthis.url = url;\n\t\tthis.route = route;\n\t\tthis.majorParameter = majorParameter;\n\t\tthis.global = global;\n\t\tthis.retryAfter = retryAfter;\n\t\tthis.sublimitTimeout = sublimitTimeout;\n\t\tthis.scope = scope;\n\t}\n\n\t/**\n\t * The name of the error\n\t */\n\tpublic override get name(): string {\n\t\treturn `${RateLimitError.name}[${this.route}]`;\n\t}\n}\n","import type { Readable } from 'node:stream';\nimport type { ReadableStream } from 'node:stream/web';\nimport type { Collection } from '@discordjs/collection';\nimport type { Awaitable } from '@discordjs/util';\nimport type { Agent, Dispatcher, RequestInit, BodyInit, Response } from 'undici';\nimport type { IHandler } from '../interfaces/Handler.js';\n\nexport interface RestEvents {\n\thandlerSweep: [sweptHandlers: Collection<string, IHandler>];\n\thashSweep: [sweptHashes: Collection<string, HashData>];\n\tinvalidRequestWarning: [invalidRequestInfo: InvalidRequestWarningData];\n\trateLimited: [rateLimitInfo: RateLimitData];\n\tresponse: [request: APIRequest, response: ResponseLike];\n\trestDebug: [info: string];\n}\n\nexport type RestEventsMap = {\n\t[K in keyof RestEvents]: RestEvents[K];\n};\n\n/**\n * Options to be passed when creating the REST instance\n */\nexport interface RESTOptions {\n\t/**\n\t * The agent to set globally\n\t */\n\tagent: Dispatcher | null;\n\t/**\n\t * The base api path, without version\n\t *\n\t * @defaultValue `'https://discord.com/api'`\n\t */\n\tapi: string;\n\t/**\n\t * The authorization prefix to use for requests, useful if you want to use\n\t * bearer tokens\n\t *\n\t * @defaultValue `'Bot'`\n\t */\n\tauthPrefix: 'Bearer' | 'Bot';\n\t/**\n\t * The cdn path\n\t *\n\t * @defaultValue `'https://cdn.discordapp.com'`\n\t */\n\tcdn: string;\n\t/**\n\t * How many requests to allow sending per second (Infinity for unlimited, 50 for the standard global limit used by Discord)\n\t *\n\t * @defaultValue `50`\n\t */\n\tglobalRequestsPerSecond: number;\n\t/**\n\t * The amount of time in milliseconds that passes between each hash sweep. (defaults to 1h)\n\t *\n\t * @defaultValue `3_600_000`\n\t */\n\thandlerSweepInterval: number;\n\t/**\n\t * The maximum amount of time a hash can exist in milliseconds without being hit with a request (defaults to 24h)\n\t *\n\t * @defaultValue `86_400_000`\n\t */\n\thashLifetime: number;\n\t/**\n\t * The amount of time in milliseconds that passes between each hash sweep. (defaults to 4h)\n\t *\n\t * @defaultValue `14_400_000`\n\t */\n\thashSweepInterval: number;\n\t/**\n\t * Additional headers to send for all API requests\n\t *\n\t * @defaultValue `{}`\n\t */\n\theaders: Record<string, string>;\n\t/**\n\t * The number of invalid REST requests (those that return 401, 403, or 429) in a 10 minute window between emitted warnings (0 for no warnings).\n\t * That is, if set to 500, warnings will be emitted at invalid request number 500, 1000, 1500, and so on.\n\t *\n\t * @defaultValue `0`\n\t */\n\tinvalidRequestWarningInterval: number;\n\t/**\n\t * The method called to perform the actual HTTP request given a url and web `fetch` options\n\t * For example, to use global fetch, simply provide `makeRequest: fetch`\n\t */\n\tmakeRequest(url: string, init: RequestInit): Promise<ResponseLike>;\n\t/**\n\t * The extra offset to add to rate limits in milliseconds\n\t *\n\t * @defaultValue `50`\n\t */\n\toffset: number;\n\t/**\n\t * Determines how rate limiting and pre-emptive throttling should be handled.\n\t * When an array of strings, each element is treated as a prefix for the request route\n\t * (e.g. `/channels` to match any route starting with `/channels` such as `/channels/:id/messages`)\n\t * for which to throw {@link RateLimitError}s. All other request routes will be queued normally\n\t *\n\t * @defaultValue `null`\n\t */\n\trejectOnRateLimit: RateLimitQueueFilter | string[] | null;\n\t/**\n\t * The number of retries for errors with the 500 code, or errors\n\t * that timeout\n\t *\n\t * @defaultValue `3`\n\t */\n\tretries: number;\n\t/**\n\t * The time to wait in milliseconds before a request is aborted\n\t *\n\t * @defaultValue `15_000`\n\t */\n\ttimeout: number;\n\t/**\n\t * Extra information to add to the user agent\n\t *\n\t * @defaultValue DefaultUserAgentAppendix\n\t */\n\tuserAgentAppendix: string;\n\t/**\n\t * The version of the API to use\n\t *\n\t * @defaultValue `'10'`\n\t */\n\tversion: string;\n}\n\n/**\n * Data emitted on `RESTEvents.RateLimited`\n */\nexport interface RateLimitData {\n\t/**\n\t * Whether the rate limit that was reached was the global limit\n\t */\n\tglobal: boolean;\n\t/**\n\t * The bucket hash for this request\n\t */\n\thash: string;\n\t/**\n\t * The amount of requests we can perform before locking requests\n\t */\n\tlimit: number;\n\t/**\n\t * The major parameter of the route\n\t *\n\t * For example, in `/channels/x`, this will be `x`.\n\t * If there is no major parameter (e.g: `/bot/gateway`) this will be `global`.\n\t */\n\tmajorParameter: string;\n\t/**\n\t * The HTTP method being performed\n\t */\n\tmethod: string;\n\t/**\n\t * The time, in milliseconds, that will need to pass before this specific request can be retried\n\t */\n\tretryAfter: number;\n\t/**\n\t * The route being hit in this request\n\t */\n\troute: string;\n\t/**\n\t * The scope of the rate limit that was hit.\n\t *\n\t * This can be `user` for rate limits that are per client, `global` for rate limits that affect all clients or `shared` for rate limits that\n\t * are shared per resource.\n\t */\n\tscope: 'global' | 'shared' | 'user';\n\t/**\n\t * The time, in milliseconds, that will need to pass before the sublimit lock for the route resets, and requests that fall under a sublimit\n\t * can be retried\n\t *\n\t * This is only present on certain sublimits, and `0` otherwise\n\t */\n\tsublimitTimeout: number;\n\t/**\n\t * The time, in milliseconds, until the route's request-lock is reset\n\t */\n\ttimeToReset: number;\n\t/**\n\t * The full URL for this request\n\t */\n\turl: string;\n}\n\n/**\n * A function that determines whether the rate limit hit should throw an Error\n */\nexport type RateLimitQueueFilter = (rateLimitData: RateLimitData) => Awaitable<boolean>;\n\nexport interface APIRequest {\n\t/**\n\t * The data that was used to form the body of this request\n\t */\n\tdata: HandlerRequestData;\n\t/**\n\t * The HTTP method used in this request\n\t */\n\tmethod: string;\n\t/**\n\t * Additional HTTP options for this request\n\t */\n\toptions: RequestInit;\n\t/**\n\t * The full path used to make the request\n\t */\n\tpath: RouteLike;\n\t/**\n\t * The number of times this request has been attempted\n\t */\n\tretries: number;\n\t/**\n\t * The API route identifying the ratelimit for this request\n\t */\n\troute: string;\n}\n\nexport interface ResponseLike\n\textends Pick<Response, 'arrayBuffer' | 'bodyUsed' | 'headers' | 'json' | 'ok' | 'status' | 'statusText' | 'text'> {\n\tbody: Readable | ReadableStream | null;\n}\n\nexport interface InvalidRequestWarningData {\n\t/**\n\t * Number of invalid requests that have been made in the window\n\t */\n\tcount: number;\n\t/**\n\t * Time in milliseconds remaining before the count resets\n\t */\n\tremainingTime: number;\n}\n\n/**\n * Represents a file to be added to the request\n */\nexport interface RawFile {\n\t/**\n\t * Content-Type of the file\n\t */\n\tcontentType?: string;\n\t/**\n\t * The actual data for the file\n\t */\n\tdata: Buffer | Uint8Array | boolean | number | string;\n\t/**\n\t * An explicit key to use for key of the formdata field for this file.\n\t * When not provided, the index of the file in the files array is used in the form `files[${index}]`.\n\t * If you wish to alter the placeholder snowflake, you must provide this property in the same form (`files[${placeholder}]`)\n\t */\n\tkey?: string;\n\t/**\n\t * The name of the file\n\t */\n\tname: string;\n}\n\n/**\n * Represents possible data to be given to an endpoint\n */\nexport interface RequestData {\n\t/**\n\t * Whether to append JSON data to form data instead of `payload_json` when sending files\n\t */\n\tappendToFormData?: boolean;\n\t/**\n\t * If this request needs the `Authorization` header\n\t *\n\t * @defaultValue `true`\n\t */\n\tauth?: boolean;\n\t/**\n\t * The authorization prefix to use for this request, useful if you use this with bearer tokens\n\t *\n\t * @defaultValue `'Bot'`\n\t */\n\tauthPrefix?: 'Bearer' | 'Bot';\n\t/**\n\t * The body to send to this request.\n\t * If providing as BodyInit, set `passThroughBody: true`\n\t */\n\tbody?: BodyInit | unknown;\n\t/**\n\t * The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} to use for the request.\n\t */\n\tdispatcher?: Agent;\n\t/**\n\t * Files to be attached to this request\n\t */\n\tfiles?: RawFile[] | undefined;\n\t/**\n\t * Additional headers to add to this request\n\t */\n\theaders?: Record<string, string>;\n\t/**\n\t * Whether to pass-through the body property directly to `fetch()`.\n\t * <warn>This only applies when files is NOT present</warn>\n\t */\n\tpassThroughBody?: boolean;\n\t/**\n\t * Query string parameters to append to the called endpoint\n\t */\n\tquery?: URLSearchParams;\n\t/**\n\t * Reason to show in the audit logs\n\t */\n\treason?: string | undefined;\n\t/**\n\t * The signal to abort the queue entry or the REST call, where applicable\n\t */\n\tsignal?: AbortSignal | undefined;\n\t/**\n\t * If this request should be versioned\n\t *\n\t * @defaultValue `true`\n\t */\n\tversioned?: boolean;\n}\n\n/**\n * Possible headers for an API call\n */\nexport interface RequestHeaders {\n\tAuthorization?: string;\n\t'User-Agent': string;\n\t'X-Audit-Log-Reason'?: string;\n}\n\n/**\n * Possible API methods to be used when doing requests\n */\nexport enum RequestMethod {\n\tDelete = 'DELETE',\n\tGet = 'GET',\n\tPatch = 'PATCH',\n\tPost = 'POST',\n\tPut = 'PUT',\n}\n\nexport type RouteLike = `/${string}`;\n\n/**\n * Internal request options\n *\n * @internal\n */\nexport interface InternalRequest extends RequestData {\n\tfullRoute: RouteLike;\n\tmethod: RequestMethod;\n}\n\nexport type HandlerRequestData = Pick<InternalRequest, 'auth' | 'body' | 'files' | 'signal'>;\n\n/**\n * Parsed route data for an endpoint\n *\n * @internal\n */\nexport interface RouteData {\n\tbucketRoute: string;\n\tmajorParameter: string;\n\toriginal: RouteLike;\n}\n\n/**\n * Represents a hash and its associated fields\n *\n * @internal\n */\nexport interface HashData {\n\tlastAccess: number;\n\tvalue: string;\n}\n","import type { RESTPatchAPIChannelJSONBody, Snowflake } from 'discord-api-types/v10';\nimport type { REST } from '../REST.js';\nimport { RateLimitError } from '../errors/RateLimitError.js';\nimport { DEPRECATION_WARNING_PREFIX } from './constants.js';\nimport { RequestMethod, type RateLimitData, type ResponseLike } from './types.js';\n\nfunction serializeSearchParam(value: unknown): string | null {\n\tswitch (typeof value) {\n\t\tcase 'string':\n\t\t\treturn value;\n\t\tcase 'number':\n\t\tcase 'bigint':\n\t\tcase 'boolean':\n\t\t\treturn value.toString();\n\t\tcase 'object':\n\t\t\tif (value === null) return null;\n\t\t\tif (value instanceof Date) {\n\t\t\t\treturn Number.isNaN(value.getTime()) ? null : value.toISOString();\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-base-to-string\n\t\t\tif (typeof value.toString === 'function' && value.toString !== Object.prototype.toString) return value.toString();\n\t\t\treturn null;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\n/**\n * Creates and populates an URLSearchParams instance from an object, stripping\n * out null and undefined values, while also coercing non-strings to strings.\n *\n * @param options - The options to use\n * @returns A populated URLSearchParams instance\n */\nexport function makeURLSearchParams<OptionsType extends object>(options?: Readonly<OptionsType>) {\n\tconst params = new URLSearchParams();\n\tif (!options) return params;\n\n\tfor (const [key, value] of Object.entries(options)) {\n\t\tconst serialized = serializeSearchParam(value);\n\t\tif (serialized !== null) params.append(key, serialized);\n\t}\n\n\treturn params;\n}\n\n/**\n * Converts the response to usable data\n *\n * @param res - The fetch response\n */\nexport async function parseResponse(res: ResponseLike): Promise<unknown> {\n\tif (res.headers.get('Content-Type')?.startsWith('application/json')) {\n\t\treturn res.json();\n\t}\n\n\treturn res.arrayBuffer();\n}\n\n/**\n * Check whether a request falls under a sublimit\n *\n * @param bucketRoute - The buckets route identifier\n * @param body - The options provided as JSON data\n * @param method - The HTTP method that will be used to make the request\n * @returns Whether the request falls under a sublimit\n */\nexport function hasSublimit(bucketRoute: string, body?: unknown, method?: string): boolean {\n\t// TODO: Update for new sublimits\n\t// Currently known sublimits:\n\t// Editing channel `name` or `topic`\n\tif (bucketRoute === '/channels/:id') {\n\t\tif (typeof body !== 'object' || body === null) return false;\n\t\t// This should never be a POST body, but just in case\n\t\tif (method !== RequestMethod.Patch) return false;\n\t\tconst castedBody = body as RESTPatchAPIChannelJSONBody;\n\t\treturn ['name', 'topic'].some((key) => Reflect.has(castedBody, key));\n\t}\n\n\t// If we are checking if a request has a sublimit on a route not checked above, sublimit all requests to avoid a flood of 429s\n\treturn true;\n}\n\n/**\n * Check whether an error indicates that a retry can be attempted\n *\n * @param error - The error thrown by the network request\n * @returns Whether the error indicates a retry should be attempted\n */\nexport function shouldRetry(error: Error | NodeJS.ErrnoException) {\n\t// Retry for possible timed out requests\n\tif (error.name === 'AbortError') return true;\n\t// Downlevel ECONNRESET to retry as it may be recoverable\n\treturn ('code' in error && error.code === 'ECONNRESET') || error.message.includes('ECONNRESET');\n}\n\n/**\n * Determines whether the request should be queued or whether a RateLimitError should be thrown\n *\n * @internal\n */\nexport async function onRateLimit(manager: REST, rateLimitData: RateLimitData) {\n\tconst { options } = manager;\n\tif (!options.rejectOnRateLimit) return;\n\n\tconst shouldThrow =\n\t\ttypeof options.rejectOnRateLimit === 'function'\n\t\t\t? await options.rejectOnRateLimit(rateLimitData)\n\t\t\t: options.rejectOnRateLimit.some((route) => rateLimitData.route.startsWith(route.toLowerCase()));\n\tif (shouldThrow) {\n\t\tthrow new RateLimitError(rateLimitData);\n\t}\n}\n\n/**\n * Calculates the default avatar index for a given user id.\n *\n * @param userId - The user id to calculate the default avatar index for\n */\nexport function calculateUserDefaultAvatarIndex(userId: Snowflake) {\n\treturn Number(BigInt(userId) >> 22n) % 6;\n}\n\n/**\n * Sleeps for a given amount of time.\n *\n * @param ms - The amount of time (in milliseconds) to sleep for\n */\nexport async function sleep(ms: number): Promise<void> {\n\treturn new Promise<void>((resolve) => {\n\t\tsetTimeout(() => resolve(), ms);\n\t});\n}\n\n/**\n * Verifies that a value is a buffer-like object.\n *\n * @param value - The value to check\n */\nexport function isBufferLike(value: unknown): value is ArrayBuffer | Buffer | Uint8Array | Uint8ClampedArray {\n\treturn value instanceof ArrayBuffer || value instanceof Uint8Array || value instanceof Uint8ClampedArray;\n}\n\n/**\n * Irrespective environment warning.\n *\n * @remarks Only the message is needed. The deprecation prefix is handled already.\n * @param message - A string the warning will emit with\n * @internal\n */\nexport function deprecationWarning(message: string) {\n\tif (typeof globalThis.process === 'undefined') {\n\t\tconsole.warn(`${DEPRECATION_WARNING_PREFIX}: ${message}`);\n\t} else {\n\t\tprocess.emitWarning(message, DEPRECATION_WARNING_PREFIX);\n\t}\n}\n","/* eslint-disable jsdoc/check-param-names */\nimport {\n\tALLOWED_EXTENSIONS,\n\tALLOWED_SIZES,\n\tALLOWED_STICKER_EXTENSIONS,\n\tDefaultRestOptions,\n\ttype ImageExtension,\n\ttype ImageSize,\n\ttype StickerExtension,\n} from './utils/constants.js';\nimport { deprecationWarning } from './utils/utils.js';\n\nlet deprecationEmittedForEmoji = false;\n\n/**\n * The options used for image URLs\n */\nexport interface BaseImageURLOptions {\n\t/**\n\t * The extension to use for the image URL\n\t *\n\t * @defaultValue `'webp'`\n\t */\n\textension?: ImageExtension;\n\t/**\n\t * The size specified in the image URL\n\t */\n\tsize?: ImageSize;\n}\n\n/**\n * The options used for image URLs with animated content\n */\nexport interface ImageURLOptions extends BaseImageURLOptions {\n\t/**\n\t * Whether or not to prefer the static version of an image asset.\n\t */\n\tforceStatic?: boolean;\n}\n\n/**\n * The options to use when making a CDN URL\n */\nexport interface MakeURLOptions {\n\t/**\n\t * The allowed extensions that can be used\n\t */\n\tallowedExtensions?: readonly string[];\n\t/**\n\t * The extension to use for the image URL\n\t *\n\t * @defaultValue `'webp'`\n\t */\n\textension?: string | undefined;\n\t/**\n\t * The size specified in the image URL\n\t */\n\tsize?: ImageSize;\n}\n\n/**\n * The CDN link builder\n */\nexport class CDN {\n\tpublic constructor(private readonly base: string = DefaultRestOptions.cdn) {}\n\n\t/**\n\t * Generates an app asset URL for a client's asset.\n\t *\n\t * @param clientId - The client id that has the asset\n\t * @param assetHash - The hash provided by Discord for this asset\n\t * @param options - Optional options for the asset\n\t */\n\tpublic appAsset(clientId: string, assetHash: string, options?: Readonly<BaseImageURLOptions>): string {\n\t\treturn this.makeURL(`/app-assets/${clientId}/${assetHash}`, options);\n\t}\n\n\t/**\n\t * Generates an app icon URL for a client's icon.\n\t *\n\t * @param clientId - The client id that has the icon\n\t * @param iconHash - The hash provided by Discord for this icon\n\t * @param options - Optional options for the icon\n\t */\n\tpublic appIcon(clientId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string {\n\t\treturn this.makeURL(`/app-icons/${clientId}/${iconHash}`, options);\n\t}\n\n\t/**\n\t * Generates an avatar URL, e.g. for a user or a webhook.\n\t *\n\t * @param id - The id that has the icon\n\t * @param avatarHash - The hash provided by Discord for this avatar\n\t * @param options - Optional options for the avatar\n\t */\n\tpublic avatar(id: string, avatarHash: string, options?: Readonly<ImageURLOptions>): string {\n\t\treturn this.dynamicMakeURL(`/avatars/${id}/${avatarHash}`, avatarHash, options);\n\t}\n\n\t/**\n\t * Generates a user avatar decoration URL.\n\t *\n\t * @param userId - The id of the user\n\t * @param userAvatarDecoration - The hash provided by Discord for this avatar decoration\n\t * @param options - Optional options for the avatar decoration\n\t */\n\tpublic avatarDecoration(\n\t\tuserId: string,\n\t\tuserAvatarDecoration: string,\n\t\toptions?: Readonly<BaseImageURLOptions>,\n\t): string {\n\t\treturn this.makeURL(`/avatar-decorations/${userId}/${userAvatarDecoration}`, options);\n\t}\n\n\t/**\n\t * Generates a banner URL, e.g. for a user or a guild.\n\t *\n\t * @param id - The id that has the banner splash\n\t * @param bannerHash - The hash provided by Discord for this banner\n\t * @param options - Optional options for the banner\n\t */\n\tpublic banner(id: string, bannerHash: string, options?: Readonly<ImageURLOptions>): string {\n\t\treturn this.dynamicMakeURL(`/banners/${id}/${bannerHash}`, bannerHash, options);\n\t}\n\n\t/**\n\t * Generates an icon URL for a channel, e.g. a group DM.\n\t *\n\t * @param channelId - The channel id that has the icon\n\t * @param iconHash - The hash provided by Discord for this channel\n\t * @param options - Optional options for the icon\n\t */\n\tpublic channelIcon(channelId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string {\n\t\treturn this.makeURL(`/channel-icons/${channelId}/${iconHash}`, options);\n\t}\n\n\t/**\n\t * Generates a default avatar URL\n\t *\n\t * @param index - The default avatar index\n\t * @remarks\n\t * To calculate the index for a user do `(userId >> 22) % 6`,\n\t * or `discriminator % 5` if they're using the legacy username system.\n\t */\n\tpublic defaultAvatar(index: number): string {\n\t\treturn this.makeURL(`/embed/avatars/${index}`, { extension: 'png' });\n\t}\n\n\t/**\n\t * Generates a discovery splash URL for a guild's discovery splash.\n\t *\n\t * @param guildId - The guild id that has the discovery splash\n\t * @param splashHash - The hash provided by Discord for this splash\n\t * @param options - Optional options for the splash\n\t */\n\tpublic discoverySplash(guildId: string, splashHash: string, options?: Readonly<BaseImageURLOptions>): string {\n\t\treturn this.makeURL(`/discovery-splashes/${guildId}/${splashHash}`, options);\n\t}\n\n\t/**\n\t * Generates an emoji's URL for an emoji.\n\t *\n\t * @param emojiId - The emoji id\n\t * @param options - Optional options for the emoji\n\t */\n\tpublic emoji(emojiId: string, options?: Readonly<BaseImageURLOptions>): string;\n\n\t/**\n\t * Generates an emoji's URL for an emoji.\n\t *\n\t * @param emojiId - The emoji id\n\t * @param extension - The extension of the emoji\n\t * @deprecated This overload is deprecated. Pass an object containing the extension instead.\n\t */\n\t// eslint-disable-next-line @typescript-eslint/unified-signatures\n\tpublic emoji(emojiId: string, extension?: ImageExtension): string;\n\n\tpublic emoji(emojiId: string, options?: ImageExtension | Readonly<BaseImageURLOptions>): string {\n\t\tlet resolvedOptions;\n\n\t\tif (typeof options === 'string') {\n\t\t\tif (!deprecationEmittedForEmoji) {\n\t\t\t\tdeprecationWarning(\n\t\t\t\t\t'Passing a string for the second parameter of CDN#emoji() is deprecated. Use an object instead.',\n\t\t\t\t);\n\n\t\t\t\tdeprecationEmittedForEmoji = true;\n\t\t\t}\n\n\t\t\tresolvedOptions = { extension: options };\n\t\t} else {\n\t\t\tresolvedOptions = options;\n\t\t}\n\n\t\treturn this.makeURL(`/emojis/${emojiId}`, resolvedOptions);\n\t}\n\n\t/**\n\t * Generates a guild member avatar URL.\n\t *\n\t * @param guildId - The id of the guild\n\t * @param userId - The id of the user\n\t * @param avatarHash - The hash provided by Discord for this avatar\n\t * @param options - Optional options for the avatar\n\t */\n\tpublic guildMemberAvatar(\n\t\tguildId: string,\n\t\tuserId: string,\n\t\tavatarHash: string,\n\t\toptions?: Readonly<ImageURLOptions>,\n\t): string {\n\t\treturn this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/avatars/${avatarHash}`, avatarHash, options);\n\t}\n\n\t/**\n\t * Generates a guild member banner URL.\n\t *\n\t * @param guildId - The id of the guild\n\t * @param userId - The id of the user\n\t * @param bannerHash - The hash provided by Discord for this banner\n\t * @param options - Optional options for the banner\n\t */\n\tpublic guildMemberBanner(\n\t\tguildId: string,\n\t\tuserId: string,\n\t\tbannerHash: string,\n\t\toptions?: Readonly<ImageURLOptions>,\n\t): string {\n\t\treturn this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/banner`, bannerHash, options);\n\t}\n\n\t/**\n\t * Generates an icon URL, e.g. for a guild.\n\t *\n\t * @param id - The id that has the icon splash\n\t * @param iconHash - The hash provided by Discord for this icon\n\t * @param options - Optional options for the icon\n\t */\n\tpublic icon(id: string, iconHash: string, options?: Readonly<ImageURLOptions>): string {\n\t\treturn this.dynamicMakeURL(`/icons/${id}/${iconHash}`, iconHash, options);\n\t}\n\n\t/**\n\t * Generates a URL for the icon of a role\n\t *\n\t * @param roleId - The id of the role that has the icon\n\t * @param roleIconHash - The hash provided by Discord for this role icon\n\t * @param options - Optional options for the role icon\n\t */\n\tpublic roleIcon(roleId: string, roleIconHash: string, options?: Readonly<BaseImageURLOptions>): string {\n\t\treturn this.makeURL(`/role-icons/${roleId}/${roleIconHash}`, options);\n\t}\n\n\t/**\n\t * Generates a guild invite splash URL for a guild's invite splash.\n\t *\n\t * @param guildId - The guild id that has the invite splash\n\t * @param splashHash - The hash provided by Discord for this splash\n\t * @param options - Optional options for the splash\n\t */\n\tpublic splash(guildId: string, splashHash: string, options?: Readonly<BaseImageURLOptions>): string {\n\t\treturn this.makeURL(`/splashes/${guildId}/${splashHash}`, options);\n\t}\n\n\t/**\n\t * Generates a sticker URL.\n\t *\n\t * @param stickerId - The sticker id\n\t * @param extension - The extension of the sticker\n\t * @privateRemarks\n\t * Stickers cannot have a `.webp` extension, so we default to a `.png`\n\t */\n\tpublic sticker(stickerId: string, extension: StickerExtension = 'png'): string {\n\t\treturn this.makeURL(`/stickers/${stickerId}`, { allowedExtensions: ALLOWED_STICKER_EXTENSIONS, extension });\n\t}\n\n\t/**\n\t * Generates a sticker pack banner URL.\n\t *\n\t * @param bannerId - The banner id\n\t * @param options - Optional options for the banner\n\t */\n\tpublic stickerPackBanner(bannerId: string, options?: Readonly<BaseImageURLOptions>): string {\n\t\treturn this.makeURL(`/app-assets/710982414301790216/store/${bannerId}`, options);\n\t}\n\n\t/**\n\t * Generates a team icon URL for a team's icon.\n\t *\n\t * @param teamId - The team id that has the icon\n\t * @param iconHash - The hash provided by Discord for this icon\n\t * @param options - Optional options for the icon\n\t */\n\tpublic teamIcon(teamId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string {\n\t\treturn this.makeURL(`/team-icons/${teamId}/${iconHash}`, options);\n\t}\n\n\t/**\n\t * Generates a cover image for a guild scheduled event.\n\t *\n\t * @param scheduledEventId - The scheduled event id\n\t * @param coverHash - The hash provided by discord for this cover image\n\t * @param options - Optional options for the cover image\n\t */\n\tpublic guildScheduledEventCover(\n\t\tscheduledEventId: string,\n\t\tcoverHash: string,\n\t\toptions?: Readonly<BaseImageURLOptions>,\n\t): string {\n\t\treturn this.makeURL(`/guild-events/${scheduledEventId}/${coverHash}`, options);\n\t}\n\n\t/**\n\t * Constructs the URL for the resource, checking whether or not `hash` starts with `a_` if `dynamic` is set to `true`.\n\t *\n\t * @param route - The base cdn route\n\t * @param hash - The hash provided by Discord for this icon\n\t * @param options - Optional options for the link\n\t */\n\tprivate dynamicMakeURL(\n\t\troute: string,\n\t\thash: string,\n\t\t{ forceStatic = false, ...options }: Readonly<ImageURLOptions> = {},\n\t): string {\n\t\treturn this.makeURL(route, !forceStatic && hash.startsWith('a_') ? { ...options, extension: 'gif' } : options);\n\t}\n\n\t/**\n\t * Constructs the URL for the resource\n\t *\n\t * @param route - The base cdn route\n\t * @param options - The extension/size options for the link\n\t */\n\tprivate makeURL(\n\t\troute: string,\n\t\t{ allowedExtensions = ALLOWED_EXTENSIONS, extension = 'webp', size }: Readonly<MakeURLOptions> = {},\n\t): string {\n\t\t// eslint-disable-next-line no-param-reassign\n\t\textension = String(extension).toLowerCase();\n\n\t\tif (!allowedExtensions.includes(extension)) {\n\t\t\tthrow new RangeError(`Invalid extension provided: ${extension}\\nMust be one of: ${allowedExtensions.join(', ')}`);\n\t\t}\n\n\t\tif (size && !ALLOWED_SIZES.includes(size)) {\n\t\t\tthrow new RangeError(`Invalid size provided: ${size}\\nMust be one of: ${ALLOWED_SIZES.join(', ')}`);\n\t\t}\n\n\t\tconst url = new URL(`${this.base}${route}.${extension}`);\n\n\t\tif (size) {\n\t\t\turl.searchParams.set('size', String(size));\n\t\t}\n\n\t\treturn url.toString();\n\t}\n}\n","import type { InternalRequest, RawFile } from '../utils/types.js';\n\ninterface DiscordErrorFieldInformation {\n\tcode: string;\n\tmessage: string;\n}\n\ninterface DiscordErrorGroupWrapper {\n\t_errors: DiscordError[];\n}\n\ntype DiscordError = DiscordErrorFieldInformation | DiscordErrorGroupWrapper | string | { [k: string]: DiscordError };\n\nexport interface DiscordErrorData {\n\tcode: number;\n\terrors?: DiscordError;\n\tmessage: string;\n}\n\nexport interface OAuthErrorData {\n\terror: string;\n\terror_description?: string;\n}\n\nexport interface RequestBody {\n\tfiles: RawFile[] | undefined;\n\tjson: unknown | undefined;\n}\n\nfunction isErrorGroupWrapper(error: DiscordError): error is DiscordErrorGroupWrapper {\n\treturn Reflect.has(error as Record<string, unknown>, '_errors');\n}\n\nfunction isErrorResponse(error: DiscordError): error is DiscordErrorFieldInformation {\n\treturn typeof Reflect.get(error as Record<string, unknown>, 'message') === 'string';\n}\n\n/**\n * Represents an API error returned by Discord\n */\nexport class DiscordAPIError extends Error {\n\tpublic requestBody: RequestBody;\n\n\t/**\n\t * @param rawError - The error reported by Discord\n\t * @param code - The error code reported by Discord\n\t * @param status - The status code of the response\n\t * @param method - The method of the request that erred\n\t * @param url - The url of the request that erred\n\t * @param bodyData - The unparsed data for the request that errored\n\t */\n\tpublic constructor(\n\t\tpublic rawError: DiscordErrorData | OAuthErrorData,\n\t\tpublic code: number | string,\n\t\tpublic status: number,\n\t\tpublic method: string,\n\t\tpublic url: string,\n\t\tbodyData: Pick<InternalRequest, 'body' | 'files'>,\n\t) {\n\t\tsuper(DiscordAPIError.getMessage(rawError));\n\n\t\tthis.requestBody = { files: bodyData.files, json: bodyData.body };\n\t}\n\n\t/**\n\t * The name of the error\n\t */\n\tpublic override get name(): string {\n\t\treturn `${DiscordAPIError.name}[${this.code}]`;\n\t}\n\n\tprivate static getMessage(error: DiscordErrorData | OAuthErrorData) {\n\t\tlet flattened = '';\n\t\tif ('code' in error) {\n\t\t\tif (error.errors) {\n\t\t\t\tflattened = [...this.flattenDiscordError(error.errors)].join('\\n');\n\t\t\t}\n\n\t\t\treturn error.message && flattened\n\t\t\t\t? `${error.message}\\n${flattened}`\n\t\t\t\t: error.message || flattened || 'Unknown Error';\n\t\t}\n\n\t\treturn error.error_description ?? 'No Description';\n\t}\n\n\tprivate static *flattenDiscordError(obj: DiscordError, key = ''): IterableIterator<string> {\n\t\tif (isErrorResponse(obj)) {\n\t\t\treturn yield `${key.length ? `${key}[${obj.code}]` : `${obj.code}`}: ${obj.message}`.trim();\n\t\t}\n\n\t\tfor (const [otherKey, val] of Object.entries(obj)) {\n\t\t\tconst nextKey = otherKey.startsWith('_')\n\t\t\t\t? key\n\t\t\t\t: key\n\t\t\t\t ? Number.isNaN(Number(otherKey))\n\t\t\t\t\t\t? `${key}.${otherKey}`\n\t\t\t\t\t\t: `${key}[${otherKey}]`\n\t\t\t\t : otherKey;\n\n\t\t\tif (typeof val === 'string') {\n\t\t\t\tyield val;\n\t\t\t} else if (isErrorGroupWrapper(val)) {\n\t\t\t\tfor (const error of val._errors) {\n\t\t\t\t\tyield* this.flattenDiscordError(error, nextKey);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tyield* this.flattenDiscordError(val, nextKey);\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { InternalRequest } from '../utils/types.js';\nimport type { RequestBody } from './DiscordAPIError.js';\n\n/**\n * Represents a HTTP error\n */\nexport class HTTPError extends Error {\n\tpublic requestBody: RequestBody;\n\n\tpublic override name = HTTPError.name;\n\n\t/**\n\t * @param status - The status code of the response\n\t * @param statusText - The status text of the response\n\t * @param method - The method of the request that erred\n\t * @param url - The url of the request that erred\n\t * @param bodyData - The unparsed data for the request that errored\n\t */\n\tpublic constructor(\n\t\tpublic status: number,\n\t\tstatusText: string,\n\t\tpublic method: string,\n\t\tpublic url: string,\n\t\tbodyData: Pick<InternalRequest, 'body' | 'files'>,\n\t) {\n\t\tsuper(statusText);\n\t\tthis.requestBody = { files: bodyData.files, json: bodyData.body };\n\t}\n}\n","import { Collection } from '@discordjs/collection';\nimport { DiscordSnowflake } from '@sapphire/snowflake';\nimport { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';\nimport { filetypeinfo } from 'magic-bytes.js';\nimport type { RequestInit, BodyInit, Dispatcher } from 'undici';\nimport { CDN } from './CDN.js';\nimport { BurstHandler } from './handlers/BurstHandler.js';\nimport { SequentialHandler } from './handlers/SequentialHandler.js';\nimport type { IHandler } from './interfaces/Handler.js';\nimport {\n\tBurstHandlerMajorIdKey,\n\tDefaultRestOptions,\n\tDefaultUserAgent,\n\tOverwrittenMimeTypes,\n\tRESTEvents,\n} from './utils/constants.js';\nimport { RequestMethod } from './utils/types.js';\nimport type {\n\tRESTOptions,\n\tResponseLike,\n\tRestEventsMap,\n\tHashData,\n\tInternalRequest,\n\tRouteLike,\n\tRequestHeaders,\n\tRouteData,\n\tRequestData,\n} from './utils/types.js';\nimport { isBufferLike, parseResponse } from './utils/utils.js';\n\n/**\n * Represents the class that manages handlers for endpoints\n */\nexport class REST extends AsyncEventEmitter<RestEventsMap> {\n\t/**\n\t * The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} for all requests\n\t * performed by this manager.\n\t */\n\tpublic agent: Dispatcher | null = null;\n\n\tpublic readonly cdn: CDN;\n\n\t/**\n\t * The number of requests remaining in the global bucket\n\t */\n\tpublic globalRemaining: number;\n\n\t/**\n\t * The promise used to wait out the global rate limit\n\t */\n\tpublic globalDelay: Promise<void> | null = null;\n\n\t/**\n\t * The timestamp at which the global bucket resets\n\t */\n\tpublic globalReset = -1;\n\n\t/**\n\t * API bucket hashes that are cached from provided routes\n\t */\n\tpublic readonly hashes = new Collection<string, HashData>();\n\n\t/**\n\t * Request handlers created from the bucket hash and the major parameters\n\t */\n\tpublic readonly handlers = new Collection<string, IHandler>();\n\n\t#token: string | null = null;\n\n\tprivate hashTimer!: NodeJS.Timer | number;\n\n\tprivate handlerTimer!: NodeJS.Timer | number;\n\n\tpublic readonly options: RESTOptions;\n\n\tpublic constructor(options: Partial<RESTOptions> = {}) {\n\t\tsuper();\n\t\tthis.cdn = new CDN(options.cdn ?? DefaultRestOptions.cdn);\n\t\tthis.options = { ...DefaultRestOptions, ...options };\n\t\tthis.options.offset = Math.max(0, this.options.offset);\n\t\tthis.globalRemaining = Math.max(1, this.options.globalRequestsPerSecond);\n\t\tthis.agent = options.agent ?? null;\n\n\t\t// Start sweepers\n\t\tthis.setupSweepers();\n\t}\n\n\tprivate setupSweepers() {\n\t\t// eslint-disable-next-line unicorn/consistent-function-scoping\n\t\tconst validateMaxInterval = (interval: number) => {\n\t\t\tif (interval > 14_400_000) {\n\t\t\t\tthrow new Error('Cannot set an interval greater than 4 hours');\n\t\t\t}\n\t\t};\n\n\t\tif (this.options.hashSweepInterval !== 0 && this.options.hashSweepInterval !== Number.POSITIVE_INFINITY) {\n\t\t\tvalidateMaxInterval(this.options.hashSweepInterval);\n\t\t\tthis.hashTimer = setInterval(() => {\n\t\t\t\tconst sweptHashes = new Collection<string, HashData>();\n\t\t\t\tconst currentDate = Date.now();\n\n\t\t\t\t// Begin sweeping hash based on lifetimes\n\t\t\t\tthis.hashes.sweep((val, key) => {\n\t\t\t\t\t// `-1` indicates a global hash\n\t\t\t\t\tif (val.lastAccess === -1) return false;\n\n\t\t\t\t\t// Check if lifetime has been exceeded\n\t\t\t\t\tconst shouldSweep = Math.floor(currentDate - val.lastAccess) > this.options.hashLifetime;\n\n\t\t\t\t\t// Add hash to collection of swept hashes\n\t\t\t\t\tif (shouldSweep) {\n\t\t\t\t\t\t// Add to swept hashes\n\t\t\t\t\t\tsweptHashes.set(key, val);\n\n\t\t\t\t\t\t// Emit debug information\n\t\t\t\t\t\tthis.emit(RESTEvents.Debug, `Hash ${val.value} for ${key} swept due to lifetime being exceeded`);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn shouldSweep;\n\t\t\t\t});\n\n\t\t\t\t// Fire event\n\t\t\t\tthis.emit(RESTEvents.HashSweep, sweptHashes);\n\t\t\t}, this.options.hashSweepInterval);\n\n\t\t\tthis.hashTimer.unref?.();\n\t\t}\n\n\t\tif (this.options.handlerSweepInterval !== 0 && this.options.handlerSweepInterval !== Number.POSITIVE_INFINITY) {\n\t\t\tvalidateMaxInterval(this.options.handlerSweepInterval);\n\t\t\tthis.handlerTimer = setInterval(() => {\n\t\t\t\tconst sweptHandlers = new Collection<string, IHandler>();\n\n\t\t\t\t// Begin sweeping handlers based on activity\n\t\t\t\tthis.handlers.sweep((val, key) => {\n\t\t\t\t\tconst { inactive } = val;\n\n\t\t\t\t\t// Collect inactive handlers\n\t\t\t\t\tif (inactive) {\n\t\t\t\t\t\tsweptHandlers.set(key, val);\n\t\t\t\t\t\tthis.emit(RESTEvents.Debug, `Handler ${val.id} for ${key} swept due to being inactive`);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn inactive;\n\t\t\t\t});\n\n\t\t\t\t// Fire event\n\t\t\t\tthis.emit(RESTEvents.HandlerSweep, sweptHandlers);\n\t\t\t}, this.options.handlerSweepInterval);\n\n\t\t\tthis.handlerTimer.unref?.();\n\t\t}\n\t}\n\n\t/**\n\t * Runs a get request from the api\n\t *\n\t * @param fullRoute - The full route to query\n\t * @param options - Optional request options\n\t */\n\tpublic async get(fullRoute: RouteLike, options: RequestData = {}) {\n\t\treturn this.request({ ...options, fullRoute, method: RequestMethod.Get });\n\t}\n\n\t/**\n\t * Runs a delete request from the api\n\t *\n\t * @param fullRoute - The full route to query\n\t * @param options - Optional request options\n\t */\n\tpublic async delete(fullRoute: RouteLike, options: RequestData = {}) {\n\t\treturn this.request({ ...options, fullRoute, method: RequestMethod.Delete });\n\t}\n\n\t/**\n\t * Runs a post request from the api\n\t *\n\t * @param fullRoute - The full route to query\n\t * @param options - Optional request options\n\t */\n\tpublic async post(fullRoute: RouteLike, options: RequestData = {}) {\n\t\treturn this.request({ ...options, fullRoute, method: RequestMethod.Post });\n\t}\n\n\t/**\n\t * Runs a put request from the api\n\t *\n\t * @param fullRoute - The full route to query\n\t * @param options - Optional request options\n\t */\n\tpublic async put(fullRoute: RouteLike, options: RequestData = {}) {\n\t\treturn this.request({ ...options, fullRoute, method: RequestMethod.Put });\n\t}\n\n\t/**\n\t * Runs a patch request from the api\n\t *\n\t * @param fullRoute - The full route to query\n\t * @param options - Optional request options\n\t */\n\tpublic async patch(fullRoute: RouteLike, options: RequestData = {}) {\n\t\treturn this.request({ ...options, fullRoute, method: RequestMethod.Patch });\n\t}\n\n\t/**\n\t * Runs a request from the api\n\t *\n\t * @param options - Request options\n\t */\n\tpublic async request(options: InternalRequest) {\n\t\tconst response = await this.queueRequest(options);\n\t\treturn parseResponse(response);\n\t}\n\n\t/**\n\t * Sets the default agent to use for requests performed by this manager\n\t *\n\t * @param agent - The agent to use\n\t */\n\tpublic setAgent(agent: Dispatcher) {\n\t\tthis.agent = agent;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Sets the authorization token that should be used for requests\n\t *\n\t * @param token - The authorization token to use\n\t */\n\tpublic setToken(token: string) {\n\t\tthis.#token = token;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Queues a request to be sent\n\t *\n\t * @param request - All the information needed to make a request\n\t * @returns The response from the api request\n\t */\n\tpublic async queueRequest(request: InternalRequest): Promise<ResponseLike> {\n\t\t// Generalize the endpoint to its route data\n\t\tconst routeId = REST.generateRouteData(request.fullRoute, request.method);\n\t\t// Get the bucket hash for the generic route, or point to a global route otherwise\n\t\tconst hash = this.hashes.get(`${request.method}:${routeId.bucketRoute}`) ?? {\n\t\t\tvalue: `Global(${request.method}:${routeId.bucketRoute})`,\n\t\t\tlastAccess: -1,\n\t\t};\n\n\t\t// Get the request handler for the obtained hash, with its major parameter\n\t\tconst handler =\n\t\t\tthis.handlers.get(`${hash.value}:${routeId.majorParameter}`) ??\n\t\t\tthis.createHandler(hash.value, routeId.majorParameter);\n\n\t\t// Resolve the request into usable fetch options\n\t\tconst { url, fetchOptions } = await this.resolveRequest(request);\n\n\t\t// Queue the request\n\t\treturn handler.queueRequest(routeId, url, fetchOptions, {\n\t\t\tbody: request.body,\n\t\t\tfiles: request.files,\n\t\t\tauth: request.auth !== false,\n\t\t\tsignal: request.signal,\n\t\t});\n\t}\n\n\t/**\n\t * Creates a new rate limit handler from a hash, based on the hash and the major parameter\n\t *\n\t * @param hash - The hash for the route\n\t * @param majorParameter - The major parameter for this handler\n\t * @internal\n\t */\n\tprivate createHandler(hash: string, majorParameter: string) {\n\t\t// Create the async request queue to handle requests\n\t\tconst queue =\n\t\t\tmajorParameter === BurstHandlerMajorIdKey\n\t\t\t\t? new BurstHandler(this, hash, majorParameter)\n\t\t\t\t: new SequentialHandler(this, hash, majorParameter);\n\t\t// Save the queue based on its id\n\t\tthis.handlers.set(queue.id, queue);\n\n\t\treturn queue;\n\t}\n\n\t/**\n\t * Formats the request data to a usable format for fetch\n\t *\n\t * @param request - The request data\n\t */\n\tprivate async resolveRequest(request: InternalRequest): Promise<{ fetchOptions: RequestInit; url: string }> {\n\t\tconst { options } = this;\n\n\t\tlet query = '';\n\n\t\t// If a query option is passed, use it\n\t\tif (request.query) {\n\t\t\tconst resolvedQuery = request.query.toString();\n\t\t\tif (resolvedQuery !== '') {\n\t\t\t\tquery = `?${resolvedQuery}`;\n\t\t\t}\n\t\t}\n\n\t\t// Create the required headers\n\t\tconst headers: RequestHeaders = {\n\t\t\t...this.options.headers,\n\t\t\t'User-Agent': `${DefaultUserAgent} ${options.userAgentAppendix}`.trim(),\n\t\t};\n\n\t\t// If this request requires authorization (allowing non-\"authorized\" requests for webhooks)\n\t\tif (request.auth !== false) {\n\t\t\t// If we haven't received a token, throw an error\n\t\t\tif (!this.#token) {\n\t\t\t\tthrow new Error('Expected token to be set for this request, but none was present');\n\t\t\t}\n\n\t\t\theaders.Authorization = `${request.authPrefix ?? this.options.authPrefix} ${this.#token}`;\n\t\t}\n\n\t\t// If a reason was set, set its appropriate header\n\t\tif (request.reason?.length) {\n\t\t\theaders['X-Audit-Log-Reason'] = encodeURIComponent(request.reason);\n\t\t}\n\n\t\t// Format the full request URL (api base, optional version, endpoint, optional querystring)\n\t\tconst url = `${options.api}${request.versioned === false ? '' : `/v${options.version}`}${\n\t\t\trequest.fullRoute\n\t\t}${query}`;\n\n\t\tlet finalBody: RequestInit['body'];\n\t\tlet additionalHeaders: Record<string, string> = {};\n\n\t\tif (request.files?.length) {\n\t\t\tconst formData = new FormData();\n\n\t\t\t// Attach all files to the request\n\t\t\tfor (const [index, file] of request.files.entries()) {\n\t\t\t\tconst fileKey = file.key ?? `files[${index}]`;\n\n\t\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/FormData/append#parameters\n\t\t\t\t// FormData.append only accepts a string or Blob.\n\t\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#parameters\n\t\t\t\t// The Blob constructor accepts TypedArray/ArrayBuffer, strings, and Blobs.\n\t\t\t\tif (isBufferLike(file.data)) {\n\t\t\t\t\t// Try to infer the content type from the buffer if one isn't passed\n\t\t\t\t\tlet contentType = file.contentType;\n\n\t\t\t\t\tif (!contentType) {\n\t\t\t\t\t\tconst [parsedType] = filetypeinfo(file.data);\n\n\t\t\t\t\t\tif (parsedType) {\n\t\t\t\t\t\t\tcontentType =\n\t\t\t\t\t\t\t\tOverwrittenMimeTypes[parsedType.mime as keyof typeof OverwrittenMimeTypes] ??\n\t\t\t\t\t\t\t\tparsedType.mime ??\n\t\t\t\t\t\t\t\t'application/octet-stream';\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tformData.append(fileKey, new Blob([file.data], { type: contentType }), file.name);\n\t\t\t\t} else {\n\t\t\t\t\tformData.append(fileKey, new Blob([`${file.data}`], { type: file.contentType }), file.name);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If a JSON body was added as well, attach it to the form data, using payload_json unless otherwise specified\n\t\t\t// eslint-disable-next-line no-eq-null, eqeqeq\n\t\t\tif (request.body != null) {\n\t\t\t\tif (request.appendToFormData) {\n\t\t\t\t\tfor (const [key, value] of Object.entries(request.body as Record<string, unknown>)) {\n\t\t\t\t\t\tformData.append(key, value);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tformData.append('payload_json', JSON.stringify(request.body));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the final body to the form data\n\t\t\tfinalBody = formData;\n\n\t\t\t// eslint-disable-next-line no-eq-null, eqeqeq\n\t\t} else if (request.body != null) {\n\t\t\tif (request.passThroughBody) {\n\t\t\t\tfinalBody = request.body as BodyInit;\n\t\t\t} else {\n\t\t\t\t// Stringify the JSON data\n\t\t\t\tfinalBody = JSON.stringify(request.body);\n\t\t\t\t// Set the additional headers to specify the content-type\n\t\t\t\tadditionalHeaders = { 'Content-Type': 'application/json' };\n\t\t\t}\n\t\t}\n\n\t\tconst method = request.method.toUpperCase();\n\n\t\t// The non null assertions in the following block are due to exactOptionalPropertyTypes, they have been tested to work with undefined\n\t\tconst fetchOptions: RequestInit = {\n\t\t\t// Set body to null on get / head requests. This does not follow fetch spec (likely because it causes subtle bugs) but is aligned with what request was doing\n\t\t\tbody: ['GET', 'HEAD'].includes(method) ? null : finalBody!,\n\t\t\theaders: { ...request.headers, ...additionalHeaders, ...headers } as Record<string, string>,\n\t\t\tmethod,\n\t\t\t// Prioritize setting an agent per request, use the agent for this instance otherwise.\n\t\t\tdispatcher: request.dispatcher ?? this.agent ?? undefined!,\n\t\t};\n\n\t\treturn { url, fetchOptions };\n\t}\n\n\t/**\n\t * Stops the hash sweeping interval\n\t */\n\tpublic clearHashSweeper() {\n\t\tclearInterval(this.hashTimer);\n\t}\n\n\t/**\n\t * Stops the request handler sweeping interval\n\t */\n\tpublic clearHandlerSweeper() {\n\t\tclearInterval(this.handlerTimer);\n\t}\n\n\t/**\n\t * Generates route data for an endpoint:method\n\t *\n\t * @param endpoint - The raw endpoint to generalize\n\t * @param method - The HTTP method this endpoint is called without\n\t * @internal\n\t */\n\tprivate static generateRouteData(endpoint: RouteLike, method: RequestMethod): RouteData {\n\t\tif (endpoint.startsWith('/interactions/') && endpoint.endsWith('/callback')) {\n\t\t\treturn {\n\t\t\t\tmajorParameter: BurstHandlerMajorIdKey,\n\t\t\t\tbucketRoute: '/interactions/:id/:token/callback',\n\t\t\t\toriginal: endpoint,\n\t\t\t};\n\t\t}\n\n\t\tconst majorIdMatch = /(?:^\\/webhooks\\/(\\d{17,19}\\/[^/?]+))|(?:^\\/(?:channels|guilds|webhooks)\\/(\\d{17,19}))/.exec(\n\t\t\tendpoint,\n\t\t);\n\n\t\t// Get the major id or id + token for this route - global otherwise\n\t\tconst majorId = majorIdMatch?.[2] ?? majorIdMatch?.[1] ?? 'global';\n\n\t\tconst baseRoute = endpoint\n\t\t\t// Strip out all ids\n\t\t\t.replaceAll(/\\d{17,19}/g, ':id')\n\t\t\t// Strip out reaction as they fall under the same bucket\n\t\t\t.replace(/\\/reactions\\/(.*)/, '/reactions/:reaction')\n\t\t\t// Strip out webhook tokens\n\t\t\t.replace(/\\/webhooks\\/:id\\/[^/?]+/, '/webhooks/:id/:token');\n\n\t\tlet exceptions = '';\n\n\t\t// Hard-Code Old Message Deletion Exception (2 week+ old messages are a different bucket)\n\t\t// https://github.com/discord/discord-api-docs/issues/1295\n\t\tif (method === RequestMethod.Delete && baseRoute === '/channels/:id/messages/:id') {\n\t\t\tconst id = /\\d{17,19}$/.exec(endpoint)![0]!;\n\t\t\tconst timestamp = DiscordSnowflake.timestampFrom(id);\n\t\t\tif (Date.now() - timestamp > 1_000 * 60 * 60 * 24 * 14) {\n\t\t\t\texceptions += '/Delete Old Message';\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tmajorParameter: majorId,\n\t\t\tbucketRoute: baseRoute + exceptions,\n\t\t\toriginal: endpoint,\n\t\t};\n\t}\n}\n","import type { RequestInit } from 'undici';\nimport type { REST } from '../REST.js';\nimport type { DiscordErrorData, OAuthErrorData } from '../errors/DiscordAPIError.js';\nimport { DiscordAPIError } from '../errors/DiscordAPIError.js';\nimport { HTTPError } from '../errors/HTTPError.js';\nimport { RESTEvents } from '../utils/constants.js';\nimport type { ResponseLike, HandlerRequestData, RouteData } from '../utils/types.js';\nimport { parseResponse, shouldRetry } from '../utils/utils.js';\n\n/**\n * Invalid request limiting is done on a per-IP basis, not a per-token basis.\n * The best we can do is track invalid counts process-wide (on the theory that\n * users could have multiple bots run from one process) rather than per-bot.\n * Therefore, store these at file scope here rather than in the client's\n * RESTManager object.\n */\nlet invalidCount = 0;\nlet invalidCountResetTime: number | null = null;\n\n/**\n * Increment the invalid request count and emit warning if necessary\n *\n * @internal\n */\nexport function incrementInvalidCount(manager: REST) {\n\tif (!invalidCountResetTime || invalidCountResetTime < Date.now()) {\n\t\tinvalidCountResetTime = Date.now() + 1_000 * 60 * 10;\n\t\tinvalidCount = 0;\n\t}\n\n\tinvalidCount++;\n\n\tconst emitInvalid =\n\t\tmanager.options.invalidRequestWarningInterval > 0 &&\n\t\tinvalidCount % manager.options.invalidRequestWarningInterval === 0;\n\tif (emitInvalid) {\n\t\t// Let library users know periodically about invalid requests\n\t\tmanager.emit(RESTEvents.InvalidRequestWarning, {\n\t\t\tcount: invalidCount,\n\t\t\tremainingTime: invalidCountResetTime - Date.now(),\n\t\t});\n\t}\n}\n\n/**\n * Performs the actual network request for a request handler\n *\n * @param manager - The manager that holds options and emits informational events\n * @param routeId - The generalized api route with literal ids for major parameters\n * @param url - The fully resolved url to make the request to\n * @param options - The fetch options needed to make the request\n * @param requestData - Extra data from the user's request needed for errors and additional processing\n * @param retries - The number of retries this request has already attempted (recursion occurs on the handler)\n * @returns The respond from the network or `null` when the request should be retried\n * @internal\n */\nexport async function makeNetworkRequest(\n\tmanager: REST,\n\trouteId: RouteData,\n\turl: string,\n\toptions: RequestInit,\n\trequestData: HandlerRequestData,\n\tretries: number,\n) {\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), manager.options.timeout);\n\tif (requestData.signal) {\n\t\t// If the user signal was aborted, abort the controller, else abort the local signal.\n\t\t// The reason why we don't re-use the user's signal, is because users may use the same signal for multiple\n\t\t// requests, and we do not want to cause unexpected side-effects.\n\t\tif (requestData.signal.aborted) controller.abort();\n\t\telse requestData.signal.addEventListener('abort', () => controller.abort());\n\t}\n\n\tlet res: ResponseLike;\n\ttry {\n\t\tres = await manager.options.makeRequest(url, { ...options, signal: controller.signal });\n\t} catch (error: unknown) {\n\t\tif (!(error instanceof Error)) throw error;\n\t\t// Retry the specified number of times if needed\n\t\tif (shouldRetry(error) && retries !== manager.options.retries) {\n\t\t\t// Retry is handled by the handler upon receiving null\n\t\t\treturn null;\n\t\t}\n\n\t\tthrow error;\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n\n\tif (manager.listenerCount(RESTEvents.Response)) {\n\t\tmanager.emit(\n\t\t\tRESTEvents.Response,\n\t\t\t{\n\t\t\t\tmethod: options.method ?? 'get',\n\t\t\t\tpath: routeId.original,\n\t\t\t\troute: routeId.bucketRoute,\n\t\t\t\toptions,\n\t\t\t\tdata: requestData,\n\t\t\t\tretries,\n\t\t\t},\n\t\t\tres instanceof Response ? res.clone() : { ...res },\n\t\t);\n\t}\n\n\treturn res;\n}\n\n/**\n * Handles 5xx and 4xx errors (not 429's) conventionally. 429's should be handled before calling this function\n *\n * @param manager - The manager that holds options and emits informational events\n * @param res - The response received from {@link makeNetworkRequest}\n * @param method - The method used to make the request\n * @param url - The fully resolved url to make the request to\n * @param requestData - Extra data from the user's request needed for errors and additional processing\n * @param retries - The number of retries this request has already attempted (recursion occurs on the handler)\n * @returns - The response if the status code is not handled or null to request a retry\n */\nexport async function handleErrors(\n\tmanager: REST,\n\tres: ResponseLike,\n\tmethod: string,\n\turl: string,\n\trequestData: HandlerRequestData,\n\tretries: number,\n) {\n\tconst status = res.status;\n\tif (status >= 500 && status < 600) {\n\t\t// Retry the specified number of times for possible server side issues\n\t\tif (retries !== manager.options.retries) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// We are out of retries, throw an error\n\t\tthrow new HTTPError(status, res.statusText, method, url, requestData);\n\t} else {\n\t\t// Handle possible malformed requests\n\t\tif (status >= 400 && status < 500) {\n\t\t\t// If we receive this status code, it means the token we had is no longer valid.\n\t\t\tif (status === 401 && requestData.auth) {\n\t\t\t\tmanager.setToken(null!);\n\t\t\t}\n\n\t\t\t// The request will not succeed for some reason, parse the error returned from the api\n\t\t\tconst data = (await parseResponse(res)) as DiscordErrorData | OAuthErrorData;\n\t\t\t// throw the API error\n\t\t\tthrow new DiscordAPIError(data, 'code' in data ? data.code : data.error, status, method, url, requestData);\n\t\t}\n\n\t\treturn res;\n\t}\n}\n","import type { RequestInit } from 'undici';\nimport type { REST } from '../REST.js';\nimport type { IHandler } from '../interfaces/Handler.js';\nimport { RESTEvents } from '../utils/constants.js';\nimport type { ResponseLike, HandlerRequestData, RouteData, RateLimitData } from '../utils/types.js';\nimport { onRateLimit, sleep } from '../utils/utils.js';\nimport { handleErrors, incrementInvalidCount, makeNetworkRequest } from './Shared.js';\n\n/**\n * The structure used to handle burst requests for a given bucket.\n * Burst requests have no ratelimit handling but allow for pre- and post-processing\n * of data in the same manner as sequentially queued requests.\n *\n * @remarks\n * This queue may still emit a rate limit error if an unexpected 429 is hit\n */\nexport class BurstHandler implements IHandler {\n\t/**\n\t * {@inheritdoc IHandler.id}\n\t */\n\tpublic readonly id: string;\n\n\t/**\n\t * {@inheritDoc IHandler.inactive}\n\t */\n\tpublic inactive = false;\n\n\t/**\n\t * @param manager - The request manager\n\t * @param hash - The hash that this RequestHandler handles\n\t * @param majorParameter - The major parameter for this handler\n\t */\n\tpublic constructor(\n\t\tprivate readonly manager: REST,\n\t\tprivate readonly hash: string,\n\t\tprivate readonly majorParameter: string,\n\t) {\n\t\tthis.id = `${hash}:${majorParameter}`;\n\t}\n\n\t/**\n\t * Emits a debug message\n\t *\n\t * @param message - The message to debug\n\t */\n\tprivate debug(message: string) {\n\t\tthis.manager.emit(RESTEvents.Debug, `[REST ${this.id}] ${message}`);\n\t}\n\n\t/**\n\t * {@inheritDoc IHandler.queueRequest}\n\t */\n\tpublic async queueRequest(\n\t\trouteId: RouteData,\n\t\turl: string,\n\t\toptions: RequestInit,\n\t\trequestData: HandlerRequestData,\n\t): Promise<ResponseLike> {\n\t\treturn this.runRequest(routeId, url, options, requestData);\n\t}\n\n\t/**\n\t * The method that actually makes the request to the API, and updates info about the bucket accordingly\n\t *\n\t * @param routeId - The generalized API route with literal ids for major parameters\n\t * @param url - The fully resolved URL to make the request to\n\t * @param options - The fetch options needed to make the request\n\t * @param requestData - Extra data from the user's request needed for errors and additional processing\n\t * @param retries - The number of retries this request has already attempted (recursion)\n\t */\n\tprivate async runRequest(\n\t\trouteId: RouteData,\n\t\turl: string,\n\t\toptions: RequestInit,\n\t\trequestData: HandlerRequestData,\n\t\tretries = 0,\n\t): Promise<ResponseLike> {\n\t\tconst method = options.method ?? 'get';\n\n\t\tconst res = await makeNetworkRequest(this.manager, routeId, url, options, requestData, retries);\n\n\t\t// Retry requested\n\t\tif (res === null) {\n\t\t\t// eslint-disable-next-line no-param-reassign\n\t\t\treturn this.runRequest(routeId, url, options, requestData, ++retries);\n\t\t}\n\n\t\tconst status = res.status;\n\t\tlet retryAfter = 0;\n\t\tconst retry = res.headers.get('Retry-After');\n\n\t\t// Amount of time in milliseconds until we should retry if rate limited (globally or otherwise)\n\t\tif (retry) retryAfter = Number(retry) * 1_000 + this.manager.options.offset;\n\n\t\t// Count the invalid requests\n\t\tif (status === 401 || status === 403 || status === 429) {\n\t\t\tincrementInvalidCount(this.manager);\n\t\t}\n\n\t\tif (status >= 200 && status < 300) {\n\t\t\treturn res;\n\t\t} else if (status === 429) {\n\t\t\t// Unexpected ratelimit\n\t\t\tconst isGlobal = res.headers.has('X-RateLimit-Global');\n\t\t\tconst scope = (res.headers.get('X-RateLimit-Scope') ?? 'user') as RateLimitData['scope'];\n\n\t\t\tawait onRateLimit(this.manager, {\n\t\t\t\tglobal: isGlobal,\n\t\t\t\tmethod,\n\t\t\t\turl,\n\t\t\t\troute: routeId.bucketRoute,\n\t\t\t\tmajorParameter: this.majorParameter,\n\t\t\t\thash: this.hash,\n\t\t\t\tlimit: Number.POSITIVE_INFINITY,\n\t\t\t\ttimeToReset: retryAfter,\n\t\t\t\tretryAfter,\n\t\t\t\tsublimitTimeout: 0,\n\t\t\t\tscope,\n\t\t\t});\n\n\t\t\tthis.debug(\n\t\t\t\t[\n\t\t\t\t\t'Encountered unexpected 429 rate limit',\n\t\t\t\t\t` Global : ${isGlobal}`,\n\t\t\t\t\t` Method : ${method}`,\n\t\t\t\t\t` URL : ${url}`,\n\t\t\t\t\t` Bucket : ${routeId.bucketRoute}`,\n\t\t\t\t\t` Major parameter: ${routeId.majorParameter}`,\n\t\t\t\t\t` Hash : ${this.hash}`,\n\t\t\t\t\t` Limit : ${Number.POSITIVE_INFINITY}`,\n\t\t\t\t\t` Retry After : ${retryAfter}ms`,\n\t\t\t\t\t` Sublimit : None`,\n\t\t\t\t\t` Scope : ${scope}`,\n\t\t\t\t].join('\\n'),\n\t\t\t);\n\n\t\t\t// We are bypassing all other limits, but an encountered limit should be respected (it's probably a non-punished rate limit anyways)\n\t\t\tawait sleep(retryAfter);\n\n\t\t\t// Since this is not a server side issue, the next request should pass, so we don't bump the retries counter\n\t\t\treturn this.runRequest(routeId, url, options, requestData, retries);\n\t\t} else {\n\t\t\tconst handled = await handleErrors(this.manager, res, method, url, requestData, retries);\n\t\t\tif (handled === null) {\n\t\t\t\t// eslint-disable-next-line no-param-reassign\n\t\t\t\treturn this.runRequest(routeId, url, options, requestData, ++retries);\n\t\t\t}\n\n\t\t\treturn handled;\n\t\t}\n\t}\n}\n","import { AsyncQueue } from '@sapphire/async-queue';\nimport type { RequestInit } from 'undici';\nimport type { REST } from '../REST.js';\nimport type { IHandler } from '../interfaces/Handler.js';\nimport { RESTEvents } from '../utils/constants.js';\nimport type { RateLimitData, ResponseLike, HandlerRequestData, RouteData } from '../utils/types.js';\nimport { hasSublimit, onRateLimit, sleep } from '../utils/utils.js';\nimport { handleErrors, incrementInvalidCount, makeNetworkRequest } from './Shared.js';\n\nconst enum QueueType {\n\tStandard,\n\tSublimit,\n}\n\n/**\n * The structure used to handle sequential requests for a given bucket\n */\nexport class SequentialHandler implements IHandler {\n\t/**\n\t * {@inheritDoc IHandler.id}\n\t */\n\tpublic readonly id: string;\n\n\t/**\n\t * The time this rate limit bucket will reset\n\t */\n\tprivate reset = -1;\n\n\t/**\n\t * The remaining requests that can be made before we are rate limited\n\t */\n\tprivate remaining = 1;\n\n\t/**\n\t * The total number of requests that can be made before we are rate limited\n\t */\n\tprivate limit = Number.POSITIVE_INFINITY;\n\n\t/**\n\t * The interface used to sequence async requests sequentially\n\t */\n\t#asyncQueue = new AsyncQueue();\n\n\t/**\n\t * The interface used to sequence sublimited async requests sequentially\n\t */\n\t#sublimitedQueue: AsyncQueue | null = null;\n\n\t/**\n\t * A promise wrapper for when the sublimited queue is finished being processed or null when not being processed\n\t */\n\t#sublimitPromise: { promise: Promise<void>; resolve(): void } | null = null;\n\n\t/**\n\t * Whether the sublimit queue needs to be shifted in the finally block\n\t */\n\t#shiftSublimit = false;\n\n\t/**\n\t * @param manager - The request manager\n\t * @param hash - The hash that this RequestHandler handles\n\t * @param majorParameter - The major parameter for this handler\n\t */\n\tpublic constructor(\n\t\tprivate readonly manager: REST,\n\t\tprivate readonly hash: string,\n\t\tprivate readonly majorParameter: string,\n\t) {\n\t\tthis.id = `${hash}:${majorParameter}`;\n\t}\n\n\t/**\n\t * {@inheritDoc IHandler.inactive}\n\t */\n\tpublic get inactive(): boolean {\n\t\treturn (\n\t\t\tthis.#asyncQueue.remaining === 0 &&\n\t\t\t(this.#sublimitedQueue === null || this.#sublimitedQueue.remaining === 0) &&\n\t\t\t!this.limited\n\t\t);\n\t}\n\n\t/**\n\t * If the rate limit bucket is currently limited by the global limit\n\t */\n\tprivate get globalLimited(): boolean {\n\t\treturn this.manager.globalRemaining <= 0 && Date.now() < this.manager.globalReset;\n\t}\n\n\t/**\n\t * If the rate limit bucket is currently limited by its limit\n\t */\n\tprivate get localLimited(): boolean {\n\t\treturn this.remaining <= 0 && Date.now() < this.reset;\n\t}\n\n\t/**\n\t * If the rate limit bucket is currently limited\n\t */\n\tprivate get limited(): boolean {\n\t\treturn this.globalLimited || this.localLimited;\n\t}\n\n\t/**\n\t * The time until queued requests can continue\n\t */\n\tprivate get timeToReset(): number {\n\t\treturn this.reset + this.manager.options.offset - Date.now();\n\t}\n\n\t/**\n\t * Emits a debug message\n\t *\n\t * @param message - The message to debug\n\t */\n\tprivate debug(message: string) {\n\t\tthis.manager.emit(RESTEvents.Debug, `[REST ${this.id}] ${message}`);\n\t}\n\n\t/**\n\t * Delay all requests for the specified amount of time, handling global rate limits\n\t *\n\t * @param time - The amount of time to delay all requests for\n\t */\n\tprivate async globalDelayFor(time: number): Promise<void> {\n\t\tawait sleep(time);\n\t\tthis.manager.globalDelay = null;\n\t}\n\n\t/**\n\t * {@inheritDoc IHandler.queueRequest}\n\t */\n\tpublic async queueRequest(\n\t\trouteId: RouteData,\n\t\turl: string,\n\t\toptions: RequestInit,\n\t\trequestData: HandlerRequestData,\n\t): Promise<ResponseLike> {\n\t\tlet queue = this.#asyncQueue;\n\t\tlet queueType = QueueType.Standard;\n\t\t// Separate sublimited requests when already sublimited\n\t\tif (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {\n\t\t\tqueue = this.#sublimitedQueue!;\n\t\t\tqueueType = QueueType.Sublimit;\n\t\t}\n\n\t\t// Wait for any previous requests to be completed before this one is run\n\t\tawait queue.wait({ signal: requestData.signal });\n\t\t// This set handles retroactively sublimiting requests\n\t\tif (queueType === QueueType.Standard) {\n\t\t\tif (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {\n\t\t\t\t/**\n\t\t\t\t * Remove the request from the standard queue, it should never be possible to get here while processing the\n\t\t\t\t * sublimit queue so there is no need to worry about shifting the wrong request\n\t\t\t\t */\n\t\t\t\tqueue = this.#sublimitedQueue!;\n\t\t\t\tconst wait = queue.wait();\n\t\t\t\tthis.#asyncQueue.shift();\n\t\t\t\tawait wait;\n\t\t\t} else if (this.#sublimitPromise) {\n\t\t\t\t// Stall requests while the sublimit queue gets processed\n\t\t\t\tawait this.#sublimitPromise.promise;\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Make the request, and return the results\n\t\t\treturn await this.runRequest(routeId, url, options, requestData);\n\t\t} finally {\n\t\t\t// Allow the next request to fire\n\t\t\tqueue.shift();\n\t\t\tif (this.#shiftSublimit) {\n\t\t\t\tthis.#shiftSublimit = false;\n\t\t\t\tthis.#sublimitedQueue?.shift();\n\t\t\t}\n\n\t\t\t// If this request is the last request in a sublimit\n\t\t\tif (this.#sublimitedQueue?.remaining === 0) {\n\t\t\t\tthis.#sublimitPromise?.resolve();\n\t\t\t\tthis.#sublimitedQueue = null;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * The method that actually makes the request to the api, and updates info about the bucket accordingly\n\t *\n\t * @param routeId - The generalized api route with literal ids for major parameters\n\t * @param url - The fully resolved url to make the request to\n\t * @param options - The fetch options needed to make the request\n\t * @param requestData - Extra data from the user's request needed for errors and additional processing\n\t * @param retries - The number of retries this request has already attempted (recursion)\n\t */\n\tprivate async runRequest(\n\t\trouteId: RouteData,\n\t\turl: string,\n\t\toptions: RequestInit,\n\t\trequestData: HandlerRequestData,\n\t\tretries = 0,\n\t): Promise<ResponseLike> {\n\t\t/*\n\t\t * After calculations have been done, pre-emptively stop further requests\n\t\t * Potentially loop until this task can run if e.g. the global rate limit is hit twice\n\t\t */\n\t\twhile (this.limited) {\n\t\t\tconst isGlobal = this.globalLimited;\n\t\t\tlet limit: number;\n\t\t\tlet timeout: number;\n\t\t\tlet delay: Promise<void>;\n\n\t\t\tif (isGlobal) {\n\t\t\t\t// Set RateLimitData based on the global limit\n\t\t\t\tlimit = this.manager.options.globalRequestsPerSecond;\n\t\t\t\ttimeout = this.manager.globalReset + this.manager.options.offset - Date.now();\n\t\t\t\t// If this is the first task to reach the global timeout, set the global delay\n\t\t\t\tif (!this.manager.globalDelay) {\n\t\t\t\t\t// The global delay function clears the global delay state when it is resolved\n\t\t\t\t\tthis.manager.globalDelay = this.globalDelayFor(timeout);\n\t\t\t\t}\n\n\t\t\t\tdelay = this.manager.globalDelay;\n\t\t\t} else {\n\t\t\t\t// Set RateLimitData based on the route-specific limit\n\t\t\t\tlimit = this.limit;\n\t\t\t\ttimeout = this.timeToReset;\n\t\t\t\tdelay = sleep(timeout);\n\t\t\t}\n\n\t\t\tconst rateLimitData: RateLimitData = {\n\t\t\t\tglobal: isGlobal,\n\t\t\t\tmethod: options.method ?? 'get',\n\t\t\t\turl,\n\t\t\t\troute: routeId.bucketRoute,\n\t\t\t\tmajorParameter: this.majorParameter,\n\t\t\t\thash: this.hash,\n\t\t\t\tlimit,\n\t\t\t\ttimeToReset: timeout,\n\t\t\t\tretryAfter: timeout,\n\t\t\t\tsublimitTimeout: 0,\n\t\t\t\tscope: 'user',\n\t\t\t};\n\n\t\t\t// Let library users know they have hit a rate limit\n\t\t\tthis.manager.emit(RESTEvents.RateLimited, rateLimitData);\n\t\t\t// Determine whether a RateLimitError should be thrown\n\t\t\tawait onRateLimit(this.manager, rateLimitData);\n\n\t\t\t// When not erroring, emit debug for what is happening\n\t\t\tif (isGlobal) {\n\t\t\t\tthis.debug(`Global rate limit hit, blocking all requests for ${timeout}ms`);\n\t\t\t} else {\n\t\t\t\tthis.debug(`Waiting ${timeout}ms for rate limit to pass`);\n\t\t\t}\n\n\t\t\t// Wait the remaining time left before the rate limit resets\n\t\t\tawait delay;\n\t\t}\n\n\t\t// As the request goes out, update the global usage information\n\t\tif (!this.manager.globalReset || this.manager.globalReset < Date.now()) {\n\t\t\tthis.manager.globalReset = Date.now() + 1_000;\n\t\t\tthis.manager.globalRemaining = this.manager.options.globalRequestsPerSecond;\n\t\t}\n\n\t\tthis.manager.globalRemaining--;\n\n\t\tconst method = options.method ?? 'get';\n\n\t\tconst res = await makeNetworkRequest(this.manager, routeId, url, options, requestData, retries);\n\n\t\t// Retry requested\n\t\tif (res === null) {\n\t\t\t// eslint-disable-next-line no-param-reassign\n\t\t\treturn this.runRequest(routeId, url, options, requestData, ++retries);\n\t\t}\n\n\t\tconst status = res.status;\n\t\tlet retryAfter = 0;\n\n\t\tconst limit = res.headers.get('X-RateLimit-Limit');\n\t\tconst remaining = res.headers.get('X-RateLimit-Remaining');\n\t\tconst reset = res.headers.get('X-RateLimit-Reset-After');\n\t\tconst hash = res.headers.get('X-RateLimit-Bucket');\n\t\tconst retry = res.headers.get('Retry-After');\n\t\tconst scope = (res.headers.get('X-RateLimit-Scope') ?? 'user') as RateLimitData['scope'];\n\n\t\t// Update the total number of requests that can be made before the rate limit resets\n\t\tthis.limit = limit ? Number(limit) : Number.POSITIVE_INFINITY;\n\t\t// Update the number of remaining requests that can be made before the rate limit resets\n\t\tthis.remaining = remaining ? Number(remaining) : 1;\n\t\t// Update the time when this rate limit resets (reset-after is in seconds)\n\t\tthis.reset = reset ? Number(reset) * 1_000 + Date.now() + this.manager.options.offset : Date.now();\n\n\t\t// Amount of time in milliseconds until we should retry if rate limited (globally or otherwise)\n\t\tif (retry) retryAfter = Number(retry) * 1_000 + this.manager.options.offset;\n\n\t\t// Handle buckets via the hash header retroactively\n\t\tif (hash && hash !== this.hash) {\n\t\t\t// Let library users know when rate limit buckets have been updated\n\t\t\tthis.debug(['Received bucket hash update', ` Old Hash : ${this.hash}`, ` New Hash : ${hash}`].join('\\n'));\n\t\t\t// This queue will eventually be eliminated via attrition\n\t\t\tthis.manager.hashes.set(`${method}:${routeId.bucketRoute}`, { value: hash, lastAccess: Date.now() });\n\t\t} else if (hash) {\n\t\t\t// Handle the case where hash value doesn't change\n\t\t\t// Fetch the hash data from the manager\n\t\t\tconst hashData = this.manager.hashes.get(`${method}:${routeId.bucketRoute}`);\n\n\t\t\t// When fetched, update the last access of the hash\n\t\t\tif (hashData) {\n\t\t\t\thashData.lastAccess = Date.now();\n\t\t\t}\n\t\t}\n\n\t\t// Handle retryAfter, which means we have actually hit a rate limit\n\t\tlet sublimitTimeout: number | null = null;\n\t\tif (retryAfter > 0) {\n\t\t\tif (res.headers.has('X-RateLimit-Global')) {\n\t\t\t\tthis.manager.globalRemaining = 0;\n\t\t\t\tthis.manager.globalReset = Date.now() + retryAfter;\n\t\t\t} else if (!this.localLimited) {\n\t\t\t\t/*\n\t\t\t\t * This is a sublimit (e.g. 2 channel name changes/10 minutes) since the headers don't indicate a\n\t\t\t\t * route-wide rate limit. Don't update remaining or reset to avoid rate limiting the whole\n\t\t\t\t * endpoint, just set a reset time on the request itself to avoid retrying too soon.\n\t\t\t\t */\n\t\t\t\tsublimitTimeout = retryAfter;\n\t\t\t}\n\t\t}\n\n\t\t// Count the invalid requests\n\t\tif (status === 401 || status === 403 || status === 429) {\n\t\t\tincrementInvalidCount(this.manager);\n\t\t}\n\n\t\tif (res.ok) {\n\t\t\treturn res;\n\t\t} else if (status === 429) {\n\t\t\t// A rate limit was hit - this may happen if the route isn't associated with an official bucket hash yet, or when first globally rate limited\n\t\t\tconst isGlobal = this.globalLimited;\n\t\t\tlet limit: number;\n\t\t\tlet timeout: number;\n\n\t\t\tif (isGlobal) {\n\t\t\t\t// Set RateLimitData based on the global limit\n\t\t\t\tlimit = this.manager.options.globalRequestsPerSecond;\n\t\t\t\ttimeout = this.manager.globalReset + this.manager.options.offset - Date.now();\n\t\t\t} else {\n\t\t\t\t// Set RateLimitData based on the route-specific limit\n\t\t\t\tlimit = this.limit;\n\t\t\t\ttimeout = this.timeToReset;\n\t\t\t}\n\n\t\t\tawait onRateLimit(this.manager, {\n\t\t\t\tglobal: isGlobal,\n\t\t\t\tmethod,\n\t\t\t\turl,\n\t\t\t\troute: routeId.bucketRoute,\n\t\t\t\tmajorParameter: this.majorParameter,\n\t\t\t\thash: this.hash,\n\t\t\t\tlimit,\n\t\t\t\ttimeToReset: timeout,\n\t\t\t\tretryAfter,\n\t\t\t\tsublimitTimeout: sublimitTimeout ?? 0,\n\t\t\t\tscope,\n\t\t\t});\n\n\t\t\tthis.debug(\n\t\t\t\t[\n\t\t\t\t\t'Encountered unexpected 429 rate limit',\n\t\t\t\t\t` Global : ${isGlobal.toString()}`,\n\t\t\t\t\t` Method : ${method}`,\n\t\t\t\t\t` URL : ${url}`,\n\t\t\t\t\t` Bucket : ${routeId.bucketRoute}`,\n\t\t\t\t\t` Major parameter: ${routeId.majorParameter}`,\n\t\t\t\t\t` Hash : ${this.hash}`,\n\t\t\t\t\t` Limit : ${limit}`,\n\t\t\t\t\t` Retry After : ${retryAfter}ms`,\n\t\t\t\t\t` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : 'None'}`,\n\t\t\t\t\t` Scope : ${scope}`,\n\t\t\t\t].join('\\n'),\n\t\t\t);\n\n\t\t\t// If caused by a sublimit, wait it out here so other requests on the route can be handled\n\t\t\tif (sublimitTimeout) {\n\t\t\t\t// Normally the sublimit queue will not exist, however, if a sublimit is hit while in the sublimit queue, it will\n\t\t\t\tconst firstSublimit = !this.#sublimitedQueue;\n\t\t\t\tif (firstSublimit) {\n\t\t\t\t\tthis.#sublimitedQueue = new AsyncQueue();\n\t\t\t\t\tvoid this.#sublimitedQueue.wait();\n\t\t\t\t\tthis.#asyncQueue.shift();\n\t\t\t\t}\n\n\t\t\t\tthis.#sublimitPromise?.resolve();\n\t\t\t\tthis.#sublimitPromise = null;\n\t\t\t\tawait sleep(sublimitTimeout);\n\t\t\t\tlet resolve: () => void;\n\t\t\t\t// eslint-disable-next-line promise/param-names, no-promise-executor-return\n\t\t\t\tconst promise = new Promise<void>((res) => (resolve = res));\n\t\t\t\tthis.#sublimitPromise = { promise, resolve: resolve! };\n\t\t\t\tif (firstSublimit) {\n\t\t\t\t\t// Re-queue this request so it can be shifted by the finally\n\t\t\t\t\tawait this.#asyncQueue.wait();\n\t\t\t\t\tthis.#shiftSublimit = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Since this is not a server side issue, the next request should pass, so we don't bump the retries counter\n\t\t\treturn this.runRequest(routeId, url, options, requestData, retries);\n\t\t} else {\n\t\t\tconst handled = await handleErrors(this.manager, res, method, url, requestData, retries);\n\t\t\tif (handled === null) {\n\t\t\t\t// eslint-disable-next-line no-param-reassign\n\t\t\t\treturn this.runRequest(routeId, url, options, requestData, ++retries);\n\t\t\t}\n\n\t\t\treturn handled;\n\t\t}\n\t}\n}\n","export * from './lib/CDN.js';\nexport * from './lib/errors/DiscordAPIError.js';\nexport * from './lib/errors/HTTPError.js';\nexport * from './lib/errors/RateLimitError.js';\nexport * from './lib/REST.js';\nexport * from './lib/utils/constants.js';\nexport * from './lib/utils/types.js';\nexport { calculateUserDefaultAvatarIndex, makeURLSearchParams, parseResponse } from './lib/utils/utils.js';\n\n/**\n * The {@link https://github.com/discordjs/discord.js/blob/main/packages/rest#readme | @discordjs/rest} version\n * that you are currently using.\n */\n// This needs to explicitly be `string` so it is not typed as a \"const string\" that gets injected by esbuild\nexport const version = '2.2.0' as string;\n","import { setDefaultStrategy } from './environment.js';\n\nsetDefaultStrategy(fetch);\n\nexport * from './shared.js';\n"],"mappings":"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","names":["RESTEvents","RequestMethod","limit","res"]} |