blob: 0c174f504741ddc9ef253d89f47119d632eb3735 [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";
TheCodedProfe92b9b52023-03-06 17:07:34 -050028import _ from "lodash";
TheCodedProfa112f612023-01-28 18:06:45 -050029
TheCodedProfe92b9b52023-03-06 17:07:34 -050030const isEqual = _.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
TheCodedProf7a83f762023-03-06 17:17:00 -0500166const defaultRoleMenuData = {
167 name: "Role Menu Page",
168 description: "A new role menu page",
169 min: 0,
170 max: 0,
171 options: []
172};
173
Skyler Greyda16adf2023-03-05 10:22:12 +0000174const editRoleMenuPage = async (
175 interaction: StringSelectMenuInteraction | ButtonInteraction,
176 m: Message,
177 data?: ObjectSchema
178): Promise<ObjectSchema | null> => {
TheCodedProf7a83f762023-03-06 17:17:00 -0500179 if (!data) data = _.cloneDeep(defaultRoleMenuData)
Skyler Greyda16adf2023-03-05 10:22:12 +0000180 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
181 new ButtonBuilder()
182 .setCustomId("back")
183 .setLabel("Back")
184 .setStyle(ButtonStyle.Secondary)
185 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
186 new ButtonBuilder()
187 .setCustomId("edit")
188 .setLabel("Edit")
189 .setStyle(ButtonStyle.Primary)
190 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
191 new ButtonBuilder()
192 .setCustomId("addRole")
193 .setLabel("Add Role")
194 .setStyle(ButtonStyle.Secondary)
195 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
196 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500197
Skyler Greyda16adf2023-03-05 10:22:12 +0000198 let back = false;
199 if (data.options.length === 0) {
200 data.options = [{ name: "Role 1", description: null, role: "No role set" }];
TheCodedProff4facde2023-01-28 13:42:48 -0500201 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500202 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000203 const previewSelect = configToDropdown("Edit Roles", {
204 name: data.name,
205 description: data.description,
206 min: 1,
207 max: 1,
208 options: data.options
209 });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500210 const embed = new EmojiEmbed()
211 .setTitle(`${data.name}`)
212 .setStatus("Success")
213 .setDescription(
214 `**Description:**\n> ${data.description}\n\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000215 `**Min:** ${data.min}` +
216 (data.min === 0 ? " (Members will be given a skip button)" : "") +
217 "\n" +
218 `**Max:** ${data.max}\n`
219 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500220
Skyler Greyda16adf2023-03-05 10:22:12 +0000221 interaction.editReply({ embeds: [embed], components: [previewSelect, buttons] });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500222 let i: StringSelectMenuInteraction | ButtonInteraction;
223 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000224 i = (await m.awaitMessageComponent({
225 time: 300000,
226 filter: (i) =>
227 i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId
228 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500229 } catch (e) {
230 back = true;
231 break;
232 }
233
234 if (i.isStringSelectMenu()) {
Skyler Greyda16adf2023-03-05 10:22:12 +0000235 if (i.customId === "roles") {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500236 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000237 await createRoleMenuOptionPage(
238 interaction,
239 m,
240 data.options.find((o) => o.role === (i as StringSelectMenuInteraction).values[0])
241 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500242 }
243 } else if (i.isButton()) {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500244 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000245 case "back": {
TheCodedProff4facde2023-01-28 13:42:48 -0500246 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500247 back = true;
248 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000249 }
250 case "edit": {
251 const [name, description] = await editNameDescription(i, interaction, m, data);
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500252 data.name = name ? name : data.name;
253 data.description = description ? description : data.description;
254 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000255 }
256 case "addRole": {
TheCodedProff4facde2023-01-28 13:42:48 -0500257 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500258 data.options.push(await createRoleMenuOptionPage(interaction, m));
259 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000260 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500261 }
262 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500263 } while (!back);
Skyler Greyda16adf2023-03-05 10:22:12 +0000264 if (isEqual(data, defaultRolePageConfig)) return null;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500265 return data;
Skyler Greyda16adf2023-03-05 10:22:12 +0000266};
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500267
Skyler Greyda16adf2023-03-05 10:22:12 +0000268const createRoleMenuOptionPage = async (
269 interaction: StringSelectMenuInteraction | ButtonInteraction,
270 m: Message,
271 data?: { name: string; description: string | null; role: string }
272) => {
273 const { renderRole } = client.logger;
274 if (!data)
275 data = {
276 name: "New role Menu Option",
277 description: null,
278 role: ""
279 };
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500280 let back = false;
Skyler Greyda16adf2023-03-05 10:22:12 +0000281 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
282 new ButtonBuilder()
283 .setCustomId("back")
284 .setLabel("Back")
285 .setStyle(ButtonStyle.Secondary)
286 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
287 new ButtonBuilder()
288 .setCustomId("edit")
289 .setLabel("Edit Details")
290 .setStyle(ButtonStyle.Primary)
291 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji)
292 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500293 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000294 const roleSelect = new RoleSelectMenuBuilder()
295 .setCustomId("role")
296 .setPlaceholder(data.role ? "Set role to" : "Set the role");
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500297 const embed = new EmojiEmbed()
PineaFanb0d0c242023-02-05 10:59:45 +0000298 .setTitle(`${data.name}`)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500299 .setStatus("Success")
300 .setDescription(
301 `**Description:**\n> ${data.description ?? "No description set"}\n\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000302 `**Role:** ${
303 data.role ? renderRole((await interaction.guild!.roles.fetch(data.role))!) : "No role set"
304 }\n`
305 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500306
Skyler Greyda16adf2023-03-05 10:22:12 +0000307 interaction.editReply({
308 embeds: [embed],
309 components: [new ActionRowBuilder<RoleSelectMenuBuilder>().addComponents(roleSelect), buttons]
310 });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500311
312 let i: RoleSelectMenuInteraction | ButtonInteraction;
313 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000314 i = (await m.awaitMessageComponent({
315 time: 300000,
316 filter: (i) =>
317 i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId
318 })) as ButtonInteraction | RoleSelectMenuInteraction;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500319 } catch (e) {
320 back = true;
321 break;
322 }
323
324 if (i.isRoleSelectMenu()) {
Skyler Greyda16adf2023-03-05 10:22:12 +0000325 if (i.customId === "role") {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500326 await i.deferUpdate();
327 data.role = (i as RoleSelectMenuInteraction).values[0]!;
328 }
329 } else if (i.isButton()) {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500330 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000331 case "back": {
TheCodedProff4facde2023-01-28 13:42:48 -0500332 await i.deferUpdate();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500333 back = true;
334 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000335 }
336 case "edit": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500337 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000338 const [name, description] = await editNameDescription(
339 i,
340 interaction,
341 m,
342 data as { name: string; description: string }
343 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500344 data.name = name ? name : data.name;
345 data.description = description ? description : data.description;
346 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000347 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500348 }
349 }
350 } while (!back);
351 return data;
Skyler Greyda16adf2023-03-05 10:22:12 +0000352};
pineafanda6e5342022-07-03 10:03:16 +0100353
pineafan63fc5e22022-08-04 22:04:10 +0100354const callback = async (interaction: CommandInteraction): Promise<void> => {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500355 if (!interaction.guild) return;
Skyler Greyda16adf2023-03-05 10:22:12 +0000356 const m = await interaction.reply({ embeds: LoadingEmbed, ephemeral: true, fetchReply: true });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500357
358 let page = 0;
359 let closed = false;
360 const config = await client.database.guilds.read(interaction.guild.id);
TheCodedProfe92b9b52023-03-06 17:07:34 -0500361 let currentObject: ObjectSchema[] = _.cloneDeep(config.roleMenu.options);
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500362 let modified = false;
363 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000364 const embed = new EmojiEmbed().setTitle("Role Menu").setEmoji("GUILD.GREEN").setStatus("Success");
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500365 const noRoleMenus = currentObject.length === 0;
366 let current: ObjectSchema;
367
368 const pageSelect = new StringSelectMenuBuilder()
369 .setCustomId("page")
370 .setPlaceholder("Select a Role Menu page to manage");
371 const actionSelect = new StringSelectMenuBuilder()
372 .setCustomId("action")
373 .setPlaceholder("Perform an action")
374 .addOptions(
375 new StringSelectMenuOptionBuilder()
376 .setLabel("Edit")
377 .setDescription("Edit this page")
378 .setValue("edit")
379 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
380 new StringSelectMenuOptionBuilder()
381 .setLabel("Delete")
382 .setDescription("Delete this page")
383 .setValue("delete")
384 .setEmoji(getEmojiByName("TICKETS.ISSUE", "id") as APIMessageComponentEmoji)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500385 );
Skyler Greyda16adf2023-03-05 10:22:12 +0000386 const buttonRow = new ActionRowBuilder<ButtonBuilder>().addComponents(
387 new ButtonBuilder()
388 .setCustomId("back")
389 .setStyle(ButtonStyle.Primary)
390 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
391 .setDisabled(page === 0),
392 new ButtonBuilder()
393 .setCustomId("next")
394 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id") as APIMessageComponentEmoji)
395 .setStyle(ButtonStyle.Primary)
TheCodedProfe92b9b52023-03-06 17:07:34 -0500396 .setDisabled(page === Object.keys(currentObject).length - 1 || noRoleMenus),
Skyler Greyda16adf2023-03-05 10:22:12 +0000397 new ButtonBuilder()
398 .setCustomId("add")
399 .setLabel("New Page")
400 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
401 .setStyle(ButtonStyle.Secondary)
402 .setDisabled(Object.keys(currentObject).length >= 24),
403 new ButtonBuilder()
404 .setCustomId("reorder")
405 .setLabel("Reorder Pages")
406 .setEmoji(getEmojiByName("ICONS.REORDER", "id") as APIMessageComponentEmoji)
407 .setStyle(ButtonStyle.Secondary)
408 .setDisabled(Object.keys(currentObject).length <= 1),
409 new ButtonBuilder()
410 .setCustomId("save")
411 .setLabel("Save")
412 .setEmoji(getEmojiByName("ICONS.SAVE", "id") as APIMessageComponentEmoji)
413 .setStyle(ButtonStyle.Success)
414 .setDisabled(!modified)
415 );
416 if (noRoleMenus) {
417 embed.setDescription(
418 "No role menu pages have been set up yet. Use the button below to add one.\n\n" +
419 createPageIndicator(1, 1, undefined, true)
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500420 );
421 pageSelect.setDisabled(true);
422 actionSelect.setDisabled(true);
Skyler Greyda16adf2023-03-05 10:22:12 +0000423 pageSelect.addOptions(new StringSelectMenuOptionBuilder().setLabel("No role menu pages").setValue("none"));
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500424 } else {
425 page = Math.min(page, Object.keys(currentObject).length - 1);
426 current = currentObject[page]!;
Skyler Greyda16adf2023-03-05 10:22:12 +0000427 embed.setDescription(
428 `**Currently Editing:** ${current.name}\n\n` +
429 `**Description:**\n> ${current.description}\n` +
430 `\n\n${createPageIndicator(Object.keys(config.roleMenu.options).length, page)}`
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500431 );
432
433 pageSelect.addOptions(
434 currentObject.map((key: ObjectSchema, index) => {
435 return new StringSelectMenuOptionBuilder()
436 .setLabel(ellipsis(key.name, 50))
437 .setDescription(ellipsis(key.description, 50))
438 .setValue(index.toString());
439 })
440 );
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500441 }
442
Skyler Greyda16adf2023-03-05 10:22:12 +0000443 await interaction.editReply({
444 embeds: [embed],
445 components: [
446 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(actionSelect),
447 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(pageSelect),
448 buttonRow
449 ]
450 });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500451 let i: StringSelectMenuInteraction | ButtonInteraction;
452 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000453 i = (await m.awaitMessageComponent({
454 time: 300000,
455 filter: (i) =>
456 i.user.id === interaction.user.id && i.message.id === m.id && i.channelId === interaction.channelId
457 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500458 } catch (e) {
459 closed = true;
PineaFanb0d0c242023-02-05 10:59:45 +0000460 continue;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500461 }
462
463 await i.deferUpdate();
464 if (i.isButton()) {
465 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000466 case "back": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500467 page--;
468 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000469 }
470 case "next": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500471 page++;
472 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000473 }
474 case "add": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000475 const newPage = await editRoleMenuPage(i, m);
TheCodedProf7a83f762023-03-06 17:17:00 -0500476 if (_.isEqual(newPage, defaultRoleMenuData)) break;
TheCodedProff4facde2023-01-28 13:42:48 -0500477 currentObject.push();
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500478 page = currentObject.length - 1;
479 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000480 }
481 case "reorder": {
482 const reordered = await reorderRoleMenuPages(interaction, m, currentObject);
Skyler Greyda16adf2023-03-05 10:22:12 +0000483 if (!reordered) break;
TheCodedProfa112f612023-01-28 18:06:45 -0500484 currentObject = reordered;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500485 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000486 }
487 case "save": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000488 await client.database.guilds.write(interaction.guild.id, { "roleMenu.options": currentObject });
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500489 modified = false;
Skyler Grey16ecb172023-03-05 07:30:32 +0000490 await client.memory.forceUpdate(interaction.guild.id);
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500491 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000492 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500493 }
494 } else if (i.isStringSelectMenu()) {
495 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000496 case "action": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000497 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000498 case "edit": {
499 const edited = await editRoleMenuPage(i, m, current!);
Skyler Greyda16adf2023-03-05 10:22:12 +0000500 if (!edited) break;
TheCodedProff4facde2023-01-28 13:42:48 -0500501 currentObject[page] = edited;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500502 modified = true;
503 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000504 }
505 case "delete": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000506 if (page === 0 && currentObject.keys.length - 1 > 0) page++;
TheCodedProff4facde2023-01-28 13:42:48 -0500507 else page--;
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500508 currentObject.splice(page, 1);
509 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000510 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500511 }
512 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000513 }
514 case "page": {
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500515 page = parseInt(i.values[0]!);
516 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000517 }
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500518 }
519 }
TheCodedProf01cba762023-02-18 15:55:05 -0500520 } while (!closed);
Skyler Greyda16adf2023-03-05 10:22:12 +0000521 await interaction.deleteReply();
pineafan63fc5e22022-08-04 22:04:10 +0100522};
pineafanda6e5342022-07-03 10:03:16 +0100523
TheCodedProff86ba092023-01-27 17:10:07 -0500524const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100525 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000526 if (!member.permissions.has("ManageRoles"))
527 return "You must have the *Manage Roles* permission to use this command";
pineafanda6e5342022-07-03 10:03:16 +0100528 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100529};
pineafanda6e5342022-07-03 10:03:16 +0100530
531export { command };
532export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100533export { check };