blob: 11c6b67ba5824eebf36dc20c05e8d741f0babc6f [file] [log] [blame]
TheCodedProfafca98b2023-01-17 22:25:43 -05001import type Discord from "discord.js";
Skyler Greyda16adf2023-03-05 10:22:12 +00002import {
3 ActionRowBuilder,
4 APIMessageComponentEmoji,
5 ButtonBuilder,
6 ButtonInteraction,
7 ButtonStyle,
8 CommandInteraction,
9 Message,
10 ModalBuilder,
11 RoleSelectMenuBuilder,
12 RoleSelectMenuInteraction,
13 StringSelectMenuBuilder,
14 StringSelectMenuInteraction,
15 StringSelectMenuOptionBuilder,
16 TextInputBuilder,
17 TextInputStyle
18} from "discord.js";
TheCodedProff86ba092023-01-27 17:10:07 -050019import type { SlashCommandSubcommandBuilder } from "discord.js";
TheCodedProf1c3ad3c2023-01-25 17:58:36 -050020import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
21import { LoadingEmbed } from "../../utils/defaults.js";
22import client from "../../utils/client.js";
23import getEmojiByName from "../../utils/getEmojiByName.js";
24import createPageIndicator from "../../utils/createPageIndicator.js";
25import { configToDropdown } from "../../actions/roleMenu.js";
TheCodedProff4facde2023-01-28 13:42:48 -050026import { modalInteractionCollector } from "../../utils/dualCollector.js";
TheCodedProfb5e9d552023-01-29 15:43:26 -050027import ellipsis from "../../utils/ellipsis.js";
Skyler Greyda16adf2023-03-05 10:22:12 +000028import lodash from "lodash";
TheCodedProfa112f612023-01-28 18:06:45 -050029
TheCodedProff4facde2023-01-28 13:42:48 -050030const isEqual = lodash.isEqual;
TheCodedProfa112f612023-01-28 18:06:45 -050031
Skyler Greyda16adf2023-03-05 10:22:12 +000032const command = (builder: SlashCommandSubcommandBuilder) => builder.setName("rolemenu").setDescription("rolemenu");
TheCodedProf1c3ad3c2023-01-25 17:58:36 -050033
34interface ObjectSchema {
35 name: string;
36 description: string;
37 min: number;
38 max: number;
39 options: {
40 name: string;
41 description: string | null;
42 role: string;
43 }[];
44}
45
TheCodedProff4facde2023-01-28 13:42:48 -050046const defaultRolePageConfig = {
47 name: "Role Menu Page",
48 description: "A new role menu page",
49 min: 0,
50 max: 0,
Skyler Greyda16adf2023-03-05 10:22:12 +000051 options: [{ name: "Role 1", description: null, role: "No role set" }]
52};
TheCodedProff4facde2023-01-28 13:42:48 -050053
TheCodedProfa112f612023-01-28 18:06:45 -050054const reorderRoleMenuPages = async (interaction: CommandInteraction, m: Message, currentObj: ObjectSchema[]) => {
Skyler Greyda16adf2023-03-05 10:22:12 +000055 const reorderRow = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
56 new StringSelectMenuBuilder()
57 .setCustomId("reorder")
58 .setPlaceholder("Select all pages in the order you want them to appear.")
59 .setMinValues(currentObj.length)
60 .setMaxValues(currentObj.length)
61 .addOptions(
62 currentObj.map((o, i) => new StringSelectMenuOptionBuilder().setLabel(o.name).setValue(i.toString()))
63 )
64 );
65 const buttonRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
66 new ButtonBuilder()
67 .setCustomId("back")
68 .setLabel("Back")
69 .setStyle(ButtonStyle.Secondary)
70 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
71 );
TheCodedProfa112f612023-01-28 18:06:45 -050072 await interaction.editReply({
73 embeds: [
74 new EmojiEmbed()
75 .setTitle("Role Menu")
76 .setDescription("Select pages in the order you want them to appear.")
77 .setStatus("Success")
78 ],
79 components: [reorderRow, buttonRow]
80 });
81 let out: StringSelectMenuInteraction | ButtonInteraction | null;
82 try {
Skyler Greyda16adf2023-03-05 10:22:12 +000083 out = (await m.awaitMessageComponent({
TheCodedProfa112f612023-01-28 18:06:45 -050084 filter: (i) => i.channel!.id === interaction.channel!.id,
85 time: 300000
Skyler Greyda16adf2023-03-05 10:22:12 +000086 })) as StringSelectMenuInteraction | ButtonInteraction | null;
TheCodedProfa112f612023-01-28 18:06:45 -050087 } catch (e) {
88 console.error(e);
89 out = null;
90 }
Skyler Greyda16adf2023-03-05 10:22:12 +000091 if (!out) return;
TheCodedProfb5e9d552023-01-29 15:43:26 -050092 out.deferUpdate();
TheCodedProfa112f612023-01-28 18:06:45 -050093 if (out.isButton()) return;
TheCodedProfa112f612023-01-28 18:06:45 -050094 const values = out.values;
95
96 const newOrder: ObjectSchema[] = currentObj.map((_, i) => {
Skyler Greyda16adf2023-03-05 10:22:12 +000097 const index = values.findIndex((v) => v === i.toString());
TheCodedProfa112f612023-01-28 18:06:45 -050098 return currentObj[index];
99 }) as ObjectSchema[];
100
101 return newOrder;
Skyler Greyda16adf2023-03-05 10:22:12 +0000102};
TheCodedProfa112f612023-01-28 18:06:45 -0500103
Skyler Greyda16adf2023-03-05 10:22:12 +0000104const editNameDescription = async (
105 i: ButtonInteraction,
106 interaction: StringSelectMenuInteraction | ButtonInteraction,
107 m: Message,
108 data: { name?: string; description?: string }
109) => {
110 let { name, description } = data;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500111 const modal = new ModalBuilder()
112 .setTitle("Edit Name and Description")
113 .setCustomId("editNameDescription")
114 .addComponents(
Skyler Greyda16adf2023-03-05 10:22:12 +0000115 new ActionRowBuilder<TextInputBuilder>().addComponents(
116 new TextInputBuilder()
117 .setLabel("Name")
118 .setCustomId("name")
119 .setPlaceholder("The name of the role (e.g. Programmer)")
120 .setStyle(TextInputStyle.Short)
121 .setValue(name ?? "")
122 .setRequired(true)
123 ),
124 new ActionRowBuilder<TextInputBuilder>().addComponents(
125 new TextInputBuilder()
126 .setLabel("Description")
127 .setCustomId("description")
128 .setPlaceholder("A short description of the role (e.g. A role for people who code)")
129 .setStyle(TextInputStyle.Short)
130 .setValue(description ?? "")
131 )
132 );
133 const button = new ActionRowBuilder<ButtonBuilder>().addComponents(
134 new ButtonBuilder()
135 .setCustomId("back")
136 .setLabel("Back")
137 .setStyle(ButtonStyle.Secondary)
138 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
139 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500140
Skyler Greyda16adf2023-03-05 10:22:12 +0000141 await i.showModal(modal);
TheCodedProff4facde2023-01-28 13:42:48 -0500142 await interaction.editReply({
143 embeds: [
144 new EmojiEmbed()
145 .setTitle("Role Menu")
146 .setDescription("Modal opened. If you can't see it, click back and try again.")
147 .setStatus("Success")
148 ],
149 components: [button]
150 });
151
152 let out: Discord.ModalSubmitInteraction | null;
153 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000154 out = (await modalInteractionCollector(m, interaction.user)) as Discord.ModalSubmitInteraction | null;
TheCodedProff4facde2023-01-28 13:42:48 -0500155 } catch (e) {
156 console.error(e);
157 out = null;
158 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000159 if (!out) return [name, description];
TheCodedProff4facde2023-01-28 13:42:48 -0500160 if (out.isButton()) return [name, description];
TheCodedProff4facde2023-01-28 13:42:48 -0500161 name = out.fields.fields.find((f) => f.customId === "name")?.value ?? name;
162 description = out.fields.fields.find((f) => f.customId === "description")?.value ?? description;
Skyler Greyda16adf2023-03-05 10:22:12 +0000163 return [name, description];
164};
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500165
Skyler Greyda16adf2023-03-05 10:22:12 +0000166const editRoleMenuPage = async (
167 interaction: StringSelectMenuInteraction | ButtonInteraction,
168 m: Message,
169 data?: ObjectSchema
170): Promise<ObjectSchema | null> => {
171 if (!data)
172 data = {
173 name: "Role Menu Page",
174 description: "A new role menu page",
175 min: 0,
176 max: 0,
177 options: []
178 };
179 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
180 new ButtonBuilder()
181 .setCustomId("back")
182 .setLabel("Back")
183 .setStyle(ButtonStyle.Secondary)
184 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
185 new ButtonBuilder()
186 .setCustomId("edit")
187 .setLabel("Edit")
188 .setStyle(ButtonStyle.Primary)
189 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
190 new ButtonBuilder()
191 .setCustomId("addRole")
192 .setLabel("Add Role")
193 .setStyle(ButtonStyle.Secondary)
194 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
195 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500196
Skyler Greyda16adf2023-03-05 10:22:12 +0000197 let back = false;
198 if (data.options.length === 0) {
199 data.options = [{ name: "Role 1", description: null, role: "No role set" }];
TheCodedProff4facde2023-01-28 13:42:48 -0500200 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500201 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000202 const previewSelect = configToDropdown("Edit Roles", {
203 name: data.name,
204 description: data.description,
205 min: 1,
206 max: 1,
207 options: data.options
208 });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500209 const embed = new EmojiEmbed()
210 .setTitle(`${data.name}`)
211 .setStatus("Success")
212 .setDescription(
213 `**Description:**\n> ${data.description}\n\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000214 `**Min:** ${data.min}` +
215 (data.min === 0 ? " (Members will be given a skip button)" : "") +
216 "\n" +
217 `**Max:** ${data.max}\n`
218 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500219
Skyler Greyda16adf2023-03-05 10:22:12 +0000220 interaction.editReply({ embeds: [embed], components: [previewSelect, buttons] });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500221 let i: StringSelectMenuInteraction | ButtonInteraction;
222 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000223 i = (await m.awaitMessageComponent({
224 time: 300000,
225 filter: (i) =>
226 i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId
227 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500228 } catch (e) {
229 back = true;
230 break;
231 }
232
233 if (i.isStringSelectMenu()) {
Skyler Greyda16adf2023-03-05 10:22:12 +0000234 if (i.customId === "roles") {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500235 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000236 await createRoleMenuOptionPage(
237 interaction,
238 m,
239 data.options.find((o) => o.role === (i as StringSelectMenuInteraction).values[0])
240 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500241 }
242 } else if (i.isButton()) {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500243 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000244 case "back": {
TheCodedProff4facde2023-01-28 13:42:48 -0500245 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500246 back = true;
247 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000248 }
249 case "edit": {
250 const [name, description] = await editNameDescription(i, interaction, m, data);
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500251 data.name = name ? name : data.name;
252 data.description = description ? description : data.description;
253 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000254 }
255 case "addRole": {
TheCodedProff4facde2023-01-28 13:42:48 -0500256 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500257 data.options.push(await createRoleMenuOptionPage(interaction, m));
258 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000259 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500260 }
261 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500262 } while (!back);
Skyler Greyda16adf2023-03-05 10:22:12 +0000263 if (isEqual(data, defaultRolePageConfig)) return null;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500264 return data;
Skyler Greyda16adf2023-03-05 10:22:12 +0000265};
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500266
Skyler Greyda16adf2023-03-05 10:22:12 +0000267const createRoleMenuOptionPage = async (
268 interaction: StringSelectMenuInteraction | ButtonInteraction,
269 m: Message,
270 data?: { name: string; description: string | null; role: string }
271) => {
272 const { renderRole } = client.logger;
273 if (!data)
274 data = {
275 name: "New role Menu Option",
276 description: null,
277 role: ""
278 };
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500279 let back = false;
Skyler Greyda16adf2023-03-05 10:22:12 +0000280 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
281 new ButtonBuilder()
282 .setCustomId("back")
283 .setLabel("Back")
284 .setStyle(ButtonStyle.Secondary)
285 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
286 new ButtonBuilder()
287 .setCustomId("edit")
288 .setLabel("Edit Details")
289 .setStyle(ButtonStyle.Primary)
290 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji)
291 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500292 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000293 const roleSelect = new RoleSelectMenuBuilder()
294 .setCustomId("role")
295 .setPlaceholder(data.role ? "Set role to" : "Set the role");
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500296 const embed = new EmojiEmbed()
PineaFanb0d0c242023-02-05 10:59:45 +0000297 .setTitle(`${data.name}`)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500298 .setStatus("Success")
299 .setDescription(
300 `**Description:**\n> ${data.description ?? "No description set"}\n\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000301 `**Role:** ${
302 data.role ? renderRole((await interaction.guild!.roles.fetch(data.role))!) : "No role set"
303 }\n`
304 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500305
Skyler Greyda16adf2023-03-05 10:22:12 +0000306 interaction.editReply({
307 embeds: [embed],
308 components: [new ActionRowBuilder<RoleSelectMenuBuilder>().addComponents(roleSelect), buttons]
309 });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500310
311 let i: RoleSelectMenuInteraction | ButtonInteraction;
312 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000313 i = (await m.awaitMessageComponent({
314 time: 300000,
315 filter: (i) =>
316 i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId
317 })) as ButtonInteraction | RoleSelectMenuInteraction;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500318 } catch (e) {
319 back = true;
320 break;
321 }
322
323 if (i.isRoleSelectMenu()) {
Skyler Greyda16adf2023-03-05 10:22:12 +0000324 if (i.customId === "role") {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500325 await i.deferUpdate();
326 data.role = (i as RoleSelectMenuInteraction).values[0]!;
327 }
328 } else if (i.isButton()) {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500329 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000330 case "back": {
TheCodedProff4facde2023-01-28 13:42:48 -0500331 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500332 back = true;
333 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000334 }
335 case "edit": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500336 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000337 const [name, description] = await editNameDescription(
338 i,
339 interaction,
340 m,
341 data as { name: string; description: string }
342 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500343 data.name = name ? name : data.name;
344 data.description = description ? description : data.description;
345 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000346 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500347 }
348 }
349 } while (!back);
350 return data;
Skyler Greyda16adf2023-03-05 10:22:12 +0000351};
pineafanda6e5342022-07-03 10:03:16 +0100352
pineafan63fc5e22022-08-04 22:04:10 +0100353const callback = async (interaction: CommandInteraction): Promise<void> => {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500354 if (!interaction.guild) return;
Skyler Greyda16adf2023-03-05 10:22:12 +0000355 const m = await interaction.reply({ embeds: LoadingEmbed, ephemeral: true, fetchReply: true });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500356
357 let page = 0;
358 let closed = false;
359 const config = await client.database.guilds.read(interaction.guild.id);
360 let currentObject: ObjectSchema[] = config.roleMenu.options;
361 let modified = false;
362 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000363 const embed = new EmojiEmbed().setTitle("Role Menu").setEmoji("GUILD.GREEN").setStatus("Success");
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500364 const noRoleMenus = currentObject.length === 0;
365 let current: ObjectSchema;
366
367 const pageSelect = new StringSelectMenuBuilder()
368 .setCustomId("page")
369 .setPlaceholder("Select a Role Menu page to manage");
370 const actionSelect = new StringSelectMenuBuilder()
371 .setCustomId("action")
372 .setPlaceholder("Perform an action")
373 .addOptions(
374 new StringSelectMenuOptionBuilder()
375 .setLabel("Edit")
376 .setDescription("Edit this page")
377 .setValue("edit")
378 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
379 new StringSelectMenuOptionBuilder()
380 .setLabel("Delete")
381 .setDescription("Delete this page")
382 .setValue("delete")
383 .setEmoji(getEmojiByName("TICKETS.ISSUE", "id") as APIMessageComponentEmoji)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500384 );
Skyler Greyda16adf2023-03-05 10:22:12 +0000385 const buttonRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
386 new ButtonBuilder()
387 .setCustomId("back")
388 .setStyle(ButtonStyle.Primary)
389 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
390 .setDisabled(page === 0),
391 new ButtonBuilder()
392 .setCustomId("next")
393 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id") as APIMessageComponentEmoji)
394 .setStyle(ButtonStyle.Primary)
395 .setDisabled(page === Object.keys(currentObject).length - 1),
396 new ButtonBuilder()
397 .setCustomId("add")
398 .setLabel("New Page")
399 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
400 .setStyle(ButtonStyle.Secondary)
401 .setDisabled(Object.keys(currentObject).length >= 24),
402 new ButtonBuilder()
403 .setCustomId("reorder")
404 .setLabel("Reorder Pages")
405 .setEmoji(getEmojiByName("ICONS.REORDER", "id") as APIMessageComponentEmoji)
406 .setStyle(ButtonStyle.Secondary)
407 .setDisabled(Object.keys(currentObject).length <= 1),
408 new ButtonBuilder()
409 .setCustomId("save")
410 .setLabel("Save")
411 .setEmoji(getEmojiByName("ICONS.SAVE", "id") as APIMessageComponentEmoji)
412 .setStyle(ButtonStyle.Success)
413 .setDisabled(!modified)
414 );
415 if (noRoleMenus) {
416 embed.setDescription(
417 "No role menu pages have been set up yet. Use the button below to add one.\n\n" +
418 createPageIndicator(1, 1, undefined, true)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500419 );
420 pageSelect.setDisabled(true);
421 actionSelect.setDisabled(true);
Skyler Greyda16adf2023-03-05 10:22:12 +0000422 pageSelect.addOptions(new StringSelectMenuOptionBuilder().setLabel("No role menu pages").setValue("none"));
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500423 } else {
424 page = Math.min(page, Object.keys(currentObject).length - 1);
425 current = currentObject[page]!;
Skyler Greyda16adf2023-03-05 10:22:12 +0000426 embed.setDescription(
427 `**Currently Editing:** ${current.name}\n\n` +
428 `**Description:**\n> ${current.description}\n` +
429 `\n\n${createPageIndicator(Object.keys(config.roleMenu.options).length, page)}`
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500430 );
431
432 pageSelect.addOptions(
433 currentObject.map((key: ObjectSchema, index) => {
434 return new StringSelectMenuOptionBuilder()
435 .setLabel(ellipsis(key.name, 50))
436 .setDescription(ellipsis(key.description, 50))
437 .setValue(index.toString());
438 })
439 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500440 }
441
Skyler Greyda16adf2023-03-05 10:22:12 +0000442 await interaction.editReply({
443 embeds: [embed],
444 components: [
445 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(actionSelect),
446 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(pageSelect),
447 buttonRow
448 ]
449 });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500450 let i: StringSelectMenuInteraction | ButtonInteraction;
451 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000452 i = (await m.awaitMessageComponent({
453 time: 300000,
454 filter: (i) =>
455 i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId
456 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500457 } catch (e) {
458 closed = true;
PineaFanb0d0c242023-02-05 10:59:45 +0000459 continue;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500460 }
461
462 await i.deferUpdate();
463 if (i.isButton()) {
464 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000465 case "back": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500466 page--;
467 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000468 }
469 case "next": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500470 page++;
471 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000472 }
473 case "add": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000474 const newPage = await editRoleMenuPage(i, m);
475 if (!newPage) break;
TheCodedProff4facde2023-01-28 13:42:48 -0500476 currentObject.push();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500477 page = currentObject.length - 1;
478 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000479 }
480 case "reorder": {
481 const reordered = await reorderRoleMenuPages(interaction, m, currentObject);
Skyler Greyda16adf2023-03-05 10:22:12 +0000482 if (!reordered) break;
TheCodedProfa112f612023-01-28 18:06:45 -0500483 currentObject = reordered;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500484 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000485 }
486 case "save": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000487 await client.database.guilds.write(interaction.guild.id, { "roleMenu.options": currentObject });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500488 modified = false;
Skyler Grey16ecb172023-03-05 07:30:32 +0000489 await client.memory.forceUpdate(interaction.guild.id);
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500490 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000491 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500492 }
493 } else if (i.isStringSelectMenu()) {
494 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000495 case "action": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000496 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000497 case "edit": {
498 const edited = await editRoleMenuPage(i, m, current!);
Skyler Greyda16adf2023-03-05 10:22:12 +0000499 if (!edited) break;
TheCodedProff4facde2023-01-28 13:42:48 -0500500 currentObject[page] = edited;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500501 modified = true;
502 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000503 }
504 case "delete": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000505 if (page === 0 && currentObject.keys.length - 1 > 0) page++;
TheCodedProff4facde2023-01-28 13:42:48 -0500506 else page--;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500507 currentObject.splice(page, 1);
508 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000509 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500510 }
511 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000512 }
513 case "page": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500514 page = parseInt(i.values[0]!);
515 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000516 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500517 }
518 }
TheCodedProf01cba762023-02-18 15:55:05 -0500519 } while (!closed);
Skyler Greyda16adf2023-03-05 10:22:12 +0000520 await interaction.deleteReply();
pineafan63fc5e22022-08-04 22:04:10 +0100521};
pineafanda6e5342022-07-03 10:03:16 +0100522
TheCodedProff86ba092023-01-27 17:10:07 -0500523const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100524 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000525 if (!member.permissions.has("ManageRoles"))
526 return "You must have the *Manage Roles* permission to use this command";
pineafanda6e5342022-07-03 10:03:16 +0100527 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100528};
pineafanda6e5342022-07-03 10:03:16 +0100529
530export { command };
531export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100532export { check };