@discordeno/rest 19.0.0-next.fdf0d53 → 19.0.0-next.fe00a6f

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,511 +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, 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
- const URL_PARTS_REGEX = /([a-z]+)\/(?:[0-9]{17,}(\/@me)?)/g;
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';
9
17
  export function createRestManager(options) {
10
- // Falsy token string check
11
- 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;
12
23
  const rest = {
13
- token: options.token,
14
- applicationId: options.applicationId ? BigInt(options.applicationId) : getBotIdFromToken(options.token),
15
- version: options.version ?? 10,
16
- baseUrl: options.proxy?.baseUrl ?? 'https://discord.com/api',
17
- maxRetryCount: Infinity,
24
+ applicationId,
25
+ authorization: options.proxy?.authorization,
26
+ baseUrl,
27
+ deleteQueueDelay: 60000,
18
28
  globallyRateLimited: false,
29
+ invalidBucket: createInvalidRequestBucket({}),
30
+ isProxied: !baseUrl.startsWith(DISCORD_API_URL),
31
+ maxRetryCount: Infinity,
19
32
  processingRateLimitedPaths: false,
20
- deleteQueueDelay: 60000,
21
33
  queues: new Map(),
22
34
  rateLimitedPaths: new Map(),
23
- invalidBucket: createInvalidRequestBucket({}),
24
- authorization: options.proxy?.authorization,
25
- routes: {
26
- webhooks: {
27
- id: (webhookId)=>{
28
- return `/webhooks/${webhookId}`;
29
- },
30
- message: (webhookId, token, messageId, options)=>{
31
- let url = `/webhooks/${webhookId}/${token}/messages/${messageId}?`;
32
- if (options) {
33
- if (options.threadId) url += `thread_id=${options.threadId}`;
34
- }
35
- return url;
36
- },
37
- original: (webhookId, token, options)=>{
38
- let url = `/webhooks/${webhookId}/${token}/messages/@original?`;
39
- if (options) {
40
- if (options.threadId) url += `thread_id=${options.threadId}`;
41
- }
42
- return url;
43
- },
44
- webhook: (webhookId, token, options)=>{
45
- let url = `/webhooks/${webhookId}/${token}?`;
46
- if (options) {
47
- if (options?.wait !== undefined) url += `wait=${options.wait.toString()}`;
48
- if (options.threadId) url += `thread_id=${options.threadId}`;
49
- }
50
- return url;
51
- }
52
- },
53
- // Miscellaneous Endpoints
54
- sessionInfo: ()=>rest.routes.gatewayBot(),
55
- // Channel Endpoints
56
- channels: {
57
- bulk: (channelId)=>{
58
- return `/channels/${channelId}/messages/bulk-delete`;
59
- },
60
- dm: ()=>{
61
- return '/users/@me/channels';
62
- },
63
- pin: (channelId, messageId)=>{
64
- return `/channels/${channelId}/pins/${messageId}`;
65
- },
66
- pins: (channelId)=>{
67
- return `/channels/${channelId}/pins`;
68
- },
69
- reactions: {
70
- bot: (channelId, messageId, emoji)=>{
71
- return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/@me`;
72
- },
73
- user: (channelId, messageId, emoji, userId)=>{
74
- return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/${userId}`;
75
- },
76
- all: (channelId, messageId)=>{
77
- return `/channels/${channelId}/messages/${messageId}/reactions`;
78
- },
79
- emoji: (channelId, messageId, emoji, options)=>{
80
- let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}?`;
81
- if (options) {
82
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
83
- if (options.after) url += `after=${options.after}`;
84
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
85
- if (options.limit) url += `&limit=${options.limit}`;
86
- }
87
- return url;
88
- },
89
- message: (channelId, messageId, emoji, options)=>{
90
- let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}?`;
91
- if (options) {
92
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
93
- if (options.after) url += `after=${options.after}`;
94
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
95
- if (options.limit) url += `&limit=${options.limit}`;
96
- }
97
- return url;
98
- }
99
- },
100
- webhooks: (channelId)=>{
101
- return `/channels/${channelId}/webhooks`;
102
- },
103
- channel: (channelId)=>{
104
- return `/channels/${channelId}`;
105
- },
106
- follow: (channelId)=>{
107
- return `/channels/${channelId}/followers`;
108
- },
109
- forum: (channelId)=>{
110
- return `/channels/${channelId}/threads?has_message=true`;
111
- },
112
- invites: (channelId)=>{
113
- return `/channels/${channelId}/invites`;
114
- },
115
- message: (channelId, messageId)=>{
116
- return `/channels/${channelId}/messages/${messageId}`;
117
- },
118
- messages: (channelId, options)=>{
119
- let url = `/channels/${channelId}/messages?`;
120
- if (options) {
121
- if (isGetMessagesAfter(options) && options.after) {
122
- url += `after=${options.after}`;
123
- }
124
- if (isGetMessagesBefore(options) && options.before) {
125
- url += `&before=${options.before}`;
126
- }
127
- if (isGetMessagesAround(options) && options.around) {
128
- url += `&around=${options.around}`;
129
- }
130
- if (isGetMessagesLimit(options) && options.limit) {
131
- url += `&limit=${options.limit}`;
132
- }
133
- }
134
- return url;
135
- },
136
- overwrite: (channelId, overwriteId)=>{
137
- return `/channels/${channelId}/permissions/${overwriteId}`;
138
- },
139
- crosspost: (channelId, messageId)=>{
140
- return `/channels/${channelId}/messages/${messageId}/crosspost`;
141
- },
142
- stages: ()=>{
143
- return '/stage-instances';
144
- },
145
- stage: (channelId)=>{
146
- return `/stage-instances/${channelId}`;
147
- },
148
- // Thread Endpoints
149
- threads: {
150
- message: (channelId, messageId)=>{
151
- return `/channels/${channelId}/messages/${messageId}/threads`;
152
- },
153
- all: (channelId)=>{
154
- return `/channels/${channelId}/threads`;
155
- },
156
- active: (guildId)=>{
157
- return `/guilds/${guildId}/threads/active`;
158
- },
159
- members: (channelId)=>{
160
- return `/channels/${channelId}/thread-members`;
161
- },
162
- me: (channelId)=>{
163
- return `/channels/${channelId}/thread-members/@me`;
164
- },
165
- user: (channelId, userId)=>{
166
- return `/channels/${channelId}/thread-members/${userId}`;
167
- },
168
- archived: (channelId)=>{
169
- return `/channels/${channelId}/threads/archived`;
170
- },
171
- public: (channelId, options)=>{
172
- let url = `/channels/${channelId}/threads/archived/public?`;
173
- if (options) {
174
- if (options.before) {
175
- url += `before=${new Date(options.before).toISOString()}`;
176
- }
177
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
178
- if (options.limit) url += `&limit=${options.limit}`;
179
- }
180
- return url;
181
- },
182
- private: (channelId, options)=>{
183
- let url = `/channels/${channelId}/threads/archived/private?`;
184
- if (options) {
185
- if (options.before) {
186
- url += `before=${new Date(options.before).toISOString()}`;
187
- }
188
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
189
- if (options.limit) url += `&limit=${options.limit}`;
190
- }
191
- return url;
192
- },
193
- joined: (channelId, options)=>{
194
- let url = `/channels/${channelId}/users/@me/threads/archived/private?`;
195
- if (options) {
196
- if (options.before) {
197
- url += `before=${new Date(options.before).toISOString()}`;
198
- }
199
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
200
- if (options.limit) url += `&limit=${options.limit}`;
201
- }
202
- return url;
203
- }
204
- },
205
- typing: (channelId)=>{
206
- return `/channels/${channelId}/typing`;
207
- }
208
- },
209
- // Guild Endpoints
210
- guilds: {
211
- all: ()=>{
212
- return '/guilds';
213
- },
214
- auditlogs: (guildId, options)=>{
215
- let url = `/guilds/${guildId}/audit-logs?`;
216
- if (options) {
217
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
218
- if (options.actionType) url += `action_type=${options.actionType}`;
219
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
220
- if (options.before) url += `&before=${options.before}`;
221
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
222
- if (options.after) url += `&after=${options.after}`;
223
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
224
- if (options.limit) url += `&limit=${options.limit}`;
225
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
226
- if (options.userId) url += `&user_id=${options.userId}`;
227
- }
228
- return url;
229
- },
230
- automod: {
231
- rule: (guildId, ruleId)=>{
232
- return `/guilds/${guildId}/auto-moderation/rules/${ruleId}`;
233
- },
234
- rules: (guildId)=>{
235
- return `/guilds/${guildId}/auto-moderation/rules`;
236
- }
237
- },
238
- channels: (guildId)=>{
239
- return `/guilds/${guildId}/channels`;
240
- },
241
- emoji: (guildId, emojiId)=>{
242
- return `/guilds/${guildId}/emojis/${emojiId}`;
243
- },
244
- emojis: (guildId)=>{
245
- return `/guilds/${guildId}/emojis`;
246
- },
247
- events: {
248
- events: (guildId, withUserCount)=>{
249
- let url = `/guilds/${guildId}/scheduled-events?`;
250
- if (withUserCount !== undefined) {
251
- url += `with_user_count=${withUserCount.toString()}`;
252
- }
253
- return url;
254
- },
255
- event: (guildId, eventId, withUserCount)=>{
256
- let url = `/guilds/${guildId}/scheduled-events/${eventId}`;
257
- if (withUserCount !== undefined) {
258
- url += `with_user_count=${withUserCount.toString()}`;
259
- }
260
- return url;
261
- },
262
- users: (guildId, eventId, options)=>{
263
- let url = `/guilds/${guildId}/scheduled-events/${eventId}/users?`;
264
- if (options) {
265
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
266
- if (options.limit !== undefined) url += `limit=${options.limit}`;
267
- if (options.withMember !== undefined) {
268
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
269
- url += `&with_member=${options.withMember.toString()}`;
270
- }
271
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
272
- if (options.after !== undefined) url += `&after=${options.after}`;
273
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
274
- if (options.before !== undefined) url += `&before=${options.before}`;
275
- }
276
- return url;
277
- }
278
- },
279
- guild (guildId, withCounts) {
280
- let url = `/guilds/${guildId}?`;
281
- if (withCounts !== undefined) {
282
- url += `with_counts=${withCounts.toString()}`;
283
- }
284
- return url;
285
- },
286
- integration (guildId, integrationId) {
287
- return `/guilds/${guildId}/integrations/${integrationId}`;
288
- },
289
- integrations: (guildId)=>{
290
- return `/guilds/${guildId}/integrations?include_applications=true`;
291
- },
292
- invite (inviteCode, options) {
293
- let url = `/invites/${inviteCode}?`;
294
- if (options) {
295
- if (options.withCounts !== undefined) {
296
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
297
- url += `with_counts=${options.withCounts.toString()}`;
298
- }
299
- if (options.withExpiration !== undefined) {
300
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
301
- url += `&with_expiration=${options.withExpiration.toString()}`;
302
- }
303
- if (options.scheduledEventId) {
304
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
305
- url += `&guild_scheduled_event_id=${options.scheduledEventId}`;
306
- }
307
- }
308
- return url;
309
- },
310
- invites: (guildId)=>{
311
- return `/guilds/${guildId}/invites`;
312
- },
313
- leave: (guildId)=>{
314
- return `/users/@me/guilds/${guildId}`;
315
- },
316
- members: {
317
- ban: (guildId, userId)=>{
318
- return `/guilds/${guildId}/bans/${userId}`;
319
- },
320
- bans: (guildId, options)=>{
321
- let url = `/guilds/${guildId}/bans?`;
322
- if (options) {
323
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
324
- if (options.limit) url += `limit=${options.limit}`;
325
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
326
- if (options.after) url += `&after=${options.after}`;
327
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
328
- if (options.before) url += `&before=${options.before}`;
329
- }
330
- return url;
331
- },
332
- bot: (guildId)=>{
333
- return `/guilds/${guildId}/members/@me`;
334
- },
335
- member: (guildId, userId)=>{
336
- return `/guilds/${guildId}/members/${userId}`;
337
- },
338
- members: (guildId, options)=>{
339
- let url = `/guilds/${guildId}/members?`;
340
- if (options !== undefined) {
341
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
342
- if (options.limit) url += `limit=${options.limit}`;
343
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
344
- if (options.after) url += `&after=${options.after}`;
345
- }
346
- return url;
347
- },
348
- search: (guildId, query, options)=>{
349
- let url = `/guilds/${guildId}/members/search?query=${encodeURIComponent(query)}`;
350
- if (options) {
351
- if (options.limit !== undefined) url += `&limit=${options.limit}`;
352
- }
353
- return url;
354
- },
355
- prune: (guildId, options)=>{
356
- let url = `/guilds/${guildId}/prune?`;
357
- if (options) {
358
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
359
- if (options.days) url += `days=${options.days}`;
360
- if (Array.isArray(options.includeRoles)) {
361
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
362
- url += `&include_roles=${options.includeRoles.join(',')}`;
363
- } else if (options.includeRoles) {
364
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
365
- url += `&include_roles=${options.includeRoles}`;
366
- }
367
- }
368
- return url;
369
- }
370
- },
371
- mfa: (guildId)=>`/guilds/${guildId}/mfa`,
372
- preview: (guildId)=>{
373
- return `/guilds/${guildId}/preview`;
374
- },
375
- prune: (guildId, options)=>{
376
- let url = `/guilds/${guildId}/prune?`;
377
- if (options) {
378
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
379
- if (options.days) url += `days=${options.days}`;
380
- if (Array.isArray(options.includeRoles)) {
381
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
382
- url += `&include_roles=${options.includeRoles.join(',')}`;
383
- } else if (options.includeRoles) {
384
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
385
- url += `&include_roles=${options.includeRoles}`;
386
- }
387
- }
388
- return url;
389
- },
390
- roles: {
391
- one: (guildId, roleId)=>{
392
- return `/guilds/${guildId}/roles/${roleId}`;
393
- },
394
- all: (guildId)=>{
395
- return `/guilds/${guildId}/roles`;
396
- },
397
- member: (guildId, memberId, roleId)=>{
398
- return `/guilds/${guildId}/members/${memberId}/roles/${roleId}`;
399
- }
400
- },
401
- stickers: (guildId)=>{
402
- return `/guilds/${guildId}/stickers`;
403
- },
404
- sticker: (guildId, stickerId)=>{
405
- return `/guilds/${guildId}/stickers/${stickerId}`;
406
- },
407
- voice: (guildId, userId)=>{
408
- return `/guilds/${guildId}/voice-states/${userId ?? '@me'}`;
409
- },
410
- templates: {
411
- code: (code)=>{
412
- return `/guilds/templates/${code}`;
413
- },
414
- guild: (guildId, code)=>{
415
- return `/guilds/${guildId}/templates/${code}`;
416
- },
417
- all: (guildId)=>{
418
- return `/guilds/${guildId}/templates`;
419
- }
420
- },
421
- vanity: (guildId)=>{
422
- return `/guilds/${guildId}/vanity-url`;
423
- },
424
- regions: (guildId)=>{
425
- return `/guilds/${guildId}/regions`;
426
- },
427
- webhooks: (guildId)=>{
428
- return `/guilds/${guildId}/webhooks`;
429
- },
430
- welcome: (guildId)=>{
431
- return `/guilds/${guildId}/welcome-screen`;
432
- },
433
- widget: (guildId)=>{
434
- return `/guilds/${guildId}/widget`;
435
- },
436
- widgetJson: (guildId)=>{
437
- return `/guilds/${guildId}/widget.json`;
438
- }
439
- },
440
- sticker: (stickerId)=>{
441
- return `/stickers/${stickerId}`;
442
- },
443
- regions: ()=>{
444
- return '/voice/regions';
445
- },
446
- // Interaction Endpoints
447
- interactions: {
448
- commands: {
449
- // Application Endpoints
450
- commands: (applicationId)=>{
451
- return `/applications/${applicationId}/commands`;
452
- },
453
- guilds: {
454
- all (applicationId, guildId) {
455
- return `/applications/${applicationId}/guilds/${guildId}/commands`;
456
- },
457
- one (applicationId, guildId, commandId, withLocalizations) {
458
- let url = `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}?`;
459
- if (withLocalizations !== undefined) {
460
- url += `with_localizations=${withLocalizations.toString()}`;
461
- }
462
- return url;
463
- }
464
- },
465
- permissions: (applicationId, guildId)=>{
466
- return `/applications/${applicationId}/guilds/${guildId}/commands/permissions`;
467
- },
468
- permission: (applicationId, guildId, commandId)=>{
469
- return `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}/permissions`;
470
- },
471
- command: (applicationId, commandId, withLocalizations)=>{
472
- let url = `/applications/${applicationId}/commands/${commandId}?`;
473
- if (withLocalizations !== undefined) {
474
- url += `withLocalizations=${withLocalizations.toString()}`;
475
- }
476
- return url;
477
- }
478
- },
479
- responses: {
480
- // Interaction Endpoints
481
- callback: (interactionId, token)=>{
482
- return `/interactions/${interactionId}/${token}/callback`;
483
- },
484
- original: (interactionId, token)=>{
485
- return `/webhooks/${interactionId}/${token}/messages/@original`;
486
- },
487
- message: (applicationId, token, messageId)=>{
488
- return `/webhooks/${applicationId}/${token}/messages/${messageId}`;
489
- }
490
- }
491
- },
492
- // User endpoints
493
- user (userId) {
494
- return `/users/${userId}`;
495
- },
496
- userBot () {
497
- return '/users/@me';
498
- },
499
- oauth2Application () {
500
- return 'oauth2/applications/@me';
501
- },
502
- gatewayBot () {
503
- return '/gateway/bot';
504
- },
505
- nitroStickerPacks () {
506
- return '/sticker-packs';
507
- }
508
- },
35
+ token: options.token,
36
+ version: options.version ?? DISCORD_API_VERSION,
37
+ routes: createRoutes(),
509
38
  checkRateLimits (url) {
510
39
  const ratelimited = rest.rateLimitedPaths.get(url);
511
40
  const global = rest.rateLimitedPaths.get('global');
@@ -526,66 +55,74 @@ export function createRestManager(options) {
526
55
  }
527
56
  const newObj = {};
528
57
  for (const key of Object.keys(obj)){
529
- // Keys that dont require snake casing
530
- if ([
531
- 'permissions',
532
- 'allow',
533
- 'deny'
534
- ].includes(key)) {
535
- newObj[key] = calculateBits(obj[key]);
536
- continue;
537
- }
538
- if (key === 'defaultMemberPermissions') {
539
- newObj.default_member_permissions = calculateBits(obj[key]);
540
- continue;
58
+ const value = obj[key];
59
+ // Some falsy values should be allowed like null or 0
60
+ if (value !== undefined) {
61
+ switch(key){
62
+ case 'permissions':
63
+ case 'allow':
64
+ case 'deny':
65
+ newObj[key] = calculateBits(value);
66
+ continue;
67
+ case 'defaultMemberPermissions':
68
+ newObj.default_member_permissions = calculateBits(value);
69
+ continue;
70
+ case 'nameLocalizations':
71
+ newObj.name_localizations = value;
72
+ continue;
73
+ case 'descriptionLocalizations':
74
+ newObj.description_localizations = value;
75
+ continue;
76
+ }
541
77
  }
542
- newObj[camelToSnakeCase(key)] = rest.changeToDiscordFormat(obj[key]);
78
+ newObj[camelToSnakeCase(key)] = rest.changeToDiscordFormat(value);
543
79
  }
544
80
  return newObj;
545
81
  }
546
82
  if (typeof obj === 'bigint') return obj.toString();
547
83
  return obj;
548
84
  },
549
- createRequest (options) {
85
+ createRequestBody (method, options) {
550
86
  const headers = {
551
87
  'user-agent': `DiscordBot (https://github.com/discordeno/discordeno, v${version})`
552
88
  };
553
- if (!options.unauthorized) headers.authorization = `Bot ${rest.token}`;
89
+ if (options?.unauthorized !== false) headers.authorization = `Bot ${rest.token}`;
554
90
  // IF A REASON IS PROVIDED ENCODE IT IN HEADERS
555
- if (options.reason !== undefined) {
556
- headers['x-audit-log-reason'] = encodeURIComponent(options.reason);
91
+ if (options?.reason !== undefined) {
92
+ headers[AUDIT_LOG_REASON_HEADER] = encodeURIComponent(options?.reason);
557
93
  }
558
94
  let body;
559
95
  // TODO: check if we need to add specific check for GET method
560
96
  // Since GET does not allow bodies
561
97
  // Have to check for attachments first, since body then has to be send in a different way.
562
- if (options.attachments !== undefined) {
98
+ if (options?.files !== undefined) {
563
99
  const form = new FormData();
564
- for(let i = 0; i < options.attachments.length; ++i){
565
- form.append(`file${i}`, options.attachments[i].blob, options.attachments[i].name);
100
+ for(let i = 0; i < options.files.length; ++i){
101
+ form.append(`file${i}`, options.files[i].blob, options.files[i].name);
566
102
  }
567
- form.append('payload_json', JSON.stringify(options.body));
103
+ form.append('payload_json', JSON.stringify({
104
+ ...options.body,
105
+ files: undefined
106
+ }));
568
107
  body = form;
569
- // TODO: boundary?
570
- // `multipart/form-data; boundary=${form.getBoundary()}`
571
- headers['content-type'] = `multipart/form-data`;
572
- } else if (options.body !== undefined) {
108
+ // No need to set the `content-type` header since `fetch` does that automatically for us when we use a `FormData` object.
109
+ } else if (options?.body !== undefined) {
573
110
  if (options.body instanceof FormData) {
574
111
  body = options.body;
575
- headers['content-type'] = `multipart/form-data`;
112
+ // No need to set the `content-type` header since `fetch` does that automatically for us when we use a `FormData` object.
576
113
  } else {
577
- body = JSON.stringify(options.body);
114
+ body = JSON.stringify(rest.changeToDiscordFormat(options.body));
578
115
  headers['content-type'] = `application/json`;
579
116
  }
580
117
  }
581
118
  // SOMETIMES SPECIAL HEADERS (E.G. CUSTOM AUTHORIZATION) NEED TO BE USED
582
- if (options.headers) {
119
+ if (options?.headers) {
583
120
  Object.assign(headers, options.headers);
584
121
  }
585
122
  return {
586
123
  body,
587
124
  headers,
588
- method: options.method
125
+ method
589
126
  };
590
127
  },
591
128
  processRateLimitedPaths () {
@@ -618,13 +155,13 @@ export function createRestManager(options) {
618
155
  /** Processes the rate limit headers and determines if it needs to be rate limited and returns the bucket id if available */ processHeaders (url, headers) {
619
156
  let rateLimited = false;
620
157
  // GET ALL NECESSARY HEADERS
621
- const remaining = headers.get('x-ratelimit-remaining');
622
- const retryAfter = headers.get('x-ratelimit-reset-after');
158
+ const remaining = headers.get(RATE_LIMIT_REMAINING_HEADER);
159
+ const retryAfter = headers.get(RATE_LIMIT_RESET_AFTER_HEADER);
623
160
  const reset = Date.now() + Number(retryAfter) * 1000;
624
- const global = headers.get('x-ratelimit-global');
161
+ const global = headers.get(RATE_LIMIT_GLOBAL_HEADER);
625
162
  // undefined override null needed for typings
626
- const bucketId = headers.get('x-ratelimit-bucket') ?? undefined;
627
- const limit = headers.get('x-ratelimit-limit');
163
+ const bucketId = headers.get(RATE_LIMIT_BUCKET_HEADER) ?? undefined;
164
+ const limit = headers.get(RATE_LIMIT_LIMIT_HEADER);
628
165
  rest.queues.get(url)?.handleCompletedRequest({
629
166
  remaining: remaining ? Number(remaining) : undefined,
630
167
  interval: retryAfter ? Number(retryAfter) * 1000 : undefined,
@@ -679,13 +216,8 @@ export function createRestManager(options) {
679
216
  return rateLimited ? bucketId : undefined;
680
217
  },
681
218
  async sendRequest (options) {
682
- const url = options.url.startsWith('https://') ? options.url : `${rest.baseUrl}/v${rest.version}${options.url}`;
683
- const payload = rest.createRequest({
684
- method: options.method,
685
- url: options.url,
686
- body: options.options?.body,
687
- ...options.options
688
- });
219
+ const url = `${rest.baseUrl}/v${rest.version}${options.route}`;
220
+ const payload = rest.createRequestBody(options.method, options.requestBodyOptions);
689
221
  logger.debug(`sending request to ${url}`, 'with payload:', {
690
222
  ...payload,
691
223
  headers: {
@@ -693,84 +225,86 @@ export function createRestManager(options) {
693
225
  authorization: 'Bot tokenhere'
694
226
  }
695
227
  });
696
- const response = await fetch(url, payload);
228
+ const response = await fetch(url, payload).catch(async (error)=>{
229
+ logger.error(error);
230
+ // Mark request and completed
231
+ rest.invalidBucket.handleCompletedRequest(999, false);
232
+ options.reject({
233
+ ok: false,
234
+ status: 999,
235
+ error: 'Possible network or request shape issue occurred. If this is rare, its a network glitch. If it occurs a lot something is wrong.'
236
+ });
237
+ throw error;
238
+ });
697
239
  logger.debug(`request fetched from ${url} with status ${response.status} & ${response.statusText}`);
240
+ // Mark request and completed
241
+ rest.invalidBucket.handleCompletedRequest(response.status, response.headers.get(RATE_LIMIT_SCOPE_HEADER) === 'shared');
698
242
  // Set the bucket id if it was available on the headers
699
- const bucketId = rest.processHeaders(rest.simplifyUrl(options.url, options.method), response.headers);
243
+ const bucketId = rest.processHeaders(rest.simplifyUrl(options.route, options.method), response.headers);
700
244
  if (bucketId) options.bucketId = bucketId;
701
245
  if (response.status < 200 || response.status >= 400) {
702
246
  logger.debug(`Request to ${url} failed.`);
703
- if (response.status === 429) {
704
- logger.debug(`Request to ${url} was ratelimited.`);
705
- // Too many attempts, get rid of request from queue.
706
- if (options.retryCount++ >= rest.maxRetryCount) {
707
- logger.debug(`Request to ${url} exceeded the maximum allowed retries.`, 'with payload:', payload);
708
- // rest.debug(`[REST - RetriesMaxed] ${JSON.stringify(options)}`)
709
- // Remove item from queue to prevent retry
710
- options.reject({
711
- ok: false,
712
- status: response.status,
713
- error: 'The options was rate limited and it maxed out the retries limit.'
714
- });
715
- return;
716
- }
717
- // Rate limited, add back to queue
718
- rest.invalidBucket.handleCompletedRequest(response.status, response.headers.get('X-RateLimit-Scope') === 'shared');
719
- const resetAfter = response.headers.get('x-ratelimit-reset-after');
720
- if (resetAfter) await delay(Number(resetAfter) * 1000);
721
- // process the response to prevent mem leak
722
- await response.json();
723
- return await options.retryRequest?.(options);
247
+ if (response.status !== 429) {
248
+ options.reject({
249
+ ok: false,
250
+ status: response.status,
251
+ body: await response.text()
252
+ });
253
+ return;
724
254
  }
725
- options.reject({
726
- ok: false,
727
- status: response.status,
728
- body: JSON.stringify(await response.json())
729
- });
730
- return;
255
+ logger.debug(`Request to ${url} was ratelimited.`);
256
+ // Too many attempts, get rid of request from queue.
257
+ if (options.retryCount >= rest.maxRetryCount) {
258
+ logger.debug(`Request to ${url} exceeded the maximum allowed retries.`, 'with payload:', payload);
259
+ // rest.debug(`[REST - RetriesMaxed] ${JSON.stringify(options)}`)
260
+ options.reject({
261
+ ok: false,
262
+ status: response.status,
263
+ error: 'The request was rate limited and it maxed out the retries limit.'
264
+ });
265
+ return;
266
+ }
267
+ options.retryCount += 1;
268
+ const resetAfter = response.headers.get(RATE_LIMIT_RESET_AFTER_HEADER);
269
+ if (resetAfter) await delay(Number(resetAfter) * 1000);
270
+ // process the response to prevent mem leak
271
+ await response.arrayBuffer();
272
+ return await options.retryRequest?.(options);
731
273
  }
732
- const is204 = response.status === 204;
733
- const json = is204 ? undefined : await response.json();
734
- // Discord sometimes sends no response with 204 code
274
+ // Discord sometimes sends no response with no content.
735
275
  options.resolve({
736
276
  ok: true,
737
277
  status: response.status,
738
- body: JSON.stringify(json)
278
+ body: response.status === 204 ? undefined : await response.text()
739
279
  });
740
280
  },
741
- // Credits: github.com/abalabahaha/eris lib/rest/RequestHandler.js#L397
742
- // Modified for our use-case
743
281
  simplifyUrl (url, method) {
744
- let route = url.replace(URL_PARTS_REGEX, function(match, pattern) {
745
- if (pattern.startsWith('channels') || pattern.startsWith('guilds')) {
746
- return match;
747
- }
748
- // GENERAL /reactions and /reactions/emoji/@me share the buckets
749
- if (pattern.startsWith('reactions')) {
750
- return 'reactions';
751
- }
752
- return `${pattern}/x`;
753
- });
754
- if (route.includes('/reactions')) {
755
- // 10 is the length of `/reactions`
756
- route = route.substring(0, route.indexOf('/reactions') + 10);
282
+ const parts = url.split('/');
283
+ const secondLastPart = parts[parts.length - 2];
284
+ if (secondLastPart === 'channels' || secondLastPart === 'guilds') {
285
+ return url;
286
+ }
287
+ if (secondLastPart === 'reactions' || parts[parts.length - 1] === '@me') {
288
+ parts.splice(-2);
289
+ parts.push('reactions');
290
+ } else {
291
+ parts.splice(-1);
292
+ parts.push('x');
757
293
  }
758
- // Delete Message endpoint has its own rate limit
759
- if (method === 'DELETE' && route.endsWith('/messages/x')) {
760
- route = 'D' + route;
294
+ if (parts[parts.length - 3] === 'reactions') {
295
+ parts.splice(-2);
296
+ }
297
+ if (method === 'DELETE' && secondLastPart === 'messages') {
298
+ return `D${parts.join('/')}`;
299
+ }
300
+ return parts.join('/');
301
+ },
302
+ async processRequest (request) {
303
+ const url = rest.simplifyUrl(request.route, request.method);
304
+ if (request.runThroughQueue === false) {
305
+ await rest.sendRequest(request);
306
+ return;
761
307
  }
762
- return route;
763
- },
764
- processRequest (request) {
765
- const route = request.url.substring(request.url.indexOf('api/'));
766
- const parts = route.split('/');
767
- // Remove the api/
768
- parts.shift();
769
- // Removes the /v#/
770
- if (parts[0]?.startsWith('v')) parts.shift();
771
- // Set the full url to discord api in case it was recieved in a proxy rest
772
- request.url = `${rest.baseUrl}/v${rest.version}/${parts.join('/')}`;
773
- const url = rest.simplifyUrl(request.url, request.method);
774
308
  const queue = rest.queues.get(url);
775
309
  if (queue !== undefined) {
776
310
  queue.makeRequest(request);
@@ -786,36 +320,14 @@ export function createRestManager(options) {
786
320
  rest.queues.set(url, bucketQueue);
787
321
  }
788
322
  },
789
- async makeRequest (method, url, options) {
790
- if (!rest.baseUrl.startsWith('https://discord.com') && url[0] === '/') {
791
- // Special handling for sending blobs across http to proxy
792
- // TODO: fix this hacky handling
793
- if (!(options?.body instanceof FormData) && !Array.isArray(options?.body) && options?.body?.file) {
794
- if (!Array.isArray(options.body.file)) {
795
- options.body.file = [
796
- options.body.file
797
- ];
798
- }
799
- // convert blobs to string before sending to proxy
800
- options.body.file = await Promise.all(options.body.file.map(async (f)=>{
801
- const url = encode(await f.blob.arrayBuffer());
802
- return {
803
- name: f.name,
804
- blob: `data:${f.blob.type};base64,${url}`
805
- };
806
- }));
807
- }
808
- const headers = {
809
- Authorization: rest.authorization ?? ''
810
- };
811
- if (options?.body) {
812
- headers['Content-Type'] = 'application/json';
323
+ async makeRequest (method, route, options) {
324
+ if (rest.isProxied) {
325
+ if (rest.authorization !== undefined) {
326
+ options ??= {};
327
+ options.headers ??= {};
328
+ options.headers.authorization = rest.authorization;
813
329
  }
814
- const result = await fetch(`${rest.baseUrl}${url}`, {
815
- body: options?.body ? JSON.stringify(options.body) : undefined,
816
- headers,
817
- method
818
- });
330
+ const result = await fetch(`${rest.baseUrl}/v${rest.version}${route}`, rest.createRequestBody(method, options));
819
331
  if (!result.ok) {
820
332
  const err = await result.json().catch(()=>{});
821
333
  // Legacy Handling to not break old code or when body is missing
@@ -824,47 +336,39 @@ export function createRestManager(options) {
824
336
  }
825
337
  return result.status !== 204 ? await result.json() : undefined;
826
338
  }
827
- return await new Promise((resolve, reject)=>{
339
+ // eslint-disable-next-line no-async-promise-executor
340
+ return await new Promise(async (resolve, reject)=>{
828
341
  const payload = {
829
- url,
342
+ route,
830
343
  method,
831
- options,
344
+ requestBodyOptions: options,
832
345
  retryCount: 0,
833
346
  retryRequest: async function(payload) {
834
- rest.processRequest(payload);
347
+ await rest.processRequest(payload);
835
348
  },
836
349
  resolve: (data)=>{
837
350
  resolve(data.status !== 204 ? JSON.parse(data.body ?? '{}') : undefined);
838
351
  },
839
- reject
352
+ reject,
353
+ runThroughQueue: options?.runThroughQueue
840
354
  };
841
- rest.processRequest(payload);
355
+ await rest.processRequest(payload);
842
356
  });
843
357
  },
844
- async get (url, body) {
845
- return camelize(await rest.makeRequest('GET', url, {
846
- body
847
- }));
358
+ async get (url, options) {
359
+ return camelize(await rest.makeRequest('GET', url, options));
848
360
  },
849
- async post (url, body) {
850
- return camelize(await rest.makeRequest('POST', url, {
851
- body
852
- }));
361
+ async post (url, options) {
362
+ return camelize(await rest.makeRequest('POST', url, options));
853
363
  },
854
- async delete (url, body) {
855
- camelize(await rest.makeRequest('DELETE', url, {
856
- body
857
- }));
364
+ async delete (url, options) {
365
+ camelize(await rest.makeRequest('DELETE', url, options));
858
366
  },
859
- async patch (url, body) {
860
- return camelize(await rest.makeRequest('PATCH', url, {
861
- body
862
- }));
367
+ async patch (url, options) {
368
+ return camelize(await rest.makeRequest('PATCH', url, options));
863
369
  },
864
- async put (url, body) {
865
- return camelize(await rest.makeRequest('PUT', url, {
866
- body
867
- }));
370
+ async put (url, options) {
371
+ return camelize(await rest.makeRequest('PUT', url, options));
868
372
  },
869
373
  async addReaction (channelId, messageId, reaction) {
870
374
  reaction = processReactionString(reaction);
@@ -889,19 +393,22 @@ export function createRestManager(options) {
889
393
  async addThreadMember (channelId, userId) {
890
394
  await rest.put(rest.routes.channels.threads.user(channelId, userId));
891
395
  },
892
- async createAutomodRule (guildId, body) {
396
+ async createAutomodRule (guildId, body, reason) {
893
397
  return await rest.post(rest.routes.guilds.automod.rules(guildId), {
894
- body
398
+ body,
399
+ reason
895
400
  });
896
401
  },
897
- async createChannel (guildId, body) {
402
+ async createChannel (guildId, body, reason) {
898
403
  return await rest.post(rest.routes.guilds.channels(guildId), {
899
- body
404
+ body,
405
+ reason
900
406
  });
901
407
  },
902
- async createEmoji (guildId, body) {
408
+ async createEmoji (guildId, body, reason) {
903
409
  return await rest.post(rest.routes.guilds.emojis(guildId), {
904
- body
410
+ body,
411
+ reason
905
412
  });
906
413
  },
907
414
  async createGlobalApplicationCommand (body) {
@@ -927,14 +434,15 @@ export function createRestManager(options) {
927
434
  body
928
435
  });
929
436
  },
930
- async createGuildSticker (guildId, options) {
437
+ async createGuildSticker (guildId, options, reason) {
931
438
  const form = new FormData();
932
439
  form.append('file', options.file.blob, options.file.name);
933
440
  form.append('name', options.name);
934
441
  form.append('description', options.description);
935
442
  form.append('tags', options.tags);
936
443
  return await rest.post(rest.routes.guilds.stickers(guildId), {
937
- body: form
444
+ body: form,
445
+ reason
938
446
  });
939
447
  },
940
448
  async createGuildTemplate (guildId, body) {
@@ -942,14 +450,17 @@ export function createRestManager(options) {
942
450
  body
943
451
  });
944
452
  },
945
- async createForumThread (channelId, body) {
453
+ async createForumThread (channelId, body, reason) {
946
454
  return await rest.post(rest.routes.channels.forum(channelId), {
947
- body
455
+ body,
456
+ files: body.files,
457
+ reason
948
458
  });
949
459
  },
950
- async createInvite (channelId, body = {}) {
460
+ async createInvite (channelId, body = {}, reason) {
951
461
  return await rest.post(rest.routes.channels.invites(channelId), {
952
- body
462
+ body,
463
+ reason
953
464
  });
954
465
  },
955
466
  async createRole (guildId, body, reason) {
@@ -958,14 +469,16 @@ export function createRestManager(options) {
958
469
  reason
959
470
  });
960
471
  },
961
- async createScheduledEvent (guildId, body) {
472
+ async createScheduledEvent (guildId, body, reason) {
962
473
  return await rest.post(rest.routes.guilds.events.events(guildId), {
963
- body
474
+ body,
475
+ reason
964
476
  });
965
477
  },
966
- async createStageInstance (body) {
478
+ async createStageInstance (body, reason) {
967
479
  return await rest.post(rest.routes.channels.stages(), {
968
- body
480
+ body,
481
+ reason
969
482
  });
970
483
  },
971
484
  async createWebhook (channelId, options, reason) {
@@ -998,7 +511,9 @@ export function createRestManager(options) {
998
511
  });
999
512
  },
1000
513
  async deleteFollowupMessage (token, messageId) {
1001
- await rest.delete(rest.routes.interactions.responses.message(rest.applicationId, token, messageId));
514
+ await rest.delete(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
515
+ unauthorized: true
516
+ });
1002
517
  },
1003
518
  async deleteGlobalApplicationCommand (commandId) {
1004
519
  await rest.delete(rest.routes.interactions.commands.command(rest.applicationId, commandId));
@@ -1017,8 +532,10 @@ export function createRestManager(options) {
1017
532
  async deleteGuildTemplate (guildId, templateCode) {
1018
533
  await rest.delete(rest.routes.guilds.templates.guild(guildId, templateCode));
1019
534
  },
1020
- async deleteIntegration (guildId, integrationId) {
1021
- await rest.delete(rest.routes.guilds.integration(guildId, integrationId));
535
+ async deleteIntegration (guildId, integrationId, reason) {
536
+ await rest.delete(rest.routes.guilds.integration(guildId, integrationId), {
537
+ reason
538
+ });
1022
539
  },
1023
540
  async deleteInvite (inviteCode, reason) {
1024
541
  await rest.delete(rest.routes.guilds.invite(inviteCode), {
@@ -1039,7 +556,9 @@ export function createRestManager(options) {
1039
556
  });
1040
557
  },
1041
558
  async deleteOriginalInteractionResponse (token) {
1042
- await rest.delete(rest.routes.interactions.responses.original(rest.applicationId, token));
559
+ await rest.delete(rest.routes.interactions.responses.original(rest.applicationId, token), {
560
+ unauthorized: true
561
+ });
1043
562
  },
1044
563
  async deleteOwnReaction (channelId, messageId, reaction) {
1045
564
  reaction = processReactionString(reaction);
@@ -1052,8 +571,10 @@ export function createRestManager(options) {
1052
571
  reaction = processReactionString(reaction);
1053
572
  await rest.delete(rest.routes.channels.reactions.emoji(channelId, messageId, reaction));
1054
573
  },
1055
- async deleteRole (guildId, roleId) {
1056
- await rest.delete(rest.routes.guilds.roles.one(guildId, roleId));
574
+ async deleteRole (guildId, roleId, reason) {
575
+ await rest.delete(rest.routes.guilds.roles.one(guildId, roleId), {
576
+ reason
577
+ });
1057
578
  },
1058
579
  async deleteScheduledEvent (guildId, eventId) {
1059
580
  await rest.delete(rest.routes.guilds.events.event(guildId, eventId));
@@ -1088,9 +609,10 @@ export function createRestManager(options) {
1088
609
  }
1089
610
  });
1090
611
  },
1091
- async editAutomodRule (guildId, ruleId, body) {
612
+ async editAutomodRule (guildId, ruleId, body, reason) {
1092
613
  return await rest.patch(rest.routes.guilds.automod.rule(guildId, ruleId), {
1093
- body
614
+ body,
615
+ reason
1094
616
  });
1095
617
  },
1096
618
  async editBotProfile (options) {
@@ -1102,14 +624,16 @@ export function createRestManager(options) {
1102
624
  }
1103
625
  });
1104
626
  },
1105
- async editChannel (channelId, body) {
627
+ async editChannel (channelId, body, reason) {
1106
628
  return await rest.patch(rest.routes.channels.channel(channelId), {
1107
- body
629
+ body,
630
+ reason
1108
631
  });
1109
632
  },
1110
- async editChannelPermissionOverrides (channelId, body) {
633
+ async editChannelPermissionOverrides (channelId, body, reason) {
1111
634
  await rest.put(rest.routes.channels.overwrite(channelId, body.id), {
1112
- body
635
+ body,
636
+ reason
1113
637
  });
1114
638
  },
1115
639
  async editChannelPositions (guildId, body) {
@@ -1117,14 +641,17 @@ export function createRestManager(options) {
1117
641
  body
1118
642
  });
1119
643
  },
1120
- async editEmoji (guildId, id, body) {
644
+ async editEmoji (guildId, id, body, reason) {
1121
645
  return await rest.patch(rest.routes.guilds.emoji(guildId, id), {
1122
- body
646
+ body,
647
+ reason
1123
648
  });
1124
649
  },
1125
650
  async editFollowupMessage (token, messageId, body) {
1126
651
  return await rest.patch(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
1127
- body
652
+ body,
653
+ files: body.files,
654
+ unauthorized: true
1128
655
  });
1129
656
  },
1130
657
  async editGlobalApplicationCommand (commandId, body) {
@@ -1132,9 +659,10 @@ export function createRestManager(options) {
1132
659
  body
1133
660
  });
1134
661
  },
1135
- async editGuild (guildId, body) {
662
+ async editGuild (guildId, body, reason) {
1136
663
  return await rest.patch(rest.routes.guilds.guild(guildId), {
1137
- body
664
+ body,
665
+ reason
1138
666
  });
1139
667
  },
1140
668
  async editGuildApplicationCommand (commandId, guildId, body) {
@@ -1150,9 +678,10 @@ export function createRestManager(options) {
1150
678
  reason
1151
679
  });
1152
680
  },
1153
- async editGuildSticker (guildId, stickerId, body) {
681
+ async editGuildSticker (guildId, stickerId, body, reason) {
1154
682
  return await rest.patch(rest.routes.guilds.sticker(guildId, stickerId), {
1155
- body
683
+ body,
684
+ reason
1156
685
  });
1157
686
  },
1158
687
  async editGuildTemplate (guildId, templateCode, body) {
@@ -1162,12 +691,14 @@ export function createRestManager(options) {
1162
691
  },
1163
692
  async editMessage (channelId, messageId, body) {
1164
693
  return await rest.patch(rest.routes.channels.message(channelId, messageId), {
1165
- body
694
+ body,
695
+ files: body.files
1166
696
  });
1167
697
  },
1168
698
  async editOriginalInteractionResponse (token, body) {
1169
699
  return await rest.patch(rest.routes.interactions.responses.original(rest.applicationId, token), {
1170
- body
700
+ body,
701
+ files: body.files
1171
702
  });
1172
703
  },
1173
704
  async editOriginalWebhookMessage (webhookId, token, options) {
@@ -1175,7 +706,9 @@ export function createRestManager(options) {
1175
706
  body: {
1176
707
  type: InteractionResponseTypes.UpdateMessage,
1177
708
  data: options
1178
- }
709
+ },
710
+ files: options.files,
711
+ unauthorized: true
1179
712
  });
1180
713
  },
1181
714
  async editOwnVoiceState (guildId, options) {
@@ -1186,19 +719,22 @@ export function createRestManager(options) {
1186
719
  }
1187
720
  });
1188
721
  },
1189
- async editScheduledEvent (guildId, eventId, body) {
722
+ async editScheduledEvent (guildId, eventId, body, reason) {
1190
723
  return await rest.patch(rest.routes.guilds.events.event(guildId, eventId), {
1191
- body
724
+ body,
725
+ reason
1192
726
  });
1193
727
  },
1194
- async editRole (guildId, roleId, body) {
728
+ async editRole (guildId, roleId, body, reason) {
1195
729
  return await rest.patch(rest.routes.guilds.roles.one(guildId, roleId), {
1196
- body
730
+ body,
731
+ reason
1197
732
  });
1198
733
  },
1199
- async editRolePositions (guildId, body) {
734
+ async editRolePositions (guildId, body, reason) {
1200
735
  return await rest.patch(rest.routes.guilds.roles.all(guildId), {
1201
- body
736
+ body,
737
+ reason
1202
738
  });
1203
739
  },
1204
740
  async editStageInstance (channelId, topic, reason) {
@@ -1214,14 +750,16 @@ export function createRestManager(options) {
1214
750
  body: options
1215
751
  });
1216
752
  },
1217
- async editWebhook (webhookId, body) {
753
+ async editWebhook (webhookId, body, reason) {
1218
754
  return await rest.patch(rest.routes.webhooks.id(webhookId), {
1219
- body
755
+ body,
756
+ reason
1220
757
  });
1221
758
  },
1222
759
  async editWebhookMessage (webhookId, token, messageId, options) {
1223
760
  return await rest.patch(rest.routes.webhooks.message(webhookId, token, messageId, options), {
1224
- body: options
761
+ body: options,
762
+ files: options.files
1225
763
  });
1226
764
  },
1227
765
  async editWebhookWithToken (webhookId, token, body) {
@@ -1229,14 +767,16 @@ export function createRestManager(options) {
1229
767
  body
1230
768
  });
1231
769
  },
1232
- async editWelcomeScreen (guildId, body) {
770
+ async editWelcomeScreen (guildId, body, reason) {
1233
771
  return await rest.patch(rest.routes.guilds.welcome(guildId), {
1234
- body
772
+ body,
773
+ reason
1235
774
  });
1236
775
  },
1237
- async editWidgetSettings (guildId, body) {
776
+ async editWidgetSettings (guildId, body, reason) {
1238
777
  return await rest.patch(rest.routes.guilds.widget(guildId), {
1239
- body
778
+ body,
779
+ reason
1240
780
  });
1241
781
  },
1242
782
  async executeWebhook (webhookId, token, options) {
@@ -1307,7 +847,9 @@ export function createRestManager(options) {
1307
847
  return await rest.get(rest.routes.guilds.emojis(guildId));
1308
848
  },
1309
849
  async getFollowupMessage (token, messageId) {
1310
- return await rest.get(rest.routes.interactions.responses.message(rest.applicationId, token, messageId));
850
+ return await rest.get(rest.routes.interactions.responses.message(rest.applicationId, token, messageId), {
851
+ unauthorized: true
852
+ });
1311
853
  },
1312
854
  async getGatewayBot () {
1313
855
  return await rest.get(rest.routes.gatewayBot());
@@ -1360,7 +902,9 @@ export function createRestManager(options) {
1360
902
  return await rest.get(rest.routes.nitroStickerPacks());
1361
903
  },
1362
904
  async getOriginalInteractionResponse (token) {
1363
- return await rest.get(rest.routes.interactions.responses.original(rest.applicationId, token));
905
+ return await rest.get(rest.routes.interactions.responses.original(rest.applicationId, token), {
906
+ unauthorized: true
907
+ });
1364
908
  },
1365
909
  async getPinnedMessages (channelId) {
1366
910
  return await rest.get(rest.routes.channels.pins(channelId));
@@ -1460,79 +1004,58 @@ export function createRestManager(options) {
1460
1004
  async removeThreadMember (channelId, userId) {
1461
1005
  await rest.delete(rest.routes.channels.threads.user(channelId, userId));
1462
1006
  },
1463
- // TODO: why that
1464
1007
  async sendFollowupMessage (token, options) {
1465
- return await new Promise((resolve, reject)=>{
1466
- rest.sendRequest({
1467
- url: rest.routes.webhooks.webhook(rest.applicationId, token),
1468
- method: 'POST',
1469
- options: {
1470
- body: options
1471
- },
1472
- retryCount: 0,
1473
- retryRequest: async function(options) {
1474
- // TODO: should change to reprocess queue item
1475
- await rest.sendRequest(options);
1476
- },
1477
- resolve: (data)=>{
1478
- resolve(data.status !== 204 ? JSON.parse(data.body ?? '{}') : undefined);
1479
- },
1480
- reject
1481
- });
1008
+ return await rest.post(rest.routes.webhooks.webhook(rest.applicationId, token), {
1009
+ body: options,
1010
+ files: options.files,
1011
+ unauthorized: true
1482
1012
  });
1483
1013
  },
1484
- // TODO: why that
1485
1014
  async sendInteractionResponse (interactionId, token, options) {
1486
- await new Promise((resolve, reject)=>{
1487
- rest.sendRequest({
1488
- url: rest.routes.interactions.responses.callback(interactionId, token),
1489
- method: 'POST',
1490
- options: {
1491
- body: options
1492
- },
1493
- retryCount: 0,
1494
- retryRequest: async function(options) {
1495
- // TODO: should change to reprocess queue item
1496
- await rest.sendRequest(options);
1497
- },
1498
- resolve: (data)=>{
1499
- resolve(data.status !== 204 ? JSON.parse(data.body ?? '{}') : undefined);
1500
- },
1501
- reject
1502
- });
1015
+ return await rest.post(rest.routes.interactions.responses.callback(interactionId, token), {
1016
+ body: options,
1017
+ files: options.data?.files,
1018
+ runThroughQueue: false,
1019
+ unauthorized: true
1503
1020
  });
1504
1021
  },
1505
1022
  async sendMessage (channelId, body) {
1506
1023
  return await rest.post(rest.routes.channels.messages(channelId), {
1507
- body
1024
+ body,
1025
+ files: body.files
1508
1026
  });
1509
1027
  },
1510
- async startThreadWithMessage (channelId, messageId, body) {
1028
+ async startThreadWithMessage (channelId, messageId, body, reason) {
1511
1029
  return await rest.post(rest.routes.channels.threads.message(channelId, messageId), {
1512
- body
1030
+ body,
1031
+ reason
1513
1032
  });
1514
1033
  },
1515
- async startThreadWithoutMessage (channelId, body) {
1034
+ async startThreadWithoutMessage (channelId, body, reason) {
1516
1035
  return await rest.post(rest.routes.channels.threads.all(channelId), {
1517
- body
1036
+ body,
1037
+ reason
1518
1038
  });
1519
1039
  },
1520
1040
  async syncGuildTemplate (guildId) {
1521
1041
  return await rest.put(rest.routes.guilds.templates.all(guildId));
1522
1042
  },
1523
- async banMember (guildId, userId, body) {
1043
+ async banMember (guildId, userId, body, reason) {
1524
1044
  await rest.put(rest.routes.guilds.members.ban(guildId, userId), {
1525
- body
1045
+ body,
1046
+ reason
1526
1047
  });
1527
1048
  },
1528
- async editBotMember (guildId, body) {
1049
+ async editBotMember (guildId, body, reason) {
1529
1050
  return await rest.patch(rest.routes.guilds.members.bot(guildId), {
1530
- body
1051
+ body,
1052
+ reason
1531
1053
  });
1532
1054
  },
1533
- async editMember (guildId, userId, body) {
1055
+ async editMember (guildId, userId, body, reason) {
1534
1056
  return await rest.patch(rest.routes.guilds.members.member(guildId, userId), {
1535
- body
1057
+ body,
1058
+ reason
1536
1059
  });
1537
1060
  },
1538
1061
  async getMember (guildId, userId) {
@@ -1551,16 +1074,19 @@ export function createRestManager(options) {
1551
1074
  reason
1552
1075
  });
1553
1076
  },
1554
- async pruneMembers (guildId, body) {
1077
+ async pruneMembers (guildId, body, reason) {
1555
1078
  return await rest.post(rest.routes.guilds.members.prune(guildId), {
1556
- body
1079
+ body,
1080
+ reason
1557
1081
  });
1558
1082
  },
1559
1083
  async searchMembers (guildId, query, options) {
1560
1084
  return await rest.get(rest.routes.guilds.members.search(guildId, query, options));
1561
1085
  },
1562
- async unbanMember (guildId, userId) {
1563
- await rest.delete(rest.routes.guilds.members.ban(guildId, userId));
1086
+ async unbanMember (guildId, userId, reason) {
1087
+ await rest.delete(rest.routes.guilds.members.ban(guildId, userId), {
1088
+ reason
1089
+ });
1564
1090
  },
1565
1091
  async unpinMessage (channelId, messageId, reason) {
1566
1092
  await rest.delete(rest.routes.channels.pin(channelId, messageId), {
@@ -1579,9 +1105,35 @@ export function createRestManager(options) {
1579
1105
  return await rest.put(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), {
1580
1106
  body
1581
1107
  });
1108
+ },
1109
+ preferSnakeCase (enabled) {
1110
+ const camelizer = enabled ? (x)=>x : camelize;
1111
+ rest.get = async (url, options)=>{
1112
+ return camelizer(await rest.makeRequest('GET', url, options));
1113
+ };
1114
+ rest.post = async (url, options)=>{
1115
+ return camelizer(await rest.makeRequest('POST', url, options));
1116
+ };
1117
+ rest.delete = async (url, options)=>{
1118
+ camelizer(await rest.makeRequest('DELETE', url, options));
1119
+ };
1120
+ rest.patch = async (url, options)=>{
1121
+ return camelizer(await rest.makeRequest('PATCH', url, options));
1122
+ };
1123
+ rest.put = async (url, options)=>{
1124
+ return camelizer(await rest.makeRequest('PUT', url, options));
1125
+ };
1126
+ return rest;
1582
1127
  }
1583
1128
  };
1584
1129
  return rest;
1585
1130
  }
1131
+ var HttpResponseCode;
1132
+ (function(HttpResponseCode) {
1133
+ HttpResponseCode[HttpResponseCode[/** Minimum value of a code in oder to consider that it was successful. */ "Success"] = 200] = "Success";
1134
+ HttpResponseCode[HttpResponseCode[/** Request completed successfully, but Discord returned an empty body. */ "NoContent"] = 204] = "NoContent";
1135
+ HttpResponseCode[HttpResponseCode[/** Minimum value of a code in order to consider that something went wrong. */ "Error"] = 400] = "Error";
1136
+ HttpResponseCode[HttpResponseCode[/** This request got rate limited. */ "TooManyRequests"] = 429] = "TooManyRequests";
1137
+ })(HttpResponseCode || (HttpResponseCode = {}));
1586
1138
 
1587
1139
  //# sourceMappingURL=manager.js.map