blob: 635a1fdda8032522b65e07d87efc3609c765ee0e [file] [log] [blame]
TheCodedProfafca98b2023-01-17 22:25:43 -05001import type Discord from "discord.js";
TheCodedProf1c3ad3c2023-01-25 17:58:36 -05002import { ActionRowBuilder, APIMessageComponentEmoji, ButtonBuilder, ButtonInteraction, ButtonStyle, CommandInteraction, Message, ModalBuilder, RoleSelectMenuBuilder, RoleSelectMenuInteraction, StringSelectMenuBuilder, StringSelectMenuInteraction, StringSelectMenuOptionBuilder, TextInputBuilder, TextInputStyle } from "discord.js";
TheCodedProff86ba092023-01-27 17:10:07 -05003import type { SlashCommandSubcommandBuilder } from "discord.js";
TheCodedProf1c3ad3c2023-01-25 17:58:36 -05004import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
5import { LoadingEmbed } from "../../utils/defaults.js";
6import client from "../../utils/client.js";
7import getEmojiByName from "../../utils/getEmojiByName.js";
8import createPageIndicator from "../../utils/createPageIndicator.js";
9import { configToDropdown } from "../../actions/roleMenu.js";
TheCodedProff4facde2023-01-28 13:42:48 -050010import { modalInteractionCollector } from "../../utils/dualCollector.js";
TheCodedProfb5e9d552023-01-29 15:43:26 -050011import ellipsis from "../../utils/ellipsis.js";
TheCodedProff4facde2023-01-28 13:42:48 -050012import lodash from 'lodash';
TheCodedProfa112f612023-01-28 18:06:45 -050013
TheCodedProff4facde2023-01-28 13:42:48 -050014const isEqual = lodash.isEqual;
TheCodedProfa112f612023-01-28 18:06:45 -050015
pineafanda6e5342022-07-03 10:03:16 +010016const command = (builder: SlashCommandSubcommandBuilder) =>
17 builder
pineafan63fc5e22022-08-04 22:04:10 +010018 .setName("rolemenu")
TheCodedProf1c3ad3c2023-01-25 17:58:36 -050019 .setDescription("rolemenu")
20
21interface ObjectSchema {
22 name: string;
23 description: string;
24 min: number;
25 max: number;
26 options: {
27 name: string;
28 description: string | null;
29 role: string;
30 }[];
31}
32
TheCodedProff4facde2023-01-28 13:42:48 -050033const defaultRolePageConfig = {
34 name: "Role Menu Page",
35 description: "A new role menu page",
36 min: 0,
37 max: 0,
38 options: [
39 {name: "Role 1", description: null, role: "No role set"}
40 ]
41}
42
TheCodedProfa112f612023-01-28 18:06:45 -050043const reorderRoleMenuPages = async (interaction: CommandInteraction, m: Message, currentObj: ObjectSchema[]) => {
PineaFanb0d0c242023-02-05 10:59:45 +000044 const reorderRow = new ActionRowBuilder<StringSelectMenuBuilder>()
TheCodedProfa112f612023-01-28 18:06:45 -050045 .addComponents(
46 new StringSelectMenuBuilder()
47 .setCustomId("reorder")
TheCodedProfb5e9d552023-01-29 15:43:26 -050048 .setPlaceholder("Select all pages in the order you want them to appear.")
49 .setMinValues(currentObj.length)
50 .setMaxValues(currentObj.length)
TheCodedProfa112f612023-01-28 18:06:45 -050051 .addOptions(
52 currentObj.map((o, i) => new StringSelectMenuOptionBuilder()
53 .setLabel(o.name)
54 .setValue(i.toString())
55 )
56 )
57 );
PineaFanb0d0c242023-02-05 10:59:45 +000058 const buttonRow = new ActionRowBuilder<ButtonBuilder>()
TheCodedProfa112f612023-01-28 18:06:45 -050059 .addComponents(
60 new ButtonBuilder()
61 .setCustomId("back")
62 .setLabel("Back")
63 .setStyle(ButtonStyle.Secondary)
64 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
65 )
66 await interaction.editReply({
67 embeds: [
68 new EmojiEmbed()
69 .setTitle("Role Menu")
70 .setDescription("Select pages in the order you want them to appear.")
71 .setStatus("Success")
72 ],
73 components: [reorderRow, buttonRow]
74 });
75 let out: StringSelectMenuInteraction | ButtonInteraction | null;
76 try {
77 out = await m.awaitMessageComponent({
78 filter: (i) => i.channel!.id === interaction.channel!.id,
79 time: 300000
80 }) as StringSelectMenuInteraction | ButtonInteraction | null;
81 } catch (e) {
82 console.error(e);
83 out = null;
84 }
85 if(!out) return;
TheCodedProfb5e9d552023-01-29 15:43:26 -050086 out.deferUpdate();
TheCodedProfa112f612023-01-28 18:06:45 -050087 if (out.isButton()) return;
TheCodedProfa112f612023-01-28 18:06:45 -050088 const values = out.values;
89
90 const newOrder: ObjectSchema[] = currentObj.map((_, i) => {
91 const index = values.findIndex(v => v === i.toString());
92 return currentObj[index];
93 }) as ObjectSchema[];
94
95 return newOrder;
96}
97
TheCodedProff4facde2023-01-28 13:42:48 -050098const editNameDescription = async (i: ButtonInteraction, interaction: StringSelectMenuInteraction | ButtonInteraction, m: Message, data: {name?: string, description?: string}) => {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -050099
100 let {name, description} = data;
101 const modal = new ModalBuilder()
102 .setTitle("Edit Name and Description")
103 .setCustomId("editNameDescription")
104 .addComponents(
105 new ActionRowBuilder<TextInputBuilder>()
106 .addComponents(
107 new TextInputBuilder()
TheCodedProff4facde2023-01-28 13:42:48 -0500108 .setLabel("Name")
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500109 .setCustomId("name")
TheCodedProff4facde2023-01-28 13:42:48 -0500110 .setPlaceholder("Name here...") // TODO: Make better placeholder
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500111 .setStyle(TextInputStyle.Short)
TheCodedProff4facde2023-01-28 13:42:48 -0500112 .setValue(name ?? "")
113 .setRequired(true)
114 ),
115 new ActionRowBuilder<TextInputBuilder>()
116 .addComponents(
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500117 new TextInputBuilder()
TheCodedProff4facde2023-01-28 13:42:48 -0500118 .setLabel("Description")
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500119 .setCustomId("description")
TheCodedProff4facde2023-01-28 13:42:48 -0500120 .setPlaceholder("Description here...") // TODO: Make better placeholder
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500121 .setStyle(TextInputStyle.Short)
TheCodedProff4facde2023-01-28 13:42:48 -0500122 .setValue(description ?? "")
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500123 )
124 )
125 const button = new ActionRowBuilder<ButtonBuilder>()
126 .addComponents(
127 new ButtonBuilder()
128 .setCustomId("back")
129 .setLabel("Back")
130 .setStyle(ButtonStyle.Secondary)
131 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
132 )
133
TheCodedProff4facde2023-01-28 13:42:48 -0500134 await i.showModal(modal)
135 await interaction.editReply({
136 embeds: [
137 new EmojiEmbed()
138 .setTitle("Role Menu")
139 .setDescription("Modal opened. If you can't see it, click back and try again.")
140 .setStatus("Success")
141 ],
142 components: [button]
143 });
144
145 let out: Discord.ModalSubmitInteraction | null;
146 try {
147 out = await modalInteractionCollector(
148 m,
149 (m) => m.channel!.id === interaction.channel!.id,
150 (_) => true
151 ) as Discord.ModalSubmitInteraction | null;
152 } catch (e) {
153 console.error(e);
154 out = null;
155 }
156 if(!out) return [name, description];
157 if (out.isButton()) return [name, description];
TheCodedProff4facde2023-01-28 13:42:48 -0500158 name = out.fields.fields.find((f) => f.customId === "name")?.value ?? name;
159 description = out.fields.fields.find((f) => f.customId === "description")?.value ?? description;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500160 return [name, description]
161
162}
163
TheCodedProfb5e9d552023-01-29 15:43:26 -0500164const editRoleMenuPage = async (interaction: StringSelectMenuInteraction | ButtonInteraction, m: Message, data?: ObjectSchema): Promise<ObjectSchema | null> => {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500165 if (!data) data = {
166 name: "Role Menu Page",
167 description: "A new role menu page",
168 min: 0,
169 max: 0,
170 options: []
171 };
172 const buttons = new ActionRowBuilder<ButtonBuilder>()
173 .addComponents(
174 new ButtonBuilder()
175 .setCustomId("back")
176 .setLabel("Back")
177 .setStyle(ButtonStyle.Secondary)
178 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
179 new ButtonBuilder()
180 .setCustomId("edit")
181 .setLabel("Edit")
182 .setStyle(ButtonStyle.Primary)
183 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
184 new ButtonBuilder()
185 .setCustomId("addRole")
186 .setLabel("Add Role")
187 .setStyle(ButtonStyle.Secondary)
188 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
189 );
190
191 let back = false
TheCodedProff4facde2023-01-28 13:42:48 -0500192 if(data.options.length === 0) {
193 data.options = [
194 {name: "Role 1", description: null, role: "No role set"}
195 ]
196 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500197 do {
198 const previewSelect = configToDropdown("Edit Roles", {name: data.name, description: data.description, min: 1, max: 1, options: data.options});
199 const embed = new EmojiEmbed()
200 .setTitle(`${data.name}`)
201 .setStatus("Success")
202 .setDescription(
203 `**Description:**\n> ${data.description}\n\n` +
204 `**Min:** ${data.min}` + (data.min === 0 ? " (Members will be given a skip button)" : "") + "\n" +
205 `**Max:** ${data.max}\n`
206 )
207
208 interaction.editReply({embeds: [embed], components: [previewSelect, buttons]});
209 let i: StringSelectMenuInteraction | ButtonInteraction;
210 try {
211 i = await m.awaitMessageComponent({ time: 300000, filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId}) as ButtonInteraction | StringSelectMenuInteraction;
212 } catch (e) {
213 back = true;
214 break;
215 }
216
217 if (i.isStringSelectMenu()) {
218 if(i.customId === "roles") {
219 await i.deferUpdate();
220 await createRoleMenuOptionPage(interaction, m, data.options.find((o) => o.role === (i as StringSelectMenuInteraction).values[0]));
221 }
222 } else if (i.isButton()) {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500223 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000224 case "back": {
TheCodedProff4facde2023-01-28 13:42:48 -0500225 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500226 back = true;
227 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000228 }
229 case "edit": {
230 const [name, description] = await editNameDescription(i, interaction, m, data);
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500231 data.name = name ? name : data.name;
232 data.description = description ? description : data.description;
233 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000234 }
235 case "addRole": {
TheCodedProff4facde2023-01-28 13:42:48 -0500236 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500237 data.options.push(await createRoleMenuOptionPage(interaction, m));
238 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000239 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500240 }
241 }
242
243 } while (!back);
TheCodedProff4facde2023-01-28 13:42:48 -0500244 if(isEqual(data, defaultRolePageConfig)) return null;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500245 return data;
246}
247
248const createRoleMenuOptionPage = async (interaction: StringSelectMenuInteraction | ButtonInteraction, m: Message, data?: {name: string; description: string | null; role: string}) => {
249 const { renderRole} = client.logger;
250 if (!data) data = {
PineaFanb0d0c242023-02-05 10:59:45 +0000251 name: "New role Menu Option",
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500252 description: null,
PineaFanb0d0c242023-02-05 10:59:45 +0000253 role: ""
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500254 };
255 let back = false;
256 const buttons = new ActionRowBuilder<ButtonBuilder>()
257 .addComponents(
258 new ButtonBuilder()
259 .setCustomId("back")
260 .setLabel("Back")
261 .setStyle(ButtonStyle.Secondary)
262 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
263 new ButtonBuilder()
264 .setCustomId("edit")
265 .setLabel("Edit Details")
266 .setStyle(ButtonStyle.Primary)
267 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji)
268 );
269 do {
270 const roleSelect = new RoleSelectMenuBuilder().setCustomId("role").setPlaceholder(data.role ? "Set role to" : "Set the role");
271 const embed = new EmojiEmbed()
PineaFanb0d0c242023-02-05 10:59:45 +0000272 .setTitle(`${data.name}`)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500273 .setStatus("Success")
274 .setDescription(
275 `**Description:**\n> ${data.description ?? "No description set"}\n\n` +
PineaFanb0d0c242023-02-05 10:59:45 +0000276 `**Role:** ${data.role ? renderRole((await interaction.guild!.roles.fetch(data.role))!) : "No role set"}\n`
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500277 )
278
279 interaction.editReply({embeds: [embed], components: [new ActionRowBuilder<RoleSelectMenuBuilder>().addComponents(roleSelect), buttons]});
280
281 let i: RoleSelectMenuInteraction | ButtonInteraction;
282 try {
283 i = await m.awaitMessageComponent({ time: 300000, filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId}) as ButtonInteraction | RoleSelectMenuInteraction;
284 } catch (e) {
285 back = true;
286 break;
287 }
288
289 if (i.isRoleSelectMenu()) {
290 if(i.customId === "role") {
291 await i.deferUpdate();
292 data.role = (i as RoleSelectMenuInteraction).values[0]!;
293 }
294 } else if (i.isButton()) {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500295 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000296 case "back": {
TheCodedProff4facde2023-01-28 13:42:48 -0500297 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500298 back = true;
299 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000300 }
301 case "edit": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500302 await i.deferUpdate();
PineaFanb0d0c242023-02-05 10:59:45 +0000303 const [name, description] = await editNameDescription(i, interaction, m, data as {name: string; description: string});
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500304 data.name = name ? name : data.name;
305 data.description = description ? description : data.description;
306 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000307 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500308 }
309 }
310 } while (!back);
311 return data;
312}
pineafanda6e5342022-07-03 10:03:16 +0100313
pineafan63fc5e22022-08-04 22:04:10 +0100314const callback = async (interaction: CommandInteraction): Promise<void> => {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500315 if (!interaction.guild) return;
316 const m = await interaction.reply({embeds: LoadingEmbed, ephemeral: true, fetchReply: true});
317
318 let page = 0;
319 let closed = false;
320 const config = await client.database.guilds.read(interaction.guild.id);
321 let currentObject: ObjectSchema[] = config.roleMenu.options;
322 let modified = false;
323 do {
324 const embed = new EmojiEmbed()
TheCodedProfb5e9d552023-01-29 15:43:26 -0500325 .setTitle("Role Menu")
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500326 .setEmoji("GUILD.GREEN")
327 .setStatus("Success");
328 const noRoleMenus = currentObject.length === 0;
329 let current: ObjectSchema;
330
331 const pageSelect = new StringSelectMenuBuilder()
332 .setCustomId("page")
333 .setPlaceholder("Select a Role Menu page to manage");
334 const actionSelect = new StringSelectMenuBuilder()
335 .setCustomId("action")
336 .setPlaceholder("Perform an action")
337 .addOptions(
338 new StringSelectMenuOptionBuilder()
339 .setLabel("Edit")
340 .setDescription("Edit this page")
341 .setValue("edit")
342 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
343 new StringSelectMenuOptionBuilder()
344 .setLabel("Delete")
345 .setDescription("Delete this page")
346 .setValue("delete")
347 .setEmoji(getEmojiByName("TICKETS.ISSUE", "id") as APIMessageComponentEmoji)
348 );
349 const buttonRow = new ActionRowBuilder<ButtonBuilder>()
350 .addComponents(
351 new ButtonBuilder()
352 .setCustomId("back")
353 .setStyle(ButtonStyle.Primary)
354 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
355 .setDisabled(page === 0),
356 new ButtonBuilder()
357 .setCustomId("next")
358 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id") as APIMessageComponentEmoji)
359 .setStyle(ButtonStyle.Primary)
360 .setDisabled(page === Object.keys(currentObject).length - 1),
361 new ButtonBuilder()
362 .setCustomId("add")
363 .setLabel("New Page")
364 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
365 .setStyle(ButtonStyle.Secondary)
366 .setDisabled(Object.keys(currentObject).length >= 24),
367 new ButtonBuilder()
368 .setCustomId("reorder")
369 .setLabel("Reorder Pages")
TheCodedProf4f79da12023-01-31 16:50:37 -0500370 .setEmoji(getEmojiByName("ICONS.REORDER", "id") as APIMessageComponentEmoji)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500371 .setStyle(ButtonStyle.Secondary)
372 .setDisabled(Object.keys(currentObject).length <= 1),
373 new ButtonBuilder()
374 .setCustomId("save")
375 .setLabel("Save")
376 .setEmoji(getEmojiByName("ICONS.SAVE", "id") as APIMessageComponentEmoji)
377 .setStyle(ButtonStyle.Success)
378 .setDisabled(!modified),
379 );
380 if(noRoleMenus) {
TheCodedProfb5e9d552023-01-29 15:43:26 -0500381 embed.setDescription("No role menu pages have been set up yet. Use the button below to add one.\n\n" +
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500382 createPageIndicator(1, 1, undefined, true)
383 );
384 pageSelect.setDisabled(true);
385 actionSelect.setDisabled(true);
386 pageSelect.addOptions(new StringSelectMenuOptionBuilder()
387 .setLabel("No role menu pages")
388 .setValue("none")
389 );
390 } else {
391 page = Math.min(page, Object.keys(currentObject).length - 1);
392 current = currentObject[page]!;
393 embed.setDescription(`**Currently Editing:** ${current.name}\n\n` +
TheCodedProfb5e9d552023-01-29 15:43:26 -0500394 `**Description:**\n> ${current.description}\n` +
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500395 `\n\n${createPageIndicator(Object.keys(config.roleMenu.options).length, page)}`
396 );
397
398 pageSelect.addOptions(
399 currentObject.map((key: ObjectSchema, index) => {
400 return new StringSelectMenuOptionBuilder()
401 .setLabel(ellipsis(key.name, 50))
402 .setDescription(ellipsis(key.description, 50))
403 .setValue(index.toString());
404 })
405 );
406
407 }
408
409 await interaction.editReply({embeds: [embed], components: [new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(actionSelect), new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(pageSelect), buttonRow]});
410 let i: StringSelectMenuInteraction | ButtonInteraction;
411 try {
412 i = await m.awaitMessageComponent({ time: 300000, filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId}) as ButtonInteraction | StringSelectMenuInteraction;
413 } catch (e) {
414 closed = true;
PineaFanb0d0c242023-02-05 10:59:45 +0000415 continue;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500416 }
417
418 await i.deferUpdate();
419 if (i.isButton()) {
420 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000421 case "back": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500422 page--;
423 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000424 }
425 case "next": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500426 page++;
427 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000428 }
429 case "add": {
430 const newPage = await editRoleMenuPage(i, m)
TheCodedProff4facde2023-01-28 13:42:48 -0500431 if(!newPage) break;
432 currentObject.push();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500433 page = currentObject.length - 1;
434 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000435 }
436 case "reorder": {
437 const reordered = await reorderRoleMenuPages(interaction, m, currentObject);
TheCodedProfa112f612023-01-28 18:06:45 -0500438 if(!reordered) break;
439 currentObject = reordered;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500440 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000441 }
442 case "save": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500443 client.database.guilds.write(interaction.guild.id, {"roleMenu.options": currentObject});
444 modified = false;
445 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000446 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500447 }
448 } else if (i.isStringSelectMenu()) {
449 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000450 case "action": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500451 switch(i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000452 case "edit": {
453 const edited = await editRoleMenuPage(i, m, current!);
TheCodedProff4facde2023-01-28 13:42:48 -0500454 if(!edited) break;
455 currentObject[page] = edited;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500456 modified = true;
457 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000458 }
459 case "delete": {
TheCodedProff4facde2023-01-28 13:42:48 -0500460 if(page === 0 && currentObject.keys.length - 1 > 0) page++;
461 else page--;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500462 currentObject.splice(page, 1);
463 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000464 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500465 }
466 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000467 }
468 case "page": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500469 page = parseInt(i.values[0]!);
470 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000471 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500472 }
473 }
474
475 } while (!closed)
pineafan63fc5e22022-08-04 22:04:10 +0100476};
pineafanda6e5342022-07-03 10:03:16 +0100477
TheCodedProff86ba092023-01-27 17:10:07 -0500478const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100479 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000480 if (!member.permissions.has("ManageRoles"))
481 return "You must have the *Manage Roles* permission to use this command";
pineafanda6e5342022-07-03 10:03:16 +0100482 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100483};
pineafanda6e5342022-07-03 10:03:16 +0100484
485export { command };
486export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100487export { check };