blob: cccb6f6f74b84ce090463b2c77d8c9f7353a4f16 [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")
TheCodedProf1f675042023-02-16 17:01:29 -0500110 .setPlaceholder("The name of the role (e.g. Programmer)")
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")
TheCodedProf1f675042023-02-16 17:01:29 -0500120 .setPlaceholder("A short description of the role (e.g. A role for people who code)")
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 {
TheCodedProf01cba762023-02-18 15:55:05 -0500147 out = await modalInteractionCollector(m, interaction.user) as Discord.ModalSubmitInteraction | null;
TheCodedProff4facde2023-01-28 13:42:48 -0500148 } catch (e) {
149 console.error(e);
150 out = null;
151 }
152 if(!out) return [name, description];
153 if (out.isButton()) return [name, description];
TheCodedProff4facde2023-01-28 13:42:48 -0500154 name = out.fields.fields.find((f) => f.customId === "name")?.value ?? name;
155 description = out.fields.fields.find((f) => f.customId === "description")?.value ?? description;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500156 return [name, description]
157
158}
159
TheCodedProfb5e9d552023-01-29 15:43:26 -0500160const editRoleMenuPage = async (interaction: StringSelectMenuInteraction | ButtonInteraction, m: Message, data?: ObjectSchema): Promise<ObjectSchema | null> => {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500161 if (!data) data = {
162 name: "Role Menu Page",
163 description: "A new role menu page",
164 min: 0,
165 max: 0,
166 options: []
167 };
168 const buttons = new ActionRowBuilder<ButtonBuilder>()
169 .addComponents(
170 new ButtonBuilder()
171 .setCustomId("back")
172 .setLabel("Back")
173 .setStyle(ButtonStyle.Secondary)
174 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
175 new ButtonBuilder()
176 .setCustomId("edit")
177 .setLabel("Edit")
178 .setStyle(ButtonStyle.Primary)
179 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
180 new ButtonBuilder()
181 .setCustomId("addRole")
182 .setLabel("Add Role")
183 .setStyle(ButtonStyle.Secondary)
184 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
185 );
186
187 let back = false
TheCodedProff4facde2023-01-28 13:42:48 -0500188 if(data.options.length === 0) {
189 data.options = [
190 {name: "Role 1", description: null, role: "No role set"}
191 ]
192 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500193 do {
194 const previewSelect = configToDropdown("Edit Roles", {name: data.name, description: data.description, min: 1, max: 1, options: data.options});
195 const embed = new EmojiEmbed()
196 .setTitle(`${data.name}`)
197 .setStatus("Success")
198 .setDescription(
199 `**Description:**\n> ${data.description}\n\n` +
200 `**Min:** ${data.min}` + (data.min === 0 ? " (Members will be given a skip button)" : "") + "\n" +
201 `**Max:** ${data.max}\n`
202 )
203
204 interaction.editReply({embeds: [embed], components: [previewSelect, buttons]});
205 let i: StringSelectMenuInteraction | ButtonInteraction;
206 try {
207 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;
208 } catch (e) {
209 back = true;
210 break;
211 }
212
213 if (i.isStringSelectMenu()) {
214 if(i.customId === "roles") {
215 await i.deferUpdate();
216 await createRoleMenuOptionPage(interaction, m, data.options.find((o) => o.role === (i as StringSelectMenuInteraction).values[0]));
217 }
218 } else if (i.isButton()) {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500219 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000220 case "back": {
TheCodedProff4facde2023-01-28 13:42:48 -0500221 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500222 back = true;
223 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000224 }
225 case "edit": {
226 const [name, description] = await editNameDescription(i, interaction, m, data);
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500227 data.name = name ? name : data.name;
228 data.description = description ? description : data.description;
229 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000230 }
231 case "addRole": {
TheCodedProff4facde2023-01-28 13:42:48 -0500232 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500233 data.options.push(await createRoleMenuOptionPage(interaction, m));
234 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000235 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500236 }
237 }
238
239 } while (!back);
TheCodedProff4facde2023-01-28 13:42:48 -0500240 if(isEqual(data, defaultRolePageConfig)) return null;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500241 return data;
242}
243
244const createRoleMenuOptionPage = async (interaction: StringSelectMenuInteraction | ButtonInteraction, m: Message, data?: {name: string; description: string | null; role: string}) => {
245 const { renderRole} = client.logger;
246 if (!data) data = {
PineaFanb0d0c242023-02-05 10:59:45 +0000247 name: "New role Menu Option",
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500248 description: null,
PineaFanb0d0c242023-02-05 10:59:45 +0000249 role: ""
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500250 };
251 let back = false;
252 const buttons = new ActionRowBuilder<ButtonBuilder>()
253 .addComponents(
254 new ButtonBuilder()
255 .setCustomId("back")
256 .setLabel("Back")
257 .setStyle(ButtonStyle.Secondary)
258 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
259 new ButtonBuilder()
260 .setCustomId("edit")
261 .setLabel("Edit Details")
262 .setStyle(ButtonStyle.Primary)
263 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji)
264 );
265 do {
266 const roleSelect = new RoleSelectMenuBuilder().setCustomId("role").setPlaceholder(data.role ? "Set role to" : "Set the role");
267 const embed = new EmojiEmbed()
PineaFanb0d0c242023-02-05 10:59:45 +0000268 .setTitle(`${data.name}`)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500269 .setStatus("Success")
270 .setDescription(
271 `**Description:**\n> ${data.description ?? "No description set"}\n\n` +
PineaFanb0d0c242023-02-05 10:59:45 +0000272 `**Role:** ${data.role ? renderRole((await interaction.guild!.roles.fetch(data.role))!) : "No role set"}\n`
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500273 )
274
275 interaction.editReply({embeds: [embed], components: [new ActionRowBuilder<RoleSelectMenuBuilder>().addComponents(roleSelect), buttons]});
276
277 let i: RoleSelectMenuInteraction | ButtonInteraction;
278 try {
279 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;
280 } catch (e) {
281 back = true;
282 break;
283 }
284
285 if (i.isRoleSelectMenu()) {
286 if(i.customId === "role") {
287 await i.deferUpdate();
288 data.role = (i as RoleSelectMenuInteraction).values[0]!;
289 }
290 } else if (i.isButton()) {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500291 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000292 case "back": {
TheCodedProff4facde2023-01-28 13:42:48 -0500293 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500294 back = true;
295 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000296 }
297 case "edit": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500298 await i.deferUpdate();
PineaFanb0d0c242023-02-05 10:59:45 +0000299 const [name, description] = await editNameDescription(i, interaction, m, data as {name: string; description: string});
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500300 data.name = name ? name : data.name;
301 data.description = description ? description : data.description;
302 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000303 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500304 }
305 }
306 } while (!back);
307 return data;
308}
pineafanda6e5342022-07-03 10:03:16 +0100309
pineafan63fc5e22022-08-04 22:04:10 +0100310const callback = async (interaction: CommandInteraction): Promise<void> => {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500311 if (!interaction.guild) return;
312 const m = await interaction.reply({embeds: LoadingEmbed, ephemeral: true, fetchReply: true});
313
314 let page = 0;
315 let closed = false;
316 const config = await client.database.guilds.read(interaction.guild.id);
317 let currentObject: ObjectSchema[] = config.roleMenu.options;
318 let modified = false;
319 do {
320 const embed = new EmojiEmbed()
TheCodedProfb5e9d552023-01-29 15:43:26 -0500321 .setTitle("Role Menu")
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500322 .setEmoji("GUILD.GREEN")
323 .setStatus("Success");
324 const noRoleMenus = currentObject.length === 0;
325 let current: ObjectSchema;
326
327 const pageSelect = new StringSelectMenuBuilder()
328 .setCustomId("page")
329 .setPlaceholder("Select a Role Menu page to manage");
330 const actionSelect = new StringSelectMenuBuilder()
331 .setCustomId("action")
332 .setPlaceholder("Perform an action")
333 .addOptions(
334 new StringSelectMenuOptionBuilder()
335 .setLabel("Edit")
336 .setDescription("Edit this page")
337 .setValue("edit")
338 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
339 new StringSelectMenuOptionBuilder()
340 .setLabel("Delete")
341 .setDescription("Delete this page")
342 .setValue("delete")
343 .setEmoji(getEmojiByName("TICKETS.ISSUE", "id") as APIMessageComponentEmoji)
344 );
345 const buttonRow = new ActionRowBuilder<ButtonBuilder>()
346 .addComponents(
347 new ButtonBuilder()
348 .setCustomId("back")
349 .setStyle(ButtonStyle.Primary)
350 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
351 .setDisabled(page === 0),
352 new ButtonBuilder()
353 .setCustomId("next")
354 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id") as APIMessageComponentEmoji)
355 .setStyle(ButtonStyle.Primary)
356 .setDisabled(page === Object.keys(currentObject).length - 1),
357 new ButtonBuilder()
358 .setCustomId("add")
359 .setLabel("New Page")
360 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
361 .setStyle(ButtonStyle.Secondary)
362 .setDisabled(Object.keys(currentObject).length >= 24),
363 new ButtonBuilder()
364 .setCustomId("reorder")
365 .setLabel("Reorder Pages")
TheCodedProf4f79da12023-01-31 16:50:37 -0500366 .setEmoji(getEmojiByName("ICONS.REORDER", "id") as APIMessageComponentEmoji)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500367 .setStyle(ButtonStyle.Secondary)
368 .setDisabled(Object.keys(currentObject).length <= 1),
369 new ButtonBuilder()
370 .setCustomId("save")
371 .setLabel("Save")
372 .setEmoji(getEmojiByName("ICONS.SAVE", "id") as APIMessageComponentEmoji)
373 .setStyle(ButtonStyle.Success)
374 .setDisabled(!modified),
375 );
376 if(noRoleMenus) {
TheCodedProfb5e9d552023-01-29 15:43:26 -0500377 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 -0500378 createPageIndicator(1, 1, undefined, true)
379 );
380 pageSelect.setDisabled(true);
381 actionSelect.setDisabled(true);
382 pageSelect.addOptions(new StringSelectMenuOptionBuilder()
383 .setLabel("No role menu pages")
384 .setValue("none")
385 );
386 } else {
387 page = Math.min(page, Object.keys(currentObject).length - 1);
388 current = currentObject[page]!;
389 embed.setDescription(`**Currently Editing:** ${current.name}\n\n` +
TheCodedProfb5e9d552023-01-29 15:43:26 -0500390 `**Description:**\n> ${current.description}\n` +
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500391 `\n\n${createPageIndicator(Object.keys(config.roleMenu.options).length, page)}`
392 );
393
394 pageSelect.addOptions(
395 currentObject.map((key: ObjectSchema, index) => {
396 return new StringSelectMenuOptionBuilder()
397 .setLabel(ellipsis(key.name, 50))
398 .setDescription(ellipsis(key.description, 50))
399 .setValue(index.toString());
400 })
401 );
402
403 }
404
405 await interaction.editReply({embeds: [embed], components: [new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(actionSelect), new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(pageSelect), buttonRow]});
406 let i: StringSelectMenuInteraction | ButtonInteraction;
407 try {
408 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;
409 } catch (e) {
410 closed = true;
PineaFanb0d0c242023-02-05 10:59:45 +0000411 continue;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500412 }
413
414 await i.deferUpdate();
415 if (i.isButton()) {
416 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000417 case "back": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500418 page--;
419 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000420 }
421 case "next": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500422 page++;
423 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000424 }
425 case "add": {
426 const newPage = await editRoleMenuPage(i, m)
TheCodedProff4facde2023-01-28 13:42:48 -0500427 if(!newPage) break;
428 currentObject.push();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500429 page = currentObject.length - 1;
430 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000431 }
432 case "reorder": {
433 const reordered = await reorderRoleMenuPages(interaction, m, currentObject);
TheCodedProfa112f612023-01-28 18:06:45 -0500434 if(!reordered) break;
435 currentObject = reordered;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500436 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000437 }
438 case "save": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500439 client.database.guilds.write(interaction.guild.id, {"roleMenu.options": currentObject});
440 modified = false;
441 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000442 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500443 }
444 } else if (i.isStringSelectMenu()) {
445 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000446 case "action": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500447 switch(i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000448 case "edit": {
449 const edited = await editRoleMenuPage(i, m, current!);
TheCodedProff4facde2023-01-28 13:42:48 -0500450 if(!edited) break;
451 currentObject[page] = edited;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500452 modified = true;
453 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000454 }
455 case "delete": {
TheCodedProff4facde2023-01-28 13:42:48 -0500456 if(page === 0 && currentObject.keys.length - 1 > 0) page++;
457 else page--;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500458 currentObject.splice(page, 1);
459 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000460 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500461 }
462 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000463 }
464 case "page": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500465 page = parseInt(i.values[0]!);
466 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000467 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500468 }
469 }
470
TheCodedProf01cba762023-02-18 15:55:05 -0500471 } while (!closed);
472 await interaction.deleteReply()
pineafan63fc5e22022-08-04 22:04:10 +0100473};
pineafanda6e5342022-07-03 10:03:16 +0100474
TheCodedProff86ba092023-01-27 17:10:07 -0500475const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100476 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000477 if (!member.permissions.has("ManageRoles"))
478 return "You must have the *Manage Roles* permission to use this command";
pineafanda6e5342022-07-03 10:03:16 +0100479 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100480};
pineafanda6e5342022-07-03 10:03:16 +0100481
482export { command };
483export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100484export { check };