@discordeno/rest 19.0.0-next.1424e55 → 19.0.0-next.1545f01

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":"invalidBucket.d.ts","sourceRoot":"","sources":["../src/invalidBucket.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,oBAAoB,CAmFrG;AAED,MAAM,WAAW,2BAA2B;IAC1C,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sGAAsG;IACtG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,6BAA6B;IAC7B,eAAe,EAAE,MAAM,CAAA;IACvB,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAA;IACX,sGAAsG;IACtG,QAAQ,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,mEAAmE;IACnE,cAAc,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,OAAO,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAA;IACzD,8DAA8D;IAC9D,UAAU,EAAE,OAAO,CAAA;IAEnB,+DAA+D;IAC/D,eAAe,EAAE,MAAM,MAAM,CAAA;IAC7B,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,OAAO,CAAA;IAC/B,yCAAyC;IACzC,yBAAyB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,uDAAuD;IACvD,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,iIAAiI;IACjI,sBAAsB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,KAAK,IAAI,CAAA;CACrE"}
1
+ {"version":3,"file":"invalidBucket.d.ts","sourceRoot":"","sources":["../src/invalidBucket.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,oBAAoB,CA2FrG;AAED,MAAM,WAAW,2BAA2B;IAC1C,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sGAAsG;IACtG,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,6BAA6B;IAC7B,eAAe,EAAE,MAAM,CAAA;IACvB,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAA;IACX,sGAAsG;IACtG,QAAQ,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,mEAAmE;IACnE,cAAc,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,OAAO,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAA;IACzD,8DAA8D;IAC9D,UAAU,EAAE,OAAO,CAAA;IAEnB,+DAA+D;IAC/D,eAAe,EAAE,MAAM,MAAM,CAAA;IAC7B,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,OAAO,CAAA;IAC/B,yCAAyC;IACzC,yBAAyB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,uDAAuD;IACvD,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,iIAAiI;IACjI,sBAAsB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,KAAK,IAAI,CAAA;CACrE"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/invalidBucket.ts"],"sourcesContent":["import { delay, logger } from '@discordeno/utils'\n\n/**\n * A invalid request bucket is used in a similar manner as a leaky bucket but a invalid request bucket can be refilled as needed.\n * It's purpose is to make sure the bot does not hit the limit to getting a 1 hr ban.\n *\n * @param options The options used to configure this bucket.\n * @returns RefillingBucket\n */\nexport function createInvalidRequestBucket(options: InvalidRequestBucketOptions): InvalidRequestBucket {\n const bucket: InvalidRequestBucket = {\n invalidRequests: options.current ?? 0,\n max: options.max ?? 10000,\n interval: options.interval ?? 600_000, // 10 minutes\n resetAt: options.resetAt,\n safety: options.safety ?? 1,\n errorStatuses: options.errorStatuses ?? [401, 403, 429],\n activeRequests: options.requested ?? 0,\n processing: false,\n\n waiting: [],\n\n requestsAllowed: function () {\n if (bucket.resetAt !== undefined && Date.now() >= bucket.resetAt) {\n bucket.invalidRequests = 0\n bucket.resetAt = Date.now() + bucket.interval\n }\n\n return bucket.max - bucket.invalidRequests - bucket.activeRequests - bucket.safety\n },\n\n isRequestAllowed: function () {\n return bucket.requestsAllowed() > 0\n },\n\n waitUntilRequestAvailable: async function () {\n // eslint-disable-next-line no-async-promise-executor\n return await new Promise(async (resolve) => {\n // If whatever amount of requests is left is more than the safety margin, allow the request\n if (bucket.isRequestAllowed()) {\n bucket.activeRequests += 1\n resolve()\n } else {\n bucket.waiting.push(resolve)\n await bucket.processWaiting()\n }\n })\n },\n\n processWaiting: async function () {\n // If already processing, that loop will handle all waiting requests.\n if (bucket.processing) return\n\n // Mark as processing so other loops don't start\n bucket.processing = true\n\n while (bucket.waiting.length > 0) {\n logger.info(`[InvalidBucket] processing waiting queue while loop ran with ${bucket.waiting.length} pending requests to be made. ${JSON.stringify(bucket)}`)\n\n if (!bucket.isRequestAllowed() && bucket.resetAt !== undefined) {\n logger.warn(`[InvalidBucket] processing waiting queue is now paused until more requests are available. ${bucket.waiting.length} pending requests. ${JSON.stringify(bucket)}`)\n await delay(bucket.resetAt - Date.now())\n }\n\n bucket.activeRequests += 1\n // Resolve the next item in the queue\n bucket.waiting.shift()?.()\n }\n\n // Mark as false so next pending request can be triggered by new loop.\n bucket.processing = false\n },\n\n handleCompletedRequest: function (code, sharedScope) {\n // Since request is complete, we can remove one from requested.\n bucket.activeRequests -= 1\n // Since it is as a valid request, we don't need to do anything\n if (!bucket.errorStatuses.includes(code)) return\n // Shared scope is not considered invalid\n if (code === 429 && sharedScope) return\n\n // INVALID REQUEST WAS MADE\n if (bucket.resetAt === undefined) {\n bucket.resetAt = Date.now() + bucket.interval\n }\n\n bucket.invalidRequests += 1\n logger.warn(`[InvalidBucket] an invalid request was made. Increasing invalidRequests count to ${bucket.invalidRequests}`)\n },\n }\n\n return bucket\n}\n\nexport interface InvalidRequestBucketOptions {\n /** current invalid amount */\n current?: number\n /** max invalid requests allowed until ban. Defaults to 10,000 */\n max?: number\n /** The time that discord allows to make the max number of invalid requests. Defaults to 10 minutes */\n interval?: number\n /** When the timeout for the bucket has started at. */\n resetAt?: number\n /** how safe to be from max. Defaults to 1 */\n safety?: number\n /** The request statuses that count as an invalid request. */\n errorStatuses?: number[]\n /** The amount of requests that were requested from this bucket. */\n requested?: number\n}\n\nexport interface InvalidRequestBucket {\n /** current invalid amount */\n invalidRequests: number\n /** max invalid requests allowed until ban. Defaults to 10,000 */\n max: number\n /** The time that discord allows to make the max number of invalid requests. Defaults to 10 minutes */\n interval: number\n /** When the timeout for this bucket has started at. */\n resetAt: number | undefined\n /** how safe to be from max. Defaults to 1 */\n safety: number\n /** The request statuses that count as an invalid request. */\n errorStatuses: number[]\n /** The amount of requests that were requested from this bucket. */\n activeRequests: number\n /** The requests that are currently pending. */\n waiting: Array<(value: void | PromiseLike<void>) => void>\n /** Whether or not the waiting queue is already processing. */\n processing: boolean\n\n /** Gives the number of requests that are currently allowed. */\n requestsAllowed: () => number\n /** Checks if a request is allowed at this time. */\n isRequestAllowed: () => boolean\n /** Waits until a request is available */\n waitUntilRequestAvailable: () => Promise<void>\n /** Begins processing the waiting queue of requests. */\n processWaiting: () => Promise<void>\n /** Handler for whenever a request is validated. This should update the requested values or trigger any other necessary stuff. */\n handleCompletedRequest: (code: number, sharedScope: boolean) => void\n}\n"],"names":["delay","logger","createInvalidRequestBucket","options","bucket","invalidRequests","current","max","interval","resetAt","safety","errorStatuses","activeRequests","requested","processing","waiting","requestsAllowed","undefined","Date","now","isRequestAllowed","waitUntilRequestAvailable","Promise","resolve","push","processWaiting","length","info","JSON","stringify","warn","shift","handleCompletedRequest","code","sharedScope","includes"],"mappings":"AAAA,SAASA,KAAK,EAAEC,MAAM,QAAQ,oBAAmB;AAEjD;;;;;;CAMC,GACD,OAAO,SAASC,2BAA2BC,OAAoC,EAAwB;IACrG,MAAMC,SAA+B;QACnCC,iBAAiBF,QAAQG,OAAO,IAAI;QACpCC,KAAKJ,QAAQI,GAAG,IAAI;QACpBC,UAAUL,QAAQK,QAAQ,IAAI;QAC9BC,SAASN,QAAQM,OAAO;QACxBC,QAAQP,QAAQO,MAAM,IAAI;QAC1BC,eAAeR,QAAQQ,aAAa,IAAI;YAAC;YAAK;YAAK;SAAI;QACvDC,gBAAgBT,QAAQU,SAAS,IAAI;QACrCC,YAAY,KAAK;QAEjBC,SAAS,EAAE;QAEXC,iBAAiB,WAAY;YAC3B,IAAIZ,OAAOK,OAAO,KAAKQ,aAAaC,KAAKC,GAAG,MAAMf,OAAOK,OAAO,EAAE;gBAChEL,OAAOC,eAAe,GAAG;gBACzBD,OAAOK,OAAO,GAAGS,KAAKC,GAAG,KAAKf,OAAOI,QAAQ;YAC/C,CAAC;YAED,OAAOJ,OAAOG,GAAG,GAAGH,OAAOC,eAAe,GAAGD,OAAOQ,cAAc,GAAGR,OAAOM,MAAM;QACpF;QAEAU,kBAAkB,WAAY;YAC5B,OAAOhB,OAAOY,eAAe,KAAK;QACpC;QAEAK,2BAA2B,iBAAkB;YAC3C,qDAAqD;YACrD,OAAO,MAAM,IAAIC,QAAQ,OAAOC,UAAY;gBAC1C,2FAA2F;gBAC3F,IAAInB,OAAOgB,gBAAgB,IAAI;oBAC7BhB,OAAOQ,cAAc,IAAI;oBACzBW;gBACF,OAAO;oBACLnB,OAAOW,OAAO,CAACS,IAAI,CAACD;oBACpB,MAAMnB,OAAOqB,cAAc;gBAC7B,CAAC;YACH;QACF;QAEAA,gBAAgB,iBAAkB;YAChC,qEAAqE;YACrE,IAAIrB,OAAOU,UAAU,EAAE;YAEvB,gDAAgD;YAChDV,OAAOU,UAAU,GAAG,IAAI;YAExB,MAAOV,OAAOW,OAAO,CAACW,MAAM,GAAG,EAAG;gBAChCzB,OAAO0B,IAAI,CAAC,CAAC,6DAA6D,EAAEvB,OAAOW,OAAO,CAACW,MAAM,CAAC,8BAA8B,EAAEE,KAAKC,SAAS,CAACzB,QAAQ,CAAC;gBAE1J,IAAI,CAACA,OAAOgB,gBAAgB,MAAMhB,OAAOK,OAAO,KAAKQ,WAAW;oBAC9DhB,OAAO6B,IAAI,CAAC,CAAC,0FAA0F,EAAE1B,OAAOW,OAAO,CAACW,MAAM,CAAC,mBAAmB,EAAEE,KAAKC,SAAS,CAACzB,QAAQ,CAAC;oBAC5K,MAAMJ,MAAMI,OAAOK,OAAO,GAAGS,KAAKC,GAAG;gBACvC,CAAC;gBAEDf,OAAOQ,cAAc,IAAI;gBACzB,qCAAqC;gBACrCR,OAAOW,OAAO,CAACgB,KAAK;YACtB;YAEA,sEAAsE;YACtE3B,OAAOU,UAAU,GAAG,KAAK;QAC3B;QAEAkB,wBAAwB,SAAUC,IAAI,EAAEC,WAAW,EAAE;YACnD,+DAA+D;YAC/D9B,OAAOQ,cAAc,IAAI;YACzB,+DAA+D;YAC/D,IAAI,CAACR,OAAOO,aAAa,CAACwB,QAAQ,CAACF,OAAO;YAC1C,yCAAyC;YACzC,IAAIA,SAAS,OAAOC,aAAa;YAEjC,2BAA2B;YAC3B,IAAI9B,OAAOK,OAAO,KAAKQ,WAAW;gBAChCb,OAAOK,OAAO,GAAGS,KAAKC,GAAG,KAAKf,OAAOI,QAAQ;YAC/C,CAAC;YAEDJ,OAAOC,eAAe,IAAI;YAC1BJ,OAAO6B,IAAI,CAAC,CAAC,iFAAiF,EAAE1B,OAAOC,eAAe,CAAC,CAAC;QAC1H;IACF;IAEA,OAAOD;AACT,CAAC"}
1
+ {"version":3,"sources":["../src/invalidBucket.ts"],"sourcesContent":["import { delay, logger } from '@discordeno/utils'\n\n/**\n * A invalid request bucket is used in a similar manner as a leaky bucket but a invalid request bucket can be refilled as needed.\n * It's purpose is to make sure the bot does not hit the limit to getting a 1 hr ban.\n *\n * @param options The options used to configure this bucket.\n * @returns RefillingBucket\n */\nexport function createInvalidRequestBucket(options: InvalidRequestBucketOptions): InvalidRequestBucket {\n const bucket: InvalidRequestBucket = {\n invalidRequests: options.current ?? 0,\n max: options.max ?? 10000,\n interval: options.interval ?? 600_000, // 10 minutes\n resetAt: options.resetAt,\n safety: options.safety ?? 1,\n errorStatuses: options.errorStatuses ?? [401, 403, 429],\n activeRequests: options.requested ?? 0,\n processing: false,\n\n waiting: [],\n\n requestsAllowed: function () {\n if (bucket.resetAt !== undefined && Date.now() >= bucket.resetAt) {\n bucket.invalidRequests = 0\n bucket.resetAt = Date.now() + bucket.interval\n }\n\n return bucket.max - bucket.invalidRequests - bucket.activeRequests - bucket.safety\n },\n\n isRequestAllowed: function () {\n return bucket.requestsAllowed() > 0\n },\n\n waitUntilRequestAvailable: async function () {\n // eslint-disable-next-line no-async-promise-executor\n return await new Promise(async (resolve) => {\n // If whatever amount of requests is left is more than the safety margin, allow the request\n if (bucket.isRequestAllowed()) {\n bucket.activeRequests += 1\n resolve()\n } else {\n bucket.waiting.push(resolve)\n await bucket.processWaiting()\n }\n })\n },\n\n processWaiting: async function () {\n // If already processing, that loop will handle all waiting requests.\n if (bucket.processing) return\n\n // Mark as processing so other loops don't start\n bucket.processing = true\n\n while (bucket.waiting.length > 0) {\n logger.info(\n `[InvalidBucket] processing waiting queue while loop ran with ${bucket.waiting.length} pending requests to be made. ${JSON.stringify(\n bucket,\n )}`,\n )\n\n if (!bucket.isRequestAllowed() && bucket.resetAt !== undefined) {\n logger.warn(\n `[InvalidBucket] processing waiting queue is now paused until more requests are available. ${\n bucket.waiting.length\n } pending requests. ${JSON.stringify(bucket)}`,\n )\n await delay(bucket.resetAt - Date.now())\n }\n\n bucket.activeRequests += 1\n // Resolve the next item in the queue\n bucket.waiting.shift()?.()\n }\n\n // Mark as false so next pending request can be triggered by new loop.\n bucket.processing = false\n },\n\n handleCompletedRequest: function (code, sharedScope) {\n // Since request is complete, we can remove one from requested.\n bucket.activeRequests -= 1\n // Since it is as a valid request, we don't need to do anything\n if (!bucket.errorStatuses.includes(code)) return\n // Shared scope is not considered invalid\n if (code === 429 && sharedScope) return\n\n // INVALID REQUEST WAS MADE\n if (bucket.resetAt === undefined) {\n bucket.resetAt = Date.now() + bucket.interval\n }\n\n bucket.invalidRequests += 1\n logger.warn(`[InvalidBucket] an invalid request was made. Increasing invalidRequests count to ${bucket.invalidRequests}`)\n },\n }\n\n return bucket\n}\n\nexport interface InvalidRequestBucketOptions {\n /** current invalid amount */\n current?: number\n /** max invalid requests allowed until ban. Defaults to 10,000 */\n max?: number\n /** The time that discord allows to make the max number of invalid requests. Defaults to 10 minutes */\n interval?: number\n /** When the timeout for the bucket has started at. */\n resetAt?: number\n /** how safe to be from max. Defaults to 1 */\n safety?: number\n /** The request statuses that count as an invalid request. */\n errorStatuses?: number[]\n /** The amount of requests that were requested from this bucket. */\n requested?: number\n}\n\nexport interface InvalidRequestBucket {\n /** current invalid amount */\n invalidRequests: number\n /** max invalid requests allowed until ban. Defaults to 10,000 */\n max: number\n /** The time that discord allows to make the max number of invalid requests. Defaults to 10 minutes */\n interval: number\n /** When the timeout for this bucket has started at. */\n resetAt: number | undefined\n /** how safe to be from max. Defaults to 1 */\n safety: number\n /** The request statuses that count as an invalid request. */\n errorStatuses: number[]\n /** The amount of requests that were requested from this bucket. */\n activeRequests: number\n /** The requests that are currently pending. */\n waiting: Array<(value: void | PromiseLike<void>) => void>\n /** Whether or not the waiting queue is already processing. */\n processing: boolean\n\n /** Gives the number of requests that are currently allowed. */\n requestsAllowed: () => number\n /** Checks if a request is allowed at this time. */\n isRequestAllowed: () => boolean\n /** Waits until a request is available */\n waitUntilRequestAvailable: () => Promise<void>\n /** Begins processing the waiting queue of requests. */\n processWaiting: () => Promise<void>\n /** Handler for whenever a request is validated. This should update the requested values or trigger any other necessary stuff. */\n handleCompletedRequest: (code: number, sharedScope: boolean) => void\n}\n"],"names":["delay","logger","createInvalidRequestBucket","options","bucket","invalidRequests","current","max","interval","resetAt","safety","errorStatuses","activeRequests","requested","processing","waiting","requestsAllowed","undefined","Date","now","isRequestAllowed","waitUntilRequestAvailable","Promise","resolve","push","processWaiting","length","info","JSON","stringify","warn","shift","handleCompletedRequest","code","sharedScope","includes"],"mappings":"AAAA,SAASA,KAAK,EAAEC,MAAM,QAAQ,oBAAmB;AAEjD;;;;;;CAMC,GACD,OAAO,SAASC,2BAA2BC,OAAoC,EAAwB;IACrG,MAAMC,SAA+B;QACnCC,iBAAiBF,QAAQG,OAAO,IAAI;QACpCC,KAAKJ,QAAQI,GAAG,IAAI;QACpBC,UAAUL,QAAQK,QAAQ,IAAI;QAC9BC,SAASN,QAAQM,OAAO;QACxBC,QAAQP,QAAQO,MAAM,IAAI;QAC1BC,eAAeR,QAAQQ,aAAa,IAAI;YAAC;YAAK;YAAK;SAAI;QACvDC,gBAAgBT,QAAQU,SAAS,IAAI;QACrCC,YAAY,KAAK;QAEjBC,SAAS,EAAE;QAEXC,iBAAiB,WAAY;YAC3B,IAAIZ,OAAOK,OAAO,KAAKQ,aAAaC,KAAKC,GAAG,MAAMf,OAAOK,OAAO,EAAE;gBAChEL,OAAOC,eAAe,GAAG;gBACzBD,OAAOK,OAAO,GAAGS,KAAKC,GAAG,KAAKf,OAAOI,QAAQ;YAC/C,CAAC;YAED,OAAOJ,OAAOG,GAAG,GAAGH,OAAOC,eAAe,GAAGD,OAAOQ,cAAc,GAAGR,OAAOM,MAAM;QACpF;QAEAU,kBAAkB,WAAY;YAC5B,OAAOhB,OAAOY,eAAe,KAAK;QACpC;QAEAK,2BAA2B,iBAAkB;YAC3C,qDAAqD;YACrD,OAAO,MAAM,IAAIC,QAAQ,OAAOC,UAAY;gBAC1C,2FAA2F;gBAC3F,IAAInB,OAAOgB,gBAAgB,IAAI;oBAC7BhB,OAAOQ,cAAc,IAAI;oBACzBW;gBACF,OAAO;oBACLnB,OAAOW,OAAO,CAACS,IAAI,CAACD;oBACpB,MAAMnB,OAAOqB,cAAc;gBAC7B,CAAC;YACH;QACF;QAEAA,gBAAgB,iBAAkB;YAChC,qEAAqE;YACrE,IAAIrB,OAAOU,UAAU,EAAE;YAEvB,gDAAgD;YAChDV,OAAOU,UAAU,GAAG,IAAI;YAExB,MAAOV,OAAOW,OAAO,CAACW,MAAM,GAAG,EAAG;gBAChCzB,OAAO0B,IAAI,CACT,CAAC,6DAA6D,EAAEvB,OAAOW,OAAO,CAACW,MAAM,CAAC,8BAA8B,EAAEE,KAAKC,SAAS,CAClIzB,QACA,CAAC;gBAGL,IAAI,CAACA,OAAOgB,gBAAgB,MAAMhB,OAAOK,OAAO,KAAKQ,WAAW;oBAC9DhB,OAAO6B,IAAI,CACT,CAAC,0FAA0F,EACzF1B,OAAOW,OAAO,CAACW,MAAM,CACtB,mBAAmB,EAAEE,KAAKC,SAAS,CAACzB,QAAQ,CAAC;oBAEhD,MAAMJ,MAAMI,OAAOK,OAAO,GAAGS,KAAKC,GAAG;gBACvC,CAAC;gBAEDf,OAAOQ,cAAc,IAAI;gBACzB,qCAAqC;gBACrCR,OAAOW,OAAO,CAACgB,KAAK;YACtB;YAEA,sEAAsE;YACtE3B,OAAOU,UAAU,GAAG,KAAK;QAC3B;QAEAkB,wBAAwB,SAAUC,IAAI,EAAEC,WAAW,EAAE;YACnD,+DAA+D;YAC/D9B,OAAOQ,cAAc,IAAI;YACzB,+DAA+D;YAC/D,IAAI,CAACR,OAAOO,aAAa,CAACwB,QAAQ,CAACF,OAAO;YAC1C,yCAAyC;YACzC,IAAIA,SAAS,OAAOC,aAAa;YAEjC,2BAA2B;YAC3B,IAAI9B,OAAOK,OAAO,KAAKQ,WAAW;gBAChCb,OAAOK,OAAO,GAAGS,KAAKC,GAAG,KAAKf,OAAOI,QAAQ;YAC/C,CAAC;YAEDJ,OAAOC,eAAe,IAAI;YAC1BJ,OAAO6B,IAAI,CAAC,CAAC,iFAAiF,EAAE1B,OAAOC,eAAe,CAAC,CAAC;QAC1H;IACF;IAEA,OAAOD;AACT,CAAC"}
@@ -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,CAuqChF"}
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,4 +1,5 @@
1
- /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable no-const-assign */ import { calculateBits, camelToSnakeCase, camelize, delay, getBotIdFromToken, logger, processReactionString, urlToBase64, snakelize } from '@discordeno/utils';
1
+ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable no-const-assign */ import { Buffer } from 'node:buffer';
2
+ import { calculateBits, camelize, camelToSnakeCase, delay, getBotIdFromToken, logger, processReactionString, urlToBase64 } from '@discordeno/utils';
2
3
  import { createInvalidRequestBucket } from './invalidBucket.js';
3
4
  import { Queue } from './queue.js';
4
5
  import { InteractionResponseTypes } from '@discordeno/types';
@@ -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) {
@@ -62,10 +70,10 @@ export function createRestManager(options) {
62
70
  case 'permissions':
63
71
  case 'allow':
64
72
  case 'deny':
65
- newObj[key] = calculateBits(value);
73
+ newObj[key] = typeof value === 'string' ? value : calculateBits(value);
66
74
  continue;
67
75
  case 'defaultMemberPermissions':
68
- newObj.default_member_permissions = calculateBits(value);
76
+ newObj.default_member_permissions = typeof value === 'string' ? value : calculateBits(value);
69
77
  continue;
70
78
  case 'nameLocalizations':
71
79
  newObj.name_localizations = value;
@@ -83,10 +91,8 @@ export function createRestManager(options) {
83
91
  return obj;
84
92
  },
85
93
  createRequestBody (method, options) {
86
- const headers = {
87
- 'user-agent': `DiscordBot (https://github.com/discordeno/discordeno, v${version})`
88
- };
89
- if (options?.unauthorized !== false) headers.authorization = `Bot ${rest.token}`;
94
+ const headers = this.createBaseHeaders();
95
+ if (options?.unauthorized !== true) headers.authorization = `Bot ${rest.token}`;
90
96
  // IF A REASON IS PROVIDED ENCODE IT IN HEADERS
91
97
  if (options?.reason !== undefined) {
92
98
  headers[AUDIT_LOG_REASON_HEADER] = encodeURIComponent(options?.reason);
@@ -100,12 +106,21 @@ export function createRestManager(options) {
100
106
  for(let i = 0; i < options.files.length; ++i){
101
107
  form.append(`file${i}`, options.files[i].blob, options.files[i].name);
102
108
  }
103
- form.append('payload_json', JSON.stringify(snakelize({
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({
104
111
  ...options.body,
105
112
  files: undefined
106
113
  })));
114
+ // No need to set the `content-type` header since `fetch` does that automatically for us when we use a `FormData` object.
107
115
  body = form;
108
- // 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('&');
109
124
  } else if (options?.body !== undefined) {
110
125
  if (options.body instanceof FormData) {
111
126
  body = options.body;
@@ -152,7 +167,7 @@ export function createRestManager(options) {
152
167
  }, 1000);
153
168
  }
154
169
  },
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) {
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) {
156
171
  let rateLimited = false;
157
172
  // GET ALL NECESSARY HEADERS
158
173
  const remaining = headers.get(RATE_LIMIT_REMAINING_HEADER);
@@ -162,7 +177,7 @@ export function createRestManager(options) {
162
177
  // undefined override null needed for typings
163
178
  const bucketId = headers.get(RATE_LIMIT_BUCKET_HEADER) ?? undefined;
164
179
  const limit = headers.get(RATE_LIMIT_LIMIT_HEADER);
165
- rest.queues.get(url)?.handleCompletedRequest({
180
+ rest.queues.get(`${requestAuthorization}${url}`)?.handleCompletedRequest({
166
181
  remaining: remaining ? Number(remaining) : undefined,
167
182
  interval: retryAfter ? Number(retryAfter) * 1000 : undefined,
168
183
  max: limit ? Number(limit) : undefined
@@ -171,14 +186,14 @@ export function createRestManager(options) {
171
186
  if (remaining === '0') {
172
187
  rateLimited = true;
173
188
  // SAVE THE URL AS LIMITED, IMPORTANT FOR NEW REQUESTS BY USER WITHOUT BUCKET
174
- rest.rateLimitedPaths.set(url, {
189
+ rest.rateLimitedPaths.set(`${requestAuthorization}${url}`, {
175
190
  url,
176
191
  resetTimestamp: reset,
177
192
  bucketId
178
193
  });
179
194
  // SAVE THE BUCKET AS LIMITED SINCE DIFFERENT URLS MAY SHARE A BUCKET
180
195
  if (bucketId) {
181
- rest.rateLimitedPaths.set(bucketId, {
196
+ rest.rateLimitedPaths.set(`${requestAuthorization}${bucketId}`, {
182
197
  url,
183
198
  resetTimestamp: reset,
184
199
  bucketId
@@ -187,8 +202,8 @@ export function createRestManager(options) {
187
202
  }
188
203
  // IF THERE IS NO REMAINING GLOBAL LIMIT, MARK IT RATE LIMITED GLOBALLY
189
204
  if (global) {
190
- const retryAfter = headers.get('retry-after');
191
- const globalReset = Date.now() + Number(retryAfter) * 1000;
205
+ const retryAfter = Number(headers.get('retry-after')) * 1000;
206
+ const globalReset = Date.now() + retryAfter;
192
207
  // rest.debug(
193
208
  // `[REST = Globally Rate Limited] URL: ${url} | Global Rest: ${globalReset}`
194
209
  // )
@@ -196,14 +211,14 @@ export function createRestManager(options) {
196
211
  rateLimited = true;
197
212
  setTimeout(()=>{
198
213
  rest.globallyRateLimited = false;
199
- }, globalReset);
214
+ }, retryAfter);
200
215
  rest.rateLimitedPaths.set('global', {
201
216
  url: 'global',
202
217
  resetTimestamp: globalReset,
203
218
  bucketId
204
219
  });
205
220
  if (bucketId) {
206
- rest.rateLimitedPaths.set(bucketId, {
221
+ rest.rateLimitedPaths.set(`${requestAuthorization}${bucketId}`, {
207
222
  url: 'global',
208
223
  resetTimestamp: globalReset,
209
224
  bucketId
@@ -218,12 +233,16 @@ export function createRestManager(options) {
218
233
  async sendRequest (options) {
219
234
  const url = `${rest.baseUrl}/v${rest.version}${options.route}`;
220
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
+ }
221
243
  logger.debug(`sending request to ${url}`, 'with payload:', {
222
244
  ...payload,
223
- headers: {
224
- ...payload.headers,
225
- authorization: 'Bot tokenhere'
226
- }
245
+ headers: loggingHeaders
227
246
  });
228
247
  const response = await fetch(url, payload).catch(async (error)=>{
229
248
  logger.error(error);
@@ -240,7 +259,7 @@ export function createRestManager(options) {
240
259
  // Mark request and completed
241
260
  rest.invalidBucket.handleCompletedRequest(response.status, response.headers.get(RATE_LIMIT_SCOPE_HEADER) === 'shared');
242
261
  // Set the bucket id if it was available on the headers
243
- 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 : '');
244
263
  if (bucketId) options.bucketId = bucketId;
245
264
  if (response.status < 200 || response.status >= 400) {
246
265
  logger.debug(`Request to ${url} failed.`);
@@ -305,19 +324,21 @@ export function createRestManager(options) {
305
324
  await rest.sendRequest(request);
306
325
  return;
307
326
  }
308
- const queue = rest.queues.get(url);
327
+ const authHeader = request.requestBodyOptions?.headers?.authorization ?? '';
328
+ const queue = rest.queues.get(`${authHeader}${url}`);
309
329
  if (queue !== undefined) {
310
330
  queue.makeRequest(request);
311
331
  } else {
312
332
  // CREATES A NEW QUEUE
313
333
  const bucketQueue = new Queue(rest, {
314
334
  url,
315
- deleteQueueDelay: rest.deleteQueueDelay
335
+ deleteQueueDelay: rest.deleteQueueDelay,
336
+ authentication: authHeader
316
337
  });
317
338
  // Add request to queue
318
339
  bucketQueue.makeRequest(request);
319
340
  // Save queue
320
- rest.queues.set(url, bucketQueue);
341
+ rest.queues.set(`${authHeader}${url}`, bucketQueue);
321
342
  }
322
343
  },
323
344
  async makeRequest (method, route, options) {
@@ -325,7 +346,7 @@ export function createRestManager(options) {
325
346
  if (rest.authorization !== undefined) {
326
347
  options ??= {};
327
348
  options.headers ??= {};
328
- options.headers.authorization = rest.authorization;
349
+ options.headers[rest.authorizationHeader] = rest.authorization;
329
350
  }
330
351
  const result = await fetch(`${rest.baseUrl}/v${rest.version}${route}`, rest.createRequestBody(method, options));
331
352
  if (!result.ok) {
@@ -393,6 +414,11 @@ export function createRestManager(options) {
393
414
  async addThreadMember (channelId, userId) {
394
415
  await rest.put(rest.routes.channels.threads.user(channelId, userId));
395
416
  },
417
+ async addDmRecipient (channelId, userId, body) {
418
+ await rest.put(rest.routes.channels.dmRecipient(channelId, userId), {
419
+ body
420
+ });
421
+ },
396
422
  async createAutomodRule (guildId, body, reason) {
397
423
  return await rest.post(rest.routes.guilds.automod.rules(guildId), {
398
424
  body,
@@ -411,20 +437,34 @@ export function createRestManager(options) {
411
437
  reason
412
438
  });
413
439
  },
414
- async createGlobalApplicationCommand (body) {
415
- return await rest.post(rest.routes.interactions.commands.commands(rest.applicationId), {
440
+ async createGlobalApplicationCommand (body, options) {
441
+ const restOptions = {
416
442
  body
417
- });
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);
418
451
  },
419
452
  async createGuild (body) {
420
453
  return await rest.post(rest.routes.guilds.all(), {
421
454
  body
422
455
  });
423
456
  },
424
- async createGuildApplicationCommand (body, guildId) {
425
- return await rest.post(rest.routes.interactions.commands.guilds.all(rest.applicationId, guildId), {
457
+ async createGuildApplicationCommand (body, guildId, options) {
458
+ const restOptions = {
426
459
  body
427
- });
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);
428
468
  },
429
469
  async createGuildFromTemplate (templateCode, body) {
430
470
  if (body.icon) {
@@ -617,7 +657,7 @@ export function createRestManager(options) {
617
657
  },
618
658
  async editBotProfile (options) {
619
659
  const avatar = options?.botAvatarURL ? await urlToBase64(options?.botAvatarURL) : options?.botAvatarURL;
620
- return await rest.patch(rest.routes.userBot(), {
660
+ return await rest.patch(rest.routes.currentUser(), {
621
661
  body: {
622
662
  username: options.username?.trim(),
623
663
  avatar
@@ -794,14 +834,62 @@ export function createRestManager(options) {
794
834
  async getActiveThreads (guildId) {
795
835
  return await rest.get(rest.routes.channels.threads.active(guildId));
796
836
  },
797
- async getApplicationCommandPermission (guildId, commandId) {
798
- return await rest.get(rest.routes.interactions.commands.permission(rest.applicationId, guildId, commandId));
799
- },
800
- async getApplicationCommandPermissions (guildId) {
801
- 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);
802
856
  },
803
857
  async getApplicationInfo () {
804
- 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
+ });
805
893
  },
806
894
  async getAuditLog (guildId, options) {
807
895
  return await rest.get(rest.routes.guilds.auditlogs(guildId, options));
@@ -840,6 +928,11 @@ export function createRestManager(options) {
840
928
  }
841
929
  });
842
930
  },
931
+ async getGroupDmChannel (body) {
932
+ return await rest.post(rest.routes.channels.dm(), {
933
+ body
934
+ });
935
+ },
843
936
  async getEmoji (guildId, emojiId) {
844
937
  return await rest.get(rest.routes.guilds.emoji(guildId, emojiId));
845
938
  },
@@ -865,6 +958,14 @@ export function createRestManager(options) {
865
958
  }) {
866
959
  return await rest.get(rest.routes.guilds.guild(guildId, options.counts));
867
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
+ },
868
969
  async getGuildApplicationCommand (commandId, guildId) {
869
970
  return await rest.get(rest.routes.interactions.commands.guilds.one(rest.applicationId, guildId, commandId));
870
971
  },
@@ -960,6 +1061,30 @@ export function createRestManager(options) {
960
1061
  async getUser (id) {
961
1062
  return await rest.get(rest.routes.user(id));
962
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
+ },
963
1088
  async getVanityUrl (guildId) {
964
1089
  return await rest.get(rest.routes.guilds.vanity(guildId));
965
1090
  },
@@ -1004,6 +1129,9 @@ export function createRestManager(options) {
1004
1129
  async removeThreadMember (channelId, userId) {
1005
1130
  await rest.delete(rest.routes.channels.threads.user(channelId, userId));
1006
1131
  },
1132
+ async removeDmRecipient (channelId, userId) {
1133
+ await rest.delete(rest.routes.channels.dmRecipient(channelId, userId));
1134
+ },
1007
1135
  async sendFollowupMessage (token, options) {
1008
1136
  return await rest.post(rest.routes.webhooks.webhook(rest.applicationId, token), {
1009
1137
  body: options,
@@ -1061,6 +1189,14 @@ export function createRestManager(options) {
1061
1189
  async getMember (guildId, userId) {
1062
1190
  return await rest.get(rest.routes.guilds.members.member(guildId, userId));
1063
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
+ },
1064
1200
  async getMembers (guildId, options) {
1065
1201
  return await rest.get(rest.routes.guilds.members.members(guildId, options));
1066
1202
  },
@@ -1096,13 +1232,41 @@ export function createRestManager(options) {
1096
1232
  async triggerTypingIndicator (channelId) {
1097
1233
  await rest.post(rest.routes.channels.typing(channelId));
1098
1234
  },
1099
- async upsertGlobalApplicationCommands (body) {
1100
- return await rest.put(rest.routes.interactions.commands.commands(rest.applicationId), {
1235
+ async upsertGlobalApplicationCommands (body, options) {
1236
+ const restOptions = {
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 = {
1101
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
1102
1266
  });
1103
1267
  },
1104
- async upsertGuildApplicationCommands (guildId, body) {
1105
- 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), {
1106
1270
  body
1107
1271
  });
1108
1272
  },