@discordjs/rest 1.6.0-dev.1677456613-ffdb197.0 → 1.6.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/dist/index.js CHANGED
@@ -19,6 +19,10 @@ var __copyProps = (to, from, except, desc) => {
19
19
  return to;
20
20
  };
21
21
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
26
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
27
  mod
24
28
  ));
@@ -54,7 +58,7 @@ var import_node_url = require("url");
54
58
  var import_node_process = __toESM(require("process"));
55
59
  var import_v10 = require("discord-api-types/v10");
56
60
  var import_undici = require("undici");
57
- var DefaultUserAgent = `DiscordBot (https://discord.js.org, 1.6.0-dev.1677456613-ffdb197.0)`;
61
+ var DefaultUserAgent = `DiscordBot (https://discord.js.org, [VI]{{inject}}[/VI])`;
58
62
  var DefaultRestOptions = {
59
63
  get agent() {
60
64
  return new import_undici.Agent({
@@ -79,19 +83,40 @@ var DefaultRestOptions = {
79
83
  hashLifetime: 864e5,
80
84
  handlerSweepInterval: 36e5
81
85
  };
82
- var RESTEvents = /* @__PURE__ */ ((RESTEvents2) => {
86
+ var RESTEvents;
87
+ (function(RESTEvents2) {
83
88
  RESTEvents2["Debug"] = "restDebug";
84
89
  RESTEvents2["HandlerSweep"] = "handlerSweep";
85
90
  RESTEvents2["HashSweep"] = "hashSweep";
86
91
  RESTEvents2["InvalidRequestWarning"] = "invalidRequestWarning";
87
92
  RESTEvents2["RateLimited"] = "rateLimited";
88
93
  RESTEvents2["Response"] = "response";
89
- return RESTEvents2;
90
- })(RESTEvents || {});
91
- var ALLOWED_EXTENSIONS = ["webp", "png", "jpg", "jpeg", "gif"];
92
- var ALLOWED_STICKER_EXTENSIONS = ["png", "json", "gif"];
93
- var ALLOWED_SIZES = [16, 32, 64, 128, 256, 512, 1024, 2048, 4096];
94
+ })(RESTEvents || (RESTEvents = {}));
95
+ var ALLOWED_EXTENSIONS = [
96
+ "webp",
97
+ "png",
98
+ "jpg",
99
+ "jpeg",
100
+ "gif"
101
+ ];
102
+ var ALLOWED_STICKER_EXTENSIONS = [
103
+ "png",
104
+ "json",
105
+ "gif"
106
+ ];
107
+ var ALLOWED_SIZES = [
108
+ 16,
109
+ 32,
110
+ 64,
111
+ 128,
112
+ 256,
113
+ 512,
114
+ 1024,
115
+ 2048,
116
+ 4096
117
+ ];
94
118
  var OverwrittenMimeTypes = {
119
+ // https://github.com/discordjs/discord.js/issues/8557
95
120
  "image/apng": "image/png"
96
121
  };
97
122
 
@@ -100,60 +125,201 @@ var CDN = class {
100
125
  constructor(base = DefaultRestOptions.cdn) {
101
126
  this.base = base;
102
127
  }
128
+ /**
129
+ * Generates an app asset URL for a client's asset.
130
+ *
131
+ * @param clientId - The client id that has the asset
132
+ * @param assetHash - The hash provided by Discord for this asset
133
+ * @param options - Optional options for the asset
134
+ */
103
135
  appAsset(clientId, assetHash, options) {
104
136
  return this.makeURL(`/app-assets/${clientId}/${assetHash}`, options);
105
137
  }
138
+ /**
139
+ * Generates an app icon URL for a client's icon.
140
+ *
141
+ * @param clientId - The client id that has the icon
142
+ * @param iconHash - The hash provided by Discord for this icon
143
+ * @param options - Optional options for the icon
144
+ */
106
145
  appIcon(clientId, iconHash, options) {
107
146
  return this.makeURL(`/app-icons/${clientId}/${iconHash}`, options);
108
147
  }
148
+ /**
149
+ * Generates an avatar URL, e.g. for a user or a webhook.
150
+ *
151
+ * @param id - The id that has the icon
152
+ * @param avatarHash - The hash provided by Discord for this avatar
153
+ * @param options - Optional options for the avatar
154
+ */
109
155
  avatar(id, avatarHash, options) {
110
156
  return this.dynamicMakeURL(`/avatars/${id}/${avatarHash}`, avatarHash, options);
111
157
  }
158
+ /**
159
+ * Generates a banner URL, e.g. for a user or a guild.
160
+ *
161
+ * @param id - The id that has the banner splash
162
+ * @param bannerHash - The hash provided by Discord for this banner
163
+ * @param options - Optional options for the banner
164
+ */
112
165
  banner(id, bannerHash, options) {
113
166
  return this.dynamicMakeURL(`/banners/${id}/${bannerHash}`, bannerHash, options);
114
167
  }
168
+ /**
169
+ * Generates an icon URL for a channel, e.g. a group DM.
170
+ *
171
+ * @param channelId - The channel id that has the icon
172
+ * @param iconHash - The hash provided by Discord for this channel
173
+ * @param options - Optional options for the icon
174
+ */
115
175
  channelIcon(channelId, iconHash, options) {
116
176
  return this.makeURL(`/channel-icons/${channelId}/${iconHash}`, options);
117
177
  }
178
+ /**
179
+ * Generates the default avatar URL for a discriminator.
180
+ *
181
+ * @param discriminator - The discriminator modulo 5
182
+ */
118
183
  defaultAvatar(discriminator) {
119
- return this.makeURL(`/embed/avatars/${discriminator}`, { extension: "png" });
184
+ return this.makeURL(`/embed/avatars/${discriminator}`, {
185
+ extension: "png"
186
+ });
120
187
  }
188
+ /**
189
+ * Generates a discovery splash URL for a guild's discovery splash.
190
+ *
191
+ * @param guildId - The guild id that has the discovery splash
192
+ * @param splashHash - The hash provided by Discord for this splash
193
+ * @param options - Optional options for the splash
194
+ */
121
195
  discoverySplash(guildId, splashHash, options) {
122
196
  return this.makeURL(`/discovery-splashes/${guildId}/${splashHash}`, options);
123
197
  }
198
+ /**
199
+ * Generates an emoji's URL for an emoji.
200
+ *
201
+ * @param emojiId - The emoji id
202
+ * @param extension - The extension of the emoji
203
+ */
124
204
  emoji(emojiId, extension) {
125
- return this.makeURL(`/emojis/${emojiId}`, { extension });
205
+ return this.makeURL(`/emojis/${emojiId}`, {
206
+ extension
207
+ });
126
208
  }
209
+ /**
210
+ * Generates a guild member avatar URL.
211
+ *
212
+ * @param guildId - The id of the guild
213
+ * @param userId - The id of the user
214
+ * @param avatarHash - The hash provided by Discord for this avatar
215
+ * @param options - Optional options for the avatar
216
+ */
127
217
  guildMemberAvatar(guildId, userId, avatarHash, options) {
128
218
  return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/avatars/${avatarHash}`, avatarHash, options);
129
219
  }
220
+ /**
221
+ * Generates a guild member banner URL.
222
+ *
223
+ * @param guildId - The id of the guild
224
+ * @param userId - The id of the user
225
+ * @param bannerHash - The hash provided by Discord for this banner
226
+ * @param options - Optional options for the banner
227
+ */
130
228
  guildMemberBanner(guildId, userId, bannerHash, options) {
131
229
  return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/banner`, bannerHash, options);
132
230
  }
231
+ /**
232
+ * Generates an icon URL, e.g. for a guild.
233
+ *
234
+ * @param id - The id that has the icon splash
235
+ * @param iconHash - The hash provided by Discord for this icon
236
+ * @param options - Optional options for the icon
237
+ */
133
238
  icon(id, iconHash, options) {
134
239
  return this.dynamicMakeURL(`/icons/${id}/${iconHash}`, iconHash, options);
135
240
  }
241
+ /**
242
+ * Generates a URL for the icon of a role
243
+ *
244
+ * @param roleId - The id of the role that has the icon
245
+ * @param roleIconHash - The hash provided by Discord for this role icon
246
+ * @param options - Optional options for the role icon
247
+ */
136
248
  roleIcon(roleId, roleIconHash, options) {
137
249
  return this.makeURL(`/role-icons/${roleId}/${roleIconHash}`, options);
138
250
  }
251
+ /**
252
+ * Generates a guild invite splash URL for a guild's invite splash.
253
+ *
254
+ * @param guildId - The guild id that has the invite splash
255
+ * @param splashHash - The hash provided by Discord for this splash
256
+ * @param options - Optional options for the splash
257
+ */
139
258
  splash(guildId, splashHash, options) {
140
259
  return this.makeURL(`/splashes/${guildId}/${splashHash}`, options);
141
260
  }
261
+ /**
262
+ * Generates a sticker URL.
263
+ *
264
+ * @param stickerId - The sticker id
265
+ * @param extension - The extension of the sticker
266
+ * @privateRemarks
267
+ * Stickers cannot have a `.webp` extension, so we default to a `.png`
268
+ */
142
269
  sticker(stickerId, extension = "png") {
143
- return this.makeURL(`/stickers/${stickerId}`, { allowedExtensions: ALLOWED_STICKER_EXTENSIONS, extension });
270
+ return this.makeURL(`/stickers/${stickerId}`, {
271
+ allowedExtensions: ALLOWED_STICKER_EXTENSIONS,
272
+ extension
273
+ });
144
274
  }
275
+ /**
276
+ * Generates a sticker pack banner URL.
277
+ *
278
+ * @param bannerId - The banner id
279
+ * @param options - Optional options for the banner
280
+ */
145
281
  stickerPackBanner(bannerId, options) {
146
282
  return this.makeURL(`/app-assets/710982414301790216/store/${bannerId}`, options);
147
283
  }
284
+ /**
285
+ * Generates a team icon URL for a team's icon.
286
+ *
287
+ * @param teamId - The team id that has the icon
288
+ * @param iconHash - The hash provided by Discord for this icon
289
+ * @param options - Optional options for the icon
290
+ */
148
291
  teamIcon(teamId, iconHash, options) {
149
292
  return this.makeURL(`/team-icons/${teamId}/${iconHash}`, options);
150
293
  }
294
+ /**
295
+ * Generates a cover image for a guild scheduled event.
296
+ *
297
+ * @param scheduledEventId - The scheduled event id
298
+ * @param coverHash - The hash provided by discord for this cover image
299
+ * @param options - Optional options for the cover image
300
+ */
151
301
  guildScheduledEventCover(scheduledEventId, coverHash, options) {
152
302
  return this.makeURL(`/guild-events/${scheduledEventId}/${coverHash}`, options);
153
303
  }
304
+ /**
305
+ * Constructs the URL for the resource, checking whether or not `hash` starts with `a_` if `dynamic` is set to `true`.
306
+ *
307
+ * @param route - The base cdn route
308
+ * @param hash - The hash provided by Discord for this icon
309
+ * @param options - Optional options for the link
310
+ */
154
311
  dynamicMakeURL(route, hash, { forceStatic = false, ...options } = {}) {
155
- return this.makeURL(route, !forceStatic && hash.startsWith("a_") ? { ...options, extension: "gif" } : options);
156
- }
312
+ return this.makeURL(route, !forceStatic && hash.startsWith("a_") ? {
313
+ ...options,
314
+ extension: "gif"
315
+ } : options);
316
+ }
317
+ /**
318
+ * Constructs the URL for the resource
319
+ *
320
+ * @param route - The base cdn route
321
+ * @param options - The extension/size options for the link
322
+ */
157
323
  makeURL(route, { allowedExtensions = ALLOWED_EXTENSIONS, extension = "webp", size } = {}) {
158
324
  extension = String(extension).toLowerCase();
159
325
  if (!allowedExtensions.includes(extension)) {
@@ -183,6 +349,14 @@ function isErrorResponse(error) {
183
349
  }
184
350
  __name(isErrorResponse, "isErrorResponse");
185
351
  var DiscordAPIError = class extends Error {
352
+ /**
353
+ * @param rawError - The error reported by Discord
354
+ * @param code - The error code reported by Discord
355
+ * @param status - The status code of the response
356
+ * @param method - The method of the request that erred
357
+ * @param url - The url of the request that erred
358
+ * @param bodyData - The unparsed data for the request that errored
359
+ */
186
360
  constructor(rawError, code, status, method, url, bodyData) {
187
361
  super(DiscordAPIError.getMessage(rawError));
188
362
  this.rawError = rawError;
@@ -190,9 +364,14 @@ var DiscordAPIError = class extends Error {
190
364
  this.status = status;
191
365
  this.method = method;
192
366
  this.url = url;
193
- this.requestBody = { files: bodyData.files, json: bodyData.body };
367
+ this.requestBody = {
368
+ files: bodyData.files,
369
+ json: bodyData.body
370
+ };
194
371
  }
195
- requestBody;
372
+ /**
373
+ * The name of the error
374
+ */
196
375
  get name() {
197
376
  return `${DiscordAPIError.name}[${this.code}]`;
198
377
  }
@@ -200,7 +379,9 @@ var DiscordAPIError = class extends Error {
200
379
  let flattened = "";
201
380
  if ("code" in error) {
202
381
  if (error.errors) {
203
- flattened = [...this.flattenDiscordError(error.errors)].join("\n");
382
+ flattened = [
383
+ ...this.flattenDiscordError(error.errors)
384
+ ].join("\n");
204
385
  }
205
386
  return error.message && flattened ? `${error.message}
206
387
  ${flattened}` : error.message || flattened || "Unknown Error";
@@ -230,28 +411,28 @@ __name(DiscordAPIError, "DiscordAPIError");
230
411
  // src/lib/errors/HTTPError.ts
231
412
  var import_node_http = require("http");
232
413
  var HTTPError = class extends Error {
414
+ /**
415
+ * @param status - The status code of the response
416
+ * @param method - The method of the request that erred
417
+ * @param url - The url of the request that erred
418
+ * @param bodyData - The unparsed data for the request that errored
419
+ */
233
420
  constructor(status, method, url, bodyData) {
234
421
  super(import_node_http.STATUS_CODES[status]);
235
422
  this.status = status;
236
423
  this.method = method;
237
424
  this.url = url;
238
- this.requestBody = { files: bodyData.files, json: bodyData.body };
425
+ this.name = HTTPError.name;
426
+ this.requestBody = {
427
+ files: bodyData.files,
428
+ json: bodyData.body
429
+ };
239
430
  }
240
- requestBody;
241
- name = HTTPError.name;
242
431
  };
243
432
  __name(HTTPError, "HTTPError");
244
433
 
245
434
  // src/lib/errors/RateLimitError.ts
246
435
  var RateLimitError = class extends Error {
247
- timeToReset;
248
- limit;
249
- method;
250
- hash;
251
- url;
252
- route;
253
- majorParameter;
254
- global;
255
436
  constructor({ timeToReset, limit, method, hash, url, route, majorParameter, global }) {
256
437
  super();
257
438
  this.timeToReset = timeToReset;
@@ -263,6 +444,9 @@ var RateLimitError = class extends Error {
263
444
  this.majorParameter = majorParameter;
264
445
  this.global = global;
265
446
  }
447
+ /**
448
+ * The name of the error
449
+ */
266
450
  get name() {
267
451
  return `${RateLimitError.name}[${this.route}]`;
268
452
  }
@@ -342,10 +526,13 @@ function hasSublimit(bucketRoute, body, method) {
342
526
  if (bucketRoute === "/channels/:id") {
343
527
  if (typeof body !== "object" || body === null)
344
528
  return false;
345
- if (method !== "PATCH" /* Patch */)
529
+ if (method !== RequestMethod.Patch)
346
530
  return false;
347
531
  const castedBody = body;
348
- return ["name", "topic"].some((key) => Reflect.has(castedBody, key));
532
+ return [
533
+ "name",
534
+ "topic"
535
+ ].some((key) => Reflect.has(castedBody, key));
349
536
  }
350
537
  return true;
351
538
  }
@@ -368,7 +555,9 @@ async function resolveBody(body) {
368
555
  } else if (body instanceof import_undici2.FormData) {
369
556
  return body;
370
557
  } else if (body[Symbol.iterator]) {
371
- const chunks = [...body];
558
+ const chunks = [
559
+ ...body
560
+ ];
372
561
  const length = chunks.reduce((a, b) => a + b.length, 0);
373
562
  const uint8 = new Uint8Array(length);
374
563
  let lengthUsed = 0;
@@ -397,43 +586,96 @@ __name(shouldRetry, "shouldRetry");
397
586
  // src/lib/handlers/SequentialHandler.ts
398
587
  var invalidCount = 0;
399
588
  var invalidCountResetTime = null;
589
+ var QueueType;
590
+ (function(QueueType2) {
591
+ QueueType2[QueueType2["Standard"] = 0] = "Standard";
592
+ QueueType2[QueueType2["Sublimit"] = 1] = "Sublimit";
593
+ })(QueueType || (QueueType = {}));
400
594
  var SequentialHandler = class {
595
+ /**
596
+ * The interface used to sequence async requests sequentially
597
+ */
598
+ #asyncQueue;
599
+ /**
600
+ * The interface used to sequence sublimited async requests sequentially
601
+ */
602
+ #sublimitedQueue;
603
+ /**
604
+ * A promise wrapper for when the sublimited queue is finished being processed or null when not being processed
605
+ */
606
+ #sublimitPromise;
607
+ /**
608
+ * Whether the sublimit queue needs to be shifted in the finally block
609
+ */
610
+ #shiftSublimit;
611
+ /**
612
+ * @param manager - The request manager
613
+ * @param hash - The hash that this RequestHandler handles
614
+ * @param majorParameter - The major parameter for this handler
615
+ */
401
616
  constructor(manager, hash, majorParameter) {
402
617
  this.manager = manager;
403
618
  this.hash = hash;
404
619
  this.majorParameter = majorParameter;
620
+ this.reset = -1;
621
+ this.remaining = 1;
622
+ this.limit = Number.POSITIVE_INFINITY;
623
+ this.#asyncQueue = new import_async_queue.AsyncQueue();
624
+ this.#sublimitedQueue = null;
625
+ this.#sublimitPromise = null;
626
+ this.#shiftSublimit = false;
405
627
  this.id = `${hash}:${majorParameter}`;
406
628
  }
407
- id;
408
- reset = -1;
409
- remaining = 1;
410
- limit = Number.POSITIVE_INFINITY;
411
- #asyncQueue = new import_async_queue.AsyncQueue();
412
- #sublimitedQueue = null;
413
- #sublimitPromise = null;
414
- #shiftSublimit = false;
629
+ /**
630
+ * {@inheritDoc IHandler.inactive}
631
+ */
415
632
  get inactive() {
416
633
  return this.#asyncQueue.remaining === 0 && (this.#sublimitedQueue === null || this.#sublimitedQueue.remaining === 0) && !this.limited;
417
634
  }
635
+ /**
636
+ * If the rate limit bucket is currently limited by the global limit
637
+ */
418
638
  get globalLimited() {
419
639
  return this.manager.globalRemaining <= 0 && Date.now() < this.manager.globalReset;
420
640
  }
641
+ /**
642
+ * If the rate limit bucket is currently limited by its limit
643
+ */
421
644
  get localLimited() {
422
645
  return this.remaining <= 0 && Date.now() < this.reset;
423
646
  }
647
+ /**
648
+ * If the rate limit bucket is currently limited
649
+ */
424
650
  get limited() {
425
651
  return this.globalLimited || this.localLimited;
426
652
  }
653
+ /**
654
+ * The time until queued requests can continue
655
+ */
427
656
  get timeToReset() {
428
657
  return this.reset + this.manager.options.offset - Date.now();
429
658
  }
659
+ /**
660
+ * Emits a debug message
661
+ *
662
+ * @param message - The message to debug
663
+ */
430
664
  debug(message) {
431
- this.manager.emit("restDebug" /* Debug */, `[REST ${this.id}] ${message}`);
665
+ this.manager.emit(RESTEvents.Debug, `[REST ${this.id}] ${message}`);
432
666
  }
667
+ /**
668
+ * Delay all requests for the specified amount of time, handling global rate limits
669
+ *
670
+ * @param time - The amount of time to delay all requests for
671
+ */
433
672
  async globalDelayFor(time) {
434
673
  await (0, import_promises.setTimeout)(time);
435
674
  this.manager.globalDelay = null;
436
675
  }
676
+ /*
677
+ * Determines whether the request should be queued or whether a RateLimitError should be thrown
678
+ */
437
679
  async onRateLimit(rateLimitData) {
438
680
  const { options } = this.manager;
439
681
  if (!options.rejectOnRateLimit)
@@ -443,15 +685,20 @@ var SequentialHandler = class {
443
685
  throw new RateLimitError(rateLimitData);
444
686
  }
445
687
  }
688
+ /**
689
+ * {@inheritDoc IHandler.queueRequest}
690
+ */
446
691
  async queueRequest(routeId, url, options, requestData) {
447
692
  let queue = this.#asyncQueue;
448
- let queueType = 0 /* Standard */;
693
+ let queueType = 0;
449
694
  if (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {
450
695
  queue = this.#sublimitedQueue;
451
- queueType = 1 /* Sublimit */;
696
+ queueType = 1;
452
697
  }
453
- await queue.wait({ signal: requestData.signal });
454
- if (queueType === 0 /* Standard */) {
698
+ await queue.wait({
699
+ signal: requestData.signal
700
+ });
701
+ if (queueType === 0) {
455
702
  if (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {
456
703
  queue = this.#sublimitedQueue;
457
704
  const wait = queue.wait();
@@ -475,6 +722,15 @@ var SequentialHandler = class {
475
722
  }
476
723
  }
477
724
  }
725
+ /**
726
+ * The method that actually makes the request to the api, and updates info about the bucket accordingly
727
+ *
728
+ * @param routeId - The generalized api route with literal ids for major parameters
729
+ * @param url - The fully resolved url to make the request to
730
+ * @param options - The fetch options needed to make the request
731
+ * @param requestData - Extra data from the user's request needed for errors and additional processing
732
+ * @param retries - The number of retries this request has already attempted (recursion)
733
+ */
478
734
  async runRequest(routeId, url, options, requestData, retries = 0) {
479
735
  while (this.limited) {
480
736
  const isGlobal = this.globalLimited;
@@ -503,7 +759,7 @@ var SequentialHandler = class {
503
759
  majorParameter: this.majorParameter,
504
760
  global: isGlobal
505
761
  };
506
- this.manager.emit("rateLimited" /* RateLimited */, rateLimitData);
762
+ this.manager.emit(RESTEvents.RateLimited, rateLimitData);
507
763
  await this.onRateLimit(rateLimitData);
508
764
  if (isGlobal) {
509
765
  this.debug(`Global rate limit hit, blocking all requests for ${timeout2}ms`);
@@ -529,7 +785,10 @@ var SequentialHandler = class {
529
785
  }
530
786
  let res;
531
787
  try {
532
- res = await (0, import_undici3.request)(url, { ...options, signal: controller.signal });
788
+ res = await (0, import_undici3.request)(url, {
789
+ ...options,
790
+ signal: controller.signal
791
+ });
533
792
  } catch (error) {
534
793
  if (!(error instanceof Error))
535
794
  throw error;
@@ -540,19 +799,17 @@ var SequentialHandler = class {
540
799
  } finally {
541
800
  (0, import_node_timers.clearTimeout)(timeout);
542
801
  }
543
- if (this.manager.listenerCount("response" /* Response */)) {
544
- this.manager.emit(
545
- "response" /* Response */,
546
- {
547
- method,
548
- path: routeId.original,
549
- route: routeId.bucketRoute,
550
- options,
551
- data: requestData,
552
- retries
553
- },
554
- { ...res }
555
- );
802
+ if (this.manager.listenerCount(RESTEvents.Response)) {
803
+ this.manager.emit(RESTEvents.Response, {
804
+ method,
805
+ path: routeId.original,
806
+ route: routeId.bucketRoute,
807
+ options,
808
+ data: requestData,
809
+ retries
810
+ }, {
811
+ ...res
812
+ });
556
813
  }
557
814
  const status = res.statusCode;
558
815
  let retryAfter = 0;
@@ -567,8 +824,15 @@ var SequentialHandler = class {
567
824
  if (retry)
568
825
  retryAfter = Number(retry) * 1e3 + this.manager.options.offset;
569
826
  if (hash && hash !== this.hash) {
570
- this.debug(["Received bucket hash update", ` Old Hash : ${this.hash}`, ` New Hash : ${hash}`].join("\n"));
571
- this.manager.hashes.set(`${method}:${routeId.bucketRoute}`, { value: hash, lastAccess: Date.now() });
827
+ this.debug([
828
+ "Received bucket hash update",
829
+ ` Old Hash : ${this.hash}`,
830
+ ` New Hash : ${hash}`
831
+ ].join("\n"));
832
+ this.manager.hashes.set(`${method}:${routeId.bucketRoute}`, {
833
+ value: hash,
834
+ lastAccess: Date.now()
835
+ });
572
836
  } else if (hash) {
573
837
  const hashData = this.manager.hashes.get(`${method}:${routeId.bucketRoute}`);
574
838
  if (hashData) {
@@ -592,7 +856,7 @@ var SequentialHandler = class {
592
856
  invalidCount++;
593
857
  const emitInvalid = this.manager.options.invalidRequestWarningInterval > 0 && invalidCount % this.manager.options.invalidRequestWarningInterval === 0;
594
858
  if (emitInvalid) {
595
- this.manager.emit("invalidRequestWarning" /* InvalidRequestWarning */, {
859
+ this.manager.emit(RESTEvents.InvalidRequestWarning, {
596
860
  count: invalidCount,
597
861
  remainingTime: invalidCountResetTime - Date.now()
598
862
  });
@@ -621,20 +885,18 @@ var SequentialHandler = class {
621
885
  majorParameter: this.majorParameter,
622
886
  global: isGlobal
623
887
  });
624
- this.debug(
625
- [
626
- "Encountered unexpected 429 rate limit",
627
- ` Global : ${isGlobal.toString()}`,
628
- ` Method : ${method}`,
629
- ` URL : ${url}`,
630
- ` Bucket : ${routeId.bucketRoute}`,
631
- ` Major parameter: ${routeId.majorParameter}`,
632
- ` Hash : ${this.hash}`,
633
- ` Limit : ${limit2}`,
634
- ` Retry After : ${retryAfter}ms`,
635
- ` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : "None"}`
636
- ].join("\n")
637
- );
888
+ this.debug([
889
+ "Encountered unexpected 429 rate limit",
890
+ ` Global : ${isGlobal.toString()}`,
891
+ ` Method : ${method}`,
892
+ ` URL : ${url}`,
893
+ ` Bucket : ${routeId.bucketRoute}`,
894
+ ` Major parameter: ${routeId.majorParameter}`,
895
+ ` Hash : ${this.hash}`,
896
+ ` Limit : ${limit2}`,
897
+ ` Retry After : ${retryAfter}ms`,
898
+ ` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : "None"}`
899
+ ].join("\n"));
638
900
  if (sublimitTimeout) {
639
901
  const firstSublimit = !this.#sublimitedQueue;
640
902
  if (firstSublimit) {
@@ -647,7 +909,10 @@ var SequentialHandler = class {
647
909
  await (0, import_promises.setTimeout)(sublimitTimeout);
648
910
  let resolve;
649
911
  const promise = new Promise((res2) => resolve = res2);
650
- this.#sublimitPromise = { promise, resolve };
912
+ this.#sublimitPromise = {
913
+ promise,
914
+ resolve
915
+ };
651
916
  if (firstSublimit) {
652
917
  await this.#asyncQueue.wait();
653
918
  this.#shiftSublimit = true;
@@ -675,28 +940,43 @@ __name(SequentialHandler, "SequentialHandler");
675
940
 
676
941
  // src/lib/RequestManager.ts
677
942
  var getFileType = (0, import_util.lazy)(async () => import("file-type"));
678
- var RequestMethod = /* @__PURE__ */ ((RequestMethod2) => {
943
+ var RequestMethod;
944
+ (function(RequestMethod2) {
679
945
  RequestMethod2["Delete"] = "DELETE";
680
946
  RequestMethod2["Get"] = "GET";
681
947
  RequestMethod2["Patch"] = "PATCH";
682
948
  RequestMethod2["Post"] = "POST";
683
949
  RequestMethod2["Put"] = "PUT";
684
- return RequestMethod2;
685
- })(RequestMethod || {});
950
+ })(RequestMethod || (RequestMethod = {}));
686
951
  var RequestManager = class extends import_node_events.EventEmitter {
952
+ /**
953
+ * The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} for all requests
954
+ * performed by this manager.
955
+ */
687
956
  agent = null;
688
- globalRemaining;
957
+ /**
958
+ * The promise used to wait out the global rate limit
959
+ */
689
960
  globalDelay = null;
961
+ /**
962
+ * The timestamp at which the global bucket resets
963
+ */
690
964
  globalReset = -1;
965
+ /**
966
+ * API bucket hashes that are cached from provided routes
967
+ */
691
968
  hashes = new import_collection.Collection();
969
+ /**
970
+ * Request handlers created from the bucket hash and the major parameters
971
+ */
692
972
  handlers = new import_collection.Collection();
693
973
  #token = null;
694
- hashTimer;
695
- handlerTimer;
696
- options;
697
974
  constructor(options) {
698
975
  super();
699
- this.options = { ...DefaultRestOptions, ...options };
976
+ this.options = {
977
+ ...DefaultRestOptions,
978
+ ...options
979
+ };
700
980
  this.options.offset = Math.max(0, this.options.offset);
701
981
  this.globalRemaining = this.options.globalRequestsPerSecond;
702
982
  this.agent = options.agent ?? null;
@@ -720,10 +1000,10 @@ var RequestManager = class extends import_node_events.EventEmitter {
720
1000
  if (shouldSweep) {
721
1001
  sweptHashes.set(key, val);
722
1002
  }
723
- this.emit("restDebug" /* Debug */, `Hash ${val.value} for ${key} swept due to lifetime being exceeded`);
1003
+ this.emit(RESTEvents.Debug, `Hash ${val.value} for ${key} swept due to lifetime being exceeded`);
724
1004
  return shouldSweep;
725
1005
  });
726
- this.emit("hashSweep" /* HashSweep */, sweptHashes);
1006
+ this.emit(RESTEvents.HashSweep, sweptHashes);
727
1007
  }, this.options.hashSweepInterval).unref();
728
1008
  }
729
1009
  if (this.options.handlerSweepInterval !== 0 && this.options.handlerSweepInterval !== Number.POSITIVE_INFINITY) {
@@ -735,21 +1015,37 @@ var RequestManager = class extends import_node_events.EventEmitter {
735
1015
  if (inactive) {
736
1016
  sweptHandlers.set(key, val);
737
1017
  }
738
- this.emit("restDebug" /* Debug */, `Handler ${val.id} for ${key} swept due to being inactive`);
1018
+ this.emit(RESTEvents.Debug, `Handler ${val.id} for ${key} swept due to being inactive`);
739
1019
  return inactive;
740
1020
  });
741
- this.emit("handlerSweep" /* HandlerSweep */, sweptHandlers);
1021
+ this.emit(RESTEvents.HandlerSweep, sweptHandlers);
742
1022
  }, this.options.handlerSweepInterval).unref();
743
1023
  }
744
1024
  }
1025
+ /**
1026
+ * Sets the default agent to use for requests performed by this manager
1027
+ *
1028
+ * @param agent - The agent to use
1029
+ */
745
1030
  setAgent(agent) {
746
1031
  this.agent = agent;
747
1032
  return this;
748
1033
  }
1034
+ /**
1035
+ * Sets the authorization token that should be used for requests
1036
+ *
1037
+ * @param token - The authorization token to use
1038
+ */
749
1039
  setToken(token) {
750
1040
  this.#token = token;
751
1041
  return this;
752
1042
  }
1043
+ /**
1044
+ * Queues a request to be sent
1045
+ *
1046
+ * @param request - All the information needed to make a request
1047
+ * @returns The response from the api request
1048
+ */
753
1049
  async queueRequest(request2) {
754
1050
  const routeId = RequestManager.generateRouteData(request2.fullRoute, request2.method);
755
1051
  const hash = this.hashes.get(`${request2.method}:${routeId.bucketRoute}`) ?? {
@@ -765,11 +1061,23 @@ var RequestManager = class extends import_node_events.EventEmitter {
765
1061
  signal: request2.signal
766
1062
  });
767
1063
  }
1064
+ /**
1065
+ * Creates a new rate limit handler from a hash, based on the hash and the major parameter
1066
+ *
1067
+ * @param hash - The hash for the route
1068
+ * @param majorParameter - The major parameter for this handler
1069
+ * @internal
1070
+ */
768
1071
  createHandler(hash, majorParameter) {
769
1072
  const queue = new SequentialHandler(this, hash, majorParameter);
770
1073
  this.handlers.set(queue.id, queue);
771
1074
  return queue;
772
1075
  }
1076
+ /**
1077
+ * Formats the request data to a usable format for fetch
1078
+ *
1079
+ * @param request - The request data
1080
+ */
773
1081
  async resolveRequest(request2) {
774
1082
  const { options } = this;
775
1083
  let query = "";
@@ -808,9 +1116,17 @@ var RequestManager = class extends import_node_events.EventEmitter {
808
1116
  contentType = OverwrittenMimeTypes[parsedType] ?? parsedType;
809
1117
  }
810
1118
  }
811
- formData.append(fileKey, new import_node_buffer2.Blob([file.data], { type: contentType }), file.name);
1119
+ formData.append(fileKey, new import_node_buffer2.Blob([
1120
+ file.data
1121
+ ], {
1122
+ type: contentType
1123
+ }), file.name);
812
1124
  } else {
813
- formData.append(fileKey, new import_node_buffer2.Blob([`${file.data}`], { type: file.contentType }), file.name);
1125
+ formData.append(fileKey, new import_node_buffer2.Blob([
1126
+ `${file.data}`
1127
+ ], {
1128
+ type: file.contentType
1129
+ }), file.name);
814
1130
  }
815
1131
  }
816
1132
  if (request2.body != null) {
@@ -828,33 +1144,55 @@ var RequestManager = class extends import_node_events.EventEmitter {
828
1144
  finalBody = request2.body;
829
1145
  } else {
830
1146
  finalBody = JSON.stringify(request2.body);
831
- additionalHeaders = { "Content-Type": "application/json" };
1147
+ additionalHeaders = {
1148
+ "Content-Type": "application/json"
1149
+ };
832
1150
  }
833
1151
  }
834
1152
  finalBody = await resolveBody(finalBody);
835
1153
  const fetchOptions = {
836
- headers: { ...request2.headers, ...additionalHeaders, ...headers },
1154
+ headers: {
1155
+ ...request2.headers,
1156
+ ...additionalHeaders,
1157
+ ...headers
1158
+ },
837
1159
  method: request2.method.toUpperCase()
838
1160
  };
839
1161
  if (finalBody !== void 0) {
840
1162
  fetchOptions.body = finalBody;
841
1163
  }
842
1164
  fetchOptions.dispatcher = request2.dispatcher ?? this.agent ?? void 0;
843
- return { url, fetchOptions };
1165
+ return {
1166
+ url,
1167
+ fetchOptions
1168
+ };
844
1169
  }
1170
+ /**
1171
+ * Stops the hash sweeping interval
1172
+ */
845
1173
  clearHashSweeper() {
846
1174
  (0, import_node_timers2.clearInterval)(this.hashTimer);
847
1175
  }
1176
+ /**
1177
+ * Stops the request handler sweeping interval
1178
+ */
848
1179
  clearHandlerSweeper() {
849
1180
  (0, import_node_timers2.clearInterval)(this.handlerTimer);
850
1181
  }
1182
+ /**
1183
+ * Generates route data for an endpoint:method
1184
+ *
1185
+ * @param endpoint - The raw endpoint to generalize
1186
+ * @param method - The HTTP method this endpoint is called without
1187
+ * @internal
1188
+ */
851
1189
  static generateRouteData(endpoint, method) {
852
- const majorIdMatch = /^\/(?:channels|guilds|webhooks)\/(\d{16,19})/.exec(endpoint);
1190
+ const majorIdMatch = /^\/(?:channels|guilds|webhooks)\/(\d{17,19})/.exec(endpoint);
853
1191
  const majorId = majorIdMatch?.[1] ?? "global";
854
- const baseRoute = endpoint.replaceAll(/\d{16,19}/g, ":id").replace(/\/reactions\/(.*)/, "/reactions/:reaction");
1192
+ const baseRoute = endpoint.replaceAll(/\d{17,19}/g, ":id").replace(/\/reactions\/(.*)/, "/reactions/:reaction");
855
1193
  let exceptions = "";
856
- if (method === "DELETE" /* Delete */ && baseRoute === "/channels/:id/messages/:id") {
857
- const id = /\d{16,19}$/.exec(endpoint)[0];
1194
+ if (method === "DELETE" && baseRoute === "/channels/:id/messages/:id") {
1195
+ const id = /\d{17,19}$/.exec(endpoint)[0];
858
1196
  const timestamp = import_snowflake.DiscordSnowflake.timestampFrom(id);
859
1197
  if (Date.now() - timestamp > 1e3 * 60 * 60 * 24 * 14) {
860
1198
  exceptions += "/Delete Old Message";
@@ -872,51 +1210,122 @@ __name(RequestManager, "RequestManager");
872
1210
  // src/lib/REST.ts
873
1211
  var import_node_events2 = require("events");
874
1212
  var REST = class extends import_node_events2.EventEmitter {
875
- cdn;
876
- requestManager;
877
1213
  constructor(options = {}) {
878
1214
  super();
879
1215
  this.cdn = new CDN(options.cdn ?? DefaultRestOptions.cdn);
880
- this.requestManager = new RequestManager(options).on("restDebug" /* Debug */, this.emit.bind(this, "restDebug" /* Debug */)).on("rateLimited" /* RateLimited */, this.emit.bind(this, "rateLimited" /* RateLimited */)).on("invalidRequestWarning" /* InvalidRequestWarning */, this.emit.bind(this, "invalidRequestWarning" /* InvalidRequestWarning */)).on("hashSweep" /* HashSweep */, this.emit.bind(this, "hashSweep" /* HashSweep */));
1216
+ this.requestManager = new RequestManager(options).on(RESTEvents.Debug, this.emit.bind(this, RESTEvents.Debug)).on(RESTEvents.RateLimited, this.emit.bind(this, RESTEvents.RateLimited)).on(RESTEvents.InvalidRequestWarning, this.emit.bind(this, RESTEvents.InvalidRequestWarning)).on(RESTEvents.HashSweep, this.emit.bind(this, RESTEvents.HashSweep));
881
1217
  this.on("newListener", (name, listener) => {
882
- if (name === "response" /* Response */)
1218
+ if (name === RESTEvents.Response)
883
1219
  this.requestManager.on(name, listener);
884
1220
  });
885
1221
  this.on("removeListener", (name, listener) => {
886
- if (name === "response" /* Response */)
1222
+ if (name === RESTEvents.Response)
887
1223
  this.requestManager.off(name, listener);
888
1224
  });
889
1225
  }
1226
+ /**
1227
+ * Gets the agent set for this instance
1228
+ */
890
1229
  getAgent() {
891
1230
  return this.requestManager.agent;
892
1231
  }
1232
+ /**
1233
+ * Sets the default agent to use for requests performed by this instance
1234
+ *
1235
+ * @param agent - Sets the agent to use
1236
+ */
893
1237
  setAgent(agent) {
894
1238
  this.requestManager.setAgent(agent);
895
1239
  return this;
896
1240
  }
1241
+ /**
1242
+ * Sets the authorization token that should be used for requests
1243
+ *
1244
+ * @param token - The authorization token to use
1245
+ */
897
1246
  setToken(token) {
898
1247
  this.requestManager.setToken(token);
899
1248
  return this;
900
1249
  }
1250
+ /**
1251
+ * Runs a get request from the api
1252
+ *
1253
+ * @param fullRoute - The full route to query
1254
+ * @param options - Optional request options
1255
+ */
901
1256
  async get(fullRoute, options = {}) {
902
- return this.request({ ...options, fullRoute, method: "GET" /* Get */ });
1257
+ return this.request({
1258
+ ...options,
1259
+ fullRoute,
1260
+ method: RequestMethod.Get
1261
+ });
903
1262
  }
1263
+ /**
1264
+ * Runs a delete request from the api
1265
+ *
1266
+ * @param fullRoute - The full route to query
1267
+ * @param options - Optional request options
1268
+ */
904
1269
  async delete(fullRoute, options = {}) {
905
- return this.request({ ...options, fullRoute, method: "DELETE" /* Delete */ });
1270
+ return this.request({
1271
+ ...options,
1272
+ fullRoute,
1273
+ method: RequestMethod.Delete
1274
+ });
906
1275
  }
1276
+ /**
1277
+ * Runs a post request from the api
1278
+ *
1279
+ * @param fullRoute - The full route to query
1280
+ * @param options - Optional request options
1281
+ */
907
1282
  async post(fullRoute, options = {}) {
908
- return this.request({ ...options, fullRoute, method: "POST" /* Post */ });
1283
+ return this.request({
1284
+ ...options,
1285
+ fullRoute,
1286
+ method: RequestMethod.Post
1287
+ });
909
1288
  }
1289
+ /**
1290
+ * Runs a put request from the api
1291
+ *
1292
+ * @param fullRoute - The full route to query
1293
+ * @param options - Optional request options
1294
+ */
910
1295
  async put(fullRoute, options = {}) {
911
- return this.request({ ...options, fullRoute, method: "PUT" /* Put */ });
1296
+ return this.request({
1297
+ ...options,
1298
+ fullRoute,
1299
+ method: RequestMethod.Put
1300
+ });
912
1301
  }
1302
+ /**
1303
+ * Runs a patch request from the api
1304
+ *
1305
+ * @param fullRoute - The full route to query
1306
+ * @param options - Optional request options
1307
+ */
913
1308
  async patch(fullRoute, options = {}) {
914
- return this.request({ ...options, fullRoute, method: "PATCH" /* Patch */ });
1309
+ return this.request({
1310
+ ...options,
1311
+ fullRoute,
1312
+ method: RequestMethod.Patch
1313
+ });
915
1314
  }
1315
+ /**
1316
+ * Runs a request from the api
1317
+ *
1318
+ * @param options - Request options
1319
+ */
916
1320
  async request(options) {
917
1321
  const response = await this.raw(options);
918
1322
  return parseResponse(response);
919
1323
  }
1324
+ /**
1325
+ * Runs a request from the API, yielding the raw Response object
1326
+ *
1327
+ * @param options - Request options
1328
+ */
920
1329
  async raw(options) {
921
1330
  return this.requestManager.queueRequest(options);
922
1331
  }
@@ -924,7 +1333,7 @@ var REST = class extends import_node_events2.EventEmitter {
924
1333
  __name(REST, "REST");
925
1334
 
926
1335
  // src/index.ts
927
- var version = "1.6.0-dev.1677456613-ffdb197.0";
1336
+ var version = "[VI]{{inject}}[/VI]";
928
1337
  // Annotate the CommonJS export names for ESM import in node:
929
1338
  0 && (module.exports = {
930
1339
  ALLOWED_EXTENSIONS,