@discordeno/rest 19.0.0-next.28cbcee → 19.0.0-next.2b83d69

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/manager.js CHANGED
@@ -1,510 +1,40 @@
1
- /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable no-const-assign */ import { InteractionResponseTypes } from '@discordeno/types';
2
- import { calculateBits, camelize, camelToSnakeCase, delay, encode, findFiles, getBotIdFromToken, isGetMessagesAfter, isGetMessagesAround, isGetMessagesBefore, isGetMessagesLimit, logger, processReactionString, urlToBase64 } from '@discordeno/utils';
3
- import fetch from 'node-fetch';
1
+ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable no-const-assign */ import { calculateBits, camelToSnakeCase, camelize, delay, getBotIdFromToken, logger, processReactionString, urlToBase64 } from '@discordeno/utils';
4
2
  import { createInvalidRequestBucket } from './invalidBucket.js';
5
3
  import { Queue } from './queue.js';
4
+ import { InteractionResponseTypes } from '@discordeno/types';
5
+ import { createRoutes } from './routes.js';
6
6
  // TODO: make dynamic based on package.json file
7
7
  const version = '19.0.0-alpha.1';
8
+ export const DISCORD_API_VERSION = 10;
9
+ export const DISCORD_API_URL = 'https://discord.com/api';
10
+ export const AUDIT_LOG_REASON_HEADER = 'x-audit-log-reason';
11
+ export const RATE_LIMIT_REMAINING_HEADER = 'x-ratelimit-remaining';
12
+ export const RATE_LIMIT_RESET_AFTER_HEADER = 'x-ratelimit-reset-after';
13
+ export const RATE_LIMIT_GLOBAL_HEADER = 'x-ratelimit-global';
14
+ export const RATE_LIMIT_BUCKET_HEADER = 'x-ratelimit-bucket';
15
+ export const RATE_LIMIT_LIMIT_HEADER = 'x-ratelimit-limit';
16
+ export const RATE_LIMIT_SCOPE_HEADER = 'x-ratelimit-scope';
8
17
  export function createRestManager(options) {
9
- // Falsy token string check
10
- if (!options.token) throw new Error('You must provide a valid token.');
18
+ const applicationId = options.applicationId ? BigInt(options.applicationId) : options.token ? getBotIdFromToken(options.token) : undefined;
19
+ if (!applicationId) {
20
+ throw new Error('`applicationId` was not provided and was not able to extract the id from the bots token. Please explicitly pass `applicationId` to the rest manager.');
21
+ }
22
+ const baseUrl = options.proxy?.baseUrl ?? DISCORD_API_URL;
11
23
  const rest = {
12
- token: options.token,
13
- applicationId: options.applicationId ? BigInt(options.applicationId) : getBotIdFromToken(options.token),
14
- version: options.version ?? 10,
15
- baseUrl: options.proxy?.baseUrl ?? 'https://discord.com/api',
16
- maxRetryCount: Infinity,
24
+ applicationId,
25
+ authorization: options.proxy?.authorization,
26
+ baseUrl,
27
+ deleteQueueDelay: 60000,
17
28
  globallyRateLimited: false,
29
+ invalidBucket: createInvalidRequestBucket({}),
30
+ isProxied: !baseUrl.startsWith(DISCORD_API_URL),
31
+ maxRetryCount: Infinity,
18
32
  processingRateLimitedPaths: false,
19
- deleteQueueDelay: 60000,
20
33
  queues: new Map(),
21
34
  rateLimitedPaths: new Map(),
22
- invalidBucket: createInvalidRequestBucket({}),
23
- authorization: options.proxy?.authorization,
24
- routes: {
25
- webhooks: {
26
- id: (webhookId)=>{
27
- return `/webhooks/${webhookId}`;
28
- },
29
- message: (webhookId, token, messageId, options)=>{
30
- let url = `/webhooks/${webhookId}/${token}/messages/${messageId}?`;
31
- if (options) {
32
- if (options.threadId) url += `thread_id=${options.threadId}`;
33
- }
34
- return url;
35
- },
36
- original: (webhookId, token, options)=>{
37
- let url = `/webhooks/${webhookId}/${token}/messages/@original?`;
38
- if (options) {
39
- if (options.threadId) url += `thread_id=${options.threadId}`;
40
- }
41
- return url;
42
- },
43
- webhook: (webhookId, token, options)=>{
44
- let url = `/webhooks/${webhookId}/${token}?`;
45
- if (options) {
46
- if (options?.wait !== undefined) url += `wait=${options.wait.toString()}`;
47
- if (options.threadId) url += `thread_id=${options.threadId}`;
48
- }
49
- return url;
50
- }
51
- },
52
- // Miscellaneous Endpoints
53
- sessionInfo: ()=>rest.routes.gatewayBot(),
54
- // Channel Endpoints
55
- channels: {
56
- bulk: (channelId)=>{
57
- return `/channels/${channelId}/messages/bulk-delete`;
58
- },
59
- dm: ()=>{
60
- return '/users/@me/channels';
61
- },
62
- pin: (channelId, messageId)=>{
63
- return `/channels/${channelId}/pins/${messageId}`;
64
- },
65
- pins: (channelId)=>{
66
- return `/channels/${channelId}/pins`;
67
- },
68
- reactions: {
69
- bot: (channelId, messageId, emoji)=>{
70
- return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/@me`;
71
- },
72
- user: (channelId, messageId, emoji, userId)=>{
73
- return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/${userId}`;
74
- },
75
- all: (channelId, messageId)=>{
76
- return `/channels/${channelId}/messages/${messageId}/reactions`;
77
- },
78
- emoji: (channelId, messageId, emoji, options)=>{
79
- let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}?`;
80
- if (options) {
81
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
82
- if (options.after) url += `after=${options.after}`;
83
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
84
- if (options.limit) url += `&limit=${options.limit}`;
85
- }
86
- return url;
87
- },
88
- message: (channelId, messageId, emoji, options)=>{
89
- let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}?`;
90
- if (options) {
91
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
92
- if (options.after) url += `after=${options.after}`;
93
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
94
- if (options.limit) url += `&limit=${options.limit}`;
95
- }
96
- return url;
97
- }
98
- },
99
- webhooks: (channelId)=>{
100
- return `/channels/${channelId}/webhooks`;
101
- },
102
- channel: (channelId)=>{
103
- return `/channels/${channelId}`;
104
- },
105
- follow: (channelId)=>{
106
- return `/channels/${channelId}/followers`;
107
- },
108
- forum: (channelId)=>{
109
- return `/channels/${channelId}/threads?has_message=true`;
110
- },
111
- invites: (channelId)=>{
112
- return `/channels/${channelId}/invites`;
113
- },
114
- message: (channelId, messageId)=>{
115
- return `/channels/${channelId}/messages/${messageId}`;
116
- },
117
- messages: (channelId, options)=>{
118
- let url = `/channels/${channelId}/messages?`;
119
- if (options) {
120
- if (isGetMessagesAfter(options) && options.after) {
121
- url += `after=${options.after}`;
122
- }
123
- if (isGetMessagesBefore(options) && options.before) {
124
- url += `&before=${options.before}`;
125
- }
126
- if (isGetMessagesAround(options) && options.around) {
127
- url += `&around=${options.around}`;
128
- }
129
- if (isGetMessagesLimit(options) && options.limit) {
130
- url += `&limit=${options.limit}`;
131
- }
132
- }
133
- return url;
134
- },
135
- overwrite: (channelId, overwriteId)=>{
136
- return `/channels/${channelId}/permissions/${overwriteId}`;
137
- },
138
- crosspost: (channelId, messageId)=>{
139
- return `/channels/${channelId}/messages/${messageId}/crosspost`;
140
- },
141
- stages: ()=>{
142
- return '/stage-instances';
143
- },
144
- stage: (channelId)=>{
145
- return `/stage-instances/${channelId}`;
146
- },
147
- // Thread Endpoints
148
- threads: {
149
- message: (channelId, messageId)=>{
150
- return `/channels/${channelId}/messages/${messageId}/threads`;
151
- },
152
- all: (channelId)=>{
153
- return `/channels/${channelId}/threads`;
154
- },
155
- active: (guildId)=>{
156
- return `/guilds/${guildId}/threads/active`;
157
- },
158
- members: (channelId)=>{
159
- return `/channels/${channelId}/thread-members`;
160
- },
161
- me: (channelId)=>{
162
- return `/channels/${channelId}/thread-members/@me`;
163
- },
164
- user: (channelId, userId)=>{
165
- return `/channels/${channelId}/thread-members/${userId}`;
166
- },
167
- archived: (channelId)=>{
168
- return `/channels/${channelId}/threads/archived`;
169
- },
170
- public: (channelId, options)=>{
171
- let url = `/channels/${channelId}/threads/archived/public?`;
172
- if (options) {
173
- if (options.before) {
174
- url += `before=${new Date(options.before).toISOString()}`;
175
- }
176
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
177
- if (options.limit) url += `&limit=${options.limit}`;
178
- }
179
- return url;
180
- },
181
- private: (channelId, options)=>{
182
- let url = `/channels/${channelId}/threads/archived/private?`;
183
- if (options) {
184
- if (options.before) {
185
- url += `before=${new Date(options.before).toISOString()}`;
186
- }
187
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
188
- if (options.limit) url += `&limit=${options.limit}`;
189
- }
190
- return url;
191
- },
192
- joined: (channelId, options)=>{
193
- let url = `/channels/${channelId}/users/@me/threads/archived/private?`;
194
- if (options) {
195
- if (options.before) {
196
- url += `before=${new Date(options.before).toISOString()}`;
197
- }
198
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
199
- if (options.limit) url += `&limit=${options.limit}`;
200
- }
201
- return url;
202
- }
203
- },
204
- typing: (channelId)=>{
205
- return `/channels/${channelId}/typing`;
206
- }
207
- },
208
- // Guild Endpoints
209
- guilds: {
210
- all: ()=>{
211
- return '/guilds';
212
- },
213
- auditlogs: (guildId, options)=>{
214
- let url = `/guilds/${guildId}/audit-logs?`;
215
- if (options) {
216
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
217
- if (options.actionType) url += `action_type=${options.actionType}`;
218
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
219
- if (options.before) url += `&before=${options.before}`;
220
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
221
- if (options.after) url += `&after=${options.after}`;
222
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
223
- if (options.limit) url += `&limit=${options.limit}`;
224
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
225
- if (options.userId) url += `&user_id=${options.userId}`;
226
- }
227
- return url;
228
- },
229
- automod: {
230
- rule: (guildId, ruleId)=>{
231
- return `/guilds/${guildId}/auto-moderation/rules/${ruleId}`;
232
- },
233
- rules: (guildId)=>{
234
- return `/guilds/${guildId}/auto-moderation/rules`;
235
- }
236
- },
237
- channels: (guildId)=>{
238
- return `/guilds/${guildId}/channels`;
239
- },
240
- emoji: (guildId, emojiId)=>{
241
- return `/guilds/${guildId}/emojis/${emojiId}`;
242
- },
243
- emojis: (guildId)=>{
244
- return `/guilds/${guildId}/emojis`;
245
- },
246
- events: {
247
- events: (guildId, withUserCount)=>{
248
- let url = `/guilds/${guildId}/scheduled-events?`;
249
- if (withUserCount !== undefined) {
250
- url += `with_user_count=${withUserCount.toString()}`;
251
- }
252
- return url;
253
- },
254
- event: (guildId, eventId, withUserCount)=>{
255
- let url = `/guilds/${guildId}/scheduled-events/${eventId}`;
256
- if (withUserCount !== undefined) {
257
- url += `with_user_count=${withUserCount.toString()}`;
258
- }
259
- return url;
260
- },
261
- users: (guildId, eventId, options)=>{
262
- let url = `/guilds/${guildId}/scheduled-events/${eventId}/users?`;
263
- if (options) {
264
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
265
- if (options.limit !== undefined) url += `limit=${options.limit}`;
266
- if (options.withMember !== undefined) {
267
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
268
- url += `&with_member=${options.withMember.toString()}`;
269
- }
270
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
271
- if (options.after !== undefined) url += `&after=${options.after}`;
272
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
273
- if (options.before !== undefined) url += `&before=${options.before}`;
274
- }
275
- return url;
276
- }
277
- },
278
- guild (guildId, withCounts) {
279
- let url = `/guilds/${guildId}?`;
280
- if (withCounts !== undefined) {
281
- url += `with_counts=${withCounts.toString()}`;
282
- }
283
- return url;
284
- },
285
- integration (guildId, integrationId) {
286
- return `/guilds/${guildId}/integrations/${integrationId}`;
287
- },
288
- integrations: (guildId)=>{
289
- return `/guilds/${guildId}/integrations?include_applications=true`;
290
- },
291
- invite (inviteCode, options) {
292
- let url = `/invites/${inviteCode}?`;
293
- if (options) {
294
- if (options.withCounts !== undefined) {
295
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
296
- url += `with_counts=${options.withCounts.toString()}`;
297
- }
298
- if (options.withExpiration !== undefined) {
299
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
300
- url += `&with_expiration=${options.withExpiration.toString()}`;
301
- }
302
- if (options.scheduledEventId) {
303
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
304
- url += `&guild_scheduled_event_id=${options.scheduledEventId}`;
305
- }
306
- }
307
- return url;
308
- },
309
- invites: (guildId)=>{
310
- return `/guilds/${guildId}/invites`;
311
- },
312
- leave: (guildId)=>{
313
- return `/users/@me/guilds/${guildId}`;
314
- },
315
- members: {
316
- ban: (guildId, userId)=>{
317
- return `/guilds/${guildId}/bans/${userId}`;
318
- },
319
- bans: (guildId, options)=>{
320
- let url = `/guilds/${guildId}/bans?`;
321
- if (options) {
322
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
323
- if (options.limit) url += `limit=${options.limit}`;
324
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
325
- if (options.after) url += `&after=${options.after}`;
326
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
327
- if (options.before) url += `&before=${options.before}`;
328
- }
329
- return url;
330
- },
331
- bot: (guildId)=>{
332
- return `/guilds/${guildId}/members/@me`;
333
- },
334
- member: (guildId, userId)=>{
335
- return `/guilds/${guildId}/members/${userId}`;
336
- },
337
- members: (guildId, options)=>{
338
- let url = `/guilds/${guildId}/members?`;
339
- if (options !== undefined) {
340
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
341
- if (options.limit) url += `limit=${options.limit}`;
342
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
343
- if (options.after) url += `&after=${options.after}`;
344
- }
345
- return url;
346
- },
347
- search: (guildId, query, options)=>{
348
- let url = `/guilds/${guildId}/members/search?query=${encodeURIComponent(query)}`;
349
- if (options) {
350
- if (options.limit !== undefined) url += `&limit=${options.limit}`;
351
- }
352
- return url;
353
- },
354
- prune: (guildId, options)=>{
355
- let url = `/guilds/${guildId}/prune?`;
356
- if (options) {
357
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
358
- if (options.days) url += `days=${options.days}`;
359
- if (Array.isArray(options.includeRoles)) {
360
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
361
- url += `&include_roles=${options.includeRoles.join(',')}`;
362
- } else if (options.includeRoles) {
363
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
364
- url += `&include_roles=${options.includeRoles}`;
365
- }
366
- }
367
- return url;
368
- }
369
- },
370
- mfa: (guildId)=>`/guilds/${guildId}/mfa`,
371
- preview: (guildId)=>{
372
- return `/guilds/${guildId}/preview`;
373
- },
374
- prune: (guildId, options)=>{
375
- let url = `/guilds/${guildId}/prune?`;
376
- if (options) {
377
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
378
- if (options.days) url += `days=${options.days}`;
379
- if (Array.isArray(options.includeRoles)) {
380
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
381
- url += `&include_roles=${options.includeRoles.join(',')}`;
382
- } else if (options.includeRoles) {
383
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
384
- url += `&include_roles=${options.includeRoles}`;
385
- }
386
- }
387
- return url;
388
- },
389
- roles: {
390
- one: (guildId, roleId)=>{
391
- return `/guilds/${guildId}/roles/${roleId}`;
392
- },
393
- all: (guildId)=>{
394
- return `/guilds/${guildId}/roles`;
395
- },
396
- member: (guildId, memberId, roleId)=>{
397
- return `/guilds/${guildId}/members/${memberId}/roles/${roleId}`;
398
- }
399
- },
400
- stickers: (guildId)=>{
401
- return `/guilds/${guildId}/stickers`;
402
- },
403
- sticker: (guildId, stickerId)=>{
404
- return `/guilds/${guildId}/stickers/${stickerId}`;
405
- },
406
- voice: (guildId, userId)=>{
407
- return `/guilds/${guildId}/voice-states/${userId ?? '@me'}`;
408
- },
409
- templates: {
410
- code: (code)=>{
411
- return `/guilds/templates/${code}`;
412
- },
413
- guild: (guildId, code)=>{
414
- return `/guilds/${guildId}/templates/${code}`;
415
- },
416
- all: (guildId)=>{
417
- return `/guilds/${guildId}/templates`;
418
- }
419
- },
420
- vanity: (guildId)=>{
421
- return `/guilds/${guildId}/vanity-url`;
422
- },
423
- regions: (guildId)=>{
424
- return `/guilds/${guildId}/regions`;
425
- },
426
- webhooks: (guildId)=>{
427
- return `/guilds/${guildId}/webhooks`;
428
- },
429
- welcome: (guildId)=>{
430
- return `/guilds/${guildId}/welcome-screen`;
431
- },
432
- widget: (guildId)=>{
433
- return `/guilds/${guildId}/widget`;
434
- },
435
- widgetJson: (guildId)=>{
436
- return `/guilds/${guildId}/widget.json`;
437
- }
438
- },
439
- sticker: (stickerId)=>{
440
- return `/stickers/${stickerId}`;
441
- },
442
- regions: ()=>{
443
- return '/voice/regions';
444
- },
445
- // Interaction Endpoints
446
- interactions: {
447
- commands: {
448
- // Application Endpoints
449
- commands: (applicationId)=>{
450
- return `/applications/${applicationId}/commands`;
451
- },
452
- guilds: {
453
- all (applicationId, guildId) {
454
- return `/applications/${applicationId}/guilds/${guildId}/commands`;
455
- },
456
- one (applicationId, guildId, commandId, withLocalizations) {
457
- let url = `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}?`;
458
- if (withLocalizations !== undefined) {
459
- url += `with_localizations=${withLocalizations.toString()}`;
460
- }
461
- return url;
462
- }
463
- },
464
- permissions: (applicationId, guildId)=>{
465
- return `/applications/${applicationId}/guilds/${guildId}/commands/permissions`;
466
- },
467
- permission: (applicationId, guildId, commandId)=>{
468
- return `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}/permissions`;
469
- },
470
- command: (applicationId, commandId, withLocalizations)=>{
471
- let url = `/applications/${applicationId}/commands/${commandId}?`;
472
- if (withLocalizations !== undefined) {
473
- url += `withLocalizations=${withLocalizations.toString()}`;
474
- }
475
- return url;
476
- }
477
- },
478
- responses: {
479
- // Interaction Endpoints
480
- callback: (interactionId, token)=>{
481
- return `/interactions/${interactionId}/${token}/callback`;
482
- },
483
- original: (interactionId, token)=>{
484
- return `/webhooks/${interactionId}/${token}/messages/@original`;
485
- },
486
- message: (applicationId, token, messageId)=>{
487
- return `/webhooks/${applicationId}/${token}/messages/${messageId}`;
488
- }
489
- }
490
- },
491
- // User endpoints
492
- user (userId) {
493
- return `/users/${userId}`;
494
- },
495
- userBot () {
496
- return '/users/@me';
497
- },
498
- oauth2Application () {
499
- return 'oauth2/applications/@me';
500
- },
501
- gatewayBot () {
502
- return '/gateway/bot';
503
- },
504
- nitroStickerPacks () {
505
- return '/sticker-packs';
506
- }
507
- },
35
+ token: options.token,
36
+ version: options.version ?? DISCORD_API_VERSION,
37
+ routes: createRoutes(),
508
38
  checkRateLimits (url) {
509
39
  const ratelimited = rest.rateLimitedPaths.get(url);
510
40
  const global = rest.rateLimitedPaths.get('global');
@@ -530,11 +60,11 @@ export function createRestManager(options) {
530
60
  'permissions',
531
61
  'allow',
532
62
  'deny'
533
- ].includes(key)) {
63
+ ].includes(key) && obj[key] !== undefined) {
534
64
  newObj[key] = calculateBits(obj[key]);
535
65
  continue;
536
66
  }
537
- if (key === 'defaultMemberPermissions') {
67
+ if (key === 'defaultMemberPermissions' && obj[key] !== undefined) {
538
68
  newObj.default_member_permissions = calculateBits(obj[key]);
539
69
  continue;
540
70
  }
@@ -545,56 +75,47 @@ export function createRestManager(options) {
545
75
  if (typeof obj === 'bigint') return obj.toString();
546
76
  return obj;
547
77
  },
548
- createRequest (options) {
78
+ createRequestBody (method, options) {
549
79
  const headers = {
550
80
  'user-agent': `DiscordBot (https://github.com/discordeno/discordeno, v${version})`
551
81
  };
552
- if (!options.unauthorized) headers.authorization = `Bot ${rest.token}`;
553
- // SOMETIMES SPECIAL HEADERS (E.G. CUSTOM AUTHORIZATION) NEED TO BE USED
554
- if (options.headers) {
555
- for(const key in options.headers){
556
- headers[key.toLowerCase()] = options.headers[key];
557
- }
558
- }
559
- // GET METHODS SHOULD NOT HAVE A BODY
560
- if (options.method === 'GET') {
561
- options.body = undefined;
562
- }
82
+ if (options?.unauthorized !== false) headers.authorization = `Bot ${rest.token}`;
563
83
  // IF A REASON IS PROVIDED ENCODE IT IN HEADERS
564
- if (options.body?.reason) {
565
- headers['X-Audit-Log-Reason'] = encodeURIComponent(options.body.reason);
566
- options.body.reason = undefined;
84
+ if (options?.reason !== undefined) {
85
+ headers[AUDIT_LOG_REASON_HEADER] = encodeURIComponent(options?.reason);
567
86
  }
568
- if (options.body) {
569
- const { file } = options.body;
570
- if (file) {
571
- const files = findFiles(file);
572
- const form = new FormData();
573
- // WHEN CREATING A STICKER, DISCORD WANTS FORM DATA ONLY
574
- if (options.url?.endsWith('/stickers') && options.method === 'POST') {
575
- form.append('file', files[0].blob, files[0].name);
576
- form.append('name', options.body.name);
577
- form.append('description', options.body.description);
578
- form.append('tags', options.body.tags);
579
- } else {
580
- for(let i = 0; i < files.length; i++){
581
- form.append(`file${i}`, files[i].blob, files[i].name);
582
- }
583
- if (file) options.body.file = undefined;
584
- form.append('payload_json', JSON.stringify(rest.changeToDiscordFormat(options.body)));
585
- }
586
- options.body.file = form;
587
- } else if (options.body && ![
588
- 'GET',
589
- 'DELETE'
590
- ].includes(options.method)) {
591
- headers['Content-Type'] = 'application/json';
87
+ let body;
88
+ // TODO: check if we need to add specific check for GET method
89
+ // Since GET does not allow bodies
90
+ // Have to check for attachments first, since body then has to be send in a different way.
91
+ if (options?.files !== undefined) {
92
+ const form = new FormData();
93
+ for(let i = 0; i < options.files.length; ++i){
94
+ form.append(`file${i}`, options.files[i].blob, options.files[i].name);
95
+ }
96
+ form.append('payload_json', JSON.stringify({
97
+ ...options.body,
98
+ files: undefined
99
+ }));
100
+ body = form;
101
+ // No need to set the `content-type` header since `fetch` does that automatically for us when we use a `FormData` object.
102
+ } else if (options?.body !== undefined) {
103
+ if (options.body instanceof FormData) {
104
+ body = options.body;
105
+ // No need to set the `content-type` header since `fetch` does that automatically for us when we use a `FormData` object.
106
+ } else {
107
+ body = JSON.stringify(rest.changeToDiscordFormat(options.body));
108
+ headers['content-type'] = `application/json`;
592
109
  }
593
110
  }
111
+ // SOMETIMES SPECIAL HEADERS (E.G. CUSTOM AUTHORIZATION) NEED TO BE USED
112
+ if (options?.headers) {
113
+ Object.assign(headers, options.headers);
114
+ }
594
115
  return {
116
+ body,
595
117
  headers,
596
- body: options.body?.file ?? JSON.stringify(rest.changeToDiscordFormat(options.body)),
597
- method: options.method
118
+ method
598
119
  };
599
120
  },
600
121
  processRateLimitedPaths () {
@@ -627,13 +148,13 @@ export function createRestManager(options) {
627
148
  /** Processes the rate limit headers and determines if it needs to be rate limited and returns the bucket id if available */ processHeaders (url, headers) {
628
149
  let rateLimited = false;
629
150
  // GET ALL NECESSARY HEADERS
630
- const remaining = headers.get('x-ratelimit-remaining');
631
- const retryAfter = headers.get('x-ratelimit-reset-after');
151
+ const remaining = headers.get(RATE_LIMIT_REMAINING_HEADER);
152
+ const retryAfter = headers.get(RATE_LIMIT_RESET_AFTER_HEADER);
632
153
  const reset = Date.now() + Number(retryAfter) * 1000;
633
- const global = headers.get('x-ratelimit-global');
154
+ const global = headers.get(RATE_LIMIT_GLOBAL_HEADER);
634
155
  // undefined override null needed for typings
635
- const bucketId = headers.get('x-ratelimit-bucket') ?? undefined;
636
- const limit = headers.get('x-ratelimit-limit');
156
+ const bucketId = headers.get(RATE_LIMIT_BUCKET_HEADER) ?? undefined;
157
+ const limit = headers.get(RATE_LIMIT_LIMIT_HEADER);
637
158
  rest.queues.get(url)?.handleCompletedRequest({
638
159
  remaining: remaining ? Number(remaining) : undefined,
639
160
  interval: retryAfter ? Number(retryAfter) * 1000 : undefined,
@@ -688,13 +209,8 @@ export function createRestManager(options) {
688
209
  return rateLimited ? bucketId : undefined;
689
210
  },
690
211
  async sendRequest (options) {
691
- const url = options.url.startsWith('https://') ? options.url : `${rest.baseUrl}/v${rest.version}${options.url}`;
692
- const payload = rest.createRequest({
693
- method: options.method,
694
- url: options.url,
695
- body: options.body,
696
- ...options.options
697
- });
212
+ const url = `${rest.baseUrl}/v${rest.version}${options.route}`;
213
+ const payload = rest.createRequestBody(options.method, options.requestBodyOptions);
698
214
  logger.debug(`sending request to ${url}`, 'with payload:', {
699
215
  ...payload,
700
216
  headers: {
@@ -702,80 +218,86 @@ export function createRestManager(options) {
702
218
  authorization: 'Bot tokenhere'
703
219
  }
704
220
  });
705
- const response = await fetch(url, payload);
221
+ const response = await fetch(url, payload).catch(async (error)=>{
222
+ logger.error(error);
223
+ // Mark request and completed
224
+ rest.invalidBucket.handleCompletedRequest(999, false);
225
+ options.reject({
226
+ ok: false,
227
+ status: 999,
228
+ error: 'Possible network or request shape issue occurred. If this is rare, its a network glitch. If it occurs a lot something is wrong.'
229
+ });
230
+ throw error;
231
+ });
706
232
  logger.debug(`request fetched from ${url} with status ${response.status} & ${response.statusText}`);
233
+ // Mark request and completed
234
+ rest.invalidBucket.handleCompletedRequest(response.status, response.headers.get(RATE_LIMIT_SCOPE_HEADER) === 'shared');
707
235
  // Set the bucket id if it was available on the headers
708
- const bucketId = rest.processHeaders(rest.simplifyUrl(options.url, options.method), response.headers);
236
+ const bucketId = rest.processHeaders(rest.simplifyUrl(options.route, options.method), response.headers);
709
237
  if (bucketId) options.bucketId = bucketId;
710
238
  if (response.status < 200 || response.status >= 400) {
711
239
  logger.debug(`Request to ${url} failed.`);
712
- if (response.status === 429) {
713
- logger.debug(`Request to ${url} was ratelimited.`);
714
- // Too many attempts, get rid of request from queue.
715
- if (options.retryCount++ >= rest.maxRetryCount) {
716
- logger.debug(`Request to ${url} exceeded the maximum allowed retries.`, 'with payload:', payload);
717
- // rest.debug(`[REST - RetriesMaxed] ${JSON.stringify(options)}`)
718
- // Remove item from queue to prevent retry
719
- options.reject({
720
- ok: false,
721
- status: response.status,
722
- error: 'The options was rate limited and it maxed out the retries limit.'
723
- });
724
- return;
725
- }
726
- // Rate limited, add back to queue
727
- rest.invalidBucket.handleCompletedRequest(response.status, response.headers.get('X-RateLimit-Scope') === 'shared');
728
- const resetAfter = response.headers.get('x-ratelimit-reset-after');
729
- if (resetAfter) await delay(Number(resetAfter) * 1000);
730
- // process the response to prevent mem leak
731
- await response.json();
732
- return await options.retryRequest?.(options);
240
+ if (response.status !== 429) {
241
+ options.reject({
242
+ ok: false,
243
+ status: response.status,
244
+ body: await response.text()
245
+ });
246
+ return;
733
247
  }
734
- options.reject({
735
- ok: false,
736
- status: response.status,
737
- body: JSON.stringify(await response.json())
738
- });
739
- return;
248
+ logger.debug(`Request to ${url} was ratelimited.`);
249
+ // Too many attempts, get rid of request from queue.
250
+ if (options.retryCount >= rest.maxRetryCount) {
251
+ logger.debug(`Request to ${url} exceeded the maximum allowed retries.`, 'with payload:', payload);
252
+ // rest.debug(`[REST - RetriesMaxed] ${JSON.stringify(options)}`)
253
+ options.reject({
254
+ ok: false,
255
+ status: response.status,
256
+ error: 'The request was rate limited and it maxed out the retries limit.'
257
+ });
258
+ return;
259
+ }
260
+ options.retryCount += 1;
261
+ const resetAfter = response.headers.get(RATE_LIMIT_RESET_AFTER_HEADER);
262
+ if (resetAfter) await delay(Number(resetAfter) * 1000);
263
+ // process the response to prevent mem leak
264
+ await response.arrayBuffer();
265
+ return await options.retryRequest?.(options);
740
266
  }
741
- const is204 = response.status === 204;
742
- const json = is204 ? undefined : await response.json();
743
- // Discord sometimes sends no response with 204 code
267
+ // Discord sometimes sends no response with no content.
744
268
  options.resolve({
745
269
  ok: true,
746
270
  status: response.status,
747
- body: JSON.stringify(json)
271
+ body: response.status === 204 ? undefined : await response.text()
748
272
  });
749
273
  },
750
- // Credits: github.com/abalabahaha/eris lib/rest/RequestHandler.js#L397
751
- // Modified for our use-case
752
274
  simplifyUrl (url, method) {
753
- let route = url.replace(/\/([a-z-]+)\/(?:[0-9]{17,19})/g, function(match, p) {
754
- return [
755
- 'channels',
756
- 'guilds'
757
- ].includes(p) ? match : `/${p}/x`;
758
- }).replace(/\/reactions\/[^/]+/g, '/reactions/x');
759
- // GENERAL /reactions and /reactions/emoji/@me share the buckets
760
- if (route.includes('/reactions')) {
761
- route = route.substring(0, route.indexOf('/reactions') + '/reactions'.length);
275
+ const parts = url.split('/');
276
+ const secondLastPart = parts[parts.length - 2];
277
+ if (secondLastPart === 'channels' || secondLastPart === 'guilds') {
278
+ return url;
279
+ }
280
+ if (secondLastPart === 'reactions' || parts[parts.length - 1] === '@me') {
281
+ parts.splice(-2);
282
+ parts.push('reactions');
283
+ } else {
284
+ parts.splice(-1);
285
+ parts.push('x');
762
286
  }
763
- // Delete Message endpoint has its own rate limit
764
- if (method === 'DELETE' && route.endsWith('/messages/x')) {
765
- route = method + route;
287
+ if (parts[parts.length - 3] === 'reactions') {
288
+ parts.splice(-2);
289
+ }
290
+ if (method === 'DELETE' && secondLastPart === 'messages') {
291
+ return `D${parts.join('/')}`;
292
+ }
293
+ return parts.join('/');
294
+ },
295
+ async processRequest (request) {
296
+ const url = rest.simplifyUrl(request.route, request.method);
297
+ if (request.runThroughQueue === false) {
298
+ await rest.sendRequest(request);
299
+ return;
766
300
  }
767
- return route;
768
- },
769
- processRequest (request) {
770
- const route = request.url.substring(request.url.indexOf('api/'));
771
- const parts = route.split('/');
772
- // Remove the api/
773
- parts.shift();
774
- // Removes the /v#/
775
- if (parts[0]?.startsWith('v')) parts.shift();
776
- // Set the full url to discord api in case it was recieved in a proxy rest
777
- request.url = `${rest.baseUrl}/v${rest.version}/${parts.join('/')}`;
778
- const url = rest.simplifyUrl(request.url, request.method);
779
301
  const queue = rest.queues.get(url);
780
302
  if (queue !== undefined) {
781
303
  queue.makeRequest(request);
@@ -791,35 +313,14 @@ export function createRestManager(options) {
791
313
  rest.queues.set(url, bucketQueue);
792
314
  }
793
315
  },
794
- async makeRequest (method, url, body, options) {
795
- if (!rest.baseUrl.startsWith('https://discord.com') && url[0] === '/') {
796
- // Special handling for sending blobs across http to proxy
797
- if (body?.file) {
798
- if (!Array.isArray(body.file)) {
799
- body.file = [
800
- body.file
801
- ];
802
- }
803
- // convert blobs to string before sending to proxy
804
- body.file = await Promise.all(body.file.map(async (f)=>{
805
- const url = encode(await f.blob.arrayBuffer());
806
- return {
807
- name: f.name,
808
- blob: `data:${f.blob.type};base64,${url}`
809
- };
810
- }));
811
- }
812
- const headers = {
813
- Authorization: rest.authorization ?? ''
814
- };
815
- if (body) {
816
- headers['Content-Type'] = 'application/json';
316
+ async makeRequest (method, route, options) {
317
+ if (rest.isProxied) {
318
+ if (rest.authorization !== undefined) {
319
+ options ??= {};
320
+ options.headers ??= {};
321
+ options.headers.authorization = rest.authorization;
817
322
  }
818
- const result = await fetch(`${rest.baseUrl}${url}`, {
819
- body: body ? JSON.stringify(body) : undefined,
820
- headers,
821
- method
822
- });
323
+ const result = await fetch(`${rest.baseUrl}/v${rest.version}${route}`, rest.createRequestBody(method, options));
823
324
  if (!result.ok) {
824
325
  const err = await result.json().catch(()=>{});
825
326
  // Legacy Handling to not break old code or when body is missing
@@ -828,38 +329,39 @@ export function createRestManager(options) {
828
329
  }
829
330
  return result.status !== 204 ? await result.json() : undefined;
830
331
  }
831
- return await new Promise((resolve, reject)=>{
332
+ // eslint-disable-next-line no-async-promise-executor
333
+ return await new Promise(async (resolve, reject)=>{
832
334
  const payload = {
833
- url,
335
+ route,
834
336
  method,
835
- body,
337
+ requestBodyOptions: options,
836
338
  retryCount: 0,
837
- retryRequest: async function(options) {
838
- rest.processRequest(payload);
339
+ retryRequest: async function(payload) {
340
+ await rest.processRequest(payload);
839
341
  },
840
342
  resolve: (data)=>{
841
343
  resolve(data.status !== 204 ? JSON.parse(data.body ?? '{}') : undefined);
842
344
  },
843
345
  reject,
844
- options
346
+ runThroughQueue: options?.runThroughQueue
845
347
  };
846
- rest.processRequest(payload);
348
+ await rest.processRequest(payload);
847
349
  });
848
350
  },
849
- async get (url) {
850
- return camelize(await rest.makeRequest('GET', url));
351
+ async get (url, options) {
352
+ return camelize(await rest.makeRequest('GET', url, options));
851
353
  },
852
- async post (url, body) {
853
- return camelize(await rest.makeRequest('POST', url, body));
354
+ async post (url, options) {
355
+ return camelize(await rest.makeRequest('POST', url, options));
854
356
  },
855
- async delete (url, body) {
856
- camelize(await rest.makeRequest('DELETE', url, body));
357
+ async delete (url, options) {
358
+ camelize(await rest.makeRequest('DELETE', url, options));
857
359
  },
858
- async patch (url, body) {
859
- return camelize(await rest.makeRequest('PATCH', url, body));
360
+ async patch (url, options) {
361
+ return camelize(await rest.makeRequest('PATCH', url, options));
860
362
  },
861
- async put (url, body, options) {
862
- return camelize(await rest.makeRequest('PUT', url, body, options));
363
+ async put (url, options) {
364
+ return camelize(await rest.makeRequest('PUT', url, options));
863
365
  },
864
366
  async addReaction (channelId, messageId, reaction) {
865
367
  reaction = processReactionString(reaction);
@@ -884,59 +386,101 @@ export function createRestManager(options) {
884
386
  async addThreadMember (channelId, userId) {
885
387
  await rest.put(rest.routes.channels.threads.user(channelId, userId));
886
388
  },
887
- async createAutomodRule (guildId, options) {
888
- return await rest.post(rest.routes.guilds.automod.rules(guildId), options);
389
+ async createAutomodRule (guildId, body, reason) {
390
+ return await rest.post(rest.routes.guilds.automod.rules(guildId), {
391
+ body,
392
+ reason
393
+ });
889
394
  },
890
- async createChannel (guildId, options) {
891
- return await rest.post(rest.routes.guilds.channels(guildId), options);
395
+ async createChannel (guildId, body, reason) {
396
+ return await rest.post(rest.routes.guilds.channels(guildId), {
397
+ body,
398
+ reason
399
+ });
892
400
  },
893
- async createEmoji (guildId, options) {
894
- return await rest.post(rest.routes.guilds.emojis(guildId), options);
401
+ async createEmoji (guildId, body, reason) {
402
+ return await rest.post(rest.routes.guilds.emojis(guildId), {
403
+ body,
404
+ reason
405
+ });
895
406
  },
896
- async createGlobalApplicationCommand (command) {
897
- return await rest.post(rest.routes.interactions.commands.commands(rest.applicationId), command);
407
+ async createGlobalApplicationCommand (body) {
408
+ return await rest.post(rest.routes.interactions.commands.commands(rest.applicationId), {
409
+ body
410
+ });
898
411
  },
899
- async createGuild (options) {
900
- return await rest.post(rest.routes.guilds.all(), options);
412
+ async createGuild (body) {
413
+ return await rest.post(rest.routes.guilds.all(), {
414
+ body
415
+ });
901
416
  },
902
- async createGuildApplicationCommand (command, guildId) {
903
- return await rest.post(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), command);
417
+ async createGuildApplicationCommand (body, guildId) {
418
+ return await rest.post(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), {
419
+ body
420
+ });
904
421
  },
905
- async createGuildFromTemplate (templateCode, options) {
906
- if (options.icon) {
907
- options.icon = await urlToBase64(options.icon);
422
+ async createGuildFromTemplate (templateCode, body) {
423
+ if (body.icon) {
424
+ body.icon = await urlToBase64(body.icon);
908
425
  }
909
- return await rest.post(rest.routes.guilds.templates.code(templateCode), options);
426
+ return await rest.post(rest.routes.guilds.templates.code(templateCode), {
427
+ body
428
+ });
910
429
  },
911
- async createGuildSticker (guildId, options) {
912
- return await rest.post(rest.routes.guilds.stickers(guildId), options);
430
+ async createGuildSticker (guildId, options, reason) {
431
+ const form = new FormData();
432
+ form.append('file', options.file.blob, options.file.name);
433
+ form.append('name', options.name);
434
+ form.append('description', options.description);
435
+ form.append('tags', options.tags);
436
+ return await rest.post(rest.routes.guilds.stickers(guildId), {
437
+ body: form,
438
+ reason
439
+ });
913
440
  },
914
- async createGuildTemplate (guildId, options) {
915
- return await rest.post(rest.routes.guilds.templates.all(guildId), options);
441
+ async createGuildTemplate (guildId, body) {
442
+ return await rest.post(rest.routes.guilds.templates.all(guildId), {
443
+ body
444
+ });
916
445
  },
917
- async createForumThread (channelId, options) {
918
- return await rest.post(rest.routes.channels.forum(channelId), options);
446
+ async createForumThread (channelId, body, reason) {
447
+ return await rest.post(rest.routes.channels.forum(channelId), {
448
+ body,
449
+ files: body.files,
450
+ reason
451
+ });
919
452
  },
920
- async createInvite (channelId, options = {}) {
921
- return await rest.post(rest.routes.channels.invites(channelId), options);
453
+ async createInvite (channelId, body = {}, reason) {
454
+ return await rest.post(rest.routes.channels.invites(channelId), {
455
+ body,
456
+ reason
457
+ });
922
458
  },
923
- async createRole (guildId, options, reason) {
459
+ async createRole (guildId, body, reason) {
924
460
  return await rest.post(rest.routes.guilds.roles.all(guildId), {
925
- ...options,
461
+ body,
926
462
  reason
927
463
  });
928
464
  },
929
- async createScheduledEvent (guildId, options) {
930
- return await rest.post(rest.routes.guilds.events.events(guildId), options);
465
+ async createScheduledEvent (guildId, body, reason) {
466
+ return await rest.post(rest.routes.guilds.events.events(guildId), {
467
+ body,
468
+ reason
469
+ });
931
470
  },
932
- async createStageInstance (options) {
933
- return await rest.post(rest.routes.channels.stages(), options);
471
+ async createStageInstance (body, reason) {
472
+ return await rest.post(rest.routes.channels.stages(), {
473
+ body,
474
+ reason
475
+ });
934
476
  },
935
- async createWebhook (channelId, options) {
477
+ async createWebhook (channelId, options, reason) {
936
478
  return await rest.post(rest.routes.channels.webhooks(channelId), {
937
- name: options.name,
938
- avatar: options.avatar ? await urlToBase64(options.avatar) : undefined,
939
- reason: options.reason
479
+ body: {
480
+ name: options.name,
481
+ avatar: options.avatar ? await urlToBase64(options.avatar) : undefined
482
+ },
483
+ reason
940
484
  });
941
485
  },
942
486
  async deleteAutomodRule (guildId, ruleId, reason) {
@@ -950,9 +494,9 @@ export function createRestManager(options) {
950
494
  });
951
495
  },
952
496
  async deleteChannelPermissionOverride (channelId, overwriteId, reason) {
953
- await rest.delete(rest.routes.channels.overwrite(channelId, overwriteId), reason ? {
497
+ await rest.delete(rest.routes.channels.overwrite(channelId, overwriteId), {
954
498
  reason
955
- } : undefined);
499
+ });
956
500
  },
957
501
  async deleteEmoji (guildId, id, reason) {
958
502
  await rest.delete(rest.routes.guilds.emoji(guildId, id), {
@@ -960,7 +504,9 @@ export function createRestManager(options) {
960
504
  });
961
505
  },
962
506
  async deleteFollowupMessage (token, messageId) {
963
- await rest.delete(rest.routes.interactions.responses.message(rest.applicationId, token, messageId));
507
+ await rest.delete(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
508
+ unauthorized: true
509
+ });
964
510
  },
965
511
  async deleteGlobalApplicationCommand (commandId) {
966
512
  await rest.delete(rest.routes.interactions.commands.command(rest.applicationId, commandId));
@@ -972,20 +518,22 @@ export function createRestManager(options) {
972
518
  await rest.delete(rest.routes.interactions.commands.guilds.one(rest.applicationId, guildId, commandId));
973
519
  },
974
520
  async deleteGuildSticker (guildId, stickerId, reason) {
975
- await rest.delete(rest.routes.guilds.sticker(guildId, stickerId), reason ? {
521
+ await rest.delete(rest.routes.guilds.sticker(guildId, stickerId), {
976
522
  reason
977
- } : undefined);
523
+ });
978
524
  },
979
525
  async deleteGuildTemplate (guildId, templateCode) {
980
526
  await rest.delete(rest.routes.guilds.templates.guild(guildId, templateCode));
981
527
  },
982
- async deleteIntegration (guildId, integrationId) {
983
- await rest.delete(rest.routes.guilds.integration(guildId, integrationId));
528
+ async deleteIntegration (guildId, integrationId, reason) {
529
+ await rest.delete(rest.routes.guilds.integration(guildId, integrationId), {
530
+ reason
531
+ });
984
532
  },
985
533
  async deleteInvite (inviteCode, reason) {
986
- await rest.delete(rest.routes.guilds.invite(inviteCode), reason ? {
534
+ await rest.delete(rest.routes.guilds.invite(inviteCode), {
987
535
  reason
988
- } : undefined);
536
+ });
989
537
  },
990
538
  async deleteMessage (channelId, messageId, reason) {
991
539
  await rest.delete(rest.routes.channels.message(channelId, messageId), {
@@ -994,12 +542,16 @@ export function createRestManager(options) {
994
542
  },
995
543
  async deleteMessages (channelId, messageIds, reason) {
996
544
  await rest.post(rest.routes.channels.bulk(channelId), {
997
- messages: messageIds.slice(0, 100).map((id)=>id.toString()),
545
+ body: {
546
+ messages: messageIds.slice(0, 100).map((id)=>id.toString())
547
+ },
998
548
  reason
999
549
  });
1000
550
  },
1001
551
  async deleteOriginalInteractionResponse (token) {
1002
- await rest.delete(rest.routes.interactions.responses.original(rest.applicationId, token));
552
+ await rest.delete(rest.routes.interactions.responses.original(rest.applicationId, token), {
553
+ unauthorized: true
554
+ });
1003
555
  },
1004
556
  async deleteOwnReaction (channelId, messageId, reaction) {
1005
557
  reaction = processReactionString(reaction);
@@ -1012,16 +564,18 @@ export function createRestManager(options) {
1012
564
  reaction = processReactionString(reaction);
1013
565
  await rest.delete(rest.routes.channels.reactions.emoji(channelId, messageId, reaction));
1014
566
  },
1015
- async deleteRole (guildId, roleId) {
1016
- await rest.delete(rest.routes.guilds.roles.one(guildId, roleId));
567
+ async deleteRole (guildId, roleId, reason) {
568
+ await rest.delete(rest.routes.guilds.roles.one(guildId, roleId), {
569
+ reason
570
+ });
1017
571
  },
1018
572
  async deleteScheduledEvent (guildId, eventId) {
1019
573
  await rest.delete(rest.routes.guilds.events.event(guildId, eventId));
1020
574
  },
1021
575
  async deleteStageInstance (channelId, reason) {
1022
- await rest.delete(rest.routes.channels.stage(channelId), reason ? {
576
+ await rest.delete(rest.routes.channels.stage(channelId), {
1023
577
  reason
1024
- } : undefined);
578
+ });
1025
579
  },
1026
580
  async deleteUserReaction (channelId, messageId, userId, reaction) {
1027
581
  reaction = processReactionString(reaction);
@@ -1038,122 +592,195 @@ export function createRestManager(options) {
1038
592
  async deleteWebhookWithToken (webhookId, token) {
1039
593
  await rest.delete(rest.routes.webhooks.webhook(webhookId, token));
1040
594
  },
1041
- async editApplicationCommandPermissions (guildId, commandId, bearerToken, options) {
595
+ async editApplicationCommandPermissions (guildId, commandId, bearerToken, permissions) {
1042
596
  return await rest.put(rest.routes.interactions.commands.permission(rest.applicationId, guildId, commandId), {
1043
- permissions: options
1044
- }, {
597
+ body: {
598
+ permissions
599
+ },
1045
600
  headers: {
1046
601
  authorization: `Bearer ${bearerToken}`
1047
602
  }
1048
603
  });
1049
604
  },
1050
- async editAutomodRule (guildId, ruleId, options) {
1051
- return await rest.patch(rest.routes.guilds.automod.rule(guildId, ruleId), options);
605
+ async editAutomodRule (guildId, ruleId, body, reason) {
606
+ return await rest.patch(rest.routes.guilds.automod.rule(guildId, ruleId), {
607
+ body,
608
+ reason
609
+ });
1052
610
  },
1053
611
  async editBotProfile (options) {
1054
612
  const avatar = options?.botAvatarURL ? await urlToBase64(options?.botAvatarURL) : options?.botAvatarURL;
1055
613
  return await rest.patch(rest.routes.userBot(), {
1056
- username: options.username?.trim(),
1057
- avatar
614
+ body: {
615
+ username: options.username?.trim(),
616
+ avatar
617
+ }
1058
618
  });
1059
619
  },
1060
- async editChannel (channelId, options) {
1061
- return await rest.patch(rest.routes.channels.channel(channelId), options);
620
+ async editChannel (channelId, body, reason) {
621
+ return await rest.patch(rest.routes.channels.channel(channelId), {
622
+ body,
623
+ reason
624
+ });
1062
625
  },
1063
- async editChannelPermissionOverrides (channelId, options) {
1064
- await rest.put(rest.routes.channels.overwrite(channelId, options.id), options);
626
+ async editChannelPermissionOverrides (channelId, body, reason) {
627
+ await rest.put(rest.routes.channels.overwrite(channelId, body.id), {
628
+ body,
629
+ reason
630
+ });
1065
631
  },
1066
- async editChannelPositions (guildId, channelPositions) {
1067
- await rest.patch(rest.routes.guilds.channels(guildId), channelPositions);
632
+ async editChannelPositions (guildId, body) {
633
+ await rest.patch(rest.routes.guilds.channels(guildId), {
634
+ body
635
+ });
1068
636
  },
1069
- async editEmoji (guildId, id, options) {
1070
- return await rest.patch(rest.routes.guilds.emoji(guildId, id), options);
637
+ async editEmoji (guildId, id, body, reason) {
638
+ return await rest.patch(rest.routes.guilds.emoji(guildId, id), {
639
+ body,
640
+ reason
641
+ });
1071
642
  },
1072
- async editFollowupMessage (token, messageId, options) {
1073
- return await rest.patch(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), options);
643
+ async editFollowupMessage (token, messageId, body) {
644
+ return await rest.patch(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
645
+ body,
646
+ files: body.files,
647
+ unauthorized: true
648
+ });
1074
649
  },
1075
- async editGlobalApplicationCommand (commandId, options) {
1076
- return await rest.patch(rest.routes.interactions.commands.command(rest.applicationId, commandId), options);
650
+ async editGlobalApplicationCommand (commandId, body) {
651
+ return await rest.patch(rest.routes.interactions.commands.command(rest.applicationId, commandId), {
652
+ body
653
+ });
1077
654
  },
1078
- async editGuild (guildId, options) {
1079
- return await rest.patch(rest.routes.guilds.guild(guildId), options);
655
+ async editGuild (guildId, body, reason) {
656
+ return await rest.patch(rest.routes.guilds.guild(guildId), {
657
+ body,
658
+ reason
659
+ });
1080
660
  },
1081
- async editGuildApplicationCommand (commandId, guildId, options) {
1082
- return await rest.patch(rest.routes.interactions.commands.guilds.one(rest.applicationId, guildId, commandId), options);
661
+ async editGuildApplicationCommand (commandId, guildId, body) {
662
+ return await rest.patch(rest.routes.interactions.commands.guilds.one(rest.applicationId, guildId, commandId), {
663
+ body
664
+ });
1083
665
  },
1084
666
  async editGuildMfaLevel (guildId, mfaLevel, reason) {
1085
667
  await rest.post(rest.routes.guilds.mfa(guildId), {
1086
- level: mfaLevel,
668
+ body: {
669
+ level: mfaLevel
670
+ },
1087
671
  reason
1088
672
  });
1089
673
  },
1090
- async editGuildSticker (guildId, stickerId, options) {
1091
- return await rest.patch(rest.routes.guilds.sticker(guildId, stickerId), options);
674
+ async editGuildSticker (guildId, stickerId, body, reason) {
675
+ return await rest.patch(rest.routes.guilds.sticker(guildId, stickerId), {
676
+ body,
677
+ reason
678
+ });
1092
679
  },
1093
- async editGuildTemplate (guildId, templateCode, options) {
1094
- return await rest.patch(rest.routes.guilds.templates.guild(guildId, templateCode), options);
680
+ async editGuildTemplate (guildId, templateCode, body) {
681
+ return await rest.patch(rest.routes.guilds.templates.guild(guildId, templateCode), {
682
+ body
683
+ });
1095
684
  },
1096
- async editMessage (channelId, messageId, options) {
1097
- return await rest.patch(rest.routes.channels.message(channelId, messageId), options);
685
+ async editMessage (channelId, messageId, body) {
686
+ return await rest.patch(rest.routes.channels.message(channelId, messageId), {
687
+ body
688
+ });
1098
689
  },
1099
- async editOriginalInteractionResponse (token, options) {
1100
- return await rest.patch(rest.routes.interactions.responses.original(rest.applicationId, token), options);
690
+ async editOriginalInteractionResponse (token, body) {
691
+ return await rest.patch(rest.routes.interactions.responses.original(rest.applicationId, token), {
692
+ body,
693
+ files: body.files
694
+ });
1101
695
  },
1102
696
  async editOriginalWebhookMessage (webhookId, token, options) {
1103
697
  return await rest.patch(rest.routes.webhooks.original(webhookId, token, options), {
1104
- type: InteractionResponseTypes.UpdateMessage,
1105
- data: options
698
+ body: {
699
+ type: InteractionResponseTypes.UpdateMessage,
700
+ data: options
701
+ },
702
+ files: options.files,
703
+ unauthorized: true
1106
704
  });
1107
705
  },
1108
706
  async editOwnVoiceState (guildId, options) {
1109
707
  await rest.patch(rest.routes.guilds.voice(guildId), {
1110
- channel_id: options.channelId,
1111
- suppress: options.suppress,
1112
- request_to_speak_timestamp: options.requestToSpeakTimestamp ? new Date(options.requestToSpeakTimestamp).toISOString() : options.requestToSpeakTimestamp
708
+ body: {
709
+ ...options,
710
+ request_to_speak_timestamp: options.requestToSpeakTimestamp ? new Date(options.requestToSpeakTimestamp).toISOString() : options.requestToSpeakTimestamp
711
+ }
1113
712
  });
1114
713
  },
1115
- async editScheduledEvent (guildId, eventId, options) {
1116
- return await rest.patch(rest.routes.guilds.events.event(guildId, eventId), options);
714
+ async editScheduledEvent (guildId, eventId, body, reason) {
715
+ return await rest.patch(rest.routes.guilds.events.event(guildId, eventId), {
716
+ body,
717
+ reason
718
+ });
1117
719
  },
1118
- async editRole (guildId, roleId, options) {
1119
- return await rest.patch(rest.routes.guilds.roles.one(guildId, roleId), options);
720
+ async editRole (guildId, roleId, body, reason) {
721
+ return await rest.patch(rest.routes.guilds.roles.one(guildId, roleId), {
722
+ body,
723
+ reason
724
+ });
1120
725
  },
1121
- async editRolePositions (guildId, options) {
1122
- return await rest.patch(rest.routes.guilds.roles.all(guildId), options);
726
+ async editRolePositions (guildId, body, reason) {
727
+ return await rest.patch(rest.routes.guilds.roles.all(guildId), {
728
+ body,
729
+ reason
730
+ });
1123
731
  },
1124
- async editStageInstance (channelId, data) {
732
+ async editStageInstance (channelId, topic, reason) {
1125
733
  return await rest.patch(rest.routes.channels.stage(channelId), {
1126
- topic: data.topic
734
+ body: {
735
+ topic
736
+ },
737
+ reason
1127
738
  });
1128
739
  },
1129
740
  async editUserVoiceState (guildId, options) {
1130
741
  await rest.patch(rest.routes.guilds.voice(guildId, options.userId), {
1131
- channel_id: options.channelId,
1132
- suppress: options.suppress,
1133
- user_id: options.userId
742
+ body: options
1134
743
  });
1135
744
  },
1136
- async editWebhook (webhookId, options) {
1137
- return await rest.patch(rest.routes.webhooks.id(webhookId), options);
745
+ async editWebhook (webhookId, body, reason) {
746
+ return await rest.patch(rest.routes.webhooks.id(webhookId), {
747
+ body,
748
+ reason
749
+ });
1138
750
  },
1139
751
  async editWebhookMessage (webhookId, token, messageId, options) {
1140
- return await rest.patch(rest.routes.webhooks.message(webhookId, token, messageId, options), options);
752
+ return await rest.patch(rest.routes.webhooks.message(webhookId, token, messageId, options), {
753
+ body: options,
754
+ files: options.files
755
+ });
1141
756
  },
1142
- async editWebhookWithToken (webhookId, token, options) {
1143
- return await rest.patch(rest.routes.webhooks.webhook(webhookId, token), options);
757
+ async editWebhookWithToken (webhookId, token, body) {
758
+ return await rest.patch(rest.routes.webhooks.webhook(webhookId, token), {
759
+ body
760
+ });
1144
761
  },
1145
- async editWelcomeScreen (guildId, options) {
1146
- return await rest.patch(rest.routes.guilds.welcome(guildId), options);
762
+ async editWelcomeScreen (guildId, body, reason) {
763
+ return await rest.patch(rest.routes.guilds.welcome(guildId), {
764
+ body,
765
+ reason
766
+ });
1147
767
  },
1148
- async editWidgetSettings (guildId, options) {
1149
- return await rest.patch(rest.routes.guilds.widget(guildId), options);
768
+ async editWidgetSettings (guildId, body, reason) {
769
+ return await rest.patch(rest.routes.guilds.widget(guildId), {
770
+ body,
771
+ reason
772
+ });
1150
773
  },
1151
774
  async executeWebhook (webhookId, token, options) {
1152
- return await rest.post(rest.routes.webhooks.webhook(webhookId, token, options), options);
775
+ return await rest.post(rest.routes.webhooks.webhook(webhookId, token, options), {
776
+ body: options
777
+ });
1153
778
  },
1154
779
  async followAnnouncement (sourceChannelId, targetChannelId) {
1155
780
  return await rest.post(rest.routes.channels.follow(sourceChannelId), {
1156
- webhook_channel_id: targetChannelId
781
+ body: {
782
+ webhook_channel_id: targetChannelId
783
+ }
1157
784
  });
1158
785
  },
1159
786
  async getActiveThreads (guildId) {
@@ -1200,7 +827,9 @@ export function createRestManager(options) {
1200
827
  },
1201
828
  async getDmChannel (userId) {
1202
829
  return await rest.post(rest.routes.channels.dm(), {
1203
- recipient_id: userId.toString()
830
+ body: {
831
+ recipient_id: userId
832
+ }
1204
833
  });
1205
834
  },
1206
835
  async getEmoji (guildId, emojiId) {
@@ -1210,7 +839,9 @@ export function createRestManager(options) {
1210
839
  return await rest.get(rest.routes.guilds.emojis(guildId));
1211
840
  },
1212
841
  async getFollowupMessage (token, messageId) {
1213
- return await rest.get(rest.routes.interactions.responses.message(rest.applicationId, token, messageId));
842
+ return await rest.get(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
843
+ unauthorized: true
844
+ });
1214
845
  },
1215
846
  async getGatewayBot () {
1216
847
  return await rest.get(rest.routes.gatewayBot());
@@ -1263,7 +894,9 @@ export function createRestManager(options) {
1263
894
  return await rest.get(rest.routes.nitroStickerPacks());
1264
895
  },
1265
896
  async getOriginalInteractionResponse (token) {
1266
- return await rest.get(rest.routes.interactions.responses.original(rest.applicationId, token));
897
+ return await rest.get(rest.routes.interactions.responses.original(rest.applicationId, token), {
898
+ unauthorized: true
899
+ });
1267
900
  },
1268
901
  async getPinnedMessages (channelId) {
1269
902
  return await rest.get(rest.routes.channels.pins(channelId));
@@ -1364,61 +997,58 @@ export function createRestManager(options) {
1364
997
  await rest.delete(rest.routes.channels.threads.user(channelId, userId));
1365
998
  },
1366
999
  async sendFollowupMessage (token, options) {
1367
- return await new Promise((resolve, reject)=>{
1368
- rest.sendRequest({
1369
- url: rest.routes.webhooks.webhook(rest.applicationId, token),
1370
- method: 'POST',
1371
- body: options,
1372
- retryCount: 0,
1373
- retryRequest: async function(options) {
1374
- // TODO: should change to reprocess queue item
1375
- await rest.sendRequest(options);
1376
- },
1377
- resolve: (data)=>{
1378
- resolve(data.status !== 204 ? JSON.parse(data.body ?? '{}') : undefined);
1379
- },
1380
- reject
1381
- });
1000
+ return await rest.post(rest.routes.webhooks.webhook(rest.applicationId, token), {
1001
+ body: options,
1002
+ files: options.files,
1003
+ unauthorized: true
1382
1004
  });
1383
1005
  },
1384
1006
  async sendInteractionResponse (interactionId, token, options) {
1385
- await new Promise((resolve, reject)=>{
1386
- rest.sendRequest({
1387
- url: rest.routes.interactions.responses.callback(interactionId, token),
1388
- method: 'POST',
1389
- body: options,
1390
- retryCount: 0,
1391
- retryRequest: async function(options) {
1392
- // TODO: should change to reprocess queue item
1393
- await rest.sendRequest(options);
1394
- },
1395
- resolve: (data)=>{
1396
- resolve(data.status !== 204 ? JSON.parse(data.body ?? '{}') : undefined);
1397
- },
1398
- reject
1399
- });
1007
+ return await rest.post(rest.routes.interactions.responses.callback(interactionId, token), {
1008
+ body: options,
1009
+ files: options.data?.files,
1010
+ runThroughQueue: false,
1011
+ unauthorized: true
1400
1012
  });
1401
1013
  },
1402
- async sendMessage (channelId, options) {
1403
- return await rest.post(rest.routes.channels.messages(channelId), options);
1014
+ async sendMessage (channelId, body) {
1015
+ return await rest.post(rest.routes.channels.messages(channelId), {
1016
+ body,
1017
+ files: body.files
1018
+ });
1404
1019
  },
1405
- async startThreadWithMessage (channelId, messageId, options) {
1406
- return await rest.post(rest.routes.channels.threads.message(channelId, messageId), options);
1020
+ async startThreadWithMessage (channelId, messageId, body, reason) {
1021
+ return await rest.post(rest.routes.channels.threads.message(channelId, messageId), {
1022
+ body,
1023
+ reason
1024
+ });
1407
1025
  },
1408
- async startThreadWithoutMessage (channelId, options) {
1409
- return await rest.post(rest.routes.channels.threads.all(channelId), options);
1026
+ async startThreadWithoutMessage (channelId, body, reason) {
1027
+ return await rest.post(rest.routes.channels.threads.all(channelId), {
1028
+ body,
1029
+ reason
1030
+ });
1410
1031
  },
1411
1032
  async syncGuildTemplate (guildId) {
1412
1033
  return await rest.put(rest.routes.guilds.templates.all(guildId));
1413
1034
  },
1414
- async banMember (guildId, userId, options) {
1415
- await rest.put(rest.routes.guilds.members.ban(guildId, userId), options);
1035
+ async banMember (guildId, userId, body, reason) {
1036
+ await rest.put(rest.routes.guilds.members.ban(guildId, userId), {
1037
+ body,
1038
+ reason
1039
+ });
1416
1040
  },
1417
- async editBotMember (guildId, options) {
1418
- return await rest.patch(rest.routes.guilds.members.bot(guildId), options);
1041
+ async editBotMember (guildId, body, reason) {
1042
+ return await rest.patch(rest.routes.guilds.members.bot(guildId), {
1043
+ body,
1044
+ reason
1045
+ });
1419
1046
  },
1420
- async editMember (guildId, userId, options) {
1421
- return await rest.patch(rest.routes.guilds.members.member(guildId, userId), options);
1047
+ async editMember (guildId, userId, body, reason) {
1048
+ return await rest.patch(rest.routes.guilds.members.member(guildId, userId), {
1049
+ body,
1050
+ reason
1051
+ });
1422
1052
  },
1423
1053
  async getMember (guildId, userId) {
1424
1054
  return await rest.get(rest.routes.guilds.members.member(guildId, userId));
@@ -1432,35 +1062,51 @@ export function createRestManager(options) {
1432
1062
  });
1433
1063
  },
1434
1064
  async pinMessage (channelId, messageId, reason) {
1435
- await rest.put(rest.routes.channels.pin(channelId, messageId), reason ? {
1065
+ await rest.put(rest.routes.channels.pin(channelId, messageId), {
1436
1066
  reason
1437
- } : undefined);
1067
+ });
1438
1068
  },
1439
- async pruneMembers (guildId, options) {
1440
- return await rest.post(rest.routes.guilds.members.prune(guildId), options);
1069
+ async pruneMembers (guildId, body, reason) {
1070
+ return await rest.post(rest.routes.guilds.members.prune(guildId), {
1071
+ body,
1072
+ reason
1073
+ });
1441
1074
  },
1442
1075
  async searchMembers (guildId, query, options) {
1443
1076
  return await rest.get(rest.routes.guilds.members.search(guildId, query, options));
1444
1077
  },
1445
- async unbanMember (guildId, userId) {
1446
- await rest.delete(rest.routes.guilds.members.ban(guildId, userId));
1078
+ async unbanMember (guildId, userId, reason) {
1079
+ await rest.delete(rest.routes.guilds.members.ban(guildId, userId), {
1080
+ reason
1081
+ });
1447
1082
  },
1448
1083
  async unpinMessage (channelId, messageId, reason) {
1449
- await rest.delete(rest.routes.channels.pin(channelId, messageId), reason ? {
1084
+ await rest.delete(rest.routes.channels.pin(channelId, messageId), {
1450
1085
  reason
1451
- } : undefined);
1086
+ });
1452
1087
  },
1453
1088
  async triggerTypingIndicator (channelId) {
1454
1089
  await rest.post(rest.routes.channels.typing(channelId));
1455
1090
  },
1456
- async upsertGlobalApplicationCommands (commands) {
1457
- return await rest.put(rest.routes.interactions.commands.commands(rest.applicationId), commands);
1091
+ async upsertGlobalApplicationCommands (body) {
1092
+ return await rest.put(rest.routes.interactions.commands.commands(rest.applicationId), {
1093
+ body
1094
+ });
1458
1095
  },
1459
- async upsertGuildApplicationCommands (guildId, commands) {
1460
- return await rest.put(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), commands);
1096
+ async upsertGuildApplicationCommands (guildId, body) {
1097
+ return await rest.put(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), {
1098
+ body
1099
+ });
1461
1100
  }
1462
1101
  };
1463
1102
  return rest;
1464
1103
  }
1104
+ var HttpResponseCode;
1105
+ (function(HttpResponseCode) {
1106
+ HttpResponseCode[HttpResponseCode[/** Minimum value of a code in oder to consider that it was successful. */ "Success"] = 200] = "Success";
1107
+ HttpResponseCode[HttpResponseCode[/** Request completed successfully, but Discord returned an empty body. */ "NoContent"] = 204] = "NoContent";
1108
+ HttpResponseCode[HttpResponseCode[/** Minimum value of a code in order to consider that something went wrong. */ "Error"] = 400] = "Error";
1109
+ HttpResponseCode[HttpResponseCode[/** This request got rate limited. */ "TooManyRequests"] = 429] = "TooManyRequests";
1110
+ })(HttpResponseCode || (HttpResponseCode = {}));
1465
1111
 
1466
1112
  //# sourceMappingURL=manager.js.map