@discordjs/rest 1.6.0-dev.1677499520-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.mjs CHANGED
@@ -8,7 +8,7 @@ import { URL } from "node:url";
8
8
  import process from "node:process";
9
9
  import { APIVersion } from "discord-api-types/v10";
10
10
  import { Agent } from "undici";
11
- var DefaultUserAgent = `DiscordBot (https://discord.js.org, 1.6.0-dev.1677499520-ffdb197.0)`;
11
+ var DefaultUserAgent = `DiscordBot (https://discord.js.org, [VI]{{inject}}[/VI])`;
12
12
  var DefaultRestOptions = {
13
13
  get agent() {
14
14
  return new Agent({
@@ -33,19 +33,40 @@ var DefaultRestOptions = {
33
33
  hashLifetime: 864e5,
34
34
  handlerSweepInterval: 36e5
35
35
  };
36
- var RESTEvents = /* @__PURE__ */ ((RESTEvents2) => {
36
+ var RESTEvents;
37
+ (function(RESTEvents2) {
37
38
  RESTEvents2["Debug"] = "restDebug";
38
39
  RESTEvents2["HandlerSweep"] = "handlerSweep";
39
40
  RESTEvents2["HashSweep"] = "hashSweep";
40
41
  RESTEvents2["InvalidRequestWarning"] = "invalidRequestWarning";
41
42
  RESTEvents2["RateLimited"] = "rateLimited";
42
43
  RESTEvents2["Response"] = "response";
43
- return RESTEvents2;
44
- })(RESTEvents || {});
45
- var ALLOWED_EXTENSIONS = ["webp", "png", "jpg", "jpeg", "gif"];
46
- var ALLOWED_STICKER_EXTENSIONS = ["png", "json", "gif"];
47
- var ALLOWED_SIZES = [16, 32, 64, 128, 256, 512, 1024, 2048, 4096];
44
+ })(RESTEvents || (RESTEvents = {}));
45
+ var ALLOWED_EXTENSIONS = [
46
+ "webp",
47
+ "png",
48
+ "jpg",
49
+ "jpeg",
50
+ "gif"
51
+ ];
52
+ var ALLOWED_STICKER_EXTENSIONS = [
53
+ "png",
54
+ "json",
55
+ "gif"
56
+ ];
57
+ var ALLOWED_SIZES = [
58
+ 16,
59
+ 32,
60
+ 64,
61
+ 128,
62
+ 256,
63
+ 512,
64
+ 1024,
65
+ 2048,
66
+ 4096
67
+ ];
48
68
  var OverwrittenMimeTypes = {
69
+ // https://github.com/discordjs/discord.js/issues/8557
49
70
  "image/apng": "image/png"
50
71
  };
51
72
 
@@ -54,60 +75,201 @@ var CDN = class {
54
75
  constructor(base = DefaultRestOptions.cdn) {
55
76
  this.base = base;
56
77
  }
78
+ /**
79
+ * Generates an app asset URL for a client's asset.
80
+ *
81
+ * @param clientId - The client id that has the asset
82
+ * @param assetHash - The hash provided by Discord for this asset
83
+ * @param options - Optional options for the asset
84
+ */
57
85
  appAsset(clientId, assetHash, options) {
58
86
  return this.makeURL(`/app-assets/${clientId}/${assetHash}`, options);
59
87
  }
88
+ /**
89
+ * Generates an app icon URL for a client's icon.
90
+ *
91
+ * @param clientId - The client id that has the icon
92
+ * @param iconHash - The hash provided by Discord for this icon
93
+ * @param options - Optional options for the icon
94
+ */
60
95
  appIcon(clientId, iconHash, options) {
61
96
  return this.makeURL(`/app-icons/${clientId}/${iconHash}`, options);
62
97
  }
98
+ /**
99
+ * Generates an avatar URL, e.g. for a user or a webhook.
100
+ *
101
+ * @param id - The id that has the icon
102
+ * @param avatarHash - The hash provided by Discord for this avatar
103
+ * @param options - Optional options for the avatar
104
+ */
63
105
  avatar(id, avatarHash, options) {
64
106
  return this.dynamicMakeURL(`/avatars/${id}/${avatarHash}`, avatarHash, options);
65
107
  }
108
+ /**
109
+ * Generates a banner URL, e.g. for a user or a guild.
110
+ *
111
+ * @param id - The id that has the banner splash
112
+ * @param bannerHash - The hash provided by Discord for this banner
113
+ * @param options - Optional options for the banner
114
+ */
66
115
  banner(id, bannerHash, options) {
67
116
  return this.dynamicMakeURL(`/banners/${id}/${bannerHash}`, bannerHash, options);
68
117
  }
118
+ /**
119
+ * Generates an icon URL for a channel, e.g. a group DM.
120
+ *
121
+ * @param channelId - The channel id that has the icon
122
+ * @param iconHash - The hash provided by Discord for this channel
123
+ * @param options - Optional options for the icon
124
+ */
69
125
  channelIcon(channelId, iconHash, options) {
70
126
  return this.makeURL(`/channel-icons/${channelId}/${iconHash}`, options);
71
127
  }
128
+ /**
129
+ * Generates the default avatar URL for a discriminator.
130
+ *
131
+ * @param discriminator - The discriminator modulo 5
132
+ */
72
133
  defaultAvatar(discriminator) {
73
- return this.makeURL(`/embed/avatars/${discriminator}`, { extension: "png" });
134
+ return this.makeURL(`/embed/avatars/${discriminator}`, {
135
+ extension: "png"
136
+ });
74
137
  }
138
+ /**
139
+ * Generates a discovery splash URL for a guild's discovery splash.
140
+ *
141
+ * @param guildId - The guild id that has the discovery splash
142
+ * @param splashHash - The hash provided by Discord for this splash
143
+ * @param options - Optional options for the splash
144
+ */
75
145
  discoverySplash(guildId, splashHash, options) {
76
146
  return this.makeURL(`/discovery-splashes/${guildId}/${splashHash}`, options);
77
147
  }
148
+ /**
149
+ * Generates an emoji's URL for an emoji.
150
+ *
151
+ * @param emojiId - The emoji id
152
+ * @param extension - The extension of the emoji
153
+ */
78
154
  emoji(emojiId, extension) {
79
- return this.makeURL(`/emojis/${emojiId}`, { extension });
155
+ return this.makeURL(`/emojis/${emojiId}`, {
156
+ extension
157
+ });
80
158
  }
159
+ /**
160
+ * Generates a guild member avatar URL.
161
+ *
162
+ * @param guildId - The id of the guild
163
+ * @param userId - The id of the user
164
+ * @param avatarHash - The hash provided by Discord for this avatar
165
+ * @param options - Optional options for the avatar
166
+ */
81
167
  guildMemberAvatar(guildId, userId, avatarHash, options) {
82
168
  return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/avatars/${avatarHash}`, avatarHash, options);
83
169
  }
170
+ /**
171
+ * Generates a guild member banner URL.
172
+ *
173
+ * @param guildId - The id of the guild
174
+ * @param userId - The id of the user
175
+ * @param bannerHash - The hash provided by Discord for this banner
176
+ * @param options - Optional options for the banner
177
+ */
84
178
  guildMemberBanner(guildId, userId, bannerHash, options) {
85
179
  return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/banner`, bannerHash, options);
86
180
  }
181
+ /**
182
+ * Generates an icon URL, e.g. for a guild.
183
+ *
184
+ * @param id - The id that has the icon splash
185
+ * @param iconHash - The hash provided by Discord for this icon
186
+ * @param options - Optional options for the icon
187
+ */
87
188
  icon(id, iconHash, options) {
88
189
  return this.dynamicMakeURL(`/icons/${id}/${iconHash}`, iconHash, options);
89
190
  }
191
+ /**
192
+ * Generates a URL for the icon of a role
193
+ *
194
+ * @param roleId - The id of the role that has the icon
195
+ * @param roleIconHash - The hash provided by Discord for this role icon
196
+ * @param options - Optional options for the role icon
197
+ */
90
198
  roleIcon(roleId, roleIconHash, options) {
91
199
  return this.makeURL(`/role-icons/${roleId}/${roleIconHash}`, options);
92
200
  }
201
+ /**
202
+ * Generates a guild invite splash URL for a guild's invite splash.
203
+ *
204
+ * @param guildId - The guild id that has the invite splash
205
+ * @param splashHash - The hash provided by Discord for this splash
206
+ * @param options - Optional options for the splash
207
+ */
93
208
  splash(guildId, splashHash, options) {
94
209
  return this.makeURL(`/splashes/${guildId}/${splashHash}`, options);
95
210
  }
211
+ /**
212
+ * Generates a sticker URL.
213
+ *
214
+ * @param stickerId - The sticker id
215
+ * @param extension - The extension of the sticker
216
+ * @privateRemarks
217
+ * Stickers cannot have a `.webp` extension, so we default to a `.png`
218
+ */
96
219
  sticker(stickerId, extension = "png") {
97
- return this.makeURL(`/stickers/${stickerId}`, { allowedExtensions: ALLOWED_STICKER_EXTENSIONS, extension });
220
+ return this.makeURL(`/stickers/${stickerId}`, {
221
+ allowedExtensions: ALLOWED_STICKER_EXTENSIONS,
222
+ extension
223
+ });
98
224
  }
225
+ /**
226
+ * Generates a sticker pack banner URL.
227
+ *
228
+ * @param bannerId - The banner id
229
+ * @param options - Optional options for the banner
230
+ */
99
231
  stickerPackBanner(bannerId, options) {
100
232
  return this.makeURL(`/app-assets/710982414301790216/store/${bannerId}`, options);
101
233
  }
234
+ /**
235
+ * Generates a team icon URL for a team's icon.
236
+ *
237
+ * @param teamId - The team id that has the icon
238
+ * @param iconHash - The hash provided by Discord for this icon
239
+ * @param options - Optional options for the icon
240
+ */
102
241
  teamIcon(teamId, iconHash, options) {
103
242
  return this.makeURL(`/team-icons/${teamId}/${iconHash}`, options);
104
243
  }
244
+ /**
245
+ * Generates a cover image for a guild scheduled event.
246
+ *
247
+ * @param scheduledEventId - The scheduled event id
248
+ * @param coverHash - The hash provided by discord for this cover image
249
+ * @param options - Optional options for the cover image
250
+ */
105
251
  guildScheduledEventCover(scheduledEventId, coverHash, options) {
106
252
  return this.makeURL(`/guild-events/${scheduledEventId}/${coverHash}`, options);
107
253
  }
254
+ /**
255
+ * Constructs the URL for the resource, checking whether or not `hash` starts with `a_` if `dynamic` is set to `true`.
256
+ *
257
+ * @param route - The base cdn route
258
+ * @param hash - The hash provided by Discord for this icon
259
+ * @param options - Optional options for the link
260
+ */
108
261
  dynamicMakeURL(route, hash, { forceStatic = false, ...options } = {}) {
109
- return this.makeURL(route, !forceStatic && hash.startsWith("a_") ? { ...options, extension: "gif" } : options);
110
- }
262
+ return this.makeURL(route, !forceStatic && hash.startsWith("a_") ? {
263
+ ...options,
264
+ extension: "gif"
265
+ } : options);
266
+ }
267
+ /**
268
+ * Constructs the URL for the resource
269
+ *
270
+ * @param route - The base cdn route
271
+ * @param options - The extension/size options for the link
272
+ */
111
273
  makeURL(route, { allowedExtensions = ALLOWED_EXTENSIONS, extension = "webp", size } = {}) {
112
274
  extension = String(extension).toLowerCase();
113
275
  if (!allowedExtensions.includes(extension)) {
@@ -137,6 +299,14 @@ function isErrorResponse(error) {
137
299
  }
138
300
  __name(isErrorResponse, "isErrorResponse");
139
301
  var DiscordAPIError = class extends Error {
302
+ /**
303
+ * @param rawError - The error reported by Discord
304
+ * @param code - The error code reported by Discord
305
+ * @param status - The status code of the response
306
+ * @param method - The method of the request that erred
307
+ * @param url - The url of the request that erred
308
+ * @param bodyData - The unparsed data for the request that errored
309
+ */
140
310
  constructor(rawError, code, status, method, url, bodyData) {
141
311
  super(DiscordAPIError.getMessage(rawError));
142
312
  this.rawError = rawError;
@@ -144,9 +314,14 @@ var DiscordAPIError = class extends Error {
144
314
  this.status = status;
145
315
  this.method = method;
146
316
  this.url = url;
147
- this.requestBody = { files: bodyData.files, json: bodyData.body };
317
+ this.requestBody = {
318
+ files: bodyData.files,
319
+ json: bodyData.body
320
+ };
148
321
  }
149
- requestBody;
322
+ /**
323
+ * The name of the error
324
+ */
150
325
  get name() {
151
326
  return `${DiscordAPIError.name}[${this.code}]`;
152
327
  }
@@ -154,7 +329,9 @@ var DiscordAPIError = class extends Error {
154
329
  let flattened = "";
155
330
  if ("code" in error) {
156
331
  if (error.errors) {
157
- flattened = [...this.flattenDiscordError(error.errors)].join("\n");
332
+ flattened = [
333
+ ...this.flattenDiscordError(error.errors)
334
+ ].join("\n");
158
335
  }
159
336
  return error.message && flattened ? `${error.message}
160
337
  ${flattened}` : error.message || flattened || "Unknown Error";
@@ -184,28 +361,28 @@ __name(DiscordAPIError, "DiscordAPIError");
184
361
  // src/lib/errors/HTTPError.ts
185
362
  import { STATUS_CODES } from "node:http";
186
363
  var HTTPError = class extends Error {
364
+ /**
365
+ * @param status - The status code of the response
366
+ * @param method - The method of the request that erred
367
+ * @param url - The url of the request that erred
368
+ * @param bodyData - The unparsed data for the request that errored
369
+ */
187
370
  constructor(status, method, url, bodyData) {
188
371
  super(STATUS_CODES[status]);
189
372
  this.status = status;
190
373
  this.method = method;
191
374
  this.url = url;
192
- this.requestBody = { files: bodyData.files, json: bodyData.body };
375
+ this.name = HTTPError.name;
376
+ this.requestBody = {
377
+ files: bodyData.files,
378
+ json: bodyData.body
379
+ };
193
380
  }
194
- requestBody;
195
- name = HTTPError.name;
196
381
  };
197
382
  __name(HTTPError, "HTTPError");
198
383
 
199
384
  // src/lib/errors/RateLimitError.ts
200
385
  var RateLimitError = class extends Error {
201
- timeToReset;
202
- limit;
203
- method;
204
- hash;
205
- url;
206
- route;
207
- majorParameter;
208
- global;
209
386
  constructor({ timeToReset, limit, method, hash, url, route, majorParameter, global }) {
210
387
  super();
211
388
  this.timeToReset = timeToReset;
@@ -217,6 +394,9 @@ var RateLimitError = class extends Error {
217
394
  this.majorParameter = majorParameter;
218
395
  this.global = global;
219
396
  }
397
+ /**
398
+ * The name of the error
399
+ */
220
400
  get name() {
221
401
  return `${RateLimitError.name}[${this.route}]`;
222
402
  }
@@ -296,10 +476,13 @@ function hasSublimit(bucketRoute, body, method) {
296
476
  if (bucketRoute === "/channels/:id") {
297
477
  if (typeof body !== "object" || body === null)
298
478
  return false;
299
- if (method !== "PATCH" /* Patch */)
479
+ if (method !== RequestMethod.Patch)
300
480
  return false;
301
481
  const castedBody = body;
302
- return ["name", "topic"].some((key) => Reflect.has(castedBody, key));
482
+ return [
483
+ "name",
484
+ "topic"
485
+ ].some((key) => Reflect.has(castedBody, key));
303
486
  }
304
487
  return true;
305
488
  }
@@ -322,7 +505,9 @@ async function resolveBody(body) {
322
505
  } else if (body instanceof FormData) {
323
506
  return body;
324
507
  } else if (body[Symbol.iterator]) {
325
- const chunks = [...body];
508
+ const chunks = [
509
+ ...body
510
+ ];
326
511
  const length = chunks.reduce((a, b) => a + b.length, 0);
327
512
  const uint8 = new Uint8Array(length);
328
513
  let lengthUsed = 0;
@@ -351,43 +536,96 @@ __name(shouldRetry, "shouldRetry");
351
536
  // src/lib/handlers/SequentialHandler.ts
352
537
  var invalidCount = 0;
353
538
  var invalidCountResetTime = null;
539
+ var QueueType;
540
+ (function(QueueType2) {
541
+ QueueType2[QueueType2["Standard"] = 0] = "Standard";
542
+ QueueType2[QueueType2["Sublimit"] = 1] = "Sublimit";
543
+ })(QueueType || (QueueType = {}));
354
544
  var SequentialHandler = class {
545
+ /**
546
+ * The interface used to sequence async requests sequentially
547
+ */
548
+ #asyncQueue;
549
+ /**
550
+ * The interface used to sequence sublimited async requests sequentially
551
+ */
552
+ #sublimitedQueue;
553
+ /**
554
+ * A promise wrapper for when the sublimited queue is finished being processed or null when not being processed
555
+ */
556
+ #sublimitPromise;
557
+ /**
558
+ * Whether the sublimit queue needs to be shifted in the finally block
559
+ */
560
+ #shiftSublimit;
561
+ /**
562
+ * @param manager - The request manager
563
+ * @param hash - The hash that this RequestHandler handles
564
+ * @param majorParameter - The major parameter for this handler
565
+ */
355
566
  constructor(manager, hash, majorParameter) {
356
567
  this.manager = manager;
357
568
  this.hash = hash;
358
569
  this.majorParameter = majorParameter;
570
+ this.reset = -1;
571
+ this.remaining = 1;
572
+ this.limit = Number.POSITIVE_INFINITY;
573
+ this.#asyncQueue = new AsyncQueue();
574
+ this.#sublimitedQueue = null;
575
+ this.#sublimitPromise = null;
576
+ this.#shiftSublimit = false;
359
577
  this.id = `${hash}:${majorParameter}`;
360
578
  }
361
- id;
362
- reset = -1;
363
- remaining = 1;
364
- limit = Number.POSITIVE_INFINITY;
365
- #asyncQueue = new AsyncQueue();
366
- #sublimitedQueue = null;
367
- #sublimitPromise = null;
368
- #shiftSublimit = false;
579
+ /**
580
+ * {@inheritDoc IHandler.inactive}
581
+ */
369
582
  get inactive() {
370
583
  return this.#asyncQueue.remaining === 0 && (this.#sublimitedQueue === null || this.#sublimitedQueue.remaining === 0) && !this.limited;
371
584
  }
585
+ /**
586
+ * If the rate limit bucket is currently limited by the global limit
587
+ */
372
588
  get globalLimited() {
373
589
  return this.manager.globalRemaining <= 0 && Date.now() < this.manager.globalReset;
374
590
  }
591
+ /**
592
+ * If the rate limit bucket is currently limited by its limit
593
+ */
375
594
  get localLimited() {
376
595
  return this.remaining <= 0 && Date.now() < this.reset;
377
596
  }
597
+ /**
598
+ * If the rate limit bucket is currently limited
599
+ */
378
600
  get limited() {
379
601
  return this.globalLimited || this.localLimited;
380
602
  }
603
+ /**
604
+ * The time until queued requests can continue
605
+ */
381
606
  get timeToReset() {
382
607
  return this.reset + this.manager.options.offset - Date.now();
383
608
  }
609
+ /**
610
+ * Emits a debug message
611
+ *
612
+ * @param message - The message to debug
613
+ */
384
614
  debug(message) {
385
- this.manager.emit("restDebug" /* Debug */, `[REST ${this.id}] ${message}`);
615
+ this.manager.emit(RESTEvents.Debug, `[REST ${this.id}] ${message}`);
386
616
  }
617
+ /**
618
+ * Delay all requests for the specified amount of time, handling global rate limits
619
+ *
620
+ * @param time - The amount of time to delay all requests for
621
+ */
387
622
  async globalDelayFor(time) {
388
623
  await sleep(time);
389
624
  this.manager.globalDelay = null;
390
625
  }
626
+ /*
627
+ * Determines whether the request should be queued or whether a RateLimitError should be thrown
628
+ */
391
629
  async onRateLimit(rateLimitData) {
392
630
  const { options } = this.manager;
393
631
  if (!options.rejectOnRateLimit)
@@ -397,15 +635,20 @@ var SequentialHandler = class {
397
635
  throw new RateLimitError(rateLimitData);
398
636
  }
399
637
  }
638
+ /**
639
+ * {@inheritDoc IHandler.queueRequest}
640
+ */
400
641
  async queueRequest(routeId, url, options, requestData) {
401
642
  let queue = this.#asyncQueue;
402
- let queueType = 0 /* Standard */;
643
+ let queueType = 0;
403
644
  if (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {
404
645
  queue = this.#sublimitedQueue;
405
- queueType = 1 /* Sublimit */;
646
+ queueType = 1;
406
647
  }
407
- await queue.wait({ signal: requestData.signal });
408
- if (queueType === 0 /* Standard */) {
648
+ await queue.wait({
649
+ signal: requestData.signal
650
+ });
651
+ if (queueType === 0) {
409
652
  if (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {
410
653
  queue = this.#sublimitedQueue;
411
654
  const wait = queue.wait();
@@ -429,6 +672,15 @@ var SequentialHandler = class {
429
672
  }
430
673
  }
431
674
  }
675
+ /**
676
+ * The method that actually makes the request to the api, and updates info about the bucket accordingly
677
+ *
678
+ * @param routeId - The generalized api route with literal ids for major parameters
679
+ * @param url - The fully resolved url to make the request to
680
+ * @param options - The fetch options needed to make the request
681
+ * @param requestData - Extra data from the user's request needed for errors and additional processing
682
+ * @param retries - The number of retries this request has already attempted (recursion)
683
+ */
432
684
  async runRequest(routeId, url, options, requestData, retries = 0) {
433
685
  while (this.limited) {
434
686
  const isGlobal = this.globalLimited;
@@ -457,7 +709,7 @@ var SequentialHandler = class {
457
709
  majorParameter: this.majorParameter,
458
710
  global: isGlobal
459
711
  };
460
- this.manager.emit("rateLimited" /* RateLimited */, rateLimitData);
712
+ this.manager.emit(RESTEvents.RateLimited, rateLimitData);
461
713
  await this.onRateLimit(rateLimitData);
462
714
  if (isGlobal) {
463
715
  this.debug(`Global rate limit hit, blocking all requests for ${timeout2}ms`);
@@ -483,7 +735,10 @@ var SequentialHandler = class {
483
735
  }
484
736
  let res;
485
737
  try {
486
- res = await request(url, { ...options, signal: controller.signal });
738
+ res = await request(url, {
739
+ ...options,
740
+ signal: controller.signal
741
+ });
487
742
  } catch (error) {
488
743
  if (!(error instanceof Error))
489
744
  throw error;
@@ -494,19 +749,17 @@ var SequentialHandler = class {
494
749
  } finally {
495
750
  clearTimeout(timeout);
496
751
  }
497
- if (this.manager.listenerCount("response" /* Response */)) {
498
- this.manager.emit(
499
- "response" /* Response */,
500
- {
501
- method,
502
- path: routeId.original,
503
- route: routeId.bucketRoute,
504
- options,
505
- data: requestData,
506
- retries
507
- },
508
- { ...res }
509
- );
752
+ if (this.manager.listenerCount(RESTEvents.Response)) {
753
+ this.manager.emit(RESTEvents.Response, {
754
+ method,
755
+ path: routeId.original,
756
+ route: routeId.bucketRoute,
757
+ options,
758
+ data: requestData,
759
+ retries
760
+ }, {
761
+ ...res
762
+ });
510
763
  }
511
764
  const status = res.statusCode;
512
765
  let retryAfter = 0;
@@ -521,8 +774,15 @@ var SequentialHandler = class {
521
774
  if (retry)
522
775
  retryAfter = Number(retry) * 1e3 + this.manager.options.offset;
523
776
  if (hash && hash !== this.hash) {
524
- this.debug(["Received bucket hash update", ` Old Hash : ${this.hash}`, ` New Hash : ${hash}`].join("\n"));
525
- this.manager.hashes.set(`${method}:${routeId.bucketRoute}`, { value: hash, lastAccess: Date.now() });
777
+ this.debug([
778
+ "Received bucket hash update",
779
+ ` Old Hash : ${this.hash}`,
780
+ ` New Hash : ${hash}`
781
+ ].join("\n"));
782
+ this.manager.hashes.set(`${method}:${routeId.bucketRoute}`, {
783
+ value: hash,
784
+ lastAccess: Date.now()
785
+ });
526
786
  } else if (hash) {
527
787
  const hashData = this.manager.hashes.get(`${method}:${routeId.bucketRoute}`);
528
788
  if (hashData) {
@@ -546,7 +806,7 @@ var SequentialHandler = class {
546
806
  invalidCount++;
547
807
  const emitInvalid = this.manager.options.invalidRequestWarningInterval > 0 && invalidCount % this.manager.options.invalidRequestWarningInterval === 0;
548
808
  if (emitInvalid) {
549
- this.manager.emit("invalidRequestWarning" /* InvalidRequestWarning */, {
809
+ this.manager.emit(RESTEvents.InvalidRequestWarning, {
550
810
  count: invalidCount,
551
811
  remainingTime: invalidCountResetTime - Date.now()
552
812
  });
@@ -575,20 +835,18 @@ var SequentialHandler = class {
575
835
  majorParameter: this.majorParameter,
576
836
  global: isGlobal
577
837
  });
578
- this.debug(
579
- [
580
- "Encountered unexpected 429 rate limit",
581
- ` Global : ${isGlobal.toString()}`,
582
- ` Method : ${method}`,
583
- ` URL : ${url}`,
584
- ` Bucket : ${routeId.bucketRoute}`,
585
- ` Major parameter: ${routeId.majorParameter}`,
586
- ` Hash : ${this.hash}`,
587
- ` Limit : ${limit2}`,
588
- ` Retry After : ${retryAfter}ms`,
589
- ` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : "None"}`
590
- ].join("\n")
591
- );
838
+ this.debug([
839
+ "Encountered unexpected 429 rate limit",
840
+ ` Global : ${isGlobal.toString()}`,
841
+ ` Method : ${method}`,
842
+ ` URL : ${url}`,
843
+ ` Bucket : ${routeId.bucketRoute}`,
844
+ ` Major parameter: ${routeId.majorParameter}`,
845
+ ` Hash : ${this.hash}`,
846
+ ` Limit : ${limit2}`,
847
+ ` Retry After : ${retryAfter}ms`,
848
+ ` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : "None"}`
849
+ ].join("\n"));
592
850
  if (sublimitTimeout) {
593
851
  const firstSublimit = !this.#sublimitedQueue;
594
852
  if (firstSublimit) {
@@ -601,7 +859,10 @@ var SequentialHandler = class {
601
859
  await sleep(sublimitTimeout);
602
860
  let resolve;
603
861
  const promise = new Promise((res2) => resolve = res2);
604
- this.#sublimitPromise = { promise, resolve };
862
+ this.#sublimitPromise = {
863
+ promise,
864
+ resolve
865
+ };
605
866
  if (firstSublimit) {
606
867
  await this.#asyncQueue.wait();
607
868
  this.#shiftSublimit = true;
@@ -629,28 +890,43 @@ __name(SequentialHandler, "SequentialHandler");
629
890
 
630
891
  // src/lib/RequestManager.ts
631
892
  var getFileType = lazy(async () => import("file-type"));
632
- var RequestMethod = /* @__PURE__ */ ((RequestMethod2) => {
893
+ var RequestMethod;
894
+ (function(RequestMethod2) {
633
895
  RequestMethod2["Delete"] = "DELETE";
634
896
  RequestMethod2["Get"] = "GET";
635
897
  RequestMethod2["Patch"] = "PATCH";
636
898
  RequestMethod2["Post"] = "POST";
637
899
  RequestMethod2["Put"] = "PUT";
638
- return RequestMethod2;
639
- })(RequestMethod || {});
900
+ })(RequestMethod || (RequestMethod = {}));
640
901
  var RequestManager = class extends EventEmitter {
902
+ /**
903
+ * The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} for all requests
904
+ * performed by this manager.
905
+ */
641
906
  agent = null;
642
- globalRemaining;
907
+ /**
908
+ * The promise used to wait out the global rate limit
909
+ */
643
910
  globalDelay = null;
911
+ /**
912
+ * The timestamp at which the global bucket resets
913
+ */
644
914
  globalReset = -1;
915
+ /**
916
+ * API bucket hashes that are cached from provided routes
917
+ */
645
918
  hashes = new Collection();
919
+ /**
920
+ * Request handlers created from the bucket hash and the major parameters
921
+ */
646
922
  handlers = new Collection();
647
923
  #token = null;
648
- hashTimer;
649
- handlerTimer;
650
- options;
651
924
  constructor(options) {
652
925
  super();
653
- this.options = { ...DefaultRestOptions, ...options };
926
+ this.options = {
927
+ ...DefaultRestOptions,
928
+ ...options
929
+ };
654
930
  this.options.offset = Math.max(0, this.options.offset);
655
931
  this.globalRemaining = this.options.globalRequestsPerSecond;
656
932
  this.agent = options.agent ?? null;
@@ -674,10 +950,10 @@ var RequestManager = class extends EventEmitter {
674
950
  if (shouldSweep) {
675
951
  sweptHashes.set(key, val);
676
952
  }
677
- this.emit("restDebug" /* Debug */, `Hash ${val.value} for ${key} swept due to lifetime being exceeded`);
953
+ this.emit(RESTEvents.Debug, `Hash ${val.value} for ${key} swept due to lifetime being exceeded`);
678
954
  return shouldSweep;
679
955
  });
680
- this.emit("hashSweep" /* HashSweep */, sweptHashes);
956
+ this.emit(RESTEvents.HashSweep, sweptHashes);
681
957
  }, this.options.hashSweepInterval).unref();
682
958
  }
683
959
  if (this.options.handlerSweepInterval !== 0 && this.options.handlerSweepInterval !== Number.POSITIVE_INFINITY) {
@@ -689,21 +965,37 @@ var RequestManager = class extends EventEmitter {
689
965
  if (inactive) {
690
966
  sweptHandlers.set(key, val);
691
967
  }
692
- this.emit("restDebug" /* Debug */, `Handler ${val.id} for ${key} swept due to being inactive`);
968
+ this.emit(RESTEvents.Debug, `Handler ${val.id} for ${key} swept due to being inactive`);
693
969
  return inactive;
694
970
  });
695
- this.emit("handlerSweep" /* HandlerSweep */, sweptHandlers);
971
+ this.emit(RESTEvents.HandlerSweep, sweptHandlers);
696
972
  }, this.options.handlerSweepInterval).unref();
697
973
  }
698
974
  }
975
+ /**
976
+ * Sets the default agent to use for requests performed by this manager
977
+ *
978
+ * @param agent - The agent to use
979
+ */
699
980
  setAgent(agent) {
700
981
  this.agent = agent;
701
982
  return this;
702
983
  }
984
+ /**
985
+ * Sets the authorization token that should be used for requests
986
+ *
987
+ * @param token - The authorization token to use
988
+ */
703
989
  setToken(token) {
704
990
  this.#token = token;
705
991
  return this;
706
992
  }
993
+ /**
994
+ * Queues a request to be sent
995
+ *
996
+ * @param request - All the information needed to make a request
997
+ * @returns The response from the api request
998
+ */
707
999
  async queueRequest(request2) {
708
1000
  const routeId = RequestManager.generateRouteData(request2.fullRoute, request2.method);
709
1001
  const hash = this.hashes.get(`${request2.method}:${routeId.bucketRoute}`) ?? {
@@ -719,11 +1011,23 @@ var RequestManager = class extends EventEmitter {
719
1011
  signal: request2.signal
720
1012
  });
721
1013
  }
1014
+ /**
1015
+ * Creates a new rate limit handler from a hash, based on the hash and the major parameter
1016
+ *
1017
+ * @param hash - The hash for the route
1018
+ * @param majorParameter - The major parameter for this handler
1019
+ * @internal
1020
+ */
722
1021
  createHandler(hash, majorParameter) {
723
1022
  const queue = new SequentialHandler(this, hash, majorParameter);
724
1023
  this.handlers.set(queue.id, queue);
725
1024
  return queue;
726
1025
  }
1026
+ /**
1027
+ * Formats the request data to a usable format for fetch
1028
+ *
1029
+ * @param request - The request data
1030
+ */
727
1031
  async resolveRequest(request2) {
728
1032
  const { options } = this;
729
1033
  let query = "";
@@ -762,9 +1066,17 @@ var RequestManager = class extends EventEmitter {
762
1066
  contentType = OverwrittenMimeTypes[parsedType] ?? parsedType;
763
1067
  }
764
1068
  }
765
- formData.append(fileKey, new Blob2([file.data], { type: contentType }), file.name);
1069
+ formData.append(fileKey, new Blob2([
1070
+ file.data
1071
+ ], {
1072
+ type: contentType
1073
+ }), file.name);
766
1074
  } else {
767
- formData.append(fileKey, new Blob2([`${file.data}`], { type: file.contentType }), file.name);
1075
+ formData.append(fileKey, new Blob2([
1076
+ `${file.data}`
1077
+ ], {
1078
+ type: file.contentType
1079
+ }), file.name);
768
1080
  }
769
1081
  }
770
1082
  if (request2.body != null) {
@@ -782,33 +1094,55 @@ var RequestManager = class extends EventEmitter {
782
1094
  finalBody = request2.body;
783
1095
  } else {
784
1096
  finalBody = JSON.stringify(request2.body);
785
- additionalHeaders = { "Content-Type": "application/json" };
1097
+ additionalHeaders = {
1098
+ "Content-Type": "application/json"
1099
+ };
786
1100
  }
787
1101
  }
788
1102
  finalBody = await resolveBody(finalBody);
789
1103
  const fetchOptions = {
790
- headers: { ...request2.headers, ...additionalHeaders, ...headers },
1104
+ headers: {
1105
+ ...request2.headers,
1106
+ ...additionalHeaders,
1107
+ ...headers
1108
+ },
791
1109
  method: request2.method.toUpperCase()
792
1110
  };
793
1111
  if (finalBody !== void 0) {
794
1112
  fetchOptions.body = finalBody;
795
1113
  }
796
1114
  fetchOptions.dispatcher = request2.dispatcher ?? this.agent ?? void 0;
797
- return { url, fetchOptions };
1115
+ return {
1116
+ url,
1117
+ fetchOptions
1118
+ };
798
1119
  }
1120
+ /**
1121
+ * Stops the hash sweeping interval
1122
+ */
799
1123
  clearHashSweeper() {
800
1124
  clearInterval(this.hashTimer);
801
1125
  }
1126
+ /**
1127
+ * Stops the request handler sweeping interval
1128
+ */
802
1129
  clearHandlerSweeper() {
803
1130
  clearInterval(this.handlerTimer);
804
1131
  }
1132
+ /**
1133
+ * Generates route data for an endpoint:method
1134
+ *
1135
+ * @param endpoint - The raw endpoint to generalize
1136
+ * @param method - The HTTP method this endpoint is called without
1137
+ * @internal
1138
+ */
805
1139
  static generateRouteData(endpoint, method) {
806
- const majorIdMatch = /^\/(?:channels|guilds|webhooks)\/(\d{16,19})/.exec(endpoint);
1140
+ const majorIdMatch = /^\/(?:channels|guilds|webhooks)\/(\d{17,19})/.exec(endpoint);
807
1141
  const majorId = majorIdMatch?.[1] ?? "global";
808
- const baseRoute = endpoint.replaceAll(/\d{16,19}/g, ":id").replace(/\/reactions\/(.*)/, "/reactions/:reaction");
1142
+ const baseRoute = endpoint.replaceAll(/\d{17,19}/g, ":id").replace(/\/reactions\/(.*)/, "/reactions/:reaction");
809
1143
  let exceptions = "";
810
- if (method === "DELETE" /* Delete */ && baseRoute === "/channels/:id/messages/:id") {
811
- const id = /\d{16,19}$/.exec(endpoint)[0];
1144
+ if (method === "DELETE" && baseRoute === "/channels/:id/messages/:id") {
1145
+ const id = /\d{17,19}$/.exec(endpoint)[0];
812
1146
  const timestamp = DiscordSnowflake.timestampFrom(id);
813
1147
  if (Date.now() - timestamp > 1e3 * 60 * 60 * 24 * 14) {
814
1148
  exceptions += "/Delete Old Message";
@@ -826,51 +1160,122 @@ __name(RequestManager, "RequestManager");
826
1160
  // src/lib/REST.ts
827
1161
  import { EventEmitter as EventEmitter2 } from "node:events";
828
1162
  var REST = class extends EventEmitter2 {
829
- cdn;
830
- requestManager;
831
1163
  constructor(options = {}) {
832
1164
  super();
833
1165
  this.cdn = new CDN(options.cdn ?? DefaultRestOptions.cdn);
834
- 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 */));
1166
+ 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));
835
1167
  this.on("newListener", (name, listener) => {
836
- if (name === "response" /* Response */)
1168
+ if (name === RESTEvents.Response)
837
1169
  this.requestManager.on(name, listener);
838
1170
  });
839
1171
  this.on("removeListener", (name, listener) => {
840
- if (name === "response" /* Response */)
1172
+ if (name === RESTEvents.Response)
841
1173
  this.requestManager.off(name, listener);
842
1174
  });
843
1175
  }
1176
+ /**
1177
+ * Gets the agent set for this instance
1178
+ */
844
1179
  getAgent() {
845
1180
  return this.requestManager.agent;
846
1181
  }
1182
+ /**
1183
+ * Sets the default agent to use for requests performed by this instance
1184
+ *
1185
+ * @param agent - Sets the agent to use
1186
+ */
847
1187
  setAgent(agent) {
848
1188
  this.requestManager.setAgent(agent);
849
1189
  return this;
850
1190
  }
1191
+ /**
1192
+ * Sets the authorization token that should be used for requests
1193
+ *
1194
+ * @param token - The authorization token to use
1195
+ */
851
1196
  setToken(token) {
852
1197
  this.requestManager.setToken(token);
853
1198
  return this;
854
1199
  }
1200
+ /**
1201
+ * Runs a get request from the api
1202
+ *
1203
+ * @param fullRoute - The full route to query
1204
+ * @param options - Optional request options
1205
+ */
855
1206
  async get(fullRoute, options = {}) {
856
- return this.request({ ...options, fullRoute, method: "GET" /* Get */ });
1207
+ return this.request({
1208
+ ...options,
1209
+ fullRoute,
1210
+ method: RequestMethod.Get
1211
+ });
857
1212
  }
1213
+ /**
1214
+ * Runs a delete request from the api
1215
+ *
1216
+ * @param fullRoute - The full route to query
1217
+ * @param options - Optional request options
1218
+ */
858
1219
  async delete(fullRoute, options = {}) {
859
- return this.request({ ...options, fullRoute, method: "DELETE" /* Delete */ });
1220
+ return this.request({
1221
+ ...options,
1222
+ fullRoute,
1223
+ method: RequestMethod.Delete
1224
+ });
860
1225
  }
1226
+ /**
1227
+ * Runs a post request from the api
1228
+ *
1229
+ * @param fullRoute - The full route to query
1230
+ * @param options - Optional request options
1231
+ */
861
1232
  async post(fullRoute, options = {}) {
862
- return this.request({ ...options, fullRoute, method: "POST" /* Post */ });
1233
+ return this.request({
1234
+ ...options,
1235
+ fullRoute,
1236
+ method: RequestMethod.Post
1237
+ });
863
1238
  }
1239
+ /**
1240
+ * Runs a put request from the api
1241
+ *
1242
+ * @param fullRoute - The full route to query
1243
+ * @param options - Optional request options
1244
+ */
864
1245
  async put(fullRoute, options = {}) {
865
- return this.request({ ...options, fullRoute, method: "PUT" /* Put */ });
1246
+ return this.request({
1247
+ ...options,
1248
+ fullRoute,
1249
+ method: RequestMethod.Put
1250
+ });
866
1251
  }
1252
+ /**
1253
+ * Runs a patch request from the api
1254
+ *
1255
+ * @param fullRoute - The full route to query
1256
+ * @param options - Optional request options
1257
+ */
867
1258
  async patch(fullRoute, options = {}) {
868
- return this.request({ ...options, fullRoute, method: "PATCH" /* Patch */ });
1259
+ return this.request({
1260
+ ...options,
1261
+ fullRoute,
1262
+ method: RequestMethod.Patch
1263
+ });
869
1264
  }
1265
+ /**
1266
+ * Runs a request from the api
1267
+ *
1268
+ * @param options - Request options
1269
+ */
870
1270
  async request(options) {
871
1271
  const response = await this.raw(options);
872
1272
  return parseResponse(response);
873
1273
  }
1274
+ /**
1275
+ * Runs a request from the API, yielding the raw Response object
1276
+ *
1277
+ * @param options - Request options
1278
+ */
874
1279
  async raw(options) {
875
1280
  return this.requestManager.queueRequest(options);
876
1281
  }
@@ -878,7 +1283,7 @@ var REST = class extends EventEmitter2 {
878
1283
  __name(REST, "REST");
879
1284
 
880
1285
  // src/index.ts
881
- var version = "1.6.0-dev.1677499520-ffdb197.0";
1286
+ var version = "[VI]{{inject}}[/VI]";
882
1287
  export {
883
1288
  ALLOWED_EXTENSIONS,
884
1289
  ALLOWED_SIZES,