@spatulox/discord-interaction-manager 1.0.0 → 1.0.1

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.
@@ -136,7 +136,7 @@ class BaseCLI {
136
136
  }
137
137
  async saveFile(folderName, filename, data) {
138
138
  let finalFilename = filename;
139
- if (await FileManager_1.FileManager.readJsonFile(`./handlers/${folderName}/${filename}`)) {
139
+ if (await FileManager_1.FileManager.readJsonFile(`./handlers/${folderName}/${filename.split(".json")[0] + ".json"}`)) {
140
140
  if (!await this.yesNoInput(`"${finalFilename}" already exists. Overwrite? (y/n): `)) {
141
141
  const timestamp = Date.now();
142
142
  finalFilename = `${filename.replace('.json', '')}-${timestamp}`;
@@ -1,11 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ContextMenuGeneratorCLI = void 0;
4
- const BaseCLI_1 = require("../BaseCLI");
5
- const discord_js_1 = require("discord.js");
6
- const DiscordRegex_1 = require("../../utils/DiscordRegex");
7
4
  const FolderName_1 = require("../../type/FolderName");
8
- class ContextMenuGeneratorCLI extends BaseCLI_1.BaseCLI {
5
+ const InteractionGeneratorCLI_1 = require("./InteractionGeneratorCLI");
6
+ class ContextMenuGeneratorCLI extends InteractionGeneratorCLI_1.InteractionGeneratorCLI {
9
7
  constructor() {
10
8
  super(...arguments);
11
9
  this.menuSelection = [
@@ -14,96 +12,41 @@ class ContextMenuGeneratorCLI extends BaseCLI_1.BaseCLI {
14
12
  ];
15
13
  }
16
14
  getTitle() {
17
- return "šŸ“ Context Menu JSON Generator";
15
+ return "šŸ½ļø Context Menu JSON Generator";
18
16
  }
19
17
  async execute() {
20
- const config = { dm_permission: false, integration_types: [], name: "", type: 2 };
21
- // 1. Context Menu Name
22
- console.clear();
23
- console.log("šŸ‘¤ 1/10 - Name");
24
- config.name = await this.requireInput("Enter Context Menu name (ex: 'Example context Menu'): ");
25
- // 2. Type (2=User, 3=Message)
26
- console.clear();
27
- console.log("šŸ”§ 2/10 - Type");
28
- console.log("2 => Context Menu for users");
29
- console.log("3 => Context Menu for messages");
30
- config.type = parseInt(await this.requireInput("Enter type (2 or 3): ", val => ["2", "3"].includes(val)));
31
- // 3. Member Permissions
32
- console.clear();
33
- console.log("šŸ” 3/10 - Permissions");
34
- console.log("šŸ“‹ Valid permissions:\n", Object.keys(discord_js_1.PermissionFlagsBits).join(', '));
35
- const permsInput = await this.requireInput("Default member permissions (comma separated, or 'none'): ", (val) => {
36
- if (!val || val.toLowerCase() === "none" || val == '')
37
- return true;
38
- const permissions = val.split(",").map(p => p.trim());
39
- const invalidPerms = permissions.filter(perm => !(perm in discord_js_1.PermissionFlagsBits));
40
- if (invalidPerms.length > 0) {
41
- console.log(`āŒ Invalid permissions: ${invalidPerms.join(', ')}`);
42
- console.log("šŸ“‹ Valid permissions:\n", Object.keys(discord_js_1.PermissionFlagsBits).join(', '));
43
- return false;
44
- }
45
- return true;
46
- }, true);
47
- if (permsInput !== '' && permsInput.toLowerCase() !== "none") {
48
- config.default_member_permissions = permsInput.split(",")
49
- .map(p => p.trim());
50
- }
51
- // 4. DM Permission
52
- console.clear();
53
- console.log("šŸ’¬ 4/10 - DM Permission");
54
- config.dm_permission = (await this.yesNoInput("Allow in DMs? (y/n): "));
55
- // 5. Integration Types
56
- console.clear();
57
- console.log("šŸ”— 5/10 - Integration Types");
58
- console.log("0 => GUILD_INSTALL");
59
- console.log("1 => USER_INSTALL");
60
- console.log("(comma separated, or 'all')");
61
- const intInput = await this.requireInput("Integration types: ");
62
- if (intInput.toLowerCase() === "all") {
63
- config.integration_types = [0, 1];
64
- }
65
- else {
66
- config.integration_types = intInput.split(",").map(i => parseInt(i.trim())).filter(i => !isNaN(i));
67
- }
68
- console.clear();
69
- console.log("🌐 6/10 - Contexts");
70
- console.log("0 => Can be used inside server");
71
- console.log("1 => Can be used inside DMs with bot");
72
- console.log("2 => Group DMs & other DMs");
73
- console.log("(comma separated, or 'all')");
74
- const ctxInput = await this.requireInput("Contexts: ");
75
- if (ctxInput.toLowerCase() === "all") {
76
- config.contexts = [0, 1, 2];
77
- }
78
- else {
79
- config.contexts = ctxInput.split(",").map(i => parseInt(i.trim())).filter(i => !isNaN(i));
80
- }
81
- // 7. Guild IDs
82
- console.clear();
83
- console.log("šŸ  7/10 - Guild IDs (optional)");
84
- console.log(" => Used to deploy specific context menu for specific guild");
85
- const guildInput = await this.requireInput("Guild IDs (comma separated, or 'none'): ", (val) => {
86
- if (!val || val.toLowerCase() === "none")
87
- return true;
88
- const ids = val.split(",").map(id => id.trim());
89
- const invalidIds = ids.filter(id => !DiscordRegex_1.DiscordRegex.GUILD_ID.test(id));
90
- if (invalidIds.length > 0) {
91
- console.log(`āŒ Invalid Guild IDs: ${invalidIds.join(', ')}`);
92
- console.log("ā„¹ļø Discord Guild ID = 18 chiffres (ex: 1111160769132896377)");
93
- return false;
94
- }
95
- console.log("āœ… Valid Guild IDs:", ids.join(', '));
96
- return true;
97
- }, true);
98
- if (guildInput.toLowerCase() !== "none" && guildInput !== "") {
99
- config.guildID = guildInput.split(",").map(id => id.trim());
18
+ const config = {
19
+ name: "",
20
+ type: 2,
21
+ dm_permission: false,
22
+ integration_types: [0, 1]
23
+ };
24
+ // 1. Type & Nom
25
+ console.clear();
26
+ console.log("šŸ½ļø 1/5 - Menu Type");
27
+ console.log("2 = User Menu | 3 = Message Menu");
28
+ config.type = parseInt(await this.requireInput("Type (2 or 3): ", val => ["2", "3"].includes(val)));
29
+ console.clear();
30
+ config.name = await this.requireInput("Name (1-32 chars): ", val => val.length >= 1 && val.length <= 32);
31
+ // 2. Permissions
32
+ console.clear();
33
+ console.log("šŸ” 2/5 - Command Permissions");
34
+ await this.addPermissions(config);
35
+ // 3. DM
36
+ console.clear();
37
+ console.log("šŸ’¬ 3/5 - DM Permissions");
38
+ config.dm_permission = await this.yesNoInput("Authorize in DM ? (y/n): ");
39
+ // 4. Guild Specific
40
+ console.clear();
41
+ console.log("āš™ļø 4/5 - Guild Specific");
42
+ if (await this.yesNoInput("Guild Specific ? (y/n): ")) {
43
+ config.guild_ids = await this.optionalGuildIds();
100
44
  }
101
- // 8. Filename
45
+ // 5. Save
102
46
  console.clear();
103
- console.log("šŸ’¾ 8/10 - File");
104
- const filename = (await this.requireInput("Filename (ex: my-context-menu): ")) + ".json";
47
+ console.log("šŸ’¾ 5/5 - Save");
48
+ const filename = `${config.name.toLowerCase().replace(/\s+/g, '-')}.json`;
105
49
  await this.saveFile(FolderName_1.FolderName.CONTEXT_MENU, filename, config);
106
- return this.showMainMenu();
107
50
  }
108
51
  }
109
52
  exports.ContextMenuGeneratorCLI = ContextMenuGeneratorCLI;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GenerationCLI = void 0;
4
4
  const BaseCLI_1 = require("../BaseCLI");
5
5
  const ContextMenuGeneratorCLI_1 = require("./ContextMenuGeneratorCLI");
6
- const ModalGeneratorCLI_1 = require("./ModalGeneratorCLI");
7
6
  const SlashCommandsGeneratorCLI_1 = require("./SlashCommandsGeneratorCLI");
8
7
  class GenerationCLI extends BaseCLI_1.BaseCLI {
9
8
  constructor() {
@@ -11,7 +10,6 @@ class GenerationCLI extends BaseCLI_1.BaseCLI {
11
10
  this.menuSelection = [
12
11
  { label: 'Generate Slash Command Template', action: () => new SlashCommandsGeneratorCLI_1.SlashCommandGeneratorCLI(this) },
13
12
  { label: 'Generate Context Menu Template', action: () => new ContextMenuGeneratorCLI_1.ContextMenuGeneratorCLI(this) },
14
- { label: 'Generate Modal Template', action: () => new ModalGeneratorCLI_1.ModalGeneratorCLI(this) },
15
13
  { label: 'Back', action: () => this.goBack() },
16
14
  ];
17
15
  }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InteractionGeneratorCLI = void 0;
4
+ const BaseCLI_1 = require("../BaseCLI");
5
+ const discord_js_1 = require("discord.js");
6
+ const DiscordRegex_1 = require("../../utils/DiscordRegex");
7
+ class InteractionGeneratorCLI extends BaseCLI_1.BaseCLI {
8
+ async addPermissions(config) {
9
+ console.clear();
10
+ const permEntries = Object.entries(discord_js_1.PermissionFlagsBits);
11
+ const numberedPerms = permEntries.map(([name, _value], index) => `${index + 1}. ${name}`).join('\n');
12
+ console.log("Valid Permissions:\n" + numberedPerms);
13
+ const input = await this.requireInput("Permission numbers (comma-separated, 'everyone', or leave empty): ", (val) => {
14
+ if (!val.trim() || val.toLowerCase() === 'everyone')
15
+ return true;
16
+ return val.split(',').every(numStr => {
17
+ const num = parseInt(numStr.trim());
18
+ return num >= 1 && num <= permEntries.length && !isNaN(num);
19
+ });
20
+ }, true);
21
+ if (!input.trim() || input.toLowerCase() === 'everyone') {
22
+ config.default_member_permissions_string = ['everyone'];
23
+ config.default_member_permissions = 0n.toString();
24
+ return;
25
+ }
26
+ const selectedNums = input.split(',').map(n => parseInt(n.trim()));
27
+ const selectedPermNames = [];
28
+ for (const i of selectedNums) {
29
+ const entry = permEntries[i];
30
+ if (entry) {
31
+ selectedPermNames.push(entry[0]);
32
+ }
33
+ }
34
+ config.default_member_permissions_string = selectedPermNames;
35
+ config.default_member_permissions = this.permissionsToBitfield(input.split(","));
36
+ }
37
+ async optionalGuildIds() {
38
+ const input = await this.prompt("Guild IDs (separated by comma, or 'none' to cancel): ");
39
+ return input.trim() && input.toLowerCase() !== 'none'
40
+ ? input.split(',').map(id => id.trim()).filter(DiscordRegex_1.DiscordRegex.GUILD_ID.test.bind(DiscordRegex_1.DiscordRegex.GUILD_ID))
41
+ : undefined;
42
+ }
43
+ permissionsToBitfield(perms) {
44
+ if (!perms || perms.length === 0)
45
+ return 0n.toString();
46
+ let bits = 0n;
47
+ for (const name of perms) {
48
+ const value = discord_js_1.PermissionFlagsBits[name];
49
+ if (!value) {
50
+ console.warn(`Unknow permission in default_member_permissions: ${name}`);
51
+ continue;
52
+ }
53
+ bits |= value;
54
+ }
55
+ return bits.toString();
56
+ }
57
+ }
58
+ exports.InteractionGeneratorCLI = InteractionGeneratorCLI;
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SlashCommandGeneratorCLI = void 0;
4
- const BaseCLI_1 = require("../BaseCLI");
5
4
  const FolderName_1 = require("../../type/FolderName");
6
- const discord_js_1 = require("discord.js");
7
- const DiscordRegex_1 = require("../../utils/DiscordRegex");
8
- class SlashCommandGeneratorCLI extends BaseCLI_1.BaseCLI {
5
+ const InteractionType_1 = require("../type/InteractionType");
6
+ const InteractionGeneratorCLI_1 = require("./InteractionGeneratorCLI");
7
+ class SlashCommandGeneratorCLI extends InteractionGeneratorCLI_1.InteractionGeneratorCLI {
9
8
  constructor() {
10
9
  super(...arguments);
11
10
  this.menuSelection = [
@@ -23,199 +22,125 @@ class SlashCommandGeneratorCLI extends BaseCLI_1.BaseCLI {
23
22
  description: "",
24
23
  options: [],
25
24
  dm_permission: false,
26
- default_member_permissions: undefined,
27
- default_member_permissions_string: undefined,
28
25
  integration_types: [0, 1],
29
26
  contexts: [0]
30
27
  };
31
- // 1. Command Name
32
28
  console.clear();
33
- console.log("šŸ“ 1/12 - Command Name");
34
- config.name = await this.requireInput("Enter command name (lowercase, no spaces): ", val => /^[a-z_-]{1,32}$/.test(val));
35
- // 2. Command Description
29
+ console.log("šŸ“ 1/6 - Base");
30
+ config.name = await this.requireInput("Name (a-z0-9_-, 1-32 chars): ", val => /^[a-z0-9_-]{1,32}$/.test(val));
31
+ config.description = await this.requireInput("Description (1-100 chars): ", val => val.length >= 1 && val.length <= 100);
36
32
  console.clear();
37
- console.log("šŸ“„ 2/12 - Command Description");
38
- config.description = await this.requireInput("Enter command description (1-100 chars): ", val => val.length >= 1 && val.length <= 100);
39
- // 3. Member Permissions
33
+ console.log("šŸ” 2/6 - Command Permissions");
34
+ await this.addPermissions(config);
40
35
  console.clear();
41
- console.log("šŸ” 3/12 - Permissions");
42
- console.log("šŸ“‹ Valid permissions:\n", Object.keys(discord_js_1.PermissionFlagsBits).join(', '));
43
- const permsInput = await this.requireInput("Default member permissions (comma separated, or 'none'): ", (val) => {
44
- if (!val || val.toLowerCase() === "none" || val === '')
45
- return true;
46
- const permissions = val.split(",").map(p => p.trim());
47
- const invalidPerms = permissions.filter(perm => !(perm in discord_js_1.PermissionFlagsBits));
48
- if (invalidPerms.length > 0) {
49
- console.log(`āŒ Invalid: ${invalidPerms.join(', ')}`);
50
- return false;
51
- }
52
- return true;
53
- }, true);
54
- if (permsInput && permsInput.toLowerCase() !== "none") {
55
- config.default_member_permissions_string = permsInput.split(",").map(p => p.trim());
56
- }
57
- // 4. DM Permission
58
- console.clear();
59
- console.log("šŸ’¬ 4/12 - DM Permission");
60
- config.dm_permission = (await this.yesNoInput("Allow in DMs? (y/n): "));
61
- // 5. Integration Types
62
- console.clear();
63
- console.log("šŸ”— 5/12 - Integration Types");
64
- console.log("0 => GUILD_INSTALL, 1 => USER_INSTALL (comma separated, or 'all')");
65
- const intInput = await this.requireInput("Integration types: ");
66
- if (intInput.toLowerCase() === "all") {
67
- config.integration_types = [0, 1];
68
- }
69
- else {
70
- config.integration_types = intInput.split(",").map(i => parseInt(i.trim())).filter(i => !isNaN(i));
71
- }
72
- // 6. Contexts
73
- console.clear();
74
- console.log("🌐 6/12 - Contexts");
75
- console.log("0 => Server, 1 => Bot DMs, 2 => Group/Other DMs (comma separated, or 'server')");
76
- const ctxInput = await this.requireInput("Contexts: ", undefined, true);
77
- if (!ctxInput || ctxInput.trim() === "") {
78
- config.contexts = [0, 1, 2];
79
- }
80
- else if (ctxInput.toLowerCase() === "all") {
81
- config.contexts = [0, 1, 2];
82
- }
83
- else {
84
- config.contexts = ctxInput.split(",").map(i => parseInt(i.trim())).filter(i => !isNaN(i));
85
- }
86
- // 7. Add Subcommands/Groups?
36
+ console.log("šŸ’¬ 3/6 - DM Permissions");
37
+ config.dm_permission = await this.yesNoInput("Authorize DM ? (y/n): ");
87
38
  console.clear();
88
- console.log("šŸ“‚ 7/12 - Structure");
89
- const addStructure = await this.yesNoInput("Add subcommands or groups? (y/n): ");
90
- if (addStructure) {
91
- await this.addCommandStructure(config);
92
- }
93
- else {
94
- // Add basic options if no structure
95
- await this.addSimpleOptions(config);
96
- }
97
- // 8. Guild IDs (optional)
39
+ console.log("āš™ļø 4/6 - Options/Subcommands");
40
+ await this.addOptions(config.options);
98
41
  console.clear();
99
- console.log("šŸ  8/12 - Guild IDs (optional)");
100
- const guildInput = await this.requireInput("Guild IDs (comma separated, or 'none'): ", (val) => {
101
- if (!val || val.toLowerCase() === "none")
102
- return true;
103
- const ids = val.split(",").map(id => id.trim());
104
- const invalidIds = ids.filter(id => !DiscordRegex_1.DiscordRegex.GUILD_ID.test(id));
105
- if (invalidIds.length > 0) {
106
- console.log(`āŒ Invalid Guild IDs: ${invalidIds.join(', ')}`);
107
- return false;
108
- }
109
- return true;
110
- }, true);
111
- if (guildInput && guildInput.toLowerCase() !== "none") {
112
- config.guildID = guildInput.split(",").map(id => id.trim());
42
+ console.log("āš™ļø 5/6 - Guild Specific");
43
+ if (await this.yesNoInput("Guild Specific ? (y/n): ")) {
44
+ config.guild_ids = await this.optionalGuildIds();
113
45
  }
114
- // 9. Filename
115
46
  console.clear();
116
- console.log("šŸ’¾ 9/12 - Filename");
117
- const filename = (await this.requireInput("Filename (without .json): ")) + ".json";
118
- await this.saveFile(FolderName_1.FolderName.SLASH_COMMANDS, filename, config);
47
+ console.log("šŸ’¾ 6/6 - Save");
48
+ const filename = await this.requireInput("Filename : ");
49
+ await this.saveFile(FolderName_1.FolderName.SLASH_COMMANDS, filename.split(".json")[0] ?? filename, config);
119
50
  }
120
- async addCommandStructure(config) {
121
- console.clear();
122
- console.log("šŸ“ Structure Type");
123
- console.log("1 => Add Sub Command Group");
124
- console.log("2 => Add Sub Command");
125
- const structureType = parseInt(await this.requireInput("Type (1 or 2): ", val => ["1", "2"].includes(val)));
126
- if (structureType === 1) {
127
- // Sub Command Group
128
- const groupName = await this.requireInput("Group name: ");
129
- const groupDesc = await this.requireInput("Group description: ");
130
- config.options = config.options || [];
131
- config.options.push({
132
- type: 2,
133
- name: groupName,
134
- description: groupDesc,
135
- options: []
136
- });
137
- await this.addSubCommands(config.options[config.options.length - 1].options);
138
- }
139
- else {
140
- // Direct Sub Command
141
- await this.addSubCommands(config.options);
51
+ async addOptions(options) {
52
+ const addOptions = await this.yesNoInput("Add options/subcommands ? (y/n): ");
53
+ if (!addOptions)
54
+ return;
55
+ while (true) {
56
+ console.clear();
57
+ console.log("šŸš€ Options type :");
58
+ console.log("Valid options : " +
59
+ Object.entries(InteractionType_1.DiscordOptionType)
60
+ .filter(([, value]) => typeof value === 'number')
61
+ .map(([key, value]) => `${value}.${key}`)
62
+ .join(', '));
63
+ const type = parseInt(await this.requireInput("Type (1-11): ", val => {
64
+ const n = parseInt(val);
65
+ return n >= 1 && n <= 11;
66
+ }));
67
+ const option = await this.buildOption(type);
68
+ options.push(option);
69
+ if (!await this.yesNoInput("Other option ? (y/n): "))
70
+ break;
142
71
  }
143
72
  }
144
- async addSubCommands(options) {
145
- let continueAdding = true;
146
- while (continueAdding) {
147
- console.clear();
148
- console.log("āž• Add Subcommand");
149
- const name = await this.requireInput("Subcommand name: ");
150
- const desc = await this.requireInput("Subcommand description: ");
151
- const subCmd = { type: 1, name, description: desc, options: [] };
152
- await this.addSubCommandOptions(subCmd.options);
153
- options.push(subCmd);
154
- continueAdding = await this.yesNoInput("Add another subcommand? (y/n): ");
73
+ async buildOption(type) {
74
+ const name = await this.requireInput("Option name (a-z0-9_-, 1-32): ", val => /^[a-z0-9_-]{1,32}$/.test(val));
75
+ const description = await this.requireInput("Description (1-100): ", val => val.length >= 1 && val.length <= 100);
76
+ const required = type !== 2 && await this.yesNoInput("Required ? (y/n): ");
77
+ const option = { type, name, description, required };
78
+ await this.handleOptionType(option, type);
79
+ if (type === 1 || type === 2) {
80
+ option.options = [];
81
+ await this.addOptions(option.options);
155
82
  }
83
+ return option;
156
84
  }
157
- async addSubCommandOptions(options) {
158
- let continueAdding = await this.yesNoInput("Add options to this subcommand? (y/n): ");
159
- while (continueAdding) {
160
- console.clear();
161
- console.log("Option Types:\n1=SUB_COMMAND,2=SUB_GROUP,3=STRING,4=INTEGER,5=BOOLEAN,6=USER,7=CHANNEL,8=ROLE,9=MENTIONNABLE,10=NUMBER");
162
- const type = parseInt(await this.requireInput("Option type (3-10): ", val => {
163
- const n = parseInt(val);
164
- return n >= 3 && n <= 10;
165
- }));
166
- const name = await this.requireInput("Option name: ");
167
- const description = await this.requireInput("Option description: ");
168
- const required = await this.yesNoInput("Required? (y/n): ");
169
- const option = { type, name, description, required };
170
- if ([3, 4, 10].includes(type)) {
171
- // String, Integer, Number
172
- option.choices = await this.addChoices();
173
- }
174
- if (type === 3) { // String
175
- option.min_length = parseInt(await this.prompt("Min length (optional, Enter=skip): ")) || undefined;
176
- option.max_length = parseInt(await this.prompt("Max length (optional, Enter=skip): ")) || undefined;
177
- }
178
- else if ([4, 10].includes(type)) { // Int/Number
179
- option.min_value = parseFloat(await this.prompt("Min value (optional, Enter=skip): ")) || undefined;
180
- option.max_value = parseFloat(await this.prompt("Max value (optional, Enter=skip): ")) || undefined;
181
- }
182
- else if (type === 7) { // Channel
85
+ async handleOptionType(option, type) {
86
+ switch (type) {
87
+ case 3: // STRING
88
+ if (await this.yesNoInput("Autocomplete ? "))
89
+ option.autocomplete = true;
90
+ option.min_length = await this.optionalNumber("Min length: ");
91
+ option.max_length = await this.optionalNumber("Max Length: ");
92
+ if (!option.autocomplete)
93
+ option.choices = await this.addChoices();
94
+ break;
95
+ case 4:
96
+ case 10: // INTEGER/NUMBER
97
+ option.min_value = await this.optionalNumber("Min value: ");
98
+ option.max_value = await this.optionalNumber("Max value: ");
99
+ if (type === 4)
100
+ option.choices = await this.addChoices();
101
+ break;
102
+ case 7: // CHANNEL
183
103
  option.channel_types = await this.addChannelTypes();
184
- }
185
- options.push(option);
186
- continueAdding = await this.yesNoInput("Add another option? (y/n): ");
104
+ break;
187
105
  }
188
106
  }
107
+ async optionalNumber(prompt) {
108
+ const input = await this.prompt(prompt);
109
+ return input.trim() ? parseFloat(input) : undefined;
110
+ }
189
111
  async addChoices() {
112
+ if (!await this.yesNoInput("Add Choices ? "))
113
+ return undefined;
190
114
  const choices = [];
191
- let continueAdding = await this.yesNoInput("Add choices? (y/n): ");
192
- while (continueAdding && choices.length < 25) {
193
- const name = await this.requireInput("Choice name: ");
194
- const value = await this.requireInput("Choice value: ");
115
+ while (choices.length < 25) {
116
+ const name = await this.requireInput("Choice name (≤100): ", val => val.length <= 100);
117
+ const value = await this.requireInput("Choice value (≤100): ", val => val.length <= 100);
195
118
  choices.push({ name, value });
196
- continueAdding = await this.yesNoInput("Add another choice? (y/n): ");
119
+ if (!await this.yesNoInput("Another choice ? "))
120
+ break;
197
121
  }
198
- return choices.length > 0 ? choices : undefined;
122
+ return choices;
199
123
  }
200
124
  async addChannelTypes() {
201
- console.log("Channel types: 0=text, 2=voice, 4=category, 5=announcement, 10=thread, 11=public-thread, 12=private-thread");
202
- const input = await this.requireInput("Channel types (comma sep, or Enter=none): ", undefined, true);
203
- return input ? input.split(",").map(i => parseInt(i.trim())).filter(i => !isNaN(i)) : undefined;
204
- }
205
- async addSimpleOptions(config) {
206
- console.clear();
207
- console.log("āž• Simple Options");
208
- let continueAdding = await this.yesNoInput("Add options? (y/n): ");
209
- config.options = [];
210
- while (continueAdding) {
211
- console.log("Quick option types: 3=string,4=int,5=bool,6=user,7=channel,8=role,9=mentionnable,10=number");
212
- const type = parseInt(await this.requireInput("Type (3-10): ", val => ["3", "4", "5", "6", "7", "8", "9", "10"].includes(val)));
213
- const name = await this.requireInput("Name: ");
214
- const desc = await this.requireInput("Description: ");
215
- const required = await this.yesNoInput("Required?: ");
216
- config.options.push({ type, name, description: desc, required });
217
- continueAdding = await this.yesNoInput("Another option? (y/n): ");
218
- }
125
+ console.log("Types: " +
126
+ Object.entries(InteractionType_1.ChannelType)
127
+ .filter(([, value]) => typeof value === 'number')
128
+ .map(([name, value]) => `${value}. ${name}`)
129
+ .join(', '));
130
+ const input = await this.requireInput("Types (separated by comma, or leave empty for all): ", (val) => {
131
+ if (!val.trim())
132
+ return true;
133
+ const trimmed = val.trim().toLowerCase();
134
+ if (trimmed === 'all')
135
+ return true;
136
+ return val.split(',').every(i => {
137
+ const num = parseInt(i.trim());
138
+ return !isNaN(num) && Object.values(InteractionType_1.ChannelType).includes(num);
139
+ });
140
+ }, true);
141
+ if (!input.trim() || input.trim() == 'all')
142
+ return undefined;
143
+ return input.split(',').map(i => parseInt(i.trim()));
219
144
  }
220
145
  }
221
146
  exports.SlashCommandGeneratorCLI = SlashCommandGeneratorCLI;
@@ -30,8 +30,7 @@ class GuildListManager extends BaseCLI_1.BaseCLI {
30
30
  try {
31
31
  this.guilds = await this.rest.get(v10_1.Routes.userGuilds());
32
32
  if (printResult) {
33
- console.table(this.guilds.map((g, i) => ({
34
- Index: i,
33
+ console.table(this.guilds.map((g, _i) => ({
35
34
  "Guild ID": g.id,
36
35
  Nom: g.name
37
36
  })));
@@ -75,7 +75,6 @@ class BaseInteractionManager {
75
75
  }
76
76
  console.log(`āœ… ${commandList.length} local ${this.folderPath}(s) not deployed\n`);
77
77
  console.table(commandList.map((cmd) => ({
78
- '#': cmd.index,
79
78
  Nom: cmd.name,
80
79
  Type: cmd.type === CommandType.SLASH ? 'Slash' :
81
80
  cmd.type === CommandType.USER_CONTEXT_MENU ? 'User' : 'Message',
@@ -162,11 +161,13 @@ class BaseInteractionManager {
162
161
  }
163
162
  });
164
163
  const results = await Promise.all(guildCommandPromises);
165
- console.log("\nšŸ“Š INTERACTION PER GUILD :\n");
164
+ const interactionTypeTitle = this.folderPath ? (this.folderPath?.toUpperCase()) : "INTERACTION";
165
+ const interactionTypeDesc = this.folderPath ? (this.folderPath?.charAt(0).toUpperCase() + this.folderPath?.slice(1)) : " Interactions";
166
+ console.log(`šŸ“Š ${interactionTypeTitle} PER GUILD :`);
166
167
  console.table(results.map(r => ({
167
168
  "Guild": r.guild,
168
- [this.folderPath ? "Global " + (this.folderPath?.charAt(0).toUpperCase() + this.folderPath?.slice(1)) : " Interactions"]: r.globalCommands.length,
169
- [this.folderPath ? "Specific " + (this.folderPath?.charAt(0).toUpperCase() + this.folderPath?.slice(1)) : " Interactions"]: r.guildCommands.length,
169
+ ["Global " + interactionTypeDesc]: r.globalCommands.length,
170
+ ["Specific " + interactionTypeDesc]: r.guildCommands.length,
170
171
  "Total": r.count
171
172
  })));
172
173
  return results.filter(r => r.count > 0);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InteractionContextType = exports.InteractionIntegrationType = void 0;
3
+ exports.ChannelType = exports.DiscordOptionType = exports.DiscordCommandType = exports.InteractionContextType = exports.InteractionIntegrationType = void 0;
4
4
  var InteractionIntegrationType;
5
5
  (function (InteractionIntegrationType) {
6
6
  InteractionIntegrationType[InteractionIntegrationType["GUILD_INSTALL"] = 0] = "GUILD_INSTALL";
@@ -12,3 +12,35 @@ var InteractionContextType;
12
12
  InteractionContextType[InteractionContextType["BOT_DM"] = 1] = "BOT_DM";
13
13
  InteractionContextType[InteractionContextType["GROUP_DM"] = 2] = "GROUP_DM";
14
14
  })(InteractionContextType || (exports.InteractionContextType = InteractionContextType = {}));
15
+ var DiscordCommandType;
16
+ (function (DiscordCommandType) {
17
+ DiscordCommandType[DiscordCommandType["CHANT_INPUT"] = 1] = "CHANT_INPUT";
18
+ DiscordCommandType[DiscordCommandType["USER"] = 2] = "USER";
19
+ DiscordCommandType[DiscordCommandType["MESSAGE"] = 3] = "MESSAGE";
20
+ })(DiscordCommandType || (exports.DiscordCommandType = DiscordCommandType = {}));
21
+ var DiscordOptionType;
22
+ (function (DiscordOptionType) {
23
+ DiscordOptionType[DiscordOptionType["SUB_COMMAND"] = 1] = "SUB_COMMAND";
24
+ DiscordOptionType[DiscordOptionType["SUB_COMMAND_GROUP"] = 2] = "SUB_COMMAND_GROUP";
25
+ DiscordOptionType[DiscordOptionType["STRING"] = 3] = "STRING";
26
+ DiscordOptionType[DiscordOptionType["INTEGER"] = 4] = "INTEGER";
27
+ DiscordOptionType[DiscordOptionType["BOOLEAN"] = 5] = "BOOLEAN";
28
+ DiscordOptionType[DiscordOptionType["USER"] = 6] = "USER";
29
+ DiscordOptionType[DiscordOptionType["CHANNEL"] = 7] = "CHANNEL";
30
+ DiscordOptionType[DiscordOptionType["ROLE"] = 8] = "ROLE";
31
+ DiscordOptionType[DiscordOptionType["MENTIONABLE"] = 9] = "MENTIONABLE";
32
+ DiscordOptionType[DiscordOptionType["NUMBER"] = 10] = "NUMBER";
33
+ DiscordOptionType[DiscordOptionType["ATTACHMENT"] = 11] = "ATTACHMENT";
34
+ })(DiscordOptionType || (exports.DiscordOptionType = DiscordOptionType = {}));
35
+ var ChannelType;
36
+ (function (ChannelType) {
37
+ ChannelType[ChannelType["Text"] = 0] = "Text";
38
+ ChannelType[ChannelType["Voice"] = 2] = "Voice";
39
+ ChannelType[ChannelType["Category"] = 4] = "Category";
40
+ ChannelType[ChannelType["Announcement"] = 5] = "Announcement";
41
+ ChannelType[ChannelType["ThreadPublic"] = 10] = "ThreadPublic";
42
+ ChannelType[ChannelType["ThreadPublicAnnouncement"] = 11] = "ThreadPublicAnnouncement";
43
+ ChannelType[ChannelType["ThreadPrivate"] = 12] = "ThreadPrivate";
44
+ ChannelType[ChannelType["Forum"] = 15] = "Forum";
45
+ ChannelType[ChannelType["Media"] = 16] = "Media";
46
+ })(ChannelType || (exports.ChannelType = ChannelType = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spatulox/discord-interaction-manager",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "author": "Spatulox",
5
5
  "description": "discord-interaction-manager is a lightweight CLI tool to manage Discord bot interactions (slash commands, context menus) in under 30 seconds. Deploy, update, delete, and generate interaction files with an interactive terminal interface.",
6
6
  "bin": {