@discordeno/rest 19.0.0-next.bb85624 → 19.0.0-next.bccbc73

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