@discordjs/rest 1.7.0-dev.1679918672-b8b852e.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +8 -5
- package/dist/index.d.ts +8 -3
- package/dist/index.js +232 -96
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +230 -96
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
# [@discordjs/rest@1.7.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@1.6.0...@discordjs/rest@1.7.0) - (2023-04-01)
|
|
6
|
+
|
|
7
|
+
## Bug Fixes
|
|
8
|
+
|
|
9
|
+
- **handlers:** Create burst handler for interaction callbacks (#8996) ([db8df10](https://github.com/discordjs/discord.js/commit/db8df104c5e70a12f35b54e5f3f7c897068dde6f))
|
|
10
|
+
- **scripts:** Accessing tsComment ([d8d5f31](https://github.com/discordjs/discord.js/commit/d8d5f31d3927fd1de62f1fa3a1a6e454243ad87b))
|
|
11
|
+
- **rest:** Remove `const enum`s in favour of regular enums (#9243) ([229ad07](https://github.com/discordjs/discord.js/commit/229ad077ff52d8706d68ed4d31983619a32eba45))
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **website:** Render syntax and mdx on the server (#9086) ([ee5169e](https://github.com/discordjs/discord.js/commit/ee5169e0aadd7bbfcd752aae614ec0f69602b68b))
|
|
16
|
+
|
|
5
17
|
# [@discordjs/rest@1.6.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@1.5.0...@discordjs/rest@1.6.0) - (2023-03-12)
|
|
6
18
|
|
|
7
19
|
## Bug Fixes
|
package/README.md
CHANGED
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
</p>
|
|
17
17
|
</div>
|
|
18
18
|
|
|
19
|
+
## About
|
|
20
|
+
|
|
21
|
+
`@discord.js/rest` is a module that allows you to easily make REST requests to the Discord API.
|
|
22
|
+
|
|
19
23
|
## Installation
|
|
20
24
|
|
|
21
25
|
**Node.js 16.9.0 or newer is required.**
|
|
@@ -80,7 +84,7 @@ try {
|
|
|
80
84
|
- [Website][website] ([source][website-source])
|
|
81
85
|
- [Documentation][documentation]
|
|
82
86
|
- [Guide][guide] ([source][guide-source])
|
|
83
|
-
|
|
87
|
+
Also see the v13 to v14 [Update Guide][guide-update], which includes updated and removed items from the library.
|
|
84
88
|
- [discord.js Discord server][discord]
|
|
85
89
|
- [Discord API Discord server][discord-api]
|
|
86
90
|
- [GitHub][source]
|
|
@@ -95,12 +99,11 @@ See [the contribution guide][contributing] if you'd like to submit a PR.
|
|
|
95
99
|
|
|
96
100
|
## Help
|
|
97
101
|
|
|
98
|
-
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
|
|
99
|
-
nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
|
|
102
|
+
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
|
|
100
103
|
|
|
101
|
-
[website]: https://discord.js.org
|
|
104
|
+
[website]: https://discord.js.org
|
|
102
105
|
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
|
|
103
|
-
[documentation]: https://discord.js.org
|
|
106
|
+
[documentation]: https://discord.js.org/docs/packages/rest/stable
|
|
104
107
|
[guide]: https://discordjs.guide/
|
|
105
108
|
[guide-source]: https://github.com/discordjs/guide
|
|
106
109
|
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,10 @@ import { URLSearchParams } from 'node:url';
|
|
|
5
5
|
import { Collection } from '@discordjs/collection';
|
|
6
6
|
|
|
7
7
|
declare const DefaultUserAgent: `DiscordBot (https://discord.js.org, ${string})`;
|
|
8
|
+
/**
|
|
9
|
+
* The default string to append onto the user agent.
|
|
10
|
+
*/
|
|
11
|
+
declare const DefaultUserAgentAppendix: string;
|
|
8
12
|
declare const DefaultRestOptions: {
|
|
9
13
|
readonly agent: Agent;
|
|
10
14
|
readonly api: "https://discord.com/api";
|
|
@@ -17,7 +21,7 @@ declare const DefaultRestOptions: {
|
|
|
17
21
|
readonly rejectOnRateLimit: null;
|
|
18
22
|
readonly retries: 3;
|
|
19
23
|
readonly timeout: 15000;
|
|
20
|
-
readonly userAgentAppendix:
|
|
24
|
+
readonly userAgentAppendix: string;
|
|
21
25
|
readonly version: "10";
|
|
22
26
|
readonly hashSweepInterval: 14400000;
|
|
23
27
|
readonly hashLifetime: 86400000;
|
|
@@ -43,6 +47,7 @@ type ImageSize = (typeof ALLOWED_SIZES)[number];
|
|
|
43
47
|
declare const OverwrittenMimeTypes: {
|
|
44
48
|
readonly 'image/apng': "image/png";
|
|
45
49
|
};
|
|
50
|
+
declare const BurstHandlerMajorIdKey = "burst";
|
|
46
51
|
|
|
47
52
|
/**
|
|
48
53
|
* The options used for image URLs
|
|
@@ -360,7 +365,7 @@ interface RESTOptions {
|
|
|
360
365
|
/**
|
|
361
366
|
* Extra information to add to the user agent
|
|
362
367
|
*
|
|
363
|
-
* @defaultValue
|
|
368
|
+
* @defaultValue DefaultUserAgentAppendix
|
|
364
369
|
*/
|
|
365
370
|
userAgentAppendix: string;
|
|
366
371
|
/**
|
|
@@ -867,4 +872,4 @@ declare function parseResponse(res: Dispatcher.ResponseData): Promise<unknown>;
|
|
|
867
872
|
*/
|
|
868
873
|
declare const version: string;
|
|
869
874
|
|
|
870
|
-
export { ALLOWED_EXTENSIONS, ALLOWED_SIZES, ALLOWED_STICKER_EXTENSIONS, APIRequest, BaseImageURLOptions, CDN, DefaultRestOptions, DefaultUserAgent, DiscordAPIError, DiscordErrorData, HTTPError, HandlerRequestData, HashData, ImageExtension, ImageSize, ImageURLOptions, InternalRequest, InvalidRequestWarningData, MakeURLOptions, OAuthErrorData, OverwrittenMimeTypes, REST, RESTEvents, RESTOptions, RateLimitData, RateLimitError, RateLimitQueueFilter, RawFile, RequestBody, RequestData, RequestHeaders, RequestManager, RequestMethod, RequestOptions, RestEvents, RouteData, RouteLike, StickerExtension, makeURLSearchParams, parseResponse, version };
|
|
875
|
+
export { ALLOWED_EXTENSIONS, ALLOWED_SIZES, ALLOWED_STICKER_EXTENSIONS, APIRequest, BaseImageURLOptions, BurstHandlerMajorIdKey, CDN, DefaultRestOptions, DefaultUserAgent, DefaultUserAgentAppendix, DiscordAPIError, DiscordErrorData, HTTPError, HandlerRequestData, HashData, ImageExtension, ImageSize, ImageURLOptions, InternalRequest, InvalidRequestWarningData, MakeURLOptions, OAuthErrorData, OverwrittenMimeTypes, REST, RESTEvents, RESTOptions, RateLimitData, RateLimitError, RateLimitQueueFilter, RawFile, RequestBody, RequestData, RequestHeaders, RequestManager, RequestMethod, RequestOptions, RestEvents, RouteData, RouteLike, StickerExtension, makeURLSearchParams, parseResponse, version };
|
package/dist/index.js
CHANGED
|
@@ -34,9 +34,11 @@ __export(src_exports, {
|
|
|
34
34
|
ALLOWED_EXTENSIONS: () => ALLOWED_EXTENSIONS,
|
|
35
35
|
ALLOWED_SIZES: () => ALLOWED_SIZES,
|
|
36
36
|
ALLOWED_STICKER_EXTENSIONS: () => ALLOWED_STICKER_EXTENSIONS,
|
|
37
|
+
BurstHandlerMajorIdKey: () => BurstHandlerMajorIdKey,
|
|
37
38
|
CDN: () => CDN,
|
|
38
39
|
DefaultRestOptions: () => DefaultRestOptions,
|
|
39
40
|
DefaultUserAgent: () => DefaultUserAgent,
|
|
41
|
+
DefaultUserAgentAppendix: () => DefaultUserAgentAppendix,
|
|
40
42
|
DiscordAPIError: () => DiscordAPIError,
|
|
41
43
|
HTTPError: () => HTTPError,
|
|
42
44
|
OverwrittenMimeTypes: () => OverwrittenMimeTypes,
|
|
@@ -58,7 +60,8 @@ var import_node_url = require("url");
|
|
|
58
60
|
var import_node_process = __toESM(require("process"));
|
|
59
61
|
var import_v10 = require("discord-api-types/v10");
|
|
60
62
|
var import_undici = require("undici");
|
|
61
|
-
var DefaultUserAgent = `DiscordBot (https://discord.js.org, 1.7.0
|
|
63
|
+
var DefaultUserAgent = `DiscordBot (https://discord.js.org, 1.7.0)`;
|
|
64
|
+
var DefaultUserAgentAppendix = import_node_process.default.release?.name === "node" ? `Node.js/${import_node_process.default.version}` : "";
|
|
62
65
|
var DefaultRestOptions = {
|
|
63
66
|
get agent() {
|
|
64
67
|
return new import_undici.Agent({
|
|
@@ -77,7 +80,7 @@ var DefaultRestOptions = {
|
|
|
77
80
|
rejectOnRateLimit: null,
|
|
78
81
|
retries: 3,
|
|
79
82
|
timeout: 15e3,
|
|
80
|
-
userAgentAppendix:
|
|
83
|
+
userAgentAppendix: DefaultUserAgentAppendix,
|
|
81
84
|
version: import_v10.APIVersion,
|
|
82
85
|
hashSweepInterval: 144e5,
|
|
83
86
|
// 4 Hours
|
|
@@ -102,6 +105,7 @@ var OverwrittenMimeTypes = {
|
|
|
102
105
|
// https://github.com/discordjs/discord.js/issues/8557
|
|
103
106
|
"image/apng": "image/png"
|
|
104
107
|
};
|
|
108
|
+
var BurstHandlerMajorIdKey = "burst";
|
|
105
109
|
|
|
106
110
|
// src/lib/CDN.ts
|
|
107
111
|
var CDN = class {
|
|
@@ -437,11 +441,8 @@ var import_util = require("@discordjs/util");
|
|
|
437
441
|
var import_snowflake = require("@sapphire/snowflake");
|
|
438
442
|
var import_undici4 = require("undici");
|
|
439
443
|
|
|
440
|
-
// src/lib/handlers/
|
|
441
|
-
var import_node_timers = require("timers");
|
|
444
|
+
// src/lib/handlers/BurstHandler.ts
|
|
442
445
|
var import_promises = require("timers/promises");
|
|
443
|
-
var import_async_queue = require("@sapphire/async-queue");
|
|
444
|
-
var import_undici3 = require("undici");
|
|
445
446
|
|
|
446
447
|
// src/lib/utils/utils.ts
|
|
447
448
|
var import_node_buffer = require("buffer");
|
|
@@ -552,10 +553,199 @@ function shouldRetry(error) {
|
|
|
552
553
|
return "code" in error && error.code === "ECONNRESET" || error.message.includes("ECONNRESET");
|
|
553
554
|
}
|
|
554
555
|
__name(shouldRetry, "shouldRetry");
|
|
556
|
+
async function onRateLimit(manager, rateLimitData) {
|
|
557
|
+
const { options } = manager;
|
|
558
|
+
if (!options.rejectOnRateLimit)
|
|
559
|
+
return;
|
|
560
|
+
const shouldThrow = typeof options.rejectOnRateLimit === "function" ? await options.rejectOnRateLimit(rateLimitData) : options.rejectOnRateLimit.some((route) => rateLimitData.route.startsWith(route.toLowerCase()));
|
|
561
|
+
if (shouldThrow) {
|
|
562
|
+
throw new RateLimitError(rateLimitData);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
__name(onRateLimit, "onRateLimit");
|
|
555
566
|
|
|
556
|
-
// src/lib/handlers/
|
|
567
|
+
// src/lib/handlers/Shared.ts
|
|
568
|
+
var import_node_timers = require("timers");
|
|
569
|
+
var import_undici3 = require("undici");
|
|
557
570
|
var invalidCount = 0;
|
|
558
571
|
var invalidCountResetTime = null;
|
|
572
|
+
function incrementInvalidCount(manager) {
|
|
573
|
+
if (!invalidCountResetTime || invalidCountResetTime < Date.now()) {
|
|
574
|
+
invalidCountResetTime = Date.now() + 1e3 * 60 * 10;
|
|
575
|
+
invalidCount = 0;
|
|
576
|
+
}
|
|
577
|
+
invalidCount++;
|
|
578
|
+
const emitInvalid = manager.options.invalidRequestWarningInterval > 0 && invalidCount % manager.options.invalidRequestWarningInterval === 0;
|
|
579
|
+
if (emitInvalid) {
|
|
580
|
+
manager.emit("invalidRequestWarning" /* InvalidRequestWarning */, {
|
|
581
|
+
count: invalidCount,
|
|
582
|
+
remainingTime: invalidCountResetTime - Date.now()
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
__name(incrementInvalidCount, "incrementInvalidCount");
|
|
587
|
+
async function makeNetworkRequest(manager, routeId, url, options, requestData, retries) {
|
|
588
|
+
const controller = new AbortController();
|
|
589
|
+
const timeout = (0, import_node_timers.setTimeout)(() => controller.abort(), manager.options.timeout).unref();
|
|
590
|
+
if (requestData.signal) {
|
|
591
|
+
const signal = requestData.signal;
|
|
592
|
+
if (signal.aborted)
|
|
593
|
+
controller.abort();
|
|
594
|
+
else
|
|
595
|
+
signal.addEventListener("abort", () => controller.abort());
|
|
596
|
+
}
|
|
597
|
+
let res;
|
|
598
|
+
try {
|
|
599
|
+
res = await (0, import_undici3.request)(url, { ...options, signal: controller.signal });
|
|
600
|
+
} catch (error) {
|
|
601
|
+
if (!(error instanceof Error))
|
|
602
|
+
throw error;
|
|
603
|
+
if (shouldRetry(error) && retries !== manager.options.retries) {
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
throw error;
|
|
607
|
+
} finally {
|
|
608
|
+
(0, import_node_timers.clearTimeout)(timeout);
|
|
609
|
+
}
|
|
610
|
+
if (manager.listenerCount("response" /* Response */)) {
|
|
611
|
+
manager.emit(
|
|
612
|
+
"response" /* Response */,
|
|
613
|
+
{
|
|
614
|
+
method: options.method ?? "get",
|
|
615
|
+
path: routeId.original,
|
|
616
|
+
route: routeId.bucketRoute,
|
|
617
|
+
options,
|
|
618
|
+
data: requestData,
|
|
619
|
+
retries
|
|
620
|
+
},
|
|
621
|
+
{ ...res }
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
return res;
|
|
625
|
+
}
|
|
626
|
+
__name(makeNetworkRequest, "makeNetworkRequest");
|
|
627
|
+
async function handleErrors(manager, res, method, url, requestData, retries) {
|
|
628
|
+
const status = res.statusCode;
|
|
629
|
+
if (status >= 500 && status < 600) {
|
|
630
|
+
if (retries !== manager.options.retries) {
|
|
631
|
+
return null;
|
|
632
|
+
}
|
|
633
|
+
throw new HTTPError(status, method, url, requestData);
|
|
634
|
+
} else {
|
|
635
|
+
if (status >= 400 && status < 500) {
|
|
636
|
+
if (status === 401 && requestData.auth) {
|
|
637
|
+
manager.setToken(null);
|
|
638
|
+
}
|
|
639
|
+
const data = await parseResponse(res);
|
|
640
|
+
throw new DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
|
|
641
|
+
}
|
|
642
|
+
return res;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
__name(handleErrors, "handleErrors");
|
|
646
|
+
|
|
647
|
+
// src/lib/handlers/BurstHandler.ts
|
|
648
|
+
var BurstHandler = class {
|
|
649
|
+
/**
|
|
650
|
+
* @param manager - The request manager
|
|
651
|
+
* @param hash - The hash that this RequestHandler handles
|
|
652
|
+
* @param majorParameter - The major parameter for this handler
|
|
653
|
+
*/
|
|
654
|
+
constructor(manager, hash, majorParameter) {
|
|
655
|
+
this.manager = manager;
|
|
656
|
+
this.hash = hash;
|
|
657
|
+
this.majorParameter = majorParameter;
|
|
658
|
+
this.id = `${hash}:${majorParameter}`;
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* {@inheritdoc IHandler.id}
|
|
662
|
+
*/
|
|
663
|
+
id;
|
|
664
|
+
/**
|
|
665
|
+
* {@inheritDoc IHandler.inactive}
|
|
666
|
+
*/
|
|
667
|
+
inactive = false;
|
|
668
|
+
/**
|
|
669
|
+
* Emits a debug message
|
|
670
|
+
*
|
|
671
|
+
* @param message - The message to debug
|
|
672
|
+
*/
|
|
673
|
+
debug(message) {
|
|
674
|
+
this.manager.emit("restDebug" /* Debug */, `[REST ${this.id}] ${message}`);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* {@inheritDoc IHandler.queueRequest}
|
|
678
|
+
*/
|
|
679
|
+
async queueRequest(routeId, url, options, requestData) {
|
|
680
|
+
return this.runRequest(routeId, url, options, requestData);
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* The method that actually makes the request to the API, and updates info about the bucket accordingly
|
|
684
|
+
*
|
|
685
|
+
* @param routeId - The generalized API route with literal ids for major parameters
|
|
686
|
+
* @param url - The fully resolved URL to make the request to
|
|
687
|
+
* @param options - The fetch options needed to make the request
|
|
688
|
+
* @param requestData - Extra data from the user's request needed for errors and additional processing
|
|
689
|
+
* @param retries - The number of retries this request has already attempted (recursion)
|
|
690
|
+
*/
|
|
691
|
+
async runRequest(routeId, url, options, requestData, retries = 0) {
|
|
692
|
+
const method = options.method ?? "get";
|
|
693
|
+
const res = await makeNetworkRequest(this.manager, routeId, url, options, requestData, retries);
|
|
694
|
+
if (res === null) {
|
|
695
|
+
return this.runRequest(routeId, url, options, requestData, ++retries);
|
|
696
|
+
}
|
|
697
|
+
const status = res.statusCode;
|
|
698
|
+
let retryAfter = 0;
|
|
699
|
+
const retry = parseHeader(res.headers["retry-after"]);
|
|
700
|
+
if (retry)
|
|
701
|
+
retryAfter = Number(retry) * 1e3 + this.manager.options.offset;
|
|
702
|
+
if (status === 401 || status === 403 || status === 429) {
|
|
703
|
+
incrementInvalidCount(this.manager);
|
|
704
|
+
}
|
|
705
|
+
if (status >= 200 && status < 300) {
|
|
706
|
+
return res;
|
|
707
|
+
} else if (status === 429) {
|
|
708
|
+
const isGlobal = res.headers["x-ratelimit-global"] !== void 0;
|
|
709
|
+
await onRateLimit(this.manager, {
|
|
710
|
+
timeToReset: retryAfter,
|
|
711
|
+
limit: Number.POSITIVE_INFINITY,
|
|
712
|
+
method,
|
|
713
|
+
hash: this.hash,
|
|
714
|
+
url,
|
|
715
|
+
route: routeId.bucketRoute,
|
|
716
|
+
majorParameter: this.majorParameter,
|
|
717
|
+
global: isGlobal
|
|
718
|
+
});
|
|
719
|
+
this.debug(
|
|
720
|
+
[
|
|
721
|
+
"Encountered unexpected 429 rate limit",
|
|
722
|
+
` Global : ${isGlobal}`,
|
|
723
|
+
` Method : ${method}`,
|
|
724
|
+
` URL : ${url}`,
|
|
725
|
+
` Bucket : ${routeId.bucketRoute}`,
|
|
726
|
+
` Major parameter: ${routeId.majorParameter}`,
|
|
727
|
+
` Hash : ${this.hash}`,
|
|
728
|
+
` Limit : ${Number.POSITIVE_INFINITY}`,
|
|
729
|
+
` Retry After : ${retryAfter}ms`,
|
|
730
|
+
` Sublimit : None`
|
|
731
|
+
].join("\n")
|
|
732
|
+
);
|
|
733
|
+
await (0, import_promises.setTimeout)(retryAfter);
|
|
734
|
+
return this.runRequest(routeId, url, options, requestData, retries);
|
|
735
|
+
} else {
|
|
736
|
+
const handled = await handleErrors(this.manager, res, method, url, requestData, retries);
|
|
737
|
+
if (handled === null) {
|
|
738
|
+
return this.runRequest(routeId, url, options, requestData, ++retries);
|
|
739
|
+
}
|
|
740
|
+
return handled;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
__name(BurstHandler, "BurstHandler");
|
|
745
|
+
|
|
746
|
+
// src/lib/handlers/SequentialHandler.ts
|
|
747
|
+
var import_promises2 = require("timers/promises");
|
|
748
|
+
var import_async_queue = require("@sapphire/async-queue");
|
|
559
749
|
var SequentialHandler = class {
|
|
560
750
|
/**
|
|
561
751
|
* @param manager - The request manager
|
|
@@ -644,21 +834,9 @@ var SequentialHandler = class {
|
|
|
644
834
|
* @param time - The amount of time to delay all requests for
|
|
645
835
|
*/
|
|
646
836
|
async globalDelayFor(time) {
|
|
647
|
-
await (0,
|
|
837
|
+
await (0, import_promises2.setTimeout)(time);
|
|
648
838
|
this.manager.globalDelay = null;
|
|
649
839
|
}
|
|
650
|
-
/*
|
|
651
|
-
* Determines whether the request should be queued or whether a RateLimitError should be thrown
|
|
652
|
-
*/
|
|
653
|
-
async onRateLimit(rateLimitData) {
|
|
654
|
-
const { options } = this.manager;
|
|
655
|
-
if (!options.rejectOnRateLimit)
|
|
656
|
-
return;
|
|
657
|
-
const shouldThrow = typeof options.rejectOnRateLimit === "function" ? await options.rejectOnRateLimit(rateLimitData) : options.rejectOnRateLimit.some((route) => rateLimitData.route.startsWith(route.toLowerCase()));
|
|
658
|
-
if (shouldThrow) {
|
|
659
|
-
throw new RateLimitError(rateLimitData);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
840
|
/**
|
|
663
841
|
* {@inheritDoc IHandler.queueRequest}
|
|
664
842
|
*/
|
|
@@ -707,22 +885,22 @@ var SequentialHandler = class {
|
|
|
707
885
|
while (this.limited) {
|
|
708
886
|
const isGlobal = this.globalLimited;
|
|
709
887
|
let limit2;
|
|
710
|
-
let
|
|
888
|
+
let timeout;
|
|
711
889
|
let delay;
|
|
712
890
|
if (isGlobal) {
|
|
713
891
|
limit2 = this.manager.options.globalRequestsPerSecond;
|
|
714
|
-
|
|
892
|
+
timeout = this.manager.globalReset + this.manager.options.offset - Date.now();
|
|
715
893
|
if (!this.manager.globalDelay) {
|
|
716
|
-
this.manager.globalDelay = this.globalDelayFor(
|
|
894
|
+
this.manager.globalDelay = this.globalDelayFor(timeout);
|
|
717
895
|
}
|
|
718
896
|
delay = this.manager.globalDelay;
|
|
719
897
|
} else {
|
|
720
898
|
limit2 = this.limit;
|
|
721
|
-
|
|
722
|
-
delay = (0,
|
|
899
|
+
timeout = this.timeToReset;
|
|
900
|
+
delay = (0, import_promises2.setTimeout)(timeout);
|
|
723
901
|
}
|
|
724
902
|
const rateLimitData = {
|
|
725
|
-
timeToReset:
|
|
903
|
+
timeToReset: timeout,
|
|
726
904
|
limit: limit2,
|
|
727
905
|
method: options.method ?? "get",
|
|
728
906
|
hash: this.hash,
|
|
@@ -732,11 +910,11 @@ var SequentialHandler = class {
|
|
|
732
910
|
global: isGlobal
|
|
733
911
|
};
|
|
734
912
|
this.manager.emit("rateLimited" /* RateLimited */, rateLimitData);
|
|
735
|
-
await this.
|
|
913
|
+
await onRateLimit(this.manager, rateLimitData);
|
|
736
914
|
if (isGlobal) {
|
|
737
|
-
this.debug(`Global rate limit hit, blocking all requests for ${
|
|
915
|
+
this.debug(`Global rate limit hit, blocking all requests for ${timeout}ms`);
|
|
738
916
|
} else {
|
|
739
|
-
this.debug(`Waiting ${
|
|
917
|
+
this.debug(`Waiting ${timeout}ms for rate limit to pass`);
|
|
740
918
|
}
|
|
741
919
|
await delay;
|
|
742
920
|
}
|
|
@@ -746,41 +924,9 @@ var SequentialHandler = class {
|
|
|
746
924
|
}
|
|
747
925
|
this.manager.globalRemaining--;
|
|
748
926
|
const method = options.method ?? "get";
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
const signal = requestData.signal;
|
|
753
|
-
if (signal.aborted)
|
|
754
|
-
controller.abort();
|
|
755
|
-
else
|
|
756
|
-
signal.addEventListener("abort", () => controller.abort());
|
|
757
|
-
}
|
|
758
|
-
let res;
|
|
759
|
-
try {
|
|
760
|
-
res = await (0, import_undici3.request)(url, { ...options, signal: controller.signal });
|
|
761
|
-
} catch (error) {
|
|
762
|
-
if (!(error instanceof Error))
|
|
763
|
-
throw error;
|
|
764
|
-
if (shouldRetry(error) && retries !== this.manager.options.retries) {
|
|
765
|
-
return await this.runRequest(routeId, url, options, requestData, ++retries);
|
|
766
|
-
}
|
|
767
|
-
throw error;
|
|
768
|
-
} finally {
|
|
769
|
-
(0, import_node_timers.clearTimeout)(timeout);
|
|
770
|
-
}
|
|
771
|
-
if (this.manager.listenerCount("response" /* Response */)) {
|
|
772
|
-
this.manager.emit(
|
|
773
|
-
"response" /* Response */,
|
|
774
|
-
{
|
|
775
|
-
method,
|
|
776
|
-
path: routeId.original,
|
|
777
|
-
route: routeId.bucketRoute,
|
|
778
|
-
options,
|
|
779
|
-
data: requestData,
|
|
780
|
-
retries
|
|
781
|
-
},
|
|
782
|
-
{ ...res }
|
|
783
|
-
);
|
|
927
|
+
const res = await makeNetworkRequest(this.manager, routeId, url, options, requestData, retries);
|
|
928
|
+
if (res === null) {
|
|
929
|
+
return this.runRequest(routeId, url, options, requestData, ++retries);
|
|
784
930
|
}
|
|
785
931
|
const status = res.statusCode;
|
|
786
932
|
let retryAfter = 0;
|
|
@@ -813,34 +959,23 @@ var SequentialHandler = class {
|
|
|
813
959
|
}
|
|
814
960
|
}
|
|
815
961
|
if (status === 401 || status === 403 || status === 429) {
|
|
816
|
-
|
|
817
|
-
invalidCountResetTime = Date.now() + 1e3 * 60 * 10;
|
|
818
|
-
invalidCount = 0;
|
|
819
|
-
}
|
|
820
|
-
invalidCount++;
|
|
821
|
-
const emitInvalid = this.manager.options.invalidRequestWarningInterval > 0 && invalidCount % this.manager.options.invalidRequestWarningInterval === 0;
|
|
822
|
-
if (emitInvalid) {
|
|
823
|
-
this.manager.emit("invalidRequestWarning" /* InvalidRequestWarning */, {
|
|
824
|
-
count: invalidCount,
|
|
825
|
-
remainingTime: invalidCountResetTime - Date.now()
|
|
826
|
-
});
|
|
827
|
-
}
|
|
962
|
+
incrementInvalidCount(this.manager);
|
|
828
963
|
}
|
|
829
964
|
if (status >= 200 && status < 300) {
|
|
830
965
|
return res;
|
|
831
966
|
} else if (status === 429) {
|
|
832
967
|
const isGlobal = this.globalLimited;
|
|
833
968
|
let limit2;
|
|
834
|
-
let
|
|
969
|
+
let timeout;
|
|
835
970
|
if (isGlobal) {
|
|
836
971
|
limit2 = this.manager.options.globalRequestsPerSecond;
|
|
837
|
-
|
|
972
|
+
timeout = this.manager.globalReset + this.manager.options.offset - Date.now();
|
|
838
973
|
} else {
|
|
839
974
|
limit2 = this.limit;
|
|
840
|
-
|
|
975
|
+
timeout = this.timeToReset;
|
|
841
976
|
}
|
|
842
|
-
await this.
|
|
843
|
-
timeToReset:
|
|
977
|
+
await onRateLimit(this.manager, {
|
|
978
|
+
timeToReset: timeout,
|
|
844
979
|
limit: limit2,
|
|
845
980
|
method,
|
|
846
981
|
hash: this.hash,
|
|
@@ -872,7 +1007,7 @@ var SequentialHandler = class {
|
|
|
872
1007
|
}
|
|
873
1008
|
this.#sublimitPromise?.resolve();
|
|
874
1009
|
this.#sublimitPromise = null;
|
|
875
|
-
await (0,
|
|
1010
|
+
await (0, import_promises2.setTimeout)(sublimitTimeout);
|
|
876
1011
|
let resolve;
|
|
877
1012
|
const promise = new Promise((res2) => resolve = res2);
|
|
878
1013
|
this.#sublimitPromise = { promise, resolve };
|
|
@@ -882,20 +1017,12 @@ var SequentialHandler = class {
|
|
|
882
1017
|
}
|
|
883
1018
|
}
|
|
884
1019
|
return this.runRequest(routeId, url, options, requestData, retries);
|
|
885
|
-
} else if (status >= 500 && status < 600) {
|
|
886
|
-
if (retries !== this.manager.options.retries) {
|
|
887
|
-
return this.runRequest(routeId, url, options, requestData, ++retries);
|
|
888
|
-
}
|
|
889
|
-
throw new HTTPError(status, method, url, requestData);
|
|
890
1020
|
} else {
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
}
|
|
895
|
-
const data = await parseResponse(res);
|
|
896
|
-
throw new DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
|
|
1021
|
+
const handled = await handleErrors(this.manager, res, method, url, requestData, retries);
|
|
1022
|
+
if (handled === null) {
|
|
1023
|
+
return this.runRequest(routeId, url, options, requestData, ++retries);
|
|
897
1024
|
}
|
|
898
|
-
return
|
|
1025
|
+
return handled;
|
|
899
1026
|
}
|
|
900
1027
|
}
|
|
901
1028
|
};
|
|
@@ -1036,7 +1163,7 @@ var RequestManager = class extends import_node_events.EventEmitter {
|
|
|
1036
1163
|
* @internal
|
|
1037
1164
|
*/
|
|
1038
1165
|
createHandler(hash, majorParameter) {
|
|
1039
|
-
const queue = new SequentialHandler(this, hash, majorParameter);
|
|
1166
|
+
const queue = majorParameter === BurstHandlerMajorIdKey ? new BurstHandler(this, hash, majorParameter) : new SequentialHandler(this, hash, majorParameter);
|
|
1040
1167
|
this.handlers.set(queue.id, queue);
|
|
1041
1168
|
return queue;
|
|
1042
1169
|
}
|
|
@@ -1137,6 +1264,13 @@ var RequestManager = class extends import_node_events.EventEmitter {
|
|
|
1137
1264
|
* @internal
|
|
1138
1265
|
*/
|
|
1139
1266
|
static generateRouteData(endpoint, method) {
|
|
1267
|
+
if (endpoint.startsWith("/interactions/") && endpoint.endsWith("/callback")) {
|
|
1268
|
+
return {
|
|
1269
|
+
majorParameter: BurstHandlerMajorIdKey,
|
|
1270
|
+
bucketRoute: "/interactions/:id/:token/callback",
|
|
1271
|
+
original: endpoint
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1140
1274
|
const majorIdMatch = /^\/(?:channels|guilds|webhooks)\/(\d{17,19})/.exec(endpoint);
|
|
1141
1275
|
const majorId = majorIdMatch?.[1] ?? "global";
|
|
1142
1276
|
const baseRoute = endpoint.replaceAll(/\d{17,19}/g, ":id").replace(/\/reactions\/(.*)/, "/reactions/:reaction");
|
|
@@ -1265,15 +1399,17 @@ var REST = class extends import_node_events2.EventEmitter {
|
|
|
1265
1399
|
__name(REST, "REST");
|
|
1266
1400
|
|
|
1267
1401
|
// src/index.ts
|
|
1268
|
-
var version = "1.7.0
|
|
1402
|
+
var version = "1.7.0";
|
|
1269
1403
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1270
1404
|
0 && (module.exports = {
|
|
1271
1405
|
ALLOWED_EXTENSIONS,
|
|
1272
1406
|
ALLOWED_SIZES,
|
|
1273
1407
|
ALLOWED_STICKER_EXTENSIONS,
|
|
1408
|
+
BurstHandlerMajorIdKey,
|
|
1274
1409
|
CDN,
|
|
1275
1410
|
DefaultRestOptions,
|
|
1276
1411
|
DefaultUserAgent,
|
|
1412
|
+
DefaultUserAgentAppendix,
|
|
1277
1413
|
DiscordAPIError,
|
|
1278
1414
|
HTTPError,
|
|
1279
1415
|
OverwrittenMimeTypes,
|