@discordeno/utils 19.0.0-next.0b02607 → 19.0.0-next.0b93eed

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/bucket.d.ts CHANGED
@@ -9,7 +9,7 @@ export declare class LeakyBucket implements LeakyBucketOptions {
9
9
  queue: Array<(value: void | PromiseLike<void>) => void>;
10
10
  /** Whether or not the queue is already processing. */
11
11
  processing: boolean;
12
- /** The timeout id for the timer to reduce the used amount by the refill amount. */
12
+ /** The timeout id for the timer to reduce the used amount by the refill amount. */
13
13
  timeoutId?: NodeJS.Timeout;
14
14
  /** The timestamp in milliseconds when the next refill is scheduled. */
15
15
  refillsAt?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"bucket.d.ts","sourceRoot":"","sources":["../src/bucket.ts"],"names":[],"mappings":";AAGA,qBAAa,WAAY,YAAW,kBAAkB;IACpD,GAAG,EAAE,MAAM,CAAA;IACX,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IAEpB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAI;IAChB,4FAA4F;IAC5F,KAAK,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAK;IAC5D,sDAAsD;IACtD,UAAU,EAAE,OAAO,CAAQ;IAC3B,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC,OAAO,CAAA;IAC1B,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;gBAEN,OAAO,CAAC,EAAE,kBAAkB;IAMxC,gDAAgD;IAChD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,oCAAoC;IACpC,YAAY,IAAI,IAAI;IAgBpB,kCAAkC;IAC5B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA0CnC,sEAAsE;IAChE,OAAO,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAWrD;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB"}
1
+ {"version":3,"file":"bucket.d.ts","sourceRoot":"","sources":["../src/bucket.ts"],"names":[],"mappings":";AAGA,qBAAa,WAAY,YAAW,kBAAkB;IACpD,GAAG,EAAE,MAAM,CAAA;IACX,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IAEpB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAI;IAChB,4FAA4F;IAC5F,KAAK,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAK;IAC5D,sDAAsD;IACtD,UAAU,EAAE,OAAO,CAAQ;IAC3B,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC,OAAO,CAAA;IAC1B,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;gBAEN,OAAO,CAAC,EAAE,kBAAkB;IAMxC,gDAAgD;IAChD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,oCAAoC;IACpC,YAAY,IAAI,IAAI;IAkBpB,kCAAkC;IAC5B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAmDnC,sEAAsE;IAChE,OAAO,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAWrD;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB"}
package/dist/bucket.js CHANGED
@@ -18,8 +18,10 @@ export class LeakyBucket {
18
18
  this.used = this.refillAmount > this.used ? 0 : this.used - this.refillAmount;
19
19
  // Reset the refillsAt timestamp since it just got refilled
20
20
  this.refillsAt = undefined;
21
+ // Reset the timeoutId
22
+ clearTimeout(this.timeoutId);
23
+ this.timeoutId = undefined;
21
24
  if (this.used > 0) {
22
- if (this.timeoutId) clearTimeout(this.timeoutId);
23
25
  this.timeoutId = setTimeout(()=>{
24
26
  this.refillBucket();
25
27
  }, this.refillInterval);
@@ -27,9 +29,10 @@ export class LeakyBucket {
27
29
  }
28
30
  }
29
31
  /** Begin processing the queue. */ async processQueue() {
30
- logger.debug('[Gateway] Processing queue');
32
+ logger.debug('[LeakyBucket] Processing queue');
31
33
  // There is already a queue that is processing
32
- if (this.processing) return logger.debug('[Gateway] Queue is already processing.');
34
+ if (this.processing) return logger.debug('[LeakyBucket] Queue is already processing.');
35
+ this.processing = true;
33
36
  // Begin going through the queue.
34
37
  while(this.queue.length){
35
38
  if (this.remaining) {
@@ -54,6 +57,9 @@ export class LeakyBucket {
54
57
  logger.debug(`[LeakyBucket] Delaying execution of leaky bucket requests for ${this.refillsAt - now}ms`);
55
58
  await delay(this.refillsAt - now);
56
59
  logger.debug(`[LeakyBucket] Resuming execution`);
60
+ } else {
61
+ logger.debug(`[LeakyBucket] Delaying execution of leaky bucket requests for 1000ms`);
62
+ await delay(1000);
57
63
  }
58
64
  }
59
65
  }
@@ -65,7 +71,7 @@ export class LeakyBucket {
65
71
  // High priority requests get added to the start of the queue
66
72
  if (highPriority) this.queue.unshift(resolve);
67
73
  else this.queue.push(resolve);
68
- // Each request should trigger the queue to be processesd.
74
+ // Each request should trigger the queue to be processed.
69
75
  void this.processQueue();
70
76
  });
71
77
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bucket.ts"],"sourcesContent":["import logger from './logger.js'\nimport { delay } from './utils.js'\n\nexport class LeakyBucket implements LeakyBucketOptions {\n max: number\n refillInterval: number\n refillAmount: number\n\n /** The amount of requests that have been used up already. */\n used: number = 0\n /** The queue of requests to acquire an available request. Mapped by <shardId, resolve()> */\n queue: Array<(value: void | PromiseLike<void>) => void> = []\n /** Whether or not the queue is already processing. */\n processing: boolean = false\n /** The timeout id for the timer to reduce the used amount by the refill amount. */\n timeoutId?: NodeJS.Timeout\n /** The timestamp in milliseconds when the next refill is scheduled. */\n refillsAt?: number\n\n constructor(options?: LeakyBucketOptions) {\n this.max = options?.max ?? 1\n this.refillAmount = options?.refillAmount ? (options.refillAmount > this.max ? this.max : options.refillAmount) : 1\n this.refillInterval = options?.refillInterval ?? 5000\n }\n\n /** The amount of requests that still remain. */\n get remaining(): number {\n return this.max < this.used ? 0 : this.max - this.used\n }\n\n /** Refills the bucket as needed. */\n refillBucket(): void {\n logger.debug(`[LeakyBucket] Timeout for leaky bucket requests executed. Refilling bucket.`)\n // Lower the used amount by the refill amount\n this.used = this.refillAmount > this.used ? 0 : this.used - this.refillAmount\n // Reset the refillsAt timestamp since it just got refilled\n this.refillsAt = undefined\n\n if (this.used > 0) {\n if (this.timeoutId) clearTimeout(this.timeoutId)\n this.timeoutId = setTimeout(() => {\n this.refillBucket()\n }, this.refillInterval)\n this.refillsAt = Date.now() + this.refillInterval\n }\n }\n\n /** Begin processing the queue. */\n async processQueue(): Promise<void> {\n logger.debug('[Gateway] Processing queue')\n // There is already a queue that is processing\n if (this.processing) return logger.debug('[Gateway] Queue is already processing.')\n\n // Begin going through the queue.\n while (this.queue.length) {\n if (this.remaining) {\n logger.debug(`[LeakyBucket] Processing queue. Remaining: ${this.remaining} Length: ${this.queue.length}`)\n // Resolves the promise allowing the paused execution of this request to resolve and continue.\n this.queue.shift()?.()\n // A request can be made\n this.used++\n\n // Create a new timeout for this request if none exists.\n if (!this.timeoutId) {\n logger.debug(`[LeakyBucket] Creating new timeout for leaky bucket requests.`)\n\n this.timeoutId = setTimeout(() => {\n this.refillBucket()\n }, this.refillInterval)\n // Set the time for when this refill will occur.\n this.refillsAt = Date.now() + this.refillInterval\n }\n }\n\n // Check if a refill is scheduled, since we have used up all available requests\n else if (this.refillsAt) {\n const now = Date.now()\n // If there is time left until next refill, just delay execution.\n if (this.refillsAt > now) {\n logger.debug(`[LeakyBucket] Delaying execution of leaky bucket requests for ${this.refillsAt - now}ms`)\n await delay(this.refillsAt - now)\n logger.debug(`[LeakyBucket] Resuming execution`)\n }\n }\n }\n\n // Loop has ended mark false so it can restart later when needed\n this.processing = false\n }\n\n /** Pauses the execution until the request is available to be made. */\n async acquire(highPriority?: boolean): Promise<void> {\n return await new Promise((resolve) => {\n // High priority requests get added to the start of the queue\n if (highPriority) this.queue.unshift(resolve)\n // All other requests get pushed to the end.\n else this.queue.push(resolve)\n\n // Each request should trigger the queue to be processesd.\n void this.processQueue()\n })\n }\n}\n\nexport interface LeakyBucketOptions {\n /**\n * Max requests allowed at once.\n * @default 1\n */\n max?: number\n /**\n * Interval in milliseconds between refills.\n * @default 5000\n */\n refillInterval?: number\n /**\n * Amount of requests to refill at each interval.\n * @default 1\n */\n refillAmount?: number\n}\n"],"names":["logger","delay","LeakyBucket","constructor","options","used","queue","processing","max","refillAmount","refillInterval","remaining","refillBucket","debug","refillsAt","undefined","timeoutId","clearTimeout","setTimeout","Date","now","processQueue","length","shift","acquire","highPriority","Promise","resolve","unshift","push"],"mappings":"AAAA,OAAOA,YAAY,cAAa;AAChC,SAASC,KAAK,QAAQ,aAAY;AAElC,OAAO,MAAMC;IAgBXC,YAAYC,OAA4B,CAAE;QAX1C,2DAA2D,QAC3DC,OAAe;QACf,0FAA0F,QAC1FC,QAA0D,EAAE;QAC5D,oDAAoD,QACpDC,aAAsB,KAAK;QAOzB,IAAI,CAACC,GAAG,GAAGJ,SAASI,OAAO;QAC3B,IAAI,CAACC,YAAY,GAAGL,SAASK,eAAgBL,QAAQK,YAAY,GAAG,IAAI,CAACD,GAAG,GAAG,IAAI,CAACA,GAAG,GAAGJ,QAAQK,YAAY,GAAI,CAAC;QACnH,IAAI,CAACC,cAAc,GAAGN,SAASM,kBAAkB;IACnD;IAEA,8CAA8C,GAC9C,IAAIC,YAAoB;QACtB,OAAO,IAAI,CAACH,GAAG,GAAG,IAAI,CAACH,IAAI,GAAG,IAAI,IAAI,CAACG,GAAG,GAAG,IAAI,CAACH,IAAI;IACxD;IAEA,kCAAkC,GAClCO,eAAqB;QACnBZ,OAAOa,KAAK,CAAC,CAAC,2EAA2E,CAAC;QAC1F,6CAA6C;QAC7C,IAAI,CAACR,IAAI,GAAG,IAAI,CAACI,YAAY,GAAG,IAAI,CAACJ,IAAI,GAAG,IAAI,IAAI,CAACA,IAAI,GAAG,IAAI,CAACI,YAAY;QAC7E,2DAA2D;QAC3D,IAAI,CAACK,SAAS,GAAGC;QAEjB,IAAI,IAAI,CAACV,IAAI,GAAG,GAAG;YACjB,IAAI,IAAI,CAACW,SAAS,EAAEC,aAAa,IAAI,CAACD,SAAS;YAC/C,IAAI,CAACA,SAAS,GAAGE,WAAW,IAAM;gBAChC,IAAI,CAACN,YAAY;YACnB,GAAG,IAAI,CAACF,cAAc;YACtB,IAAI,CAACI,SAAS,GAAGK,KAAKC,GAAG,KAAK,IAAI,CAACV,cAAc;QACnD,CAAC;IACH;IAEA,gCAAgC,GAChC,MAAMW,eAA8B;QAClCrB,OAAOa,KAAK,CAAC;QACb,8CAA8C;QAC9C,IAAI,IAAI,CAACN,UAAU,EAAE,OAAOP,OAAOa,KAAK,CAAC;QAEzC,iCAAiC;QACjC,MAAO,IAAI,CAACP,KAAK,CAACgB,MAAM,CAAE;YACxB,IAAI,IAAI,CAACX,SAAS,EAAE;gBAClBX,OAAOa,KAAK,CAAC,CAAC,2CAA2C,EAAE,IAAI,CAACF,SAAS,CAAC,SAAS,EAAE,IAAI,CAACL,KAAK,CAACgB,MAAM,CAAC,CAAC;gBACxG,8FAA8F;gBAC9F,IAAI,CAAChB,KAAK,CAACiB,KAAK;gBAChB,wBAAwB;gBACxB,IAAI,CAAClB,IAAI;gBAET,wDAAwD;gBACxD,IAAI,CAAC,IAAI,CAACW,SAAS,EAAE;oBACnBhB,OAAOa,KAAK,CAAC,CAAC,6DAA6D,CAAC;oBAE5E,IAAI,CAACG,SAAS,GAAGE,WAAW,IAAM;wBAChC,IAAI,CAACN,YAAY;oBACnB,GAAG,IAAI,CAACF,cAAc;oBACtB,gDAAgD;oBAChD,IAAI,CAACI,SAAS,GAAGK,KAAKC,GAAG,KAAK,IAAI,CAACV,cAAc;gBACnD,CAAC;YACH,OAGK,IAAI,IAAI,CAACI,SAAS,EAAE;gBACvB,MAAMM,MAAMD,KAAKC,GAAG;gBACpB,iEAAiE;gBACjE,IAAI,IAAI,CAACN,SAAS,GAAGM,KAAK;oBACxBpB,OAAOa,KAAK,CAAC,CAAC,8DAA8D,EAAE,IAAI,CAACC,SAAS,GAAGM,IAAI,EAAE,CAAC;oBACtG,MAAMnB,MAAM,IAAI,CAACa,SAAS,GAAGM;oBAC7BpB,OAAOa,KAAK,CAAC,CAAC,gCAAgC,CAAC;gBACjD,CAAC;YACH,CAAC;QACH;QAEA,gEAAgE;QAChE,IAAI,CAACN,UAAU,GAAG,KAAK;IACzB;IAEA,oEAAoE,GACpE,MAAMiB,QAAQC,YAAsB,EAAiB;QACnD,OAAO,MAAM,IAAIC,QAAQ,CAACC,UAAY;YACpC,6DAA6D;YAC7D,IAAIF,cAAc,IAAI,CAACnB,KAAK,CAACsB,OAAO,CAACD;iBAEhC,IAAI,CAACrB,KAAK,CAACuB,IAAI,CAACF;YAErB,0DAA0D;YAC1D,KAAK,IAAI,CAACN,YAAY;QACxB;IACF;AACF,CAAC"}
1
+ {"version":3,"sources":["../src/bucket.ts"],"sourcesContent":["import logger from './logger.js'\nimport { delay } from './utils.js'\n\nexport class LeakyBucket implements LeakyBucketOptions {\n max: number\n refillInterval: number\n refillAmount: number\n\n /** The amount of requests that have been used up already. */\n used: number = 0\n /** The queue of requests to acquire an available request. Mapped by <shardId, resolve()> */\n queue: Array<(value: void | PromiseLike<void>) => void> = []\n /** Whether or not the queue is already processing. */\n processing: boolean = false\n /** The timeout id for the timer to reduce the used amount by the refill amount. */\n timeoutId?: NodeJS.Timeout\n /** The timestamp in milliseconds when the next refill is scheduled. */\n refillsAt?: number\n\n constructor(options?: LeakyBucketOptions) {\n this.max = options?.max ?? 1\n this.refillAmount = options?.refillAmount ? (options.refillAmount > this.max ? this.max : options.refillAmount) : 1\n this.refillInterval = options?.refillInterval ?? 5000\n }\n\n /** The amount of requests that still remain. */\n get remaining(): number {\n return this.max < this.used ? 0 : this.max - this.used\n }\n\n /** Refills the bucket as needed. */\n refillBucket(): void {\n logger.debug(`[LeakyBucket] Timeout for leaky bucket requests executed. Refilling bucket.`)\n // Lower the used amount by the refill amount\n this.used = this.refillAmount > this.used ? 0 : this.used - this.refillAmount\n // Reset the refillsAt timestamp since it just got refilled\n this.refillsAt = undefined\n // Reset the timeoutId\n clearTimeout(this.timeoutId)\n this.timeoutId = undefined\n\n if (this.used > 0) {\n this.timeoutId = setTimeout(() => {\n this.refillBucket()\n }, this.refillInterval)\n this.refillsAt = Date.now() + this.refillInterval\n }\n }\n\n /** Begin processing the queue. */\n async processQueue(): Promise<void> {\n logger.debug('[LeakyBucket] Processing queue')\n\n // There is already a queue that is processing\n if (this.processing) return logger.debug('[LeakyBucket] Queue is already processing.')\n\n this.processing = true\n\n // Begin going through the queue.\n while (this.queue.length) {\n if (this.remaining) {\n logger.debug(`[LeakyBucket] Processing queue. Remaining: ${this.remaining} Length: ${this.queue.length}`)\n // Resolves the promise allowing the paused execution of this request to resolve and continue.\n this.queue.shift()?.()\n // A request can be made\n this.used++\n\n // Create a new timeout for this request if none exists.\n if (!this.timeoutId) {\n logger.debug(`[LeakyBucket] Creating new timeout for leaky bucket requests.`)\n\n this.timeoutId = setTimeout(() => {\n this.refillBucket()\n }, this.refillInterval)\n // Set the time for when this refill will occur.\n this.refillsAt = Date.now() + this.refillInterval\n }\n }\n\n // Check if a refill is scheduled, since we have used up all available requests\n else if (this.refillsAt) {\n const now = Date.now()\n // If there is time left until next refill, just delay execution.\n if (this.refillsAt > now) {\n logger.debug(`[LeakyBucket] Delaying execution of leaky bucket requests for ${this.refillsAt - now}ms`)\n await delay(this.refillsAt - now)\n logger.debug(`[LeakyBucket] Resuming execution`)\n }\n\n // If the refillsAt has passed but the timeout didn't yet execute delay the execution\n else {\n logger.debug(`[LeakyBucket] Delaying execution of leaky bucket requests for 1000ms`)\n await delay(1000)\n }\n }\n }\n\n // Loop has ended mark false so it can restart later when needed\n this.processing = false\n }\n\n /** Pauses the execution until the request is available to be made. */\n async acquire(highPriority?: boolean): Promise<void> {\n return await new Promise((resolve) => {\n // High priority requests get added to the start of the queue\n if (highPriority) this.queue.unshift(resolve)\n // All other requests get pushed to the end.\n else this.queue.push(resolve)\n\n // Each request should trigger the queue to be processed.\n void this.processQueue()\n })\n }\n}\n\nexport interface LeakyBucketOptions {\n /**\n * Max requests allowed at once.\n * @default 1\n */\n max?: number\n /**\n * Interval in milliseconds between refills.\n * @default 5000\n */\n refillInterval?: number\n /**\n * Amount of requests to refill at each interval.\n * @default 1\n */\n refillAmount?: number\n}\n"],"names":["logger","delay","LeakyBucket","constructor","options","used","queue","processing","max","refillAmount","refillInterval","remaining","refillBucket","debug","refillsAt","undefined","clearTimeout","timeoutId","setTimeout","Date","now","processQueue","length","shift","acquire","highPriority","Promise","resolve","unshift","push"],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import type { DiscordEmbed, DiscordEmbedAuthor, DiscordEmbedField, DiscordEmbedFooter, DiscordEmbedImage, DiscordEmbedThumbnail, DiscordEmbedVideo } from '@discordeno/types';
2
+ /**
3
+ * A builder to help create Discord embeds.
4
+ *
5
+ * @export
6
+ * @class EmbedsBuilder
7
+ * @typedef {EmbedsBuilder}
8
+ * @extends {Array<DiscordEmbed>}
9
+ * @example
10
+ * const embeds = new EmbedBuilder()
11
+ * .setTitle('My Embed')
12
+ * .setDescription('This is my new embed')
13
+ * .newEmbed()
14
+ * .setTitle('My Second Embed')
15
+ */
16
+ export declare class EmbedsBuilder extends Array<DiscordEmbed> {
17
+ #private;
18
+ /**
19
+ * Adds a new field to the embed fields array.
20
+ *
21
+ * @param {string} name - Field name
22
+ * @param {string} value - Field value
23
+ * @param {?boolean} [inline=false] - Field should be inline or not.
24
+ * @returns {EmbedsBuilder}
25
+ */
26
+ addField(name: string, value: string, inline?: boolean): EmbedsBuilder;
27
+ /**
28
+ * Creates a blank embed.
29
+ *
30
+ * @returns {EmbedsBuilder}
31
+ */
32
+ newEmbed(): EmbedsBuilder;
33
+ /**
34
+ * Set the current embed author.
35
+ *
36
+ * @param {string} name - Name of the author
37
+ * @param {?Omit<DiscordEmbedAuthor, 'name'>} [options] - Extra author options
38
+ * @returns {EmbedsBuilder}
39
+ */
40
+ setAuthor(name: string, options?: Omit<DiscordEmbedAuthor, 'name'>): EmbedsBuilder;
41
+ /**
42
+ * Set the color on the side of the current embed.
43
+ *
44
+ * @param {(number | string)} color - The color, in base16 or hex color code
45
+ * @returns {EmbedsBuilder}
46
+ */
47
+ setColor(color: number | string): EmbedsBuilder;
48
+ /**
49
+ * Set the current embed to a different index.
50
+ *
51
+ * WARNING: Only use this method if you know what you're doing. Make sure to set it back to the latest when you're done.
52
+ *
53
+ * @param {?number} [index] - The index of the embed in the EmbedsBuilder array
54
+ * @returns {EmbedsBuilder}
55
+ */
56
+ setCurrentEmbed(index?: number): EmbedsBuilder;
57
+ /**
58
+ * Set the description of the current embed.
59
+ *
60
+ * @param {string} description - Description
61
+ * @returns {EmbedsBuilder}
62
+ */
63
+ setDescription(description: string): EmbedsBuilder;
64
+ /**
65
+ * Overwrite all fields on the current embed.
66
+ *
67
+ * @param {DiscordEmbedField[]} fields
68
+ * @returns {EmbedsBuilder}
69
+ */
70
+ setFields(fields: DiscordEmbedField[]): EmbedsBuilder;
71
+ /**
72
+ * Set the footer in the current embed.
73
+ *
74
+ * @param {string} text - The text to display in the footer
75
+ * @param {?Omit<DiscordEmbedFooter, 'text'>} [options]
76
+ * @returns {EmbedsBuilder}
77
+ */
78
+ setFooter(text: string, options?: Omit<DiscordEmbedFooter, 'text'>): EmbedsBuilder;
79
+ /**
80
+ * Set the image in the current embed.
81
+ *
82
+ * @param {string} url - URL of the image
83
+ * @param {?Omit<DiscordEmbedImage, 'url'>} [options]
84
+ * @returns {EmbedsBuilder}
85
+ */
86
+ setImage(url: string, options?: Omit<DiscordEmbedImage, 'url'>): EmbedsBuilder;
87
+ /**
88
+ * Set the provider of the current embed.
89
+ *
90
+ * @param {string} name
91
+ * @param {?string} [url]
92
+ * @returns {EmbedsBuilder}
93
+ */
94
+ setProvider(name: string, url?: string): EmbedsBuilder;
95
+ /**
96
+ * Set the color of the current embed to a random value.
97
+ *
98
+ * @returns {EmbedsBuilder}
99
+ */
100
+ setRandomColor(): EmbedsBuilder;
101
+ /**
102
+ * Set the title of the current embed.
103
+ *
104
+ * @param {string} title
105
+ * @param {?string} [url]
106
+ * @returns {EmbedsBuilder}
107
+ */
108
+ setTitle(title: string, url?: string): EmbedsBuilder;
109
+ /**
110
+ * Set the timestamp of the current embed.
111
+ *
112
+ * @param {?(string | number | Date)} [timestamp]
113
+ * @returns {EmbedsBuilder}
114
+ */
115
+ setTimestamp(timestamp?: string | number | Date): EmbedsBuilder;
116
+ /**
117
+ * Set the thumbnail of the current embed.
118
+ *
119
+ * @param {string} url - URL of the image
120
+ * @param {?Omit<DiscordEmbedThumbnail, 'url'>} [options]
121
+ * @returns {EmbedsBuilder}
122
+ */
123
+ setThumbnail(url: string, options?: Omit<DiscordEmbedThumbnail, 'url'>): EmbedsBuilder;
124
+ /**
125
+ * Set the URL of the current embed title.
126
+ *
127
+ * @param {string} url
128
+ * @returns {EmbedsBuilder}
129
+ */
130
+ setUrl(url: string): EmbedsBuilder;
131
+ /**
132
+ * Set the video of the current embed.
133
+ *
134
+ * @param {string} url
135
+ * @param {?Omit<DiscordEmbedVideo, 'url'>} [options]
136
+ * @returns {EmbedsBuilder}
137
+ */
138
+ setVideo(url: string, options?: Omit<DiscordEmbedVideo, 'url'>): EmbedsBuilder;
139
+ /**
140
+ * Validate all embeds available against current known Discord limits to help prevent bad requests.
141
+ *
142
+ * @returns {EmbedsBuilder}
143
+ */
144
+ validate(): EmbedsBuilder;
145
+ }
146
+ //# sourceMappingURL=embeds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeds.d.ts","sourceRoot":"","sources":["../../src/builders/embeds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,mBAAmB,CAAA;AAE1B;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,SAAQ,KAAK,CAAC,YAAY,CAAC;;IAGpD;;;;;;;OAOG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,aAAa;IActE;;;;OAIG;IACH,QAAQ,IAAI,aAAa;IAWzB;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,GAAG,aAAa;IAUlF;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa;IAW/C;;;;;;;OAOG;IACH,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa;IAgB9C;;;;;OAKG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa;IAMlD;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,iBAAiB,EAAE,GAAG,aAAa;IAMrD;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,GAAG,aAAa;IAUlF;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,GAAG,aAAa;IAU9E;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,aAAa;IAStD;;;;OAIG;IACH,cAAc,IAAI,aAAa;IAI/B;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,aAAa;IAUpD;;;;;OAKG;IACH,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,aAAa;IAM/D;;;;;;OAMG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,KAAK,CAAC,GAAG,aAAa;IAUtF;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa;IAMlC;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,GAAG,aAAa;IAU9E;;;;OAIG;IACH,QAAQ,IAAI,aAAa;CA4F1B"}
@@ -0,0 +1,295 @@
1
+ /**
2
+ * A builder to help create Discord embeds.
3
+ *
4
+ * @export
5
+ * @class EmbedsBuilder
6
+ * @typedef {EmbedsBuilder}
7
+ * @extends {Array<DiscordEmbed>}
8
+ * @example
9
+ * const embeds = new EmbedBuilder()
10
+ * .setTitle('My Embed')
11
+ * .setDescription('This is my new embed')
12
+ * .newEmbed()
13
+ * .setTitle('My Second Embed')
14
+ */ export class EmbedsBuilder extends Array {
15
+ #currentEmbedIndex;
16
+ /**
17
+ * Adds a new field to the embed fields array.
18
+ *
19
+ * @param {string} name - Field name
20
+ * @param {string} value - Field value
21
+ * @param {?boolean} [inline=false] - Field should be inline or not.
22
+ * @returns {EmbedsBuilder}
23
+ */ addField(name, value, inline) {
24
+ if (this.#currentEmbed.fields === undefined) {
25
+ this.#currentEmbed.fields = [];
26
+ }
27
+ this.#currentEmbed.fields.push({
28
+ name,
29
+ value,
30
+ inline
31
+ });
32
+ return this;
33
+ }
34
+ /**
35
+ * Creates a blank embed.
36
+ *
37
+ * @returns {EmbedsBuilder}
38
+ */ newEmbed() {
39
+ if (this.length >= 10) {
40
+ throw new Error('Maximum embed count exceeded. You can not have more than 10 embeds.');
41
+ }
42
+ this.push({});
43
+ this.setCurrentEmbed();
44
+ return this;
45
+ }
46
+ /**
47
+ * Set the current embed author.
48
+ *
49
+ * @param {string} name - Name of the author
50
+ * @param {?Omit<DiscordEmbedAuthor, 'name'>} [options] - Extra author options
51
+ * @returns {EmbedsBuilder}
52
+ */ setAuthor(name, options) {
53
+ this.#currentEmbed.author = {
54
+ ...this.#currentEmbed.author,
55
+ ...options,
56
+ name
57
+ };
58
+ return this;
59
+ }
60
+ /**
61
+ * Set the color on the side of the current embed.
62
+ *
63
+ * @param {(number | string)} color - The color, in base16 or hex color code
64
+ * @returns {EmbedsBuilder}
65
+ */ setColor(color) {
66
+ if (typeof color === 'string') {
67
+ const convertedValue = parseInt(color.replace('#', ''), 16);
68
+ color = Number.isNaN(convertedValue) ? 0 : convertedValue;
69
+ }
70
+ this.#currentEmbed.color = color;
71
+ return this;
72
+ }
73
+ /**
74
+ * Set the current embed to a different index.
75
+ *
76
+ * WARNING: Only use this method if you know what you're doing. Make sure to set it back to the latest when you're done.
77
+ *
78
+ * @param {?number} [index] - The index of the embed in the EmbedsBuilder array
79
+ * @returns {EmbedsBuilder}
80
+ */ setCurrentEmbed(index) {
81
+ if (index === undefined) {
82
+ this.#currentEmbedIndex = this.length - 1;
83
+ return this;
84
+ }
85
+ if (index >= this.length || index < 0) {
86
+ throw new Error('Can not set the current embed to a index out of bounds.');
87
+ }
88
+ this.#currentEmbedIndex = index;
89
+ return this;
90
+ }
91
+ /**
92
+ * Set the description of the current embed.
93
+ *
94
+ * @param {string} description - Description
95
+ * @returns {EmbedsBuilder}
96
+ */ setDescription(description) {
97
+ this.#currentEmbed.description = description;
98
+ return this;
99
+ }
100
+ /**
101
+ * Overwrite all fields on the current embed.
102
+ *
103
+ * @param {DiscordEmbedField[]} fields
104
+ * @returns {EmbedsBuilder}
105
+ */ setFields(fields) {
106
+ this.#currentEmbed.fields = fields;
107
+ return this;
108
+ }
109
+ /**
110
+ * Set the footer in the current embed.
111
+ *
112
+ * @param {string} text - The text to display in the footer
113
+ * @param {?Omit<DiscordEmbedFooter, 'text'>} [options]
114
+ * @returns {EmbedsBuilder}
115
+ */ setFooter(text, options) {
116
+ this.#currentEmbed.footer = {
117
+ ...this.#currentEmbed.footer,
118
+ ...options,
119
+ text
120
+ };
121
+ return this;
122
+ }
123
+ /**
124
+ * Set the image in the current embed.
125
+ *
126
+ * @param {string} url - URL of the image
127
+ * @param {?Omit<DiscordEmbedImage, 'url'>} [options]
128
+ * @returns {EmbedsBuilder}
129
+ */ setImage(url, options) {
130
+ this.#currentEmbed.image = {
131
+ ...this.#currentEmbed.image,
132
+ ...options,
133
+ url
134
+ };
135
+ return this;
136
+ }
137
+ /**
138
+ * Set the provider of the current embed.
139
+ *
140
+ * @param {string} name
141
+ * @param {?string} [url]
142
+ * @returns {EmbedsBuilder}
143
+ */ setProvider(name, url) {
144
+ this.#currentEmbed.provider = {
145
+ name,
146
+ url
147
+ };
148
+ return this;
149
+ }
150
+ /**
151
+ * Set the color of the current embed to a random value.
152
+ *
153
+ * @returns {EmbedsBuilder}
154
+ */ setRandomColor() {
155
+ return this.setColor(Math.floor(Math.random() * (0xffffff + 1)));
156
+ }
157
+ /**
158
+ * Set the title of the current embed.
159
+ *
160
+ * @param {string} title
161
+ * @param {?string} [url]
162
+ * @returns {EmbedsBuilder}
163
+ */ setTitle(title, url) {
164
+ this.#currentEmbed.title = title;
165
+ if (url) {
166
+ this.setUrl(url);
167
+ }
168
+ return this;
169
+ }
170
+ /**
171
+ * Set the timestamp of the current embed.
172
+ *
173
+ * @param {?(string | number | Date)} [timestamp]
174
+ * @returns {EmbedsBuilder}
175
+ */ setTimestamp(timestamp) {
176
+ this.#currentEmbed.timestamp = new Date(timestamp).toISOString();
177
+ return this;
178
+ }
179
+ /**
180
+ * Set the thumbnail of the current embed.
181
+ *
182
+ * @param {string} url - URL of the image
183
+ * @param {?Omit<DiscordEmbedThumbnail, 'url'>} [options]
184
+ * @returns {EmbedsBuilder}
185
+ */ setThumbnail(url, options) {
186
+ this.#currentEmbed.thumbnail = {
187
+ ...this.#currentEmbed.thumbnail,
188
+ ...options,
189
+ url
190
+ };
191
+ return this;
192
+ }
193
+ /**
194
+ * Set the URL of the current embed title.
195
+ *
196
+ * @param {string} url
197
+ * @returns {EmbedsBuilder}
198
+ */ setUrl(url) {
199
+ this.#currentEmbed.url = url;
200
+ return this;
201
+ }
202
+ /**
203
+ * Set the video of the current embed.
204
+ *
205
+ * @param {string} url
206
+ * @param {?Omit<DiscordEmbedVideo, 'url'>} [options]
207
+ * @returns {EmbedsBuilder}
208
+ */ setVideo(url, options) {
209
+ this.#currentEmbed.video = {
210
+ ...this.#currentEmbed.video,
211
+ ...options,
212
+ url
213
+ };
214
+ return this;
215
+ }
216
+ /**
217
+ * Validate all embeds available against current known Discord limits to help prevent bad requests.
218
+ *
219
+ * @returns {EmbedsBuilder}
220
+ */ validate() {
221
+ let totalCharacters = 0;
222
+ if (this.length > 10) {
223
+ throw new Error('You can not have more than 10 embeds on a single message.');
224
+ }
225
+ this.forEach(({ author , description , fields , footer , title }, index)=>{
226
+ if (title) {
227
+ const trimmedTitle = title.trim();
228
+ if (trimmedTitle.length > 256) {
229
+ throw new Error(`Title of embed ${index} can not be longer than 256 characters.`);
230
+ }
231
+ totalCharacters += trimmedTitle.length;
232
+ }
233
+ if (description) {
234
+ const trimmedDescription = description.trim();
235
+ if (trimmedDescription.length > 4096) {
236
+ throw new Error(`Description of embed ${index} can not be longer than 4096 characters.`);
237
+ }
238
+ totalCharacters += trimmedDescription.length;
239
+ }
240
+ if (fields) {
241
+ if (fields.length > 25) {
242
+ throw new Error(`embed ${index} can not have more than 25 fields.`);
243
+ }
244
+ fields.forEach(({ name , value }, fieldIndex)=>{
245
+ const trimmedName = name.trim();
246
+ const trimmedValue = value.trim();
247
+ if (trimmedName.length > 256) {
248
+ throw new Error(`Name of field ${fieldIndex} on embed ${index} can not be longer than 256 characters.`);
249
+ }
250
+ if (trimmedValue.length > 4096) {
251
+ throw new Error(`Value of field ${fieldIndex} on embed ${index} can not be longer than 1024 characters.`);
252
+ }
253
+ totalCharacters += trimmedName.length;
254
+ totalCharacters += trimmedValue.length;
255
+ });
256
+ }
257
+ if (footer) {
258
+ const trimmedFooterText = footer.text.trim();
259
+ if (trimmedFooterText.length > 2048) {
260
+ throw new Error(`Footer text of embed ${index} can not be longer than 2048 characters.`);
261
+ }
262
+ totalCharacters += trimmedFooterText.length;
263
+ }
264
+ if (author) {
265
+ const trimmedAuthorName = author.name.trim();
266
+ if (trimmedAuthorName.length > 256) {
267
+ throw new Error(`Author name of embed ${index} can not be longer than 256 characters.`);
268
+ }
269
+ totalCharacters += trimmedAuthorName.length;
270
+ }
271
+ });
272
+ if (totalCharacters > 6000) {
273
+ throw new Error('Total character length of all embeds can not exceed 6000 characters.');
274
+ }
275
+ return this;
276
+ }
277
+ /**
278
+ * Returns the current embed.
279
+ *
280
+ * @readonly
281
+ * @type {DiscordEmbed}
282
+ */ get #currentEmbed() {
283
+ if (this.length === 0) {
284
+ this.newEmbed();
285
+ this.setCurrentEmbed();
286
+ }
287
+ return this[this.#currentEmbedIndex];
288
+ }
289
+ constructor(...args){
290
+ super(...args);
291
+ this.#currentEmbedIndex = 0;
292
+ }
293
+ }
294
+
295
+ //# sourceMappingURL=embeds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/builders/embeds.ts"],"sourcesContent":["import type {\n DiscordEmbed,\n DiscordEmbedAuthor,\n DiscordEmbedField,\n DiscordEmbedFooter,\n DiscordEmbedImage,\n DiscordEmbedThumbnail,\n DiscordEmbedVideo,\n} from '@discordeno/types'\n\n/**\n * A builder to help create Discord embeds.\n *\n * @export\n * @class EmbedsBuilder\n * @typedef {EmbedsBuilder}\n * @extends {Array<DiscordEmbed>}\n * @example\n * const embeds = new EmbedBuilder()\n * .setTitle('My Embed')\n * .setDescription('This is my new embed')\n * .newEmbed()\n * .setTitle('My Second Embed')\n */\nexport class EmbedsBuilder extends Array<DiscordEmbed> {\n #currentEmbedIndex: number = 0\n\n /**\n * Adds a new field to the embed fields array.\n *\n * @param {string} name - Field name\n * @param {string} value - Field value\n * @param {?boolean} [inline=false] - Field should be inline or not.\n * @returns {EmbedsBuilder}\n */\n addField(name: string, value: string, inline?: boolean): EmbedsBuilder {\n if (this.#currentEmbed.fields === undefined) {\n this.#currentEmbed.fields = []\n }\n\n this.#currentEmbed.fields.push({\n name,\n value,\n inline,\n })\n\n return this\n }\n\n /**\n * Creates a blank embed.\n *\n * @returns {EmbedsBuilder}\n */\n newEmbed(): EmbedsBuilder {\n if (this.length >= 10) {\n throw new Error('Maximum embed count exceeded. You can not have more than 10 embeds.')\n }\n\n this.push({})\n this.setCurrentEmbed()\n\n return this\n }\n\n /**\n * Set the current embed author.\n *\n * @param {string} name - Name of the author\n * @param {?Omit<DiscordEmbedAuthor, 'name'>} [options] - Extra author options\n * @returns {EmbedsBuilder}\n */\n setAuthor(name: string, options?: Omit<DiscordEmbedAuthor, 'name'>): EmbedsBuilder {\n this.#currentEmbed.author = {\n ...this.#currentEmbed.author,\n ...options,\n name,\n }\n\n return this\n }\n\n /**\n * Set the color on the side of the current embed.\n *\n * @param {(number | string)} color - The color, in base16 or hex color code\n * @returns {EmbedsBuilder}\n */\n setColor(color: number | string): EmbedsBuilder {\n if (typeof color === 'string') {\n const convertedValue = parseInt(color.replace('#', ''), 16)\n color = Number.isNaN(convertedValue) ? 0 : convertedValue\n }\n\n this.#currentEmbed.color = color\n\n return this\n }\n\n /**\n * Set the current embed to a different index.\n *\n * WARNING: Only use this method if you know what you're doing. Make sure to set it back to the latest when you're done.\n *\n * @param {?number} [index] - The index of the embed in the EmbedsBuilder array\n * @returns {EmbedsBuilder}\n */\n setCurrentEmbed(index?: number): EmbedsBuilder {\n if (index === undefined) {\n this.#currentEmbedIndex = this.length - 1\n\n return this\n }\n\n if (index >= this.length || index < 0) {\n throw new Error('Can not set the current embed to a index out of bounds.')\n }\n\n this.#currentEmbedIndex = index\n\n return this\n }\n\n /**\n * Set the description of the current embed.\n *\n * @param {string} description - Description\n * @returns {EmbedsBuilder}\n */\n setDescription(description: string): EmbedsBuilder {\n this.#currentEmbed.description = description\n\n return this\n }\n\n /**\n * Overwrite all fields on the current embed.\n *\n * @param {DiscordEmbedField[]} fields\n * @returns {EmbedsBuilder}\n */\n setFields(fields: DiscordEmbedField[]): EmbedsBuilder {\n this.#currentEmbed.fields = fields\n\n return this\n }\n\n /**\n * Set the footer in the current embed.\n *\n * @param {string} text - The text to display in the footer\n * @param {?Omit<DiscordEmbedFooter, 'text'>} [options]\n * @returns {EmbedsBuilder}\n */\n setFooter(text: string, options?: Omit<DiscordEmbedFooter, 'text'>): EmbedsBuilder {\n this.#currentEmbed.footer = {\n ...this.#currentEmbed.footer,\n ...options,\n text,\n }\n\n return this\n }\n\n /**\n * Set the image in the current embed.\n *\n * @param {string} url - URL of the image\n * @param {?Omit<DiscordEmbedImage, 'url'>} [options]\n * @returns {EmbedsBuilder}\n */\n setImage(url: string, options?: Omit<DiscordEmbedImage, 'url'>): EmbedsBuilder {\n this.#currentEmbed.image = {\n ...this.#currentEmbed.image,\n ...options,\n url,\n }\n\n return this\n }\n\n /**\n * Set the provider of the current embed.\n *\n * @param {string} name\n * @param {?string} [url]\n * @returns {EmbedsBuilder}\n */\n setProvider(name: string, url?: string): EmbedsBuilder {\n this.#currentEmbed.provider = {\n name,\n url,\n }\n\n return this\n }\n\n /**\n * Set the color of the current embed to a random value.\n *\n * @returns {EmbedsBuilder}\n */\n setRandomColor(): EmbedsBuilder {\n return this.setColor(Math.floor(Math.random() * (0xffffff + 1)))\n }\n\n /**\n * Set the title of the current embed.\n *\n * @param {string} title\n * @param {?string} [url]\n * @returns {EmbedsBuilder}\n */\n setTitle(title: string, url?: string): EmbedsBuilder {\n this.#currentEmbed.title = title\n\n if (url) {\n this.setUrl(url)\n }\n\n return this\n }\n\n /**\n * Set the timestamp of the current embed.\n *\n * @param {?(string | number | Date)} [timestamp]\n * @returns {EmbedsBuilder}\n */\n setTimestamp(timestamp?: string | number | Date): EmbedsBuilder {\n this.#currentEmbed.timestamp = new Date(timestamp!).toISOString()\n\n return this\n }\n\n /**\n * Set the thumbnail of the current embed.\n *\n * @param {string} url - URL of the image\n * @param {?Omit<DiscordEmbedThumbnail, 'url'>} [options]\n * @returns {EmbedsBuilder}\n */\n setThumbnail(url: string, options?: Omit<DiscordEmbedThumbnail, 'url'>): EmbedsBuilder {\n this.#currentEmbed.thumbnail = {\n ...this.#currentEmbed.thumbnail,\n ...options,\n url,\n }\n\n return this\n }\n\n /**\n * Set the URL of the current embed title.\n *\n * @param {string} url\n * @returns {EmbedsBuilder}\n */\n setUrl(url: string): EmbedsBuilder {\n this.#currentEmbed.url = url\n\n return this\n }\n\n /**\n * Set the video of the current embed.\n *\n * @param {string} url\n * @param {?Omit<DiscordEmbedVideo, 'url'>} [options]\n * @returns {EmbedsBuilder}\n */\n setVideo(url: string, options?: Omit<DiscordEmbedVideo, 'url'>): EmbedsBuilder {\n this.#currentEmbed.video = {\n ...this.#currentEmbed.video,\n ...options,\n url,\n }\n\n return this\n }\n\n /**\n * Validate all embeds available against current known Discord limits to help prevent bad requests.\n *\n * @returns {EmbedsBuilder}\n */\n validate(): EmbedsBuilder {\n let totalCharacters = 0\n\n if (this.length > 10) {\n throw new Error('You can not have more than 10 embeds on a single message.')\n }\n\n this.forEach(({ author, description, fields, footer, title }, index) => {\n if (title) {\n const trimmedTitle = title.trim()\n\n if (trimmedTitle.length > 256) {\n throw new Error(`Title of embed ${index} can not be longer than 256 characters.`)\n }\n\n totalCharacters += trimmedTitle.length\n }\n\n if (description) {\n const trimmedDescription = description.trim()\n\n if (trimmedDescription.length > 4096) {\n throw new Error(`Description of embed ${index} can not be longer than 4096 characters.`)\n }\n\n totalCharacters += trimmedDescription.length\n }\n\n if (fields) {\n if (fields.length > 25) {\n throw new Error(`embed ${index} can not have more than 25 fields.`)\n }\n\n fields.forEach(({ name, value }, fieldIndex) => {\n const trimmedName = name.trim()\n const trimmedValue = value.trim()\n\n if (trimmedName.length > 256) {\n throw new Error(`Name of field ${fieldIndex} on embed ${index} can not be longer than 256 characters.`)\n }\n\n if (trimmedValue.length > 4096) {\n throw new Error(`Value of field ${fieldIndex} on embed ${index} can not be longer than 1024 characters.`)\n }\n\n totalCharacters += trimmedName.length\n totalCharacters += trimmedValue.length\n })\n }\n\n if (footer) {\n const trimmedFooterText = footer.text.trim()\n\n if (trimmedFooterText.length > 2048) {\n throw new Error(`Footer text of embed ${index} can not be longer than 2048 characters.`)\n }\n\n totalCharacters += trimmedFooterText.length\n }\n\n if (author) {\n const trimmedAuthorName = author.name.trim()\n\n if (trimmedAuthorName.length > 256) {\n throw new Error(`Author name of embed ${index} can not be longer than 256 characters.`)\n }\n\n totalCharacters += trimmedAuthorName.length\n }\n })\n\n if (totalCharacters > 6000) {\n throw new Error('Total character length of all embeds can not exceed 6000 characters.')\n }\n\n return this\n }\n\n /**\n * Returns the current embed.\n *\n * @readonly\n * @type {DiscordEmbed}\n */\n get #currentEmbed(): DiscordEmbed {\n if (this.length === 0) {\n this.newEmbed()\n this.setCurrentEmbed()\n }\n\n return this[this.#currentEmbedIndex]\n }\n}\n"],"names":["EmbedsBuilder","Array","currentEmbedIndex","addField","name","value","inline","currentEmbed","fields","undefined","push","newEmbed","length","Error","setCurrentEmbed","setAuthor","options","author","setColor","color","convertedValue","parseInt","replace","Number","isNaN","index","setDescription","description","setFields","setFooter","text","footer","setImage","url","image","setProvider","provider","setRandomColor","Math","floor","random","setTitle","title","setUrl","setTimestamp","timestamp","Date","toISOString","setThumbnail","thumbnail","setVideo","video","validate","totalCharacters","forEach","trimmedTitle","trim","trimmedDescription","fieldIndex","trimmedName","trimmedValue","trimmedFooterText","trimmedAuthorName"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { EmbedsBuilder } from './builders/embeds.js';
2
+ export * from './builders/embeds.js';
3
+ export declare const createEmbeds: () => EmbedsBuilder;
4
+ //# sourceMappingURL=builders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEpD,cAAc,sBAAsB,CAAA;AAEpC,eAAO,MAAM,YAAY,QAAO,aAAoC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { EmbedsBuilder } from './builders/embeds.js';
2
+ export * from './builders/embeds.js';
3
+ export const createEmbeds = ()=>new EmbedsBuilder();
4
+
5
+ //# sourceMappingURL=builders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/builders.ts"],"sourcesContent":["import { EmbedsBuilder } from './builders/embeds.js'\n\nexport * from './builders/embeds.js'\n\nexport const createEmbeds = (): EmbedsBuilder => new EmbedsBuilder()\n"],"names":["EmbedsBuilder","createEmbeds"],"mappings":"AAAA,SAASA,aAAa,QAAQ,uBAAsB;AAEpD,cAAc,uBAAsB;AAEpC,OAAO,MAAMC,eAAe,IAAqB,IAAID,gBAAe"}
package/dist/images.js CHANGED
@@ -19,7 +19,7 @@
19
19
  * @param options - The parameters for the building of the URL.
20
20
  * @returns The link to the resource.
21
21
  */ export function avatarUrl(userId, discriminator, options) {
22
- return options?.avatar ? formatImageUrl(`https://cdn.discordapp.com/avatars/${userId}/${typeof options.avatar === 'string' ? options.avatar : iconBigintToHash(options.avatar)}`, options?.size ?? 128, options?.format) : `https://cdn.discordapp.com/embed/avatars/${Number(discriminator) % 5}.png`;
22
+ return options?.avatar ? formatImageUrl(`https://cdn.discordapp.com/avatars/${userId}/${typeof options.avatar === 'string' ? options.avatar : iconBigintToHash(options.avatar)}`, options?.size ?? 128, options?.format) : `https://cdn.discordapp.com/embed/avatars/${discriminator === '0' ? (BigInt(userId) >> BigInt(22)) % BigInt(6) : Number(discriminator) % 5}.png`;
23
23
  }
24
24
  /**
25
25
  * Builds a URL to the guild banner stored in the Discord CDN.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/images.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/restrict-template-expressions */\nimport type { BigString, GetGuildWidgetImageQuery, ImageFormat, ImageSize } from '@discordeno/types'\nimport { iconBigintToHash } from './hash.js'\n\n/** Help format an image url. */\nexport function formatImageUrl(url: string, size: ImageSize = 128, format?: ImageFormat): string {\n return `${url}.${format ?? (url.includes('/a_') ? 'gif' : 'jpg')}?size=${size}`\n}\n\n/**\n * Get the url for an emoji.\n *\n * @param emojiId The id of the emoji\n * @param animated Whether or not the emoji is animated\n * @returns string\n */\nexport function emojiUrl(emojiId: BigString, animated = false): string {\n return `https://cdn.discordapp.com/emojis/${emojiId}.${animated ? 'gif' : 'png'}`\n}\n\n/**\n * Builds a URL to a user's avatar stored in the Discord CDN.\n *\n * @param userId - The ID of the user to get the avatar of.\n * @param discriminator - The user's discriminator. (4-digit tag after the hashtag.)\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource.\n */\nexport function avatarUrl(\n userId: BigString,\n discriminator: string,\n options?: {\n avatar: BigString | undefined\n size?: ImageSize\n format?: ImageFormat\n },\n): string {\n return options?.avatar\n ? formatImageUrl(\n `https://cdn.discordapp.com/avatars/${userId}/${typeof options.avatar === 'string' ? options.avatar : iconBigintToHash(options.avatar)}`,\n options?.size ?? 128,\n options?.format,\n )\n : `https://cdn.discordapp.com/embed/avatars/${Number(discriminator) % 5}.png`\n}\n\n/**\n * Builds a URL to the guild banner stored in the Discord CDN.\n *\n * @param guildId - The ID of the guild to get the link to the banner for.\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource or `undefined` if no banner has been set.\n */\nexport function guildBannerUrl(\n guildId: BigString,\n options: {\n banner?: string | bigint\n size?: ImageSize\n format?: ImageFormat\n },\n): string | undefined {\n return options.banner\n ? formatImageUrl(\n `https://cdn.discordapp.com/banners/${guildId}/${typeof options.banner === 'string' ? options.banner : iconBigintToHash(options.banner)}`,\n options.size ?? 128,\n options.format,\n )\n : undefined\n}\n\n/**\n * Builds a URL to the guild icon stored in the Discord CDN.\n *\n * @param guildId - The ID of the guild to get the link to the banner for.\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource or `undefined` if no banner has been set.\n */\nexport function guildIconUrl(\n guildId: BigString,\n imageHash: BigString | undefined,\n options?: {\n size?: ImageSize\n format?: ImageFormat\n },\n): string | undefined {\n return imageHash\n ? formatImageUrl(\n `https://cdn.discordapp.com/icons/${guildId}/${typeof imageHash === 'string' ? imageHash : iconBigintToHash(imageHash)}`,\n options?.size ?? 128,\n options?.format,\n )\n : undefined\n}\n\n/**\n * Builds the URL to a guild splash stored in the Discord CDN.\n *\n * @param guildId - The ID of the guild to get the splash of.\n * @param imageHash - The hash identifying the splash image.\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource or `undefined` if the guild does not have a splash image set.\n */\nexport function guildSplashUrl(\n guildId: BigString,\n imageHash: BigString | undefined,\n options?: {\n size?: ImageSize\n format?: ImageFormat\n },\n): string | undefined {\n return imageHash\n ? formatImageUrl(\n `https://cdn.discordapp.com/splashes/${guildId}/${typeof imageHash === 'string' ? imageHash : iconBigintToHash(imageHash)}`,\n options?.size ?? 128,\n options?.format,\n )\n : undefined\n}\n\n/**\n * Builds a URL to the guild widget image stored in the Discord CDN.\n *\n * @param guildId - The ID of the guild to get the link to the widget image for.\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource.\n */\nexport function getWidgetImageUrl(guildId: BigString, options?: GetGuildWidgetImageQuery): string {\n let url = `https://discordapp.com/api/guilds/${guildId}/widget.png`\n\n if (options?.style) {\n url += `?style=${options.style}`\n }\n\n return url\n}\n"],"names":["iconBigintToHash","formatImageUrl","url","size","format","includes","emojiUrl","emojiId","animated","avatarUrl","userId","discriminator","options","avatar","Number","guildBannerUrl","guildId","banner","undefined","guildIconUrl","imageHash","guildSplashUrl","getWidgetImageUrl","style"],"mappings":"AAAA,mEAAmE,GAEnE,SAASA,gBAAgB,QAAQ,YAAW;AAE5C,8BAA8B,GAC9B,OAAO,SAASC,eAAeC,GAAW,EAAEC,OAAkB,GAAG,EAAEC,MAAoB,EAAU;IAC/F,OAAO,CAAC,EAAEF,IAAI,CAAC,EAAEE,UAAWF,CAAAA,IAAIG,QAAQ,CAAC,SAAS,QAAQ,KAAK,AAAD,EAAG,MAAM,EAAEF,KAAK,CAAC;AACjF,CAAC;AAED;;;;;;CAMC,GACD,OAAO,SAASG,SAASC,OAAkB,EAAEC,WAAW,KAAK,EAAU;IACrE,OAAO,CAAC,kCAAkC,EAAED,QAAQ,CAAC,EAAEC,WAAW,QAAQ,KAAK,CAAC,CAAC;AACnF,CAAC;AAED;;;;;;;CAOC,GACD,OAAO,SAASC,UACdC,MAAiB,EACjBC,aAAqB,EACrBC,OAIC,EACO;IACR,OAAOA,SAASC,SACZZ,eACE,CAAC,mCAAmC,EAAES,OAAO,CAAC,EAAE,OAAOE,QAAQC,MAAM,KAAK,WAAWD,QAAQC,MAAM,GAAGb,iBAAiBY,QAAQC,MAAM,CAAC,CAAC,CAAC,EACxID,SAAST,QAAQ,KACjBS,SAASR,UAEX,CAAC,yCAAyC,EAAEU,OAAOH,iBAAiB,EAAE,IAAI,CAAC;AACjF,CAAC;AAED;;;;;;CAMC,GACD,OAAO,SAASI,eACdC,OAAkB,EAClBJ,OAIC,EACmB;IACpB,OAAOA,QAAQK,MAAM,GACjBhB,eACE,CAAC,mCAAmC,EAAEe,QAAQ,CAAC,EAAE,OAAOJ,QAAQK,MAAM,KAAK,WAAWL,QAAQK,MAAM,GAAGjB,iBAAiBY,QAAQK,MAAM,CAAC,CAAC,CAAC,EACzIL,QAAQT,IAAI,IAAI,KAChBS,QAAQR,MAAM,IAEhBc,SAAS;AACf,CAAC;AAED;;;;;;CAMC,GACD,OAAO,SAASC,aACdH,OAAkB,EAClBI,SAAgC,EAChCR,OAGC,EACmB;IACpB,OAAOQ,YACHnB,eACE,CAAC,iCAAiC,EAAEe,QAAQ,CAAC,EAAE,OAAOI,cAAc,WAAWA,YAAYpB,iBAAiBoB,UAAU,CAAC,CAAC,EACxHR,SAAST,QAAQ,KACjBS,SAASR,UAEXc,SAAS;AACf,CAAC;AAED;;;;;;;CAOC,GACD,OAAO,SAASG,eACdL,OAAkB,EAClBI,SAAgC,EAChCR,OAGC,EACmB;IACpB,OAAOQ,YACHnB,eACE,CAAC,oCAAoC,EAAEe,QAAQ,CAAC,EAAE,OAAOI,cAAc,WAAWA,YAAYpB,iBAAiBoB,UAAU,CAAC,CAAC,EAC3HR,SAAST,QAAQ,KACjBS,SAASR,UAEXc,SAAS;AACf,CAAC;AAED;;;;;;CAMC,GACD,OAAO,SAASI,kBAAkBN,OAAkB,EAAEJ,OAAkC,EAAU;IAChG,IAAIV,MAAM,CAAC,kCAAkC,EAAEc,QAAQ,WAAW,CAAC;IAEnE,IAAIJ,SAASW,OAAO;QAClBrB,OAAO,CAAC,OAAO,EAAEU,QAAQW,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,OAAOrB;AACT,CAAC"}
1
+ {"version":3,"sources":["../src/images.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/restrict-template-expressions */\nimport type { BigString, GetGuildWidgetImageQuery, ImageFormat, ImageSize } from '@discordeno/types'\nimport { iconBigintToHash } from './hash.js'\n\n/** Help format an image url. */\nexport function formatImageUrl(url: string, size: ImageSize = 128, format?: ImageFormat): string {\n return `${url}.${format ?? (url.includes('/a_') ? 'gif' : 'jpg')}?size=${size}`\n}\n\n/**\n * Get the url for an emoji.\n *\n * @param emojiId The id of the emoji\n * @param animated Whether or not the emoji is animated\n * @returns string\n */\nexport function emojiUrl(emojiId: BigString, animated = false): string {\n return `https://cdn.discordapp.com/emojis/${emojiId}.${animated ? 'gif' : 'png'}`\n}\n\n/**\n * Builds a URL to a user's avatar stored in the Discord CDN.\n *\n * @param userId - The ID of the user to get the avatar of.\n * @param discriminator - The user's discriminator. (4-digit tag after the hashtag.)\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource.\n */\nexport function avatarUrl(\n userId: BigString,\n discriminator: string,\n options?: {\n avatar: BigString | undefined\n size?: ImageSize\n format?: ImageFormat\n },\n): string {\n return options?.avatar\n ? formatImageUrl(\n `https://cdn.discordapp.com/avatars/${userId}/${typeof options.avatar === 'string' ? options.avatar : iconBigintToHash(options.avatar)}`,\n options?.size ?? 128,\n options?.format,\n )\n : `https://cdn.discordapp.com/embed/avatars/${discriminator === '0' ? (BigInt(userId) >> BigInt(22)) % BigInt(6) : Number(discriminator) % 5}.png`\n}\n\n/**\n * Builds a URL to the guild banner stored in the Discord CDN.\n *\n * @param guildId - The ID of the guild to get the link to the banner for.\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource or `undefined` if no banner has been set.\n */\nexport function guildBannerUrl(\n guildId: BigString,\n options: {\n banner?: string | bigint\n size?: ImageSize\n format?: ImageFormat\n },\n): string | undefined {\n return options.banner\n ? formatImageUrl(\n `https://cdn.discordapp.com/banners/${guildId}/${typeof options.banner === 'string' ? options.banner : iconBigintToHash(options.banner)}`,\n options.size ?? 128,\n options.format,\n )\n : undefined\n}\n\n/**\n * Builds a URL to the guild icon stored in the Discord CDN.\n *\n * @param guildId - The ID of the guild to get the link to the banner for.\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource or `undefined` if no banner has been set.\n */\nexport function guildIconUrl(\n guildId: BigString,\n imageHash: BigString | undefined,\n options?: {\n size?: ImageSize\n format?: ImageFormat\n },\n): string | undefined {\n return imageHash\n ? formatImageUrl(\n `https://cdn.discordapp.com/icons/${guildId}/${typeof imageHash === 'string' ? imageHash : iconBigintToHash(imageHash)}`,\n options?.size ?? 128,\n options?.format,\n )\n : undefined\n}\n\n/**\n * Builds the URL to a guild splash stored in the Discord CDN.\n *\n * @param guildId - The ID of the guild to get the splash of.\n * @param imageHash - The hash identifying the splash image.\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource or `undefined` if the guild does not have a splash image set.\n */\nexport function guildSplashUrl(\n guildId: BigString,\n imageHash: BigString | undefined,\n options?: {\n size?: ImageSize\n format?: ImageFormat\n },\n): string | undefined {\n return imageHash\n ? formatImageUrl(\n `https://cdn.discordapp.com/splashes/${guildId}/${typeof imageHash === 'string' ? imageHash : iconBigintToHash(imageHash)}`,\n options?.size ?? 128,\n options?.format,\n )\n : undefined\n}\n\n/**\n * Builds a URL to the guild widget image stored in the Discord CDN.\n *\n * @param guildId - The ID of the guild to get the link to the widget image for.\n * @param options - The parameters for the building of the URL.\n * @returns The link to the resource.\n */\nexport function getWidgetImageUrl(guildId: BigString, options?: GetGuildWidgetImageQuery): string {\n let url = `https://discordapp.com/api/guilds/${guildId}/widget.png`\n\n if (options?.style) {\n url += `?style=${options.style}`\n }\n\n return url\n}\n"],"names":["iconBigintToHash","formatImageUrl","url","size","format","includes","emojiUrl","emojiId","animated","avatarUrl","userId","discriminator","options","avatar","BigInt","Number","guildBannerUrl","guildId","banner","undefined","guildIconUrl","imageHash","guildSplashUrl","getWidgetImageUrl","style"],"mappings":"AAAA,mEAAmE,GAEnE,SAASA,gBAAgB,QAAQ,YAAW;AAE5C,8BAA8B,GAC9B,OAAO,SAASC,eAAeC,GAAW,EAAEC,OAAkB,GAAG,EAAEC,MAAoB,EAAU;IAC/F,OAAO,CAAC,EAAEF,IAAI,CAAC,EAAEE,UAAWF,CAAAA,IAAIG,QAAQ,CAAC,SAAS,QAAQ,KAAK,AAAD,EAAG,MAAM,EAAEF,KAAK,CAAC;AACjF,CAAC;AAED;;;;;;CAMC,GACD,OAAO,SAASG,SAASC,OAAkB,EAAEC,WAAW,KAAK,EAAU;IACrE,OAAO,CAAC,kCAAkC,EAAED,QAAQ,CAAC,EAAEC,WAAW,QAAQ,KAAK,CAAC,CAAC;AACnF,CAAC;AAED;;;;;;;CAOC,GACD,OAAO,SAASC,UACdC,MAAiB,EACjBC,aAAqB,EACrBC,OAIC,EACO;IACR,OAAOA,SAASC,SACZZ,eACE,CAAC,mCAAmC,EAAES,OAAO,CAAC,EAAE,OAAOE,QAAQC,MAAM,KAAK,WAAWD,QAAQC,MAAM,GAAGb,iBAAiBY,QAAQC,MAAM,CAAC,CAAC,CAAC,EACxID,SAAST,QAAQ,KACjBS,SAASR,UAEX,CAAC,yCAAyC,EAAEO,kBAAkB,MAAM,AAACG,CAAAA,OAAOJ,WAAWI,OAAO,GAAE,IAAKA,OAAO,KAAKC,OAAOJ,iBAAiB,CAAC,CAAC,IAAI,CAAC;AACtJ,CAAC;AAED;;;;;;CAMC,GACD,OAAO,SAASK,eACdC,OAAkB,EAClBL,OAIC,EACmB;IACpB,OAAOA,QAAQM,MAAM,GACjBjB,eACE,CAAC,mCAAmC,EAAEgB,QAAQ,CAAC,EAAE,OAAOL,QAAQM,MAAM,KAAK,WAAWN,QAAQM,MAAM,GAAGlB,iBAAiBY,QAAQM,MAAM,CAAC,CAAC,CAAC,EACzIN,QAAQT,IAAI,IAAI,KAChBS,QAAQR,MAAM,IAEhBe,SAAS;AACf,CAAC;AAED;;;;;;CAMC,GACD,OAAO,SAASC,aACdH,OAAkB,EAClBI,SAAgC,EAChCT,OAGC,EACmB;IACpB,OAAOS,YACHpB,eACE,CAAC,iCAAiC,EAAEgB,QAAQ,CAAC,EAAE,OAAOI,cAAc,WAAWA,YAAYrB,iBAAiBqB,UAAU,CAAC,CAAC,EACxHT,SAAST,QAAQ,KACjBS,SAASR,UAEXe,SAAS;AACf,CAAC;AAED;;;;;;;CAOC,GACD,OAAO,SAASG,eACdL,OAAkB,EAClBI,SAAgC,EAChCT,OAGC,EACmB;IACpB,OAAOS,YACHpB,eACE,CAAC,oCAAoC,EAAEgB,QAAQ,CAAC,EAAE,OAAOI,cAAc,WAAWA,YAAYrB,iBAAiBqB,UAAU,CAAC,CAAC,EAC3HT,SAAST,QAAQ,KACjBS,SAASR,UAEXe,SAAS;AACf,CAAC;AAED;;;;;;CAMC,GACD,OAAO,SAASI,kBAAkBN,OAAkB,EAAEL,OAAkC,EAAU;IAChG,IAAIV,MAAM,CAAC,kCAAkC,EAAEe,QAAQ,WAAW,CAAC;IAEnE,IAAIL,SAASY,OAAO;QAClBtB,OAAO,CAAC,OAAO,EAAEU,QAAQY,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,OAAOtB;AACT,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,13 @@
1
+ export * from './Collection.js';
1
2
  export * from './base64.js';
2
3
  export * from './bucket.js';
4
+ export * from './builders.js';
3
5
  export * from './casing.js';
4
- export * from './Collection.js';
5
6
  export * from './colors.js';
6
7
  export * from './hash.js';
7
8
  export * from './images.js';
8
9
  export * from './logger.js';
10
+ export * from './oauth2.js';
9
11
  export * from './permissions.js';
10
12
  export * from './reactions.js';
11
13
  export * from './token.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
+ export * from './Collection.js';
1
2
  export * from './base64.js';
2
3
  export * from './bucket.js';
4
+ export * from './builders.js';
3
5
  export * from './casing.js';
4
- export * from './Collection.js';
5
6
  export * from './colors.js';
6
7
  export * from './hash.js';
7
8
  export * from './images.js';
8
9
  export * from './logger.js';
10
+ export * from './oauth2.js';
9
11
  export * from './permissions.js';
10
12
  export * from './reactions.js';
11
13
  export * from './token.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './base64.js'\nexport * from './bucket.js'\nexport * from './casing.js'\nexport * from './Collection.js'\nexport * from './colors.js'\nexport * from './hash.js'\nexport * from './images.js'\nexport * from './logger.js'\nexport * from './permissions.js'\nexport * from './reactions.js'\nexport * from './token.js'\nexport * from './typeguards.js'\nexport * from './urlToBase64.js'\nexport * from './utils.js'\n"],"names":[],"mappings":"AAAA,cAAc,cAAa;AAC3B,cAAc,cAAa;AAC3B,cAAc,cAAa;AAC3B,cAAc,kBAAiB;AAC/B,cAAc,cAAa;AAC3B,cAAc,YAAW;AACzB,cAAc,cAAa;AAC3B,cAAc,cAAa;AAC3B,cAAc,mBAAkB;AAChC,cAAc,iBAAgB;AAC9B,cAAc,aAAY;AAC1B,cAAc,kBAAiB;AAC/B,cAAc,mBAAkB;AAChC,cAAc,aAAY"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './Collection.js'\nexport * from './base64.js'\nexport * from './bucket.js'\nexport * from './builders.js'\nexport * from './casing.js'\nexport * from './colors.js'\nexport * from './hash.js'\nexport * from './images.js'\nexport * from './logger.js'\nexport * from './oauth2.js'\nexport * from './permissions.js'\nexport * from './reactions.js'\nexport * from './token.js'\nexport * from './typeguards.js'\nexport * from './urlToBase64.js'\nexport * from './utils.js'\n"],"names":[],"mappings":"AAAA,cAAc,kBAAiB;AAC/B,cAAc,cAAa;AAC3B,cAAc,cAAa;AAC3B,cAAc,gBAAe;AAC7B,cAAc,cAAa;AAC3B,cAAc,cAAa;AAC3B,cAAc,YAAW;AACzB,cAAc,cAAa;AAC3B,cAAc,cAAa;AAC3B,cAAc,cAAa;AAC3B,cAAc,mBAAkB;AAChC,cAAc,iBAAgB;AAC9B,cAAc,aAAY;AAC1B,cAAc,kBAAiB;AAC/B,cAAc,mBAAkB;AAChC,cAAc,aAAY"}
@@ -0,0 +1,58 @@
1
+ import type { BigString, OAuth2Scope, PermissionStrings } from '@discordeno/types';
2
+ export declare function createOAuth2Link(options: CreateOAuth2LinkOptions): string;
3
+ export interface CreateOAuth2LinkOptions {
4
+ /**
5
+ * The type of response
6
+ *
7
+ * @remarks
8
+ * Should be defined only if using either OAuth2 authorization, implicit or not, or [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization)
9
+ */
10
+ responseType?: 'code' | 'token';
11
+ /** The id of the application */
12
+ clientId: BigString;
13
+ /** The scopes for the application */
14
+ scope: OAuth2Scope[];
15
+ /**
16
+ * The optional state for security
17
+ *
18
+ * @see https://discord.com/developers/docs/topics/oauth2#state-and-security
19
+ */
20
+ state?: string;
21
+ /**
22
+ * The redirect uri for after the authentication
23
+ *
24
+ * @remarks
25
+ * Should be defined only if using either OAuth2 authorization, implicit or not, or [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization)
26
+ */
27
+ redirectUri?: string;
28
+ /**
29
+ * The type of prompt to give to the user
30
+ *
31
+ * @remarks
32
+ * If set to `none`, it will skip the authorization screen and redirect them back to your redirect URI without requesting their authorization.
33
+ * For passthrough scopes, like bot and webhook.incoming, authorization is always required.
34
+ */
35
+ prompt?: 'consent' | 'none';
36
+ /**
37
+ * The permissions of the invited bot
38
+ *
39
+ * @remarks
40
+ * Should be defined only in a [bot authorization flow](https://discord.com/developers/docs/topics/oauth2#bot-authorization-flow) or with [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization)
41
+ */
42
+ permissions?: BigString | PermissionStrings[];
43
+ /**
44
+ * Pre-fills the dropdown picker with a guild for the user
45
+ *
46
+ * @remarks
47
+ * Should be defined only in a [bot authorization flow](https://discord.com/developers/docs/topics/oauth2#bot-authorization-flow) or with [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization) or with the `webhook.incoming` scope
48
+ */
49
+ guildId?: BigString;
50
+ /**
51
+ * Disallows the user from changing the guild dropdown if set to true
52
+ *
53
+ * @remarks
54
+ * Should be defined only in a [bot authorization flow](https://discord.com/developers/docs/topics/oauth2#bot-authorization-flow), with [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization) or with the `webhook.incoming` scope
55
+ */
56
+ disableGuildSelect?: boolean;
57
+ }
58
+ //# sourceMappingURL=oauth2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth2.d.ts","sourceRoot":"","sources":["../src/oauth2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAGlF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAezE;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC/B,gCAAgC;IAChC,QAAQ,EAAE,SAAS,CAAA;IACnB,qCAAqC;IACrC,KAAK,EAAE,WAAW,EAAE,CAAA;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC3B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,GAAG,iBAAiB,EAAE,CAAA;IAC7C;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B"}
package/dist/oauth2.js ADDED
@@ -0,0 +1,16 @@
1
+ import { calculateBits } from './permissions.js';
2
+ export function createOAuth2Link(options) {
3
+ const joinedScopeString = options.scope.join(' ');
4
+ let url = `https://discord.com/oauth2/authorize?client_id=${options.clientId}&scope=${joinedScopeString}`;
5
+ if (options.responseType) url += `&response_type=${options.responseType}`;
6
+ if (options.state) url += `&state=${encodeURIComponent(options.state)}`;
7
+ if (options.redirectUri) url += `&redirect_uri=${encodeURIComponent(options.redirectUri)}`;
8
+ if (options.prompt) url += `&prompt=${options.prompt}`;
9
+ if (options.permissions) url += `&permissions=${Array.isArray(options.permissions) ? calculateBits(options.permissions) : options.permissions}`;
10
+ if (options.guildId) url += `&guild_id=${options.guildId}`;
11
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
12
+ if (options.disableGuildSelect !== undefined) url += `&disable_guild_select=${options.disableGuildSelect}`;
13
+ return url;
14
+ }
15
+
16
+ //# sourceMappingURL=oauth2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/oauth2.ts"],"sourcesContent":["import type { BigString, OAuth2Scope, PermissionStrings } from '@discordeno/types'\nimport { calculateBits } from './permissions.js'\n\nexport function createOAuth2Link(options: CreateOAuth2LinkOptions): string {\n const joinedScopeString = options.scope.join(' ')\n\n let url = `https://discord.com/oauth2/authorize?client_id=${options.clientId}&scope=${joinedScopeString}`\n\n if (options.responseType) url += `&response_type=${options.responseType}`\n if (options.state) url += `&state=${encodeURIComponent(options.state)}`\n if (options.redirectUri) url += `&redirect_uri=${encodeURIComponent(options.redirectUri)}`\n if (options.prompt) url += `&prompt=${options.prompt}`\n if (options.permissions) url += `&permissions=${Array.isArray(options.permissions) ? calculateBits(options.permissions) : options.permissions}`\n if (options.guildId) url += `&guild_id=${options.guildId}`\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n if (options.disableGuildSelect !== undefined) url += `&disable_guild_select=${options.disableGuildSelect}`\n\n return url\n}\n\nexport interface CreateOAuth2LinkOptions {\n /**\n * The type of response\n *\n * @remarks\n * Should be defined only if using either OAuth2 authorization, implicit or not, or [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization)\n */\n responseType?: 'code' | 'token'\n /** The id of the application */\n clientId: BigString\n /** The scopes for the application */\n scope: OAuth2Scope[]\n /**\n * The optional state for security\n *\n * @see https://discord.com/developers/docs/topics/oauth2#state-and-security\n */\n state?: string\n /**\n * The redirect uri for after the authentication\n *\n * @remarks\n * Should be defined only if using either OAuth2 authorization, implicit or not, or [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization)\n */\n redirectUri?: string\n /**\n * The type of prompt to give to the user\n *\n * @remarks\n * If set to `none`, it will skip the authorization screen and redirect them back to your redirect URI without requesting their authorization.\n * For passthrough scopes, like bot and webhook.incoming, authorization is always required.\n */\n prompt?: 'consent' | 'none'\n /**\n * The permissions of the invited bot\n *\n * @remarks\n * Should be defined only in a [bot authorization flow](https://discord.com/developers/docs/topics/oauth2#bot-authorization-flow) or with [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization)\n */\n permissions?: BigString | PermissionStrings[]\n /**\n * Pre-fills the dropdown picker with a guild for the user\n *\n * @remarks\n * Should be defined only in a [bot authorization flow](https://discord.com/developers/docs/topics/oauth2#bot-authorization-flow) or with [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization) or with the `webhook.incoming` scope\n */\n guildId?: BigString\n /**\n * Disallows the user from changing the guild dropdown if set to true\n *\n * @remarks\n * Should be defined only in a [bot authorization flow](https://discord.com/developers/docs/topics/oauth2#bot-authorization-flow), with [advanced bot authorization](https://discord.com/developers/docs/topics/oauth2#advanced-bot-authorization) or with the `webhook.incoming` scope\n */\n disableGuildSelect?: boolean\n}\n"],"names":["calculateBits","createOAuth2Link","options","joinedScopeString","scope","join","url","clientId","responseType","state","encodeURIComponent","redirectUri","prompt","permissions","Array","isArray","guildId","disableGuildSelect","undefined"],"mappings":"AACA,SAASA,aAAa,QAAQ,mBAAkB;AAEhD,OAAO,SAASC,iBAAiBC,OAAgC,EAAU;IACzE,MAAMC,oBAAoBD,QAAQE,KAAK,CAACC,IAAI,CAAC;IAE7C,IAAIC,MAAM,CAAC,+CAA+C,EAAEJ,QAAQK,QAAQ,CAAC,OAAO,EAAEJ,kBAAkB,CAAC;IAEzG,IAAID,QAAQM,YAAY,EAAEF,OAAO,CAAC,eAAe,EAAEJ,QAAQM,YAAY,CAAC,CAAC;IACzE,IAAIN,QAAQO,KAAK,EAAEH,OAAO,CAAC,OAAO,EAAEI,mBAAmBR,QAAQO,KAAK,EAAE,CAAC;IACvE,IAAIP,QAAQS,WAAW,EAAEL,OAAO,CAAC,cAAc,EAAEI,mBAAmBR,QAAQS,WAAW,EAAE,CAAC;IAC1F,IAAIT,QAAQU,MAAM,EAAEN,OAAO,CAAC,QAAQ,EAAEJ,QAAQU,MAAM,CAAC,CAAC;IACtD,IAAIV,QAAQW,WAAW,EAAEP,OAAO,CAAC,aAAa,EAAEQ,MAAMC,OAAO,CAACb,QAAQW,WAAW,IAAIb,cAAcE,QAAQW,WAAW,IAAIX,QAAQW,WAAW,CAAC,CAAC;IAC/I,IAAIX,QAAQc,OAAO,EAAEV,OAAO,CAAC,UAAU,EAAEJ,QAAQc,OAAO,CAAC,CAAC;IAC1D,4EAA4E;IAC5E,IAAId,QAAQe,kBAAkB,KAAKC,WAAWZ,OAAO,CAAC,sBAAsB,EAAEJ,QAAQe,kBAAkB,CAAC,CAAC;IAE1G,OAAOX;AACT,CAAC"}
package/dist/token.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- /** Removes the Bot before the token. */
1
+ /** Removes the Bot/Bearer before the token. */
2
2
  export declare function removeTokenPrefix(token?: string, type?: 'GATEWAY' | 'REST'): string;
3
3
  /** Get the bot id from the bot token. WARNING: Discord staff has mentioned this may not be stable forever. Use at your own risk. However, note for over 5 years this has never broken. */
4
4
  export declare function getBotIdFromToken(token: string): bigint;
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAEA,wCAAwC;AACxC,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,SAAS,GAAG,MAAe,GAAG,MAAM,CAS3F;AAED,0LAA0L;AAC1L,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAIA,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,SAAS,GAAG,MAAe,GAAG,MAAM,CAY3F;AAED,0LAA0L;AAC1L,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD"}
package/dist/token.js CHANGED
@@ -1,13 +1,18 @@
1
1
  import { Buffer } from 'node:buffer';
2
- /** Removes the Bot before the token. */ export function removeTokenPrefix(token, type = 'REST') {
2
+ const validTokenPrefixes = [
3
+ 'Bot',
4
+ 'Bearer'
5
+ ];
6
+ /** Removes the Bot/Bearer before the token. */ export function removeTokenPrefix(token, type = 'REST') {
3
7
  // If no token is provided, throw an error
4
8
  if (token === undefined) {
5
9
  throw new Error(`The ${type} was not given a token. Please provide a token and try again.`);
6
10
  }
11
+ const splittedToken = token.split(' ');
7
12
  // If the token does not have a prefix just return token
8
- if (!token.startsWith('Bot ')) return token;
13
+ if (splittedToken.length < 2 || !validTokenPrefixes.includes(splittedToken[0])) return token;
9
14
  // Remove the prefix and return only the token.
10
- return token.substring(token.indexOf(' ') + 1);
15
+ return splittedToken.splice(1).join(' ');
11
16
  }
12
17
  /** Get the bot id from the bot token. WARNING: Discord staff has mentioned this may not be stable forever. Use at your own risk. However, note for over 5 years this has never broken. */ export function getBotIdFromToken(token) {
13
18
  return BigInt(Buffer.from(token.split('.')[0], 'base64').toString());
package/dist/token.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/token.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\n\n/** Removes the Bot before the token. */\nexport function removeTokenPrefix(token?: string, type: 'GATEWAY' | 'REST' = 'REST'): string {\n // If no token is provided, throw an error\n if (token === undefined) {\n throw new Error(`The ${type} was not given a token. Please provide a token and try again.`)\n }\n // If the token does not have a prefix just return token\n if (!token.startsWith('Bot ')) return token\n // Remove the prefix and return only the token.\n return token.substring(token.indexOf(' ') + 1)\n}\n\n/** Get the bot id from the bot token. WARNING: Discord staff has mentioned this may not be stable forever. Use at your own risk. However, note for over 5 years this has never broken. */\nexport function getBotIdFromToken(token: string): bigint {\n return BigInt(Buffer.from(token.split('.')[0], 'base64').toString())\n}\n"],"names":["Buffer","removeTokenPrefix","token","type","undefined","Error","startsWith","substring","indexOf","getBotIdFromToken","BigInt","from","split","toString"],"mappings":"AAAA,SAASA,MAAM,QAAQ,cAAa;AAEpC,sCAAsC,GACtC,OAAO,SAASC,kBAAkBC,KAAc,EAAEC,OAA2B,MAAM,EAAU;IAC3F,0CAA0C;IAC1C,IAAID,UAAUE,WAAW;QACvB,MAAM,IAAIC,MAAM,CAAC,IAAI,EAAEF,KAAK,6DAA6D,CAAC,EAAC;IAC7F,CAAC;IACD,wDAAwD;IACxD,IAAI,CAACD,MAAMI,UAAU,CAAC,SAAS,OAAOJ;IACtC,+CAA+C;IAC/C,OAAOA,MAAMK,SAAS,CAACL,MAAMM,OAAO,CAAC,OAAO;AAC9C,CAAC;AAED,wLAAwL,GACxL,OAAO,SAASC,kBAAkBP,KAAa,EAAU;IACvD,OAAOQ,OAAOV,OAAOW,IAAI,CAACT,MAAMU,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,UAAUC,QAAQ;AACnE,CAAC"}
1
+ {"version":3,"sources":["../src/token.ts"],"sourcesContent":["import { Buffer } from 'node:buffer'\n\nconst validTokenPrefixes = ['Bot', 'Bearer']\n\n/** Removes the Bot/Bearer before the token. */\nexport function removeTokenPrefix(token?: string, type: 'GATEWAY' | 'REST' = 'REST'): string {\n // If no token is provided, throw an error\n if (token === undefined) {\n throw new Error(`The ${type} was not given a token. Please provide a token and try again.`)\n }\n\n const splittedToken = token.split(' ')\n\n // If the token does not have a prefix just return token\n if (splittedToken.length < 2 || !validTokenPrefixes.includes(splittedToken[0])) return token\n // Remove the prefix and return only the token.\n return splittedToken.splice(1).join(' ')\n}\n\n/** Get the bot id from the bot token. WARNING: Discord staff has mentioned this may not be stable forever. Use at your own risk. However, note for over 5 years this has never broken. */\nexport function getBotIdFromToken(token: string): bigint {\n return BigInt(Buffer.from(token.split('.')[0], 'base64').toString())\n}\n"],"names":["Buffer","validTokenPrefixes","removeTokenPrefix","token","type","undefined","Error","splittedToken","split","length","includes","splice","join","getBotIdFromToken","BigInt","from","toString"],"mappings":"AAAA,SAASA,MAAM,QAAQ,cAAa;AAEpC,MAAMC,qBAAqB;IAAC;IAAO;CAAS;AAE5C,6CAA6C,GAC7C,OAAO,SAASC,kBAAkBC,KAAc,EAAEC,OAA2B,MAAM,EAAU;IAC3F,0CAA0C;IAC1C,IAAID,UAAUE,WAAW;QACvB,MAAM,IAAIC,MAAM,CAAC,IAAI,EAAEF,KAAK,6DAA6D,CAAC,EAAC;IAC7F,CAAC;IAED,MAAMG,gBAAgBJ,MAAMK,KAAK,CAAC;IAElC,wDAAwD;IACxD,IAAID,cAAcE,MAAM,GAAG,KAAK,CAACR,mBAAmBS,QAAQ,CAACH,aAAa,CAAC,EAAE,GAAG,OAAOJ;IACvF,+CAA+C;IAC/C,OAAOI,cAAcI,MAAM,CAAC,GAAGC,IAAI,CAAC;AACtC,CAAC;AAED,wLAAwL,GACxL,OAAO,SAASC,kBAAkBV,KAAa,EAAU;IACvD,OAAOW,OAAOd,OAAOe,IAAI,CAACZ,MAAMK,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,UAAUQ,QAAQ;AACnE,CAAC"}
@@ -1,6 +1,7 @@
1
- import type { GetMessagesAfter, GetMessagesAround, GetMessagesBefore, GetMessagesLimit, GetMessagesOptions } from '@discordeno/types';
1
+ import type { DiscordInviteCreate, DiscordInviteMetadata, GetMessagesAfter, GetMessagesAround, GetMessagesBefore, GetMessagesLimit, GetMessagesOptions } from '@discordeno/types';
2
2
  export declare function isGetMessagesAfter(options: GetMessagesOptions): options is GetMessagesAfter;
3
3
  export declare function isGetMessagesBefore(options: GetMessagesOptions): options is GetMessagesBefore;
4
4
  export declare function isGetMessagesAround(options: GetMessagesOptions): options is GetMessagesAround;
5
5
  export declare function isGetMessagesLimit(options: GetMessagesOptions): options is GetMessagesLimit;
6
+ export declare function isInviteWithMetadata(options: DiscordInviteCreate | DiscordInviteMetadata): options is DiscordInviteMetadata;
6
7
  //# sourceMappingURL=typeguards.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"typeguards.d.ts","sourceRoot":"","sources":["../src/typeguards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAGrI,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,IAAI,gBAAgB,CAE3F;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,IAAI,iBAAiB,CAE7F;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,IAAI,iBAAiB,CAE7F;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,IAAI,gBAAgB,CAE3F"}
1
+ {"version":3,"file":"typeguards.d.ts","sourceRoot":"","sources":["../src/typeguards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,mBAAmB,CAAA;AAG1B,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,IAAI,gBAAgB,CAE3F;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,IAAI,iBAAiB,CAE7F;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,IAAI,iBAAiB,CAE7F;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,IAAI,gBAAgB,CAE3F;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,qBAAqB,GAAG,OAAO,IAAI,qBAAqB,CAE3H"}
@@ -11,5 +11,8 @@ export function isGetMessagesAround(options) {
11
11
  export function isGetMessagesLimit(options) {
12
12
  return hasProperty(options, 'limit');
13
13
  }
14
+ export function isInviteWithMetadata(options) {
15
+ return !hasProperty(options, 'channel_id');
16
+ }
14
17
 
15
18
  //# sourceMappingURL=typeguards.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/typeguards.ts"],"sourcesContent":["import type { GetMessagesAfter, GetMessagesAround, GetMessagesBefore, GetMessagesLimit, GetMessagesOptions } from '@discordeno/types'\nimport { hasProperty } from './utils.js'\n\nexport function isGetMessagesAfter(options: GetMessagesOptions): options is GetMessagesAfter {\n return hasProperty(options, 'after')\n}\n\nexport function isGetMessagesBefore(options: GetMessagesOptions): options is GetMessagesBefore {\n return hasProperty(options, 'before')\n}\n\nexport function isGetMessagesAround(options: GetMessagesOptions): options is GetMessagesAround {\n return hasProperty(options, 'around')\n}\n\nexport function isGetMessagesLimit(options: GetMessagesOptions): options is GetMessagesLimit {\n return hasProperty(options, 'limit')\n}\n"],"names":["hasProperty","isGetMessagesAfter","options","isGetMessagesBefore","isGetMessagesAround","isGetMessagesLimit"],"mappings":"AACA,SAASA,WAAW,QAAQ,aAAY;AAExC,OAAO,SAASC,mBAAmBC,OAA2B,EAA+B;IAC3F,OAAOF,YAAYE,SAAS;AAC9B,CAAC;AAED,OAAO,SAASC,oBAAoBD,OAA2B,EAAgC;IAC7F,OAAOF,YAAYE,SAAS;AAC9B,CAAC;AAED,OAAO,SAASE,oBAAoBF,OAA2B,EAAgC;IAC7F,OAAOF,YAAYE,SAAS;AAC9B,CAAC;AAED,OAAO,SAASG,mBAAmBH,OAA2B,EAA+B;IAC3F,OAAOF,YAAYE,SAAS;AAC9B,CAAC"}
1
+ {"version":3,"sources":["../src/typeguards.ts"],"sourcesContent":["import type {\n DiscordInviteCreate,\n DiscordInviteMetadata,\n GetMessagesAfter,\n GetMessagesAround,\n GetMessagesBefore,\n GetMessagesLimit,\n GetMessagesOptions,\n} from '@discordeno/types'\nimport { hasProperty } from './utils.js'\n\nexport function isGetMessagesAfter(options: GetMessagesOptions): options is GetMessagesAfter {\n return hasProperty(options, 'after')\n}\n\nexport function isGetMessagesBefore(options: GetMessagesOptions): options is GetMessagesBefore {\n return hasProperty(options, 'before')\n}\n\nexport function isGetMessagesAround(options: GetMessagesOptions): options is GetMessagesAround {\n return hasProperty(options, 'around')\n}\n\nexport function isGetMessagesLimit(options: GetMessagesOptions): options is GetMessagesLimit {\n return hasProperty(options, 'limit')\n}\n\nexport function isInviteWithMetadata(options: DiscordInviteCreate | DiscordInviteMetadata): options is DiscordInviteMetadata {\n return !hasProperty(options, 'channel_id')\n}\n"],"names":["hasProperty","isGetMessagesAfter","options","isGetMessagesBefore","isGetMessagesAround","isGetMessagesLimit","isInviteWithMetadata"],"mappings":"AASA,SAASA,WAAW,QAAQ,aAAY;AAExC,OAAO,SAASC,mBAAmBC,OAA2B,EAA+B;IAC3F,OAAOF,YAAYE,SAAS;AAC9B,CAAC;AAED,OAAO,SAASC,oBAAoBD,OAA2B,EAAgC;IAC7F,OAAOF,YAAYE,SAAS;AAC9B,CAAC;AAED,OAAO,SAASE,oBAAoBF,OAA2B,EAAgC;IAC7F,OAAOF,YAAYE,SAAS;AAC9B,CAAC;AAED,OAAO,SAASG,mBAAmBH,OAA2B,EAA+B;IAC3F,OAAOF,YAAYE,SAAS;AAC9B,CAAC;AAED,OAAO,SAASI,qBAAqBJ,OAAoD,EAAoC;IAC3H,OAAO,CAACF,YAAYE,SAAS;AAC/B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"urlToBase64.d.ts","sourceRoot":"","sources":["../src/urlToBase64.ts"],"names":[],"mappings":"AAGA,uFAAuF;AACvF,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK9D"}
1
+ {"version":3,"file":"urlToBase64.d.ts","sourceRoot":"","sources":["../src/urlToBase64.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK9D"}
@@ -1,4 +1,3 @@
1
- import fetch from 'node-fetch';
2
1
  import { encode } from './base64.js';
3
2
  /** Converts a url to base 64. Useful for example, uploading/creating server emojis. */ export async function urlToBase64(url) {
4
3
  const buffer = await fetch(url).then(async (res)=>await res.arrayBuffer());
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/urlToBase64.ts"],"sourcesContent":["import fetch from 'node-fetch'\nimport { encode } from './base64.js'\n\n/** Converts a url to base 64. Useful for example, uploading/creating server emojis. */\nexport async function urlToBase64(url: string): Promise<string> {\n const buffer = await fetch(url).then(async (res) => await res.arrayBuffer())\n const imageStr = encode(buffer)\n const type = url.substring(url.lastIndexOf('.') + 1)\n return `data:image/${type};base64,${imageStr}`\n}\n"],"names":["fetch","encode","urlToBase64","url","buffer","then","res","arrayBuffer","imageStr","type","substring","lastIndexOf"],"mappings":"AAAA,OAAOA,WAAW,aAAY;AAC9B,SAASC,MAAM,QAAQ,cAAa;AAEpC,qFAAqF,GACrF,OAAO,eAAeC,YAAYC,GAAW,EAAmB;IAC9D,MAAMC,SAAS,MAAMJ,MAAMG,KAAKE,IAAI,CAAC,OAAOC,MAAQ,MAAMA,IAAIC,WAAW;IACzE,MAAMC,WAAWP,OAAOG;IACxB,MAAMK,OAAON,IAAIO,SAAS,CAACP,IAAIQ,WAAW,CAAC,OAAO;IAClD,OAAO,CAAC,WAAW,EAAEF,KAAK,QAAQ,EAAED,SAAS,CAAC;AAChD,CAAC"}
1
+ {"version":3,"sources":["../src/urlToBase64.ts"],"sourcesContent":["import { encode } from './base64.js'\n\n/** Converts a url to base 64. Useful for example, uploading/creating server emojis. */\nexport async function urlToBase64(url: string): Promise<string> {\n const buffer = await fetch(url).then(async (res) => await res.arrayBuffer())\n const imageStr = encode(buffer)\n const type = url.substring(url.lastIndexOf('.') + 1)\n return `data:image/${type};base64,${imageStr}`\n}\n"],"names":["encode","urlToBase64","url","buffer","fetch","then","res","arrayBuffer","imageStr","type","substring","lastIndexOf"],"mappings":"AAAA,SAASA,MAAM,QAAQ,cAAa;AAEpC,qFAAqF,GACrF,OAAO,eAAeC,YAAYC,GAAW,EAAmB;IAC9D,MAAMC,SAAS,MAAMC,MAAMF,KAAKG,IAAI,CAAC,OAAOC,MAAQ,MAAMA,IAAIC,WAAW;IACzE,MAAMC,WAAWR,OAAOG;IACxB,MAAMM,OAAOP,IAAIQ,SAAS,CAACR,IAAIS,WAAW,CAAC,OAAO;IAClD,OAAO,CAAC,WAAW,EAAEF,KAAK,QAAQ,EAAED,SAAS,CAAC;AAChD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@discordeno/utils",
3
- "version": "19.0.0-next.0b02607",
3
+ "version": "19.0.0-next.0b93eed",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "type": "module",
@@ -18,13 +18,13 @@
18
18
  "test:unit-coverage": "c8 mocha --no-warnings 'tests/**/*.spec.ts'",
19
19
  "test:unit": "c8 --r lcov mocha --no-warnings 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js utils",
20
20
  "test:deno-unit": "swc tests --delete-dir-on-start -C jsc.minify.mangle=false --out-dir denoTestsDist && node ../../scripts/fixDenoTestExtension.js && deno test -A --import-map ../../denoImportMap.json denoTestsDist",
21
+ "test:bun-unit": "node ../../scripts/fixBunTestExtension.js && bun test bunTestsDist",
21
22
  "test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/**/*.spec.ts'",
22
23
  "test:type": "tsc --noEmit",
23
24
  "test:test-type": "tsc --project tsconfig.test.json"
24
25
  },
25
26
  "dependencies": {
26
- "@discordeno/types": "19.0.0-next.0b02607",
27
- "node-fetch": "^3.3.1",
27
+ "@discordeno/types": "19.0.0-next.0b93eed",
28
28
  "tweetnacl": "^1.0.3"
29
29
  },
30
30
  "devDependencies": {