commandkit 0.1.6-dev.20231112143016 → 0.1.6-dev.20231113064545

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/bin/build.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  // @ts-check
2
2
 
3
3
  import { build } from 'tsup';
4
- import ora from 'ora';
5
4
  import { Colors, erase, findCommandKitJSON, panic, write } from './common.mjs';
5
+ import ora from 'ora';
6
6
 
7
7
  export async function bootstrapProductionBuild(config) {
8
8
  const { minify = false, outDir = 'dist', main, src } = findCommandKitJSON(config);
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { CommandInteraction, Client, ChatInputCommandInteraction, ContextMenuCommandInteraction, PermissionResolvable, APIApplicationCommandOption, ButtonInteraction, Awaitable, Message, InteractionCollectorOptions, ButtonBuilder } from 'discord.js';
1
+ import { CommandInteraction, Client, ChatInputCommandInteraction, ContextMenuCommandInteraction, PermissionsString, APIApplicationCommandOption, ButtonInteraction, Awaitable, Message, InteractionCollectorOptions, ButtonBuilder } from 'discord.js';
2
2
 
3
3
  interface CommandProps {
4
4
  interaction: CommandInteraction;
@@ -25,8 +25,8 @@ interface CommandOptions {
25
25
  guildOnly?: boolean;
26
26
  devOnly?: boolean;
27
27
  deleted?: boolean;
28
- userPermissions?: PermissionResolvable;
29
- botPermissions?: PermissionResolvable;
28
+ userPermissions?: PermissionsString[];
29
+ botPermissions?: PermissionsString[];
30
30
  [key: string]: any;
31
31
  }
32
32
  declare enum CommandType {
@@ -176,13 +176,15 @@ declare class ButtonKit extends ButtonBuilder {
176
176
  * .setStyle(ButtonStyle.Primary)
177
177
  * .setCustomId('click_me');
178
178
  *
179
- * const message = await channel.send({ content: 'Click the button', components: [new MessageActionRow().addComponents(button)] });
179
+ * const row = new ActionRowBuilder().addComponents(button);
180
+ *
181
+ * const message = await channel.send({ content: 'Click the button', components: [row] });
180
182
  *
181
183
  * button.onClick(async (interaction) => {
182
184
  * await interaction.reply('You clicked me!');
183
185
  * }, { message });
184
186
  *
185
- * // remove onClick handler and destroy the interaction collector
187
+ * // Remove onClick handler and destroy the interaction collector
186
188
  * button.onClick(null);
187
189
  * ```
188
190
  */
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CommandInteraction, Client, ChatInputCommandInteraction, ContextMenuCommandInteraction, PermissionResolvable, APIApplicationCommandOption, ButtonInteraction, Awaitable, Message, InteractionCollectorOptions, ButtonBuilder } from 'discord.js';
1
+ import { CommandInteraction, Client, ChatInputCommandInteraction, ContextMenuCommandInteraction, PermissionsString, APIApplicationCommandOption, ButtonInteraction, Awaitable, Message, InteractionCollectorOptions, ButtonBuilder } from 'discord.js';
2
2
 
3
3
  interface CommandProps {
4
4
  interaction: CommandInteraction;
@@ -25,8 +25,8 @@ interface CommandOptions {
25
25
  guildOnly?: boolean;
26
26
  devOnly?: boolean;
27
27
  deleted?: boolean;
28
- userPermissions?: PermissionResolvable;
29
- botPermissions?: PermissionResolvable;
28
+ userPermissions?: PermissionsString[];
29
+ botPermissions?: PermissionsString[];
30
30
  [key: string]: any;
31
31
  }
32
32
  declare enum CommandType {
@@ -176,13 +176,15 @@ declare class ButtonKit extends ButtonBuilder {
176
176
  * .setStyle(ButtonStyle.Primary)
177
177
  * .setCustomId('click_me');
178
178
  *
179
- * const message = await channel.send({ content: 'Click the button', components: [new MessageActionRow().addComponents(button)] });
179
+ * const row = new ActionRowBuilder().addComponents(button);
180
+ *
181
+ * const message = await channel.send({ content: 'Click the button', components: [row] });
180
182
  *
181
183
  * button.onClick(async (interaction) => {
182
184
  * await interaction.reply('You clicked me!');
183
185
  * }, { message });
184
186
  *
185
- * // remove onClick handler and destroy the interaction collector
187
+ * // Remove onClick handler and destroy the interaction collector
186
188
  * button.onClick(null);
187
189
  * ```
188
190
  */
package/dist/index.js CHANGED
@@ -364,33 +364,6 @@ async function registerDevCommands(client, commands, guildIds) {
364
364
  }
365
365
  }
366
366
 
367
- // src/handlers/command-handler/validations/botPermissions.ts
368
- function botPermissions_default({ interaction, targetCommand }) {
369
- const botMember = interaction.guild?.members.me;
370
- let commandPermissions = targetCommand.options?.botPermissions;
371
- if (!botMember || !commandPermissions)
372
- return;
373
- if (!Array.isArray(commandPermissions)) {
374
- commandPermissions = [commandPermissions];
375
- }
376
- const missingPermissions = [];
377
- for (const permission of commandPermissions) {
378
- const hasPermission = botMember.permissions.has(permission);
379
- if (!hasPermission) {
380
- missingPermissions.push(`\`${permission.toString()}\``);
381
- }
382
- }
383
- if (missingPermissions.length) {
384
- interaction.reply({
385
- content: `\u274C I do not have enough permissions to execute this command. Missing: ${missingPermissions.join(
386
- ", "
387
- )}`,
388
- ephemeral: true
389
- });
390
- return true;
391
- }
392
- }
393
-
394
367
  // src/handlers/command-handler/validations/devOnly.ts
395
368
  function devOnly_default({ interaction, targetCommand, handlerData }) {
396
369
  if (targetCommand.options?.devOnly) {
@@ -431,35 +404,66 @@ function guildOnly_default({ interaction, targetCommand }) {
431
404
  }
432
405
  }
433
406
 
434
- // src/handlers/command-handler/validations/userPermissions.ts
435
- function userPermissions_default({ interaction, targetCommand }) {
436
- const memberPermissions = interaction.memberPermissions;
437
- let commandPermissions = targetCommand.options?.userPermissions;
438
- if (!memberPermissions || !commandPermissions)
407
+ // src/handlers/command-handler/validations/permissions.ts
408
+ var import_discord = require("discord.js");
409
+ function permissions_default({ interaction, targetCommand }) {
410
+ const userPermissions = interaction.memberPermissions;
411
+ let userPermissionsRequired = targetCommand.options?.userPermissions;
412
+ let missingUserPermissions = [];
413
+ const botPermissions = interaction.guild?.members.me?.permissions;
414
+ let botPermissionsRequired = targetCommand.options?.botPermissions;
415
+ let missingBotPermissions = [];
416
+ if (!userPermissionsRequired?.length && !botPermissionsRequired?.length) {
439
417
  return;
440
- if (!Array.isArray(commandPermissions)) {
441
- commandPermissions = [commandPermissions];
442
418
  }
443
- const missingPermissions = [];
444
- for (const permission of commandPermissions) {
445
- const hasPermission = memberPermissions.has(permission);
446
- if (!hasPermission) {
447
- missingPermissions.push(`\`${permission.toString()}\``);
419
+ if (userPermissions && userPermissionsRequired) {
420
+ for (const permission of userPermissionsRequired) {
421
+ const hasPermission = userPermissions.has(permission);
422
+ if (!hasPermission) {
423
+ missingUserPermissions.push(permission);
424
+ }
448
425
  }
449
426
  }
450
- if (missingPermissions.length) {
451
- interaction.reply({
452
- content: `\u274C You do not have enough permissions to run this command. Missing: ${missingPermissions.join(
453
- ", "
454
- )}`,
455
- ephemeral: true
456
- });
457
- return true;
427
+ if (botPermissions && botPermissionsRequired) {
428
+ for (const permission of botPermissionsRequired) {
429
+ const hasPermission = botPermissions.has(permission);
430
+ if (!hasPermission) {
431
+ missingBotPermissions.push(permission);
432
+ }
433
+ }
434
+ }
435
+ if (!missingUserPermissions.length && !missingBotPermissions.length) {
436
+ return;
458
437
  }
438
+ const pattern = /([a-z])([A-Z])|([A-Z]+)([A-Z][a-z])/g;
439
+ missingUserPermissions = missingUserPermissions.map((str) => str.replace(pattern, "$1$3 $2$4"));
440
+ missingBotPermissions = missingBotPermissions.map((str) => str.replace(pattern, "$1$3 $2$4"));
441
+ let embedDescription = "";
442
+ const formatter = new Intl.ListFormat("en", { style: "long", type: "conjunction" });
443
+ const getPermissionWord = (permissions) => permissions.length === 1 ? "permission" : "permissions";
444
+ if (missingUserPermissions.length) {
445
+ const formattedPermissions = missingUserPermissions.map((p) => `\`${p}\``);
446
+ const permissionsString = formatter.format(formattedPermissions);
447
+ embedDescription += `- You must have the ${permissionsString} ${getPermissionWord(
448
+ missingUserPermissions
449
+ )} to be able to run this command.
450
+ `;
451
+ }
452
+ if (missingBotPermissions.length) {
453
+ const formattedPermissions = missingBotPermissions.map((p) => `\`${p}\``);
454
+ const permissionsString = formatter.format(formattedPermissions);
455
+ embedDescription += `- I must have the ${permissionsString} ${getPermissionWord(
456
+ missingBotPermissions
457
+ )} to be able to execute this command.
458
+ `;
459
+ }
460
+ const embed = new import_discord.EmbedBuilder().setTitle(`:x: Missing permissions!`).setDescription(embedDescription).setColor("Red");
461
+ interaction.reply({ embeds: [embed], ephemeral: true });
462
+ return true;
459
463
  }
460
464
 
461
465
  // src/handlers/command-handler/validations/index.ts
462
- var validations_default = [botPermissions_default, devOnly_default, guildOnly_default, userPermissions_default];
466
+ var validations_default = [devOnly_default, guildOnly_default, permissions_default];
463
467
 
464
468
  // src/handlers/command-handler/CommandHandler.ts
465
469
  var import_rfdc = __toESM(require("rfdc"));
@@ -903,15 +907,15 @@ var CommandKit = class {
903
907
  }
904
908
  };
905
909
 
906
- // src/components/Button.ts
907
- var import_discord = require("discord.js");
908
- var ButtonKit = class extends import_discord.ButtonBuilder {
910
+ // src/components/ButtonKit.ts
911
+ var import_discord2 = require("discord.js");
912
+ var ButtonKit = class extends import_discord2.ButtonBuilder {
909
913
  #onClickHandler = null;
910
914
  #contextData = null;
911
915
  #collector = null;
912
916
  onClick(handler, data) {
913
- if (this.data.style === import_discord.ButtonStyle.Link) {
914
- throw new TypeError('Cannot setup "onClick" handler for link buttons');
917
+ if (this.data.style === import_discord2.ButtonStyle.Link) {
918
+ throw new TypeError('Cannot setup "onClick" handler on link buttons.');
915
919
  }
916
920
  this.#destroyCollector();
917
921
  this.#onClickHandler = handler;
@@ -923,14 +927,14 @@ var ButtonKit = class extends import_discord.ButtonBuilder {
923
927
  #setupInteractionCollector() {
924
928
  if (!this.#contextData || !this.#onClickHandler)
925
929
  return;
926
- const message = this.#contextData?.message;
930
+ const message = this.#contextData.message;
927
931
  if (!message) {
928
932
  throw new TypeError(
929
- 'Cannot setup "onClick" handler without a message in the context data'
933
+ 'Cannot setup "onClick" handler without a message in the context data.'
930
934
  );
931
935
  }
932
936
  if ("customId" in this.data && !this.data.customId) {
933
- throw new TypeError('Cannot setup "onClick" handler without a custom id');
937
+ throw new TypeError('Cannot setup "onClick" handler on a button without a custom id.');
934
938
  }
935
939
  const data = {
936
940
  time: 864e5,
@@ -939,7 +943,7 @@ var ButtonKit = class extends import_discord.ButtonBuilder {
939
943
  };
940
944
  const collector = this.#collector = message.createMessageComponentCollector({
941
945
  filter: (interaction) => interaction.customId === this.data.custom_id && interaction.message.id === message.id,
942
- componentType: import_discord.ComponentType.Button,
946
+ componentType: import_discord2.ComponentType.Button,
943
947
  ...data
944
948
  });
945
949
  this.#collector.on("collect", (interaction) => {
@@ -950,7 +954,7 @@ var ButtonKit = class extends import_discord.ButtonBuilder {
950
954
  return collector.stop("destroyed");
951
955
  }
952
956
  if (data.autoReset) {
953
- this.#collector?.resetTimer();
957
+ this.#collector.resetTimer();
954
958
  }
955
959
  return handler(interaction);
956
960
  });
package/dist/index.mjs CHANGED
@@ -331,33 +331,6 @@ async function registerDevCommands(client, commands, guildIds) {
331
331
  }
332
332
  }
333
333
 
334
- // src/handlers/command-handler/validations/botPermissions.ts
335
- function botPermissions_default({ interaction, targetCommand }) {
336
- const botMember = interaction.guild?.members.me;
337
- let commandPermissions = targetCommand.options?.botPermissions;
338
- if (!botMember || !commandPermissions)
339
- return;
340
- if (!Array.isArray(commandPermissions)) {
341
- commandPermissions = [commandPermissions];
342
- }
343
- const missingPermissions = [];
344
- for (const permission of commandPermissions) {
345
- const hasPermission = botMember.permissions.has(permission);
346
- if (!hasPermission) {
347
- missingPermissions.push(`\`${permission.toString()}\``);
348
- }
349
- }
350
- if (missingPermissions.length) {
351
- interaction.reply({
352
- content: `\u274C I do not have enough permissions to execute this command. Missing: ${missingPermissions.join(
353
- ", "
354
- )}`,
355
- ephemeral: true
356
- });
357
- return true;
358
- }
359
- }
360
-
361
334
  // src/handlers/command-handler/validations/devOnly.ts
362
335
  function devOnly_default({ interaction, targetCommand, handlerData }) {
363
336
  if (targetCommand.options?.devOnly) {
@@ -398,35 +371,66 @@ function guildOnly_default({ interaction, targetCommand }) {
398
371
  }
399
372
  }
400
373
 
401
- // src/handlers/command-handler/validations/userPermissions.ts
402
- function userPermissions_default({ interaction, targetCommand }) {
403
- const memberPermissions = interaction.memberPermissions;
404
- let commandPermissions = targetCommand.options?.userPermissions;
405
- if (!memberPermissions || !commandPermissions)
374
+ // src/handlers/command-handler/validations/permissions.ts
375
+ import { EmbedBuilder } from "discord.js";
376
+ function permissions_default({ interaction, targetCommand }) {
377
+ const userPermissions = interaction.memberPermissions;
378
+ let userPermissionsRequired = targetCommand.options?.userPermissions;
379
+ let missingUserPermissions = [];
380
+ const botPermissions = interaction.guild?.members.me?.permissions;
381
+ let botPermissionsRequired = targetCommand.options?.botPermissions;
382
+ let missingBotPermissions = [];
383
+ if (!userPermissionsRequired?.length && !botPermissionsRequired?.length) {
406
384
  return;
407
- if (!Array.isArray(commandPermissions)) {
408
- commandPermissions = [commandPermissions];
409
385
  }
410
- const missingPermissions = [];
411
- for (const permission of commandPermissions) {
412
- const hasPermission = memberPermissions.has(permission);
413
- if (!hasPermission) {
414
- missingPermissions.push(`\`${permission.toString()}\``);
386
+ if (userPermissions && userPermissionsRequired) {
387
+ for (const permission of userPermissionsRequired) {
388
+ const hasPermission = userPermissions.has(permission);
389
+ if (!hasPermission) {
390
+ missingUserPermissions.push(permission);
391
+ }
415
392
  }
416
393
  }
417
- if (missingPermissions.length) {
418
- interaction.reply({
419
- content: `\u274C You do not have enough permissions to run this command. Missing: ${missingPermissions.join(
420
- ", "
421
- )}`,
422
- ephemeral: true
423
- });
424
- return true;
394
+ if (botPermissions && botPermissionsRequired) {
395
+ for (const permission of botPermissionsRequired) {
396
+ const hasPermission = botPermissions.has(permission);
397
+ if (!hasPermission) {
398
+ missingBotPermissions.push(permission);
399
+ }
400
+ }
401
+ }
402
+ if (!missingUserPermissions.length && !missingBotPermissions.length) {
403
+ return;
425
404
  }
405
+ const pattern = /([a-z])([A-Z])|([A-Z]+)([A-Z][a-z])/g;
406
+ missingUserPermissions = missingUserPermissions.map((str) => str.replace(pattern, "$1$3 $2$4"));
407
+ missingBotPermissions = missingBotPermissions.map((str) => str.replace(pattern, "$1$3 $2$4"));
408
+ let embedDescription = "";
409
+ const formatter = new Intl.ListFormat("en", { style: "long", type: "conjunction" });
410
+ const getPermissionWord = (permissions) => permissions.length === 1 ? "permission" : "permissions";
411
+ if (missingUserPermissions.length) {
412
+ const formattedPermissions = missingUserPermissions.map((p) => `\`${p}\``);
413
+ const permissionsString = formatter.format(formattedPermissions);
414
+ embedDescription += `- You must have the ${permissionsString} ${getPermissionWord(
415
+ missingUserPermissions
416
+ )} to be able to run this command.
417
+ `;
418
+ }
419
+ if (missingBotPermissions.length) {
420
+ const formattedPermissions = missingBotPermissions.map((p) => `\`${p}\``);
421
+ const permissionsString = formatter.format(formattedPermissions);
422
+ embedDescription += `- I must have the ${permissionsString} ${getPermissionWord(
423
+ missingBotPermissions
424
+ )} to be able to execute this command.
425
+ `;
426
+ }
427
+ const embed = new EmbedBuilder().setTitle(`:x: Missing permissions!`).setDescription(embedDescription).setColor("Red");
428
+ interaction.reply({ embeds: [embed], ephemeral: true });
429
+ return true;
426
430
  }
427
431
 
428
432
  // src/handlers/command-handler/validations/index.ts
429
- var validations_default = [botPermissions_default, devOnly_default, guildOnly_default, userPermissions_default];
433
+ var validations_default = [devOnly_default, guildOnly_default, permissions_default];
430
434
 
431
435
  // src/handlers/command-handler/CommandHandler.ts
432
436
  import rdfc from "rfdc";
@@ -870,15 +874,19 @@ var CommandKit = class {
870
874
  }
871
875
  };
872
876
 
873
- // src/components/Button.ts
874
- import { ButtonBuilder, ButtonStyle, ComponentType } from "discord.js";
877
+ // src/components/ButtonKit.ts
878
+ import {
879
+ ButtonStyle,
880
+ ButtonBuilder,
881
+ ComponentType
882
+ } from "discord.js";
875
883
  var ButtonKit = class extends ButtonBuilder {
876
884
  #onClickHandler = null;
877
885
  #contextData = null;
878
886
  #collector = null;
879
887
  onClick(handler, data) {
880
888
  if (this.data.style === ButtonStyle.Link) {
881
- throw new TypeError('Cannot setup "onClick" handler for link buttons');
889
+ throw new TypeError('Cannot setup "onClick" handler on link buttons.');
882
890
  }
883
891
  this.#destroyCollector();
884
892
  this.#onClickHandler = handler;
@@ -890,14 +898,14 @@ var ButtonKit = class extends ButtonBuilder {
890
898
  #setupInteractionCollector() {
891
899
  if (!this.#contextData || !this.#onClickHandler)
892
900
  return;
893
- const message = this.#contextData?.message;
901
+ const message = this.#contextData.message;
894
902
  if (!message) {
895
903
  throw new TypeError(
896
- 'Cannot setup "onClick" handler without a message in the context data'
904
+ 'Cannot setup "onClick" handler without a message in the context data.'
897
905
  );
898
906
  }
899
907
  if ("customId" in this.data && !this.data.customId) {
900
- throw new TypeError('Cannot setup "onClick" handler without a custom id');
908
+ throw new TypeError('Cannot setup "onClick" handler on a button without a custom id.');
901
909
  }
902
910
  const data = {
903
911
  time: 864e5,
@@ -917,7 +925,7 @@ var ButtonKit = class extends ButtonBuilder {
917
925
  return collector.stop("destroyed");
918
926
  }
919
927
  if (data.autoReset) {
920
- this.#collector?.resetTimer();
928
+ this.#collector.resetTimer();
921
929
  }
922
930
  return handler(interaction);
923
931
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "commandkit",
3
3
  "description": "Beginner friendly command & event handler for Discord.js",
4
- "version": "0.1.6-dev.20231112143016",
4
+ "version": "0.1.6-dev.20231113064545",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",