blob: 48ca49c65ea101e544edd800c35b63830e38378b [file] [log] [blame]
TheCodedProf21c08592022-09-13 14:14:43 -04001import { Interaction, ButtonBuilder, CommandInteraction, Role, ButtonStyle } from "discord.js";
pineafan63fc5e22022-08-04 22:04:10 +01002import EmojiEmbed from "../utils/generateEmojiEmbed.js";
TheCodedProf21c08592022-09-13 14:14:43 -04003import { ActionRowBuilder, SelectMenuBuilder } from "discord.js";
pineafan813bdf42022-07-24 10:39:10 +01004import getEmojiByName from "../utils/getEmojiByName.js";
5import client from "../utils/client.js";
pineafane23c4ec2022-07-27 21:56:27 +01006import { LoadingEmbed } from "../utils/defaultEmbeds.js";
Skyler Grey11236ba2022-08-08 21:13:33 +01007import type { GuildConfig } from "../utils/database.js";
TheCodedProf21c08592022-09-13 14:14:43 -04008import type { ButtonComponent } from "@discordjs/builders";
pineafan813bdf42022-07-24 10:39:10 +01009
Skyler Grey11236ba2022-08-08 21:13:33 +010010export interface RoleMenuSchema {
11 guild: string;
12 guildName: string;
13 guildIcon: string;
14 user: string;
15 username: string;
16 data: GuildConfig["roleMenu"]["options"];
17 interaction: Interaction;
18}
19
TheCodedProf21c08592022-09-13 14:14:43 -040020export async function callback(interaction: CommandInteraction) {
21 if(!interaction.guild) return interaction.reply({ content: "This command can only be used in a server.", ephemeral: true });
22 if(!interaction.member) return interaction.reply({ content: "You must be in a server to use this command.", ephemeral: true });
pineafan63fc5e22022-08-04 22:04:10 +010023 const config = await client.database.guilds.read(interaction.guild.id);
Skyler Grey75ea9172022-08-06 10:22:23 +010024 if (!config.roleMenu.enabled)
25 return await interaction.reply({
26 embeds: [
27 new EmojiEmbed()
28 .setTitle("Roles")
29 .setDescription(
30 "Self roles are currently disabled. Please contact a staff member or try again later."
31 )
32 .setStatus("Danger")
33 .setEmoji("CONTROL.BLOCKCROSS")
34 ],
35 ephemeral: true
36 });
37 if (config.roleMenu.options.length === 0)
38 return await interaction.reply({
39 embeds: [
40 new EmojiEmbed()
41 .setTitle("Roles")
Skyler Grey11236ba2022-08-08 21:13:33 +010042 .setDescription("There are no roles available. Please contact a staff member or try again later.")
Skyler Grey75ea9172022-08-06 10:22:23 +010043 .setStatus("Danger")
44 .setEmoji("CONTROL.BLOCKCROSS")
45 ],
46 ephemeral: true
47 });
48 await interaction.reply({ embeds: LoadingEmbed, ephemeral: true });
pineafan813bdf42022-07-24 10:39:10 +010049 let m;
50 if (config.roleMenu.allowWebUI) {
pineafan63fc5e22022-08-04 22:04:10 +010051 let code = "";
52 let length = 5;
53 let itt = 0;
Skyler Grey11236ba2022-08-08 21:13:33 +010054 const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
pineafan63fc5e22022-08-04 22:04:10 +010055 let valid = false;
56 while (!valid) {
57 itt += 1;
58 code = "";
Skyler Grey75ea9172022-08-06 10:22:23 +010059 for (let i = 0; i < length; i++) {
60 code += chars.charAt(Math.floor(Math.random() * chars.length));
61 }
pineafan813bdf42022-07-24 10:39:10 +010062 if (code in client.roleMenu) continue;
63 if (itt > 1000) {
pineafan63fc5e22022-08-04 22:04:10 +010064 itt = 0;
65 length += 1;
pineafan813bdf42022-07-24 10:39:10 +010066 continue;
67 }
pineafan63fc5e22022-08-04 22:04:10 +010068 valid = true;
pineafan813bdf42022-07-24 10:39:10 +010069 }
70 client.roleMenu[code] = {
71 guild: interaction.guild.id,
72 guildName: interaction.guild.name,
TheCodedProf21c08592022-09-13 14:14:43 -040073 guildIcon: interaction.guild.iconURL({ extension: "png" }),
pineafan813bdf42022-07-24 10:39:10 +010074 user: interaction.member.user.id,
75 username: interaction.member.user.username,
76 data: config.roleMenu.options,
77 interaction: interaction
78 };
pineafan63fc5e22022-08-04 22:04:10 +010079 let up = true;
Skyler Grey11236ba2022-08-08 21:13:33 +010080 up = false; // FIXME: Role menu does not yet exist, so the web UI is never up
81 /* try {
82 const status = await fetch(client.config.baseUrl).then((res) => res.status);
pineafan63fc5e22022-08-04 22:04:10 +010083 if (status !== 200) up = false;
Skyler Grey75ea9172022-08-06 10:22:23 +010084 } catch {
85 up = false;
Skyler Grey11236ba2022-08-08 21:13:33 +010086 }*/
pineafan813bdf42022-07-24 10:39:10 +010087 m = await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +010088 embeds: [
89 new EmojiEmbed()
90 .setTitle("Roles")
91 .setDescription("Select how to choose your roles")
92 .setStatus("Success")
93 .setEmoji("GUILD.GREEN")
94 ],
95 components: [
TheCodedProf21c08592022-09-13 14:14:43 -040096 new ActionRowBuilder().addComponents([
97 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010098 .setLabel("Online")
TheCodedProf21c08592022-09-13 14:14:43 -040099 .setStyle(ButtonStyle.Link)
Skyler Grey75ea9172022-08-06 10:22:23 +0100100 .setDisabled(!up)
Skyler Grey11236ba2022-08-08 21:13:33 +0100101 .setURL(`${client.config.baseUrl}nucleus/rolemenu?code=${code}`),
TheCodedProf21c08592022-09-13 14:14:43 -0400102 new ButtonBuilder().setLabel("Manual").setStyle(ButtonStyle.Primary).setCustomId("manual")
Skyler Grey75ea9172022-08-06 10:22:23 +0100103 ])
104 ]
pineafan63fc5e22022-08-04 22:04:10 +0100105 });
pineafan813bdf42022-07-24 10:39:10 +0100106 }
107 let component;
TheCodedProf21c08592022-09-13 14:14:43 -0400108 if (!m) return;
Skyler Grey75ea9172022-08-06 10:22:23 +0100109 try {
110 component = await m.awaitMessageComponent({ time: 300000 });
111 } catch (e) {
112 return;
113 }
pineafan63fc5e22022-08-04 22:04:10 +0100114 component.deferUpdate();
TheCodedProf21c08592022-09-13 14:14:43 -0400115 let rolesToAdd: Role[] = [];
pineafan813bdf42022-07-24 10:39:10 +0100116 for (let i = 0; i < config.roleMenu.options.length; i++) {
pineafan63fc5e22022-08-04 22:04:10 +0100117 const object = config.roleMenu.options[i];
118 const m = await interaction.editReply({
pineafan813bdf42022-07-24 10:39:10 +0100119 embeds: [
120 new EmojiEmbed()
121 .setTitle("Roles")
122 .setEmoji("GUILD.GREEN")
Skyler Grey75ea9172022-08-06 10:22:23 +0100123 .setDescription(
124 `**${object.name}**` +
Skyler Grey11236ba2022-08-08 21:13:33 +0100125 (object.description ? `\n${object.description}` : "") +
Skyler Grey75ea9172022-08-06 10:22:23 +0100126 `\n\nSelect ${object.min}` +
Skyler Grey11236ba2022-08-08 21:13:33 +0100127 (object.min !== object.max ? ` to ${object.max}` : "") +
Skyler Grey75ea9172022-08-06 10:22:23 +0100128 ` role${object.max === 1 ? "" : "s"} to add.`
129 )
pineafan813bdf42022-07-24 10:39:10 +0100130 .setStatus("Success")
Skyler Grey75ea9172022-08-06 10:22:23 +0100131 .setFooter({
132 text: `Step ${i + 1}/${config.roleMenu.options.length}`
133 })
pineafan813bdf42022-07-24 10:39:10 +0100134 ],
135 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400136 new ActionRowBuilder().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100137 [
TheCodedProf21c08592022-09-13 14:14:43 -0400138 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100139 .setLabel("Cancel")
TheCodedProf21c08592022-09-13 14:14:43 -0400140 .setStyle(ButtonStyle.Danger)
Skyler Grey75ea9172022-08-06 10:22:23 +0100141 .setCustomId("cancel")
142 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
143 ].concat(
144 object.min === 0
145 ? [
TheCodedProf21c08592022-09-13 14:14:43 -0400146 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100147 .setLabel("Skip")
TheCodedProf21c08592022-09-13 14:14:43 -0400148 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100149 .setCustomId("skip")
Skyler Grey11236ba2022-08-08 21:13:33 +0100150 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
Skyler Grey75ea9172022-08-06 10:22:23 +0100151 ]
152 : []
153 )
154 )
155 ].concat([
TheCodedProf21c08592022-09-13 14:14:43 -0400156 new ActionRowBuilder().addComponents([
157 new SelectMenuBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100158 .setPlaceholder(`${object.name}`)
159 .setCustomId("rolemenu")
160 .setMinValues(object.min)
161 .setMaxValues(object.max)
162 .setOptions(
163 object.options.map((o) => {
164 return {
165 label: o.name,
166 description: o.description,
167 value: o.role
168 };
169 })
170 )
171 ])
172 ])
pineafan813bdf42022-07-24 10:39:10 +0100173 });
174 let component;
175 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100176 component = await m.awaitMessageComponent({ time: 300000 });
pineafan813bdf42022-07-24 10:39:10 +0100177 } catch (e) {
pineafan63fc5e22022-08-04 22:04:10 +0100178 return;
pineafan813bdf42022-07-24 10:39:10 +0100179 }
pineafan63fc5e22022-08-04 22:04:10 +0100180 component.deferUpdate();
pineafane23c4ec2022-07-27 21:56:27 +0100181 if (component.customId === "rolemenu") {
pineafan63fc5e22022-08-04 22:04:10 +0100182 rolesToAdd = rolesToAdd.concat(component.values);
pineafane23c4ec2022-07-27 21:56:27 +0100183 } else if (component.customId === "cancel") {
Skyler Grey75ea9172022-08-06 10:22:23 +0100184 return await interaction.editReply({
185 embeds: [
186 new EmojiEmbed()
187 .setTitle("Roles")
188 .setDescription("Cancelled. No changes were made.")
189 .setStatus("Danger")
190 .setEmoji("GUILD.RED")
191 ],
192 components: []
193 });
pineafan813bdf42022-07-24 10:39:10 +0100194 }
195 }
Skyler Grey11236ba2022-08-08 21:13:33 +0100196 let rolesToRemove = config.roleMenu.options.map((o) => o.options.map((o) => o.role)).flat();
Skyler Grey75ea9172022-08-06 10:22:23 +0100197 const memberRoles = interaction.member.roles.cache.map((r) => r.id);
Skyler Grey11236ba2022-08-08 21:13:33 +0100198 rolesToRemove = rolesToRemove.filter((r) => memberRoles.includes(r)).filter((r) => !rolesToAdd.includes(r));
Skyler Grey75ea9172022-08-06 10:22:23 +0100199 rolesToAdd = rolesToAdd.filter((r) => !memberRoles.includes(r));
pineafan813bdf42022-07-24 10:39:10 +0100200 try {
pineafan63fc5e22022-08-04 22:04:10 +0100201 await interaction.member.roles.remove(rolesToRemove);
202 await interaction.member.roles.add(rolesToAdd);
pineafan813bdf42022-07-24 10:39:10 +0100203 } catch (e) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100204 return await interaction.reply({
205 embeds: [
206 new EmojiEmbed()
207 .setTitle("Roles")
208 .setDescription(
209 "Something went wrong and your roles were not added. Please contact a staff member or try again later."
210 )
211 .setStatus("Danger")
212 .setEmoji("GUILD.RED")
213 ],
214 components: []
215 });
pineafan813bdf42022-07-24 10:39:10 +0100216 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100217 await interaction.editReply({
218 embeds: [
219 new EmojiEmbed()
220 .setTitle("Roles")
Skyler Grey11236ba2022-08-08 21:13:33 +0100221 .setDescription("Roles have been added. You may close this message.")
Skyler Grey75ea9172022-08-06 10:22:23 +0100222 .setStatus("Success")
223 .setEmoji("GUILD.GREEN")
224 ],
225 components: []
226 });
pineafan63fc5e22022-08-04 22:04:10 +0100227 return;
pineafan813bdf42022-07-24 10:39:10 +0100228}