@discordeno/rest 19.0.0-next.e70bfc3 → 19.0.0-next.eb6dd97

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.
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAA4B,wBAAwB,EAAE,WAAW,EAAsB,MAAM,YAAY,CAAA;AAKrH,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC,eAAO,MAAM,eAAe,4BAA4B,CAAA;AAExD,eAAO,MAAM,uBAAuB,uBAAuB,CAAA;AAC3D,eAAO,MAAM,2BAA2B,0BAA0B,CAAA;AAClE,eAAO,MAAM,6BAA6B,4BAA4B,CAAA;AACtE,eAAO,MAAM,wBAAwB,uBAAuB,CAAA;AAC5D,eAAO,MAAM,wBAAwB,uBAAuB,CAAA;AAC5D,eAAO,MAAM,uBAAuB,sBAAsB,CAAA;AAC1D,eAAO,MAAM,uBAAuB,sBAAsB,CAAA;AAE1D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,WAAW,CAkoChF"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAA4B,wBAAwB,EAAsB,WAAW,EAAsB,MAAM,YAAY,CAAA;AAKzI,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC,eAAO,MAAM,eAAe,4BAA4B,CAAA;AAExD,eAAO,MAAM,uBAAuB,uBAAuB,CAAA;AAC3D,eAAO,MAAM,2BAA2B,0BAA0B,CAAA;AAClE,eAAO,MAAM,6BAA6B,4BAA4B,CAAA;AACtE,eAAO,MAAM,wBAAwB,uBAAuB,CAAA;AAC5D,eAAO,MAAM,wBAAwB,uBAAuB,CAAA;AAC5D,eAAO,MAAM,uBAAuB,sBAAsB,CAAA;AAC1D,eAAO,MAAM,uBAAuB,sBAAsB,CAAA;AAE1D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,WAAW,CAs3ChF"}
package/dist/manager.js CHANGED
@@ -1,7 +1,8 @@
1
- /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable no-const-assign */ import { InteractionResponseTypes } from '@discordeno/types';
1
+ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable no-const-assign */ import { Buffer } from 'node:buffer';
2
2
  import { calculateBits, camelize, camelToSnakeCase, 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';
5
6
  import { createRoutes } from './routes.js';
6
7
  // TODO: make dynamic based on package.json file
7
8
  const version = '19.0.0-alpha.1';
@@ -23,6 +24,7 @@ export function createRestManager(options) {
23
24
  const rest = {
24
25
  applicationId,
25
26
  authorization: options.proxy?.authorization,
27
+ authorizationHeader: options.proxy?.authorizationHeader ?? 'authorization',
26
28
  baseUrl,
27
29
  deleteQueueDelay: 60000,
28
30
  globallyRateLimited: false,
@@ -35,8 +37,14 @@ export function createRestManager(options) {
35
37
  token: options.token,
36
38
  version: options.version ?? DISCORD_API_VERSION,
37
39
  routes: createRoutes(),
38
- checkRateLimits (url) {
39
- const ratelimited = rest.rateLimitedPaths.get(url);
40
+ createBaseHeaders () {
41
+ return {
42
+ 'user-agent': `DiscordBot (https://github.com/discordeno/discordeno, v${version})`
43
+ };
44
+ },
45
+ checkRateLimits (url, headers) {
46
+ const authHeader = headers?.authorization ?? '';
47
+ const ratelimited = rest.rateLimitedPaths.get(`${authHeader}${url}`);
40
48
  const global = rest.rateLimitedPaths.get('global');
41
49
  const now = Date.now();
42
50
  if (ratelimited && now < ratelimited.resetTimestamp) {
@@ -55,20 +63,27 @@ export function createRestManager(options) {
55
63
  }
56
64
  const newObj = {};
57
65
  for (const key of Object.keys(obj)){
58
- // Keys that dont require snake casing
59
- if ([
60
- 'permissions',
61
- 'allow',
62
- 'deny'
63
- ].includes(key) && obj[key] !== undefined) {
64
- newObj[key] = calculateBits(obj[key]);
65
- continue;
66
+ const value = obj[key];
67
+ // Some falsy values should be allowed like null or 0
68
+ if (value !== undefined) {
69
+ switch(key){
70
+ case 'permissions':
71
+ case 'allow':
72
+ case 'deny':
73
+ newObj[key] = typeof value === 'string' ? value : calculateBits(value);
74
+ continue;
75
+ case 'defaultMemberPermissions':
76
+ newObj.default_member_permissions = typeof value === 'string' ? value : calculateBits(value);
77
+ continue;
78
+ case 'nameLocalizations':
79
+ newObj.name_localizations = value;
80
+ continue;
81
+ case 'descriptionLocalizations':
82
+ newObj.description_localizations = value;
83
+ continue;
84
+ }
66
85
  }
67
- if (key === 'defaultMemberPermissions' && obj[key] !== undefined) {
68
- newObj.default_member_permissions = calculateBits(obj[key]);
69
- continue;
70
- }
71
- newObj[camelToSnakeCase(key)] = rest.changeToDiscordFormat(obj[key]);
86
+ newObj[camelToSnakeCase(key)] = rest.changeToDiscordFormat(value);
72
87
  }
73
88
  return newObj;
74
89
  }
@@ -76,10 +91,8 @@ export function createRestManager(options) {
76
91
  return obj;
77
92
  },
78
93
  createRequestBody (method, options) {
79
- const headers = {
80
- 'user-agent': `DiscordBot (https://github.com/discordeno/discordeno, v${version})`
81
- };
82
- if (options?.unauthorized !== false) headers.authorization = `Bot ${rest.token}`;
94
+ const headers = this.createBaseHeaders();
95
+ if (options?.unauthorized !== true) headers.authorization = `Bot ${rest.token}`;
83
96
  // IF A REASON IS PROVIDED ENCODE IT IN HEADERS
84
97
  if (options?.reason !== undefined) {
85
98
  headers[AUDIT_LOG_REASON_HEADER] = encodeURIComponent(options?.reason);
@@ -93,12 +106,21 @@ export function createRestManager(options) {
93
106
  for(let i = 0; i < options.files.length; ++i){
94
107
  form.append(`file${i}`, options.files[i].blob, options.files[i].name);
95
108
  }
96
- form.append('payload_json', JSON.stringify({
109
+ // Have to use changeToDiscordFormat or else JSON.stringify may throw an error for the presence of BigInt(s) in the json
110
+ form.append('payload_json', JSON.stringify(rest.changeToDiscordFormat({
97
111
  ...options.body,
98
112
  files: undefined
99
- }));
113
+ })));
114
+ // No need to set the `content-type` header since `fetch` does that automatically for us when we use a `FormData` object.
100
115
  body = form;
101
- // No need to set the `content-type` header since `fetch` does that automatically for us when we use a `FormData` object.
116
+ } else if (options?.body && options.headers && options.headers['content-type'] === 'application/x-www-form-urlencoded') {
117
+ // OAuth2 body handling
118
+ const formBody = [];
119
+ const discordBody = rest.changeToDiscordFormat(options.body);
120
+ for(const prop in discordBody){
121
+ formBody.push(`${encodeURIComponent(prop)}=${encodeURIComponent(discordBody[prop])}`);
122
+ }
123
+ body = formBody.join('&');
102
124
  } else if (options?.body !== undefined) {
103
125
  if (options.body instanceof FormData) {
104
126
  body = options.body;
@@ -145,7 +167,7 @@ export function createRestManager(options) {
145
167
  }, 1000);
146
168
  }
147
169
  },
148
- /** Processes the rate limit headers and determines if it needs to be rate limited and returns the bucket id if available */ processHeaders (url, headers) {
170
+ /** 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) {
149
171
  let rateLimited = false;
150
172
  // GET ALL NECESSARY HEADERS
151
173
  const remaining = headers.get(RATE_LIMIT_REMAINING_HEADER);
@@ -155,7 +177,7 @@ export function createRestManager(options) {
155
177
  // undefined override null needed for typings
156
178
  const bucketId = headers.get(RATE_LIMIT_BUCKET_HEADER) ?? undefined;
157
179
  const limit = headers.get(RATE_LIMIT_LIMIT_HEADER);
158
- rest.queues.get(url)?.handleCompletedRequest({
180
+ rest.queues.get(`${requestAuthorization}${url}`)?.handleCompletedRequest({
159
181
  remaining: remaining ? Number(remaining) : undefined,
160
182
  interval: retryAfter ? Number(retryAfter) * 1000 : undefined,
161
183
  max: limit ? Number(limit) : undefined
@@ -164,14 +186,14 @@ export function createRestManager(options) {
164
186
  if (remaining === '0') {
165
187
  rateLimited = true;
166
188
  // SAVE THE URL AS LIMITED, IMPORTANT FOR NEW REQUESTS BY USER WITHOUT BUCKET
167
- rest.rateLimitedPaths.set(url, {
189
+ rest.rateLimitedPaths.set(`${requestAuthorization}${url}`, {
168
190
  url,
169
191
  resetTimestamp: reset,
170
192
  bucketId
171
193
  });
172
194
  // SAVE THE BUCKET AS LIMITED SINCE DIFFERENT URLS MAY SHARE A BUCKET
173
195
  if (bucketId) {
174
- rest.rateLimitedPaths.set(bucketId, {
196
+ rest.rateLimitedPaths.set(`${requestAuthorization}${bucketId}`, {
175
197
  url,
176
198
  resetTimestamp: reset,
177
199
  bucketId
@@ -180,8 +202,8 @@ export function createRestManager(options) {
180
202
  }
181
203
  // IF THERE IS NO REMAINING GLOBAL LIMIT, MARK IT RATE LIMITED GLOBALLY
182
204
  if (global) {
183
- const retryAfter = headers.get('retry-after');
184
- const globalReset = Date.now() + Number(retryAfter) * 1000;
205
+ const retryAfter = Number(headers.get('retry-after')) * 1000;
206
+ const globalReset = Date.now() + retryAfter;
185
207
  // rest.debug(
186
208
  // `[REST = Globally Rate Limited] URL: ${url} | Global Rest: ${globalReset}`
187
209
  // )
@@ -189,14 +211,14 @@ export function createRestManager(options) {
189
211
  rateLimited = true;
190
212
  setTimeout(()=>{
191
213
  rest.globallyRateLimited = false;
192
- }, globalReset);
214
+ }, retryAfter);
193
215
  rest.rateLimitedPaths.set('global', {
194
216
  url: 'global',
195
217
  resetTimestamp: globalReset,
196
218
  bucketId
197
219
  });
198
220
  if (bucketId) {
199
- rest.rateLimitedPaths.set(bucketId, {
221
+ rest.rateLimitedPaths.set(`${requestAuthorization}${bucketId}`, {
200
222
  url: 'global',
201
223
  resetTimestamp: globalReset,
202
224
  bucketId
@@ -211,12 +233,16 @@ export function createRestManager(options) {
211
233
  async sendRequest (options) {
212
234
  const url = `${rest.baseUrl}/v${rest.version}${options.route}`;
213
235
  const payload = rest.createRequestBody(options.method, options.requestBodyOptions);
236
+ const loggingHeaders = {
237
+ ...payload.headers
238
+ };
239
+ const authenticationScheme = payload.headers.authorization?.split(' ')[0];
240
+ if (payload.headers.authorization) {
241
+ loggingHeaders.authorization = `${authenticationScheme} tokenhere`;
242
+ }
214
243
  logger.debug(`sending request to ${url}`, 'with payload:', {
215
244
  ...payload,
216
- headers: {
217
- ...payload.headers,
218
- authorization: 'Bot tokenhere'
219
- }
245
+ headers: loggingHeaders
220
246
  });
221
247
  const response = await fetch(url, payload).catch(async (error)=>{
222
248
  logger.error(error);
@@ -233,7 +259,7 @@ export function createRestManager(options) {
233
259
  // Mark request and completed
234
260
  rest.invalidBucket.handleCompletedRequest(response.status, response.headers.get(RATE_LIMIT_SCOPE_HEADER) === 'shared');
235
261
  // Set the bucket id if it was available on the headers
236
- const bucketId = rest.processHeaders(rest.simplifyUrl(options.route, options.method), response.headers);
262
+ const bucketId = rest.processHeaders(rest.simplifyUrl(options.route, options.method), response.headers, authenticationScheme === 'Bearer' ? payload.headers.authorization : '');
237
263
  if (bucketId) options.bucketId = bucketId;
238
264
  if (response.status < 200 || response.status >= 400) {
239
265
  logger.debug(`Request to ${url} failed.`);
@@ -298,19 +324,21 @@ export function createRestManager(options) {
298
324
  await rest.sendRequest(request);
299
325
  return;
300
326
  }
301
- const queue = rest.queues.get(url);
327
+ const authHeader = request.requestBodyOptions?.headers?.authorization ?? '';
328
+ const queue = rest.queues.get(`${authHeader}${url}`);
302
329
  if (queue !== undefined) {
303
330
  queue.makeRequest(request);
304
331
  } else {
305
332
  // CREATES A NEW QUEUE
306
333
  const bucketQueue = new Queue(rest, {
307
334
  url,
308
- deleteQueueDelay: rest.deleteQueueDelay
335
+ deleteQueueDelay: rest.deleteQueueDelay,
336
+ authentication: authHeader
309
337
  });
310
338
  // Add request to queue
311
339
  bucketQueue.makeRequest(request);
312
340
  // Save queue
313
- rest.queues.set(url, bucketQueue);
341
+ rest.queues.set(`${authHeader}${url}`, bucketQueue);
314
342
  }
315
343
  },
316
344
  async makeRequest (method, route, options) {
@@ -318,7 +346,7 @@ export function createRestManager(options) {
318
346
  if (rest.authorization !== undefined) {
319
347
  options ??= {};
320
348
  options.headers ??= {};
321
- options.headers.authorization = rest.authorization;
349
+ options.headers[rest.authorizationHeader] = rest.authorization;
322
350
  }
323
351
  const result = await fetch(`${rest.baseUrl}/v${rest.version}${route}`, rest.createRequestBody(method, options));
324
352
  if (!result.ok) {
@@ -386,6 +414,11 @@ export function createRestManager(options) {
386
414
  async addThreadMember (channelId, userId) {
387
415
  await rest.put(rest.routes.channels.threads.user(channelId, userId));
388
416
  },
417
+ async addDmRecipient (channelId, userId, body) {
418
+ await rest.put(rest.routes.channels.dmRecipient(channelId, userId), {
419
+ body
420
+ });
421
+ },
389
422
  async createAutomodRule (guildId, body, reason) {
390
423
  return await rest.post(rest.routes.guilds.automod.rules(guildId), {
391
424
  body,
@@ -404,20 +437,34 @@ export function createRestManager(options) {
404
437
  reason
405
438
  });
406
439
  },
407
- async createGlobalApplicationCommand (body) {
408
- return await rest.post(rest.routes.interactions.commands.commands(rest.applicationId), {
440
+ async createGlobalApplicationCommand (body, options) {
441
+ const restOptions = {
409
442
  body
410
- });
443
+ };
444
+ if (options?.bearerToken) {
445
+ restOptions.unauthorized = true;
446
+ restOptions.headers = {
447
+ authorization: `Bearer ${options.bearerToken}`
448
+ };
449
+ }
450
+ return await rest.post(rest.routes.interactions.commands.commands(rest.applicationId), restOptions);
411
451
  },
412
452
  async createGuild (body) {
413
453
  return await rest.post(rest.routes.guilds.all(), {
414
454
  body
415
455
  });
416
456
  },
417
- async createGuildApplicationCommand (body, guildId) {
418
- return await rest.post(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), {
457
+ async createGuildApplicationCommand (body, guildId, options) {
458
+ const restOptions = {
419
459
  body
420
- });
460
+ };
461
+ if (options?.bearerToken) {
462
+ restOptions.unauthorized = true;
463
+ restOptions.headers = {
464
+ authorization: `Bearer ${options.bearerToken}`
465
+ };
466
+ }
467
+ return await rest.post(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), restOptions);
421
468
  },
422
469
  async createGuildFromTemplate (templateCode, body) {
423
470
  if (body.icon) {
@@ -610,7 +657,7 @@ export function createRestManager(options) {
610
657
  },
611
658
  async editBotProfile (options) {
612
659
  const avatar = options?.botAvatarURL ? await urlToBase64(options?.botAvatarURL) : options?.botAvatarURL;
613
- return await rest.patch(rest.routes.userBot(), {
660
+ return await rest.patch(rest.routes.currentUser(), {
614
661
  body: {
615
662
  username: options.username?.trim(),
616
663
  avatar
@@ -684,7 +731,8 @@ export function createRestManager(options) {
684
731
  },
685
732
  async editMessage (channelId, messageId, body) {
686
733
  return await rest.patch(rest.routes.channels.message(channelId, messageId), {
687
- body
734
+ body,
735
+ files: body.files
688
736
  });
689
737
  },
690
738
  async editOriginalInteractionResponse (token, body) {
@@ -786,14 +834,62 @@ export function createRestManager(options) {
786
834
  async getActiveThreads (guildId) {
787
835
  return await rest.get(rest.routes.channels.threads.active(guildId));
788
836
  },
789
- async getApplicationCommandPermission (guildId, commandId) {
790
- return await rest.get(rest.routes.interactions.commands.permission(rest.applicationId, guildId, commandId));
791
- },
792
- async getApplicationCommandPermissions (guildId) {
793
- return await rest.get(rest.routes.interactions.commands.permissions(rest.applicationId, guildId));
837
+ async getApplicationCommandPermission (guildId, commandId, options) {
838
+ const restOptions = {};
839
+ if (options?.accessToken) {
840
+ restOptions.unauthorized = true;
841
+ restOptions.headers = {
842
+ authorization: `Bearer ${options.accessToken}`
843
+ };
844
+ }
845
+ return await rest.get(rest.routes.interactions.commands.permission(options?.applicationId ?? rest.applicationId, guildId, commandId), restOptions);
846
+ },
847
+ async getApplicationCommandPermissions (guildId, options) {
848
+ const restOptions = {};
849
+ if (options?.accessToken) {
850
+ restOptions.unauthorized = true;
851
+ restOptions.headers = {
852
+ authorization: `Bearer ${options.accessToken}`
853
+ };
854
+ }
855
+ return await rest.get(rest.routes.interactions.commands.permissions(options?.applicationId ?? rest.applicationId, guildId), restOptions);
794
856
  },
795
857
  async getApplicationInfo () {
796
- return await rest.get(rest.routes.oauth2Application());
858
+ return await rest.get(rest.routes.oauth2.application());
859
+ },
860
+ async getCurrentAuthenticationInfo (token) {
861
+ return await rest.get(rest.routes.oauth2.currentAuthorization(), {
862
+ headers: {
863
+ authorization: `Bearer ${token}`
864
+ },
865
+ unauthorized: true
866
+ });
867
+ },
868
+ async exchangeToken (clientId, clientSecret, body) {
869
+ const basicCredentials = Buffer.from(`${clientId}:${clientSecret}`);
870
+ const restOptions = {
871
+ body,
872
+ headers: {
873
+ 'content-type': 'application/x-www-form-urlencoded',
874
+ authorization: `Basic ${basicCredentials.toString('base64')}`
875
+ },
876
+ unauthorized: true
877
+ };
878
+ if (body.grantType === 'client_credentials') {
879
+ restOptions.body.scope = body.scope.join(' ');
880
+ }
881
+ return await rest.post(rest.routes.oauth2.tokenExchange(), restOptions);
882
+ },
883
+ async revokeToken (clientId, clientSecret, body) {
884
+ const basicCredentials = Buffer.from(`${clientId}:${clientSecret}`);
885
+ await rest.post(rest.routes.oauth2.tokenRevoke(), {
886
+ body,
887
+ headers: {
888
+ 'content-type': 'application/x-www-form-urlencoded',
889
+ authorization: `Basic ${basicCredentials.toString('base64')}`
890
+ },
891
+ unauthorized: true
892
+ });
797
893
  },
798
894
  async getAuditLog (guildId, options) {
799
895
  return await rest.get(rest.routes.guilds.auditlogs(guildId, options));
@@ -832,6 +928,11 @@ export function createRestManager(options) {
832
928
  }
833
929
  });
834
930
  },
931
+ async getGroupDmChannel (body) {
932
+ return await rest.post(rest.routes.channels.dm(), {
933
+ body
934
+ });
935
+ },
835
936
  async getEmoji (guildId, emojiId) {
836
937
  return await rest.get(rest.routes.guilds.emoji(guildId, emojiId));
837
938
  },
@@ -857,6 +958,14 @@ export function createRestManager(options) {
857
958
  }) {
858
959
  return await rest.get(rest.routes.guilds.guild(guildId, options.counts));
859
960
  },
961
+ async getGuilds (token, options) {
962
+ return await rest.get(rest.routes.guilds.userGuilds(options), {
963
+ headers: {
964
+ authorization: `Bearer ${token}`
965
+ },
966
+ unauthorized: true
967
+ });
968
+ },
860
969
  async getGuildApplicationCommand (commandId, guildId) {
861
970
  return await rest.get(rest.routes.interactions.commands.guilds.one(rest.applicationId, guildId, commandId));
862
971
  },
@@ -952,6 +1061,30 @@ export function createRestManager(options) {
952
1061
  async getUser (id) {
953
1062
  return await rest.get(rest.routes.user(id));
954
1063
  },
1064
+ async getCurrentUser (token) {
1065
+ return await rest.get(rest.routes.currentUser(), {
1066
+ headers: {
1067
+ authorization: `Bearer ${token}`
1068
+ },
1069
+ unauthorized: true
1070
+ });
1071
+ },
1072
+ async getUserConnections (token) {
1073
+ return await rest.get(rest.routes.oauth2.connections(), {
1074
+ headers: {
1075
+ authorization: `Bearer ${token}`
1076
+ },
1077
+ unauthorized: true
1078
+ });
1079
+ },
1080
+ async getUserApplicationRoleConnection (token, applicationId) {
1081
+ return await rest.get(rest.routes.oauth2.roleConnections(applicationId), {
1082
+ headers: {
1083
+ authorization: `Bearer ${token}`
1084
+ },
1085
+ unauthorized: true
1086
+ });
1087
+ },
955
1088
  async getVanityUrl (guildId) {
956
1089
  return await rest.get(rest.routes.guilds.vanity(guildId));
957
1090
  },
@@ -996,6 +1129,9 @@ export function createRestManager(options) {
996
1129
  async removeThreadMember (channelId, userId) {
997
1130
  await rest.delete(rest.routes.channels.threads.user(channelId, userId));
998
1131
  },
1132
+ async removeDmRecipient (channelId, userId) {
1133
+ await rest.delete(rest.routes.channels.dmRecipient(channelId, userId));
1134
+ },
999
1135
  async sendFollowupMessage (token, options) {
1000
1136
  return await rest.post(rest.routes.webhooks.webhook(rest.applicationId, token), {
1001
1137
  body: options,
@@ -1053,6 +1189,14 @@ export function createRestManager(options) {
1053
1189
  async getMember (guildId, userId) {
1054
1190
  return await rest.get(rest.routes.guilds.members.member(guildId, userId));
1055
1191
  },
1192
+ async getCurrentMember (guildId, token) {
1193
+ return await rest.get(rest.routes.guilds.members.currentMember(guildId), {
1194
+ headers: {
1195
+ authorization: `Bearer ${token}`
1196
+ },
1197
+ unauthorized: true
1198
+ });
1199
+ },
1056
1200
  async getMembers (guildId, options) {
1057
1201
  return await rest.get(rest.routes.guilds.members.members(guildId, options));
1058
1202
  },
@@ -1088,15 +1232,62 @@ export function createRestManager(options) {
1088
1232
  async triggerTypingIndicator (channelId) {
1089
1233
  await rest.post(rest.routes.channels.typing(channelId));
1090
1234
  },
1091
- async upsertGlobalApplicationCommands (body) {
1092
- return await rest.put(rest.routes.interactions.commands.commands(rest.applicationId), {
1235
+ async upsertGlobalApplicationCommands (body, options) {
1236
+ const restOptions = {
1093
1237
  body
1238
+ };
1239
+ if (options?.bearerToken) {
1240
+ restOptions.unauthorized = true;
1241
+ restOptions.headers = {
1242
+ authorization: `Bearer ${options.bearerToken}`
1243
+ };
1244
+ }
1245
+ return await rest.put(rest.routes.interactions.commands.commands(rest.applicationId), restOptions);
1246
+ },
1247
+ async upsertGuildApplicationCommands (guildId, body, options) {
1248
+ const restOptions = {
1249
+ body
1250
+ };
1251
+ if (options?.bearerToken) {
1252
+ restOptions.unauthorized = true;
1253
+ restOptions.headers = {
1254
+ authorization: `Bearer ${options.bearerToken}`
1255
+ };
1256
+ }
1257
+ return await rest.put(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), restOptions);
1258
+ },
1259
+ async editUserApplicationRoleConnection (token, applicationId, body) {
1260
+ return await rest.put(rest.routes.oauth2.roleConnections(applicationId), {
1261
+ body,
1262
+ headers: {
1263
+ authorization: `Bearer ${token}`
1264
+ },
1265
+ unauthorized: true
1094
1266
  });
1095
1267
  },
1096
- async upsertGuildApplicationCommands (guildId, body) {
1097
- return await rest.put(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), {
1268
+ async addGuildMember (guildId, userId, body) {
1269
+ return await rest.put(rest.routes.guilds.members.member(guildId, userId), {
1098
1270
  body
1099
1271
  });
1272
+ },
1273
+ preferSnakeCase (enabled) {
1274
+ const camelizer = enabled ? (x)=>x : camelize;
1275
+ rest.get = async (url, options)=>{
1276
+ return camelizer(await rest.makeRequest('GET', url, options));
1277
+ };
1278
+ rest.post = async (url, options)=>{
1279
+ return camelizer(await rest.makeRequest('POST', url, options));
1280
+ };
1281
+ rest.delete = async (url, options)=>{
1282
+ camelizer(await rest.makeRequest('DELETE', url, options));
1283
+ };
1284
+ rest.patch = async (url, options)=>{
1285
+ return camelizer(await rest.makeRequest('PATCH', url, options));
1286
+ };
1287
+ rest.put = async (url, options)=>{
1288
+ return camelizer(await rest.makeRequest('PUT', url, options));
1289
+ };
1290
+ return rest;
1100
1291
  }
1101
1292
  };
1102
1293
  return rest;