blob: a8b0ae0b47a45a2b3afdfa59b03866327b96a0e4 [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed } from "../../utils/defaults.js";
Skyler Grey75ea9172022-08-06 10:22:23 +01002import Discord, {
3 CommandInteraction,
pineafan3a02ea32022-08-11 21:35:04 +01004 Interaction,
Skyler Grey75ea9172022-08-06 10:22:23 +01005 Message,
TheCodedProf21c08592022-09-13 14:14:43 -04006 ActionRowBuilder,
7 Component,
8 ButtonBuilder,
Skyler Grey75ea9172022-08-06 10:22:23 +01009 MessageComponentInteraction,
TheCodedProf21c08592022-09-13 14:14:43 -040010 SelectMenuBuilder,
pineafan3a02ea32022-08-11 21:35:04 +010011 ModalSubmitInteraction,
Skyler Grey75ea9172022-08-06 10:22:23 +010012 Role,
13 SelectMenuInteraction,
TheCodedProf21c08592022-09-13 14:14:43 -040014 TextInputComponent,
15 ButtonStyle
Skyler Grey75ea9172022-08-06 10:22:23 +010016} from "discord.js";
pineafanda6e5342022-07-03 10:03:16 +010017import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
18import confirmationMessage from "../../utils/confirmationMessage.js";
19import getEmojiByName from "../../utils/getEmojiByName.js";
pineafan3a02ea32022-08-11 21:35:04 +010020import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
pineafanda6e5342022-07-03 10:03:16 +010021import client from "../../utils/client.js";
pineafan63fc5e22022-08-04 22:04:10 +010022import { modalInteractionCollector } from "../../utils/dualCollector.js";
pineafan4f164f32022-02-26 22:07:12 +000023
24const command = (builder: SlashCommandSubcommandBuilder) =>
25 builder
pineafan63fc5e22022-08-04 22:04:10 +010026 .setName("verify")
27 .setDescription("Manage the role given after typing /verify")
Skyler Grey75ea9172022-08-06 10:22:23 +010028 .addRoleOption((option) =>
Skyler Grey11236ba2022-08-08 21:13:33 +010029 option.setName("role").setDescription("The role to give after verifying").setRequired(false)
Skyler Grey75ea9172022-08-06 10:22:23 +010030 );
pineafan4f164f32022-02-26 22:07:12 +000031
pineafan3a02ea32022-08-11 21:35:04 +010032const callback = async (interaction: CommandInteraction): Promise<unknown> => {
PineaFana00db1b2023-01-02 15:32:54 +000033 if (!interaction.guild) return;
Skyler Grey75ea9172022-08-06 10:22:23 +010034 const m = (await interaction.reply({
35 embeds: LoadingEmbed,
36 ephemeral: true,
37 fetchReply: true
38 })) as Message;
pineafan6702cef2022-06-13 17:52:37 +010039 if (interaction.options.getRole("role")) {
Skyler Grey1a67e182022-08-04 23:05:44 +010040 let role: Role;
pineafan6702cef2022-06-13 17:52:37 +010041 try {
Skyler Grey1a67e182022-08-04 23:05:44 +010042 role = interaction.options.getRole("role") as Role;
pineafan6702cef2022-06-13 17:52:37 +010043 } catch {
Skyler Grey75ea9172022-08-06 10:22:23 +010044 return await interaction.editReply({
45 embeds: [
46 new EmojiEmbed()
47 .setEmoji("GUILD.ROLES.DELETE")
48 .setTitle("Verify Role")
Skyler Grey11236ba2022-08-08 21:13:33 +010049 .setDescription("The role you provided is not a valid role")
Skyler Grey75ea9172022-08-06 10:22:23 +010050 .setStatus("Danger")
51 ]
52 });
pineafan6702cef2022-06-13 17:52:37 +010053 }
pineafan63fc5e22022-08-04 22:04:10 +010054 role = role as Discord.Role;
PineaFana00db1b2023-01-02 15:32:54 +000055 if (role.guild.id !== interaction.guild.id) {
Skyler Grey75ea9172022-08-06 10:22:23 +010056 return interaction.editReply({
57 embeds: [
58 new EmojiEmbed()
59 .setTitle("Verify Role")
60 .setDescription("You must choose a role in this server")
61 .setStatus("Danger")
62 .setEmoji("GUILD.ROLES.DELETE")
63 ]
64 });
pineafan6702cef2022-06-13 17:52:37 +010065 }
pineafan63fc5e22022-08-04 22:04:10 +010066 const confirmation = await new confirmationMessage(interaction)
pineafan62ce1922022-08-25 20:34:45 +010067 .setEmoji("GUILD.ROLES.EDIT", "GUILD.ROLES.DELETE")
pineafan6702cef2022-06-13 17:52:37 +010068 .setTitle("Verify Role")
Skyler Grey11236ba2022-08-08 21:13:33 +010069 .setDescription(`Are you sure you want to set the verify role to <@&${role.id}>?`)
pineafan6702cef2022-06-13 17:52:37 +010070 .setColor("Warning")
71 .setInverted(true)
pineafan63fc5e22022-08-04 22:04:10 +010072 .send(true);
73 if (confirmation.cancelled) return;
pineafan6702cef2022-06-13 17:52:37 +010074 if (confirmation.success) {
75 try {
PineaFana00db1b2023-01-02 15:32:54 +000076 await client.database.guilds.write(interaction.guild.id, {
Skyler Grey75ea9172022-08-06 10:22:23 +010077 "verify.role": role.id,
78 "verify.enabled": true
79 });
Skyler Grey11236ba2022-08-08 21:13:33 +010080 const { log, NucleusColors, entry, renderUser, renderRole } = client.logger;
pineafan63fc5e22022-08-04 22:04:10 +010081 const data = {
Skyler Grey75ea9172022-08-06 10:22:23 +010082 meta: {
pineafan63fc5e22022-08-04 22:04:10 +010083 type: "verifyRoleChanged",
84 displayName: "Verify Role Changed",
85 calculateType: "nucleusSettingsUpdated",
86 color: NucleusColors.green,
87 emoji: "CONTROL.BLOCKTICK",
88 timestamp: new Date().getTime()
89 },
90 list: {
Skyler Grey11236ba2022-08-08 21:13:33 +010091 memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
92 changedBy: entry(interaction.user.id, renderUser(interaction.user)),
pineafan63fc5e22022-08-04 22:04:10 +010093 role: entry(role.id, renderRole(role))
94 },
95 hidden: {
PineaFana00db1b2023-01-02 15:32:54 +000096 guild: interaction.guild.id
pineafanda6e5342022-07-03 10:03:16 +010097 }
pineafan63fc5e22022-08-04 22:04:10 +010098 };
99 log(data);
pineafan6702cef2022-06-13 17:52:37 +0100100 } catch (e) {
pineafan63fc5e22022-08-04 22:04:10 +0100101 console.log(e);
Skyler Grey75ea9172022-08-06 10:22:23 +0100102 return interaction.editReply({
103 embeds: [
104 new EmojiEmbed()
105 .setTitle("Verify Role")
Skyler Grey11236ba2022-08-08 21:13:33 +0100106 .setDescription("Something went wrong while setting the verify role")
Skyler Grey75ea9172022-08-06 10:22:23 +0100107 .setStatus("Danger")
108 .setEmoji("GUILD.ROLES.DELETE")
109 ],
110 components: []
111 });
pineafan6702cef2022-06-13 17:52:37 +0100112 }
113 } else {
Skyler Grey75ea9172022-08-06 10:22:23 +0100114 return interaction.editReply({
115 embeds: [
116 new EmojiEmbed()
117 .setTitle("Verify Role")
118 .setDescription("No changes were made")
119 .setStatus("Success")
120 .setEmoji("GUILD.ROLES.CREATE")
121 ],
122 components: []
123 });
pineafan6702cef2022-06-13 17:52:37 +0100124 }
125 }
126 let clicks = 0;
PineaFana00db1b2023-01-02 15:32:54 +0000127 const data = await client.database.guilds.read(interaction.guild.id);
pineafan6702cef2022-06-13 17:52:37 +0100128 let role = data.verify.role;
Skyler Greyad002172022-08-16 18:48:26 +0100129
130 let timedOut = false;
131 while (!timedOut) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100132 await interaction.editReply({
133 embeds: [
134 new EmojiEmbed()
135 .setTitle("Verify Role")
136 .setDescription(
Skyler Grey11236ba2022-08-08 21:13:33 +0100137 role ? `Your verify role is currently set to <@&${role}>` : "You have not set a verify role"
Skyler Grey75ea9172022-08-06 10:22:23 +0100138 )
139 .setStatus("Success")
140 .setEmoji("GUILD.ROLES.CREATE")
141 ],
142 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400143 new ActionRowBuilder().addComponents([
144 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100145 .setCustomId("clear")
Skyler Grey11236ba2022-08-08 21:13:33 +0100146 .setLabel(clicks ? "Click again to confirm" : "Reset role")
147 .setEmoji(getEmojiByName(clicks ? "TICKETS.ISSUE" : "CONTROL.CROSS", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400148 .setStyle(ButtonStyle.Danger)
Skyler Grey75ea9172022-08-06 10:22:23 +0100149 .setDisabled(!role),
TheCodedProf21c08592022-09-13 14:14:43 -0400150 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100151 .setCustomId("send")
152 .setLabel("Add verify button")
153 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400154 .setStyle(ButtonStyle.Primary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100155 ])
156 ]
157 });
Skyler Grey1a67e182022-08-04 23:05:44 +0100158 let i: MessageComponentInteraction;
pineafan6702cef2022-06-13 17:52:37 +0100159 try {
PineaFan0d06edc2023-01-17 22:10:31 +0000160 i = await m.awaitMessageComponent({
161 time: 300000,
162 filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id }
163 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100164 } catch (e) {
Skyler Greyad002172022-08-16 18:48:26 +0100165 timedOut = true;
166 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100167 }
pineafan63fc5e22022-08-04 22:04:10 +0100168 i.deferUpdate();
TheCodedProf21c08592022-09-13 14:14:43 -0400169 if ((i.component as Component).customId === "clear") {
pineafan6702cef2022-06-13 17:52:37 +0100170 clicks += 1;
pineafane23c4ec2022-07-27 21:56:27 +0100171 if (clicks === 2) {
pineafan6702cef2022-06-13 17:52:37 +0100172 clicks = 0;
PineaFana00db1b2023-01-02 15:32:54 +0000173 await client.database.guilds.write(interaction.guild.id, null, ["verify.role", "verify.enabled"]);
pineafan6702cef2022-06-13 17:52:37 +0100174 role = undefined;
175 }
TheCodedProf21c08592022-09-13 14:14:43 -0400176 } else if ((i.component as Component).customId === "send") {
pineafan41d93562022-07-30 22:10:15 +0100177 const verifyMessages = [
Skyler Grey75ea9172022-08-06 10:22:23 +0100178 {
179 label: "Verify",
180 description: "Click the button below to get verified"
181 },
182 {
183 label: "Get verified",
Skyler Grey11236ba2022-08-08 21:13:33 +0100184 description: "To get access to the rest of the server, click the button below"
Skyler Grey75ea9172022-08-06 10:22:23 +0100185 },
186 {
187 label: "Ready to verify?",
188 description: "Click the button below to verify yourself"
189 }
pineafan63fc5e22022-08-04 22:04:10 +0100190 ];
Skyler Greyad002172022-08-16 18:48:26 +0100191 let innerTimedOut = false;
192 let templateSelected = false;
193 while (!innerTimedOut && !templateSelected) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100194 await interaction.editReply({
195 embeds: [
196 new EmojiEmbed()
197 .setTitle("Verify Button")
Skyler Grey11236ba2022-08-08 21:13:33 +0100198 .setDescription("Select a message template to send in this channel")
Skyler Grey75ea9172022-08-06 10:22:23 +0100199 .setFooter({
Skyler Grey11236ba2022-08-08 21:13:33 +0100200 text: role ? "" : "You do no have a verify role set so the button will not work."
Skyler Grey75ea9172022-08-06 10:22:23 +0100201 })
202 .setStatus(role ? "Success" : "Warning")
203 .setEmoji("GUILD.ROLES.CREATE")
204 ],
205 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400206 new ActionRowBuilder().addComponents([
207 new SelectMenuBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100208 .setOptions(
209 verifyMessages.map(
210 (
211 t: {
212 label: string;
213 description: string;
214 value?: string;
215 },
216 index
217 ) => {
218 t.value = index.toString();
219 return t as {
220 value: string;
221 label: string;
222 description: string;
223 };
224 }
225 )
226 )
227 .setCustomId("template")
228 .setMaxValues(1)
229 .setMinValues(1)
230 .setPlaceholder("Select a message template")
231 ]),
TheCodedProf21c08592022-09-13 14:14:43 -0400232 new ActionRowBuilder().addComponents([
233 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100234 .setCustomId("back")
235 .setLabel("Back")
236 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400237 .setStyle(ButtonStyle.Danger),
238 new ButtonBuilder().setCustomId("blank").setLabel("Empty").setStyle(ButtonStyle.Secondary),
239 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100240 .setCustomId("custom")
241 .setLabel("Custom")
242 .setEmoji(getEmojiByName("TICKETS.OTHER", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400243 .setStyle(ButtonStyle.Primary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100244 ])
245 ]
246 });
Skyler Grey1a67e182022-08-04 23:05:44 +0100247 let i: MessageComponentInteraction;
pineafan41d93562022-07-30 22:10:15 +0100248 try {
PineaFan0d06edc2023-01-17 22:10:31 +0000249 i = await m.awaitMessageComponent({
250 time: 300000,
251 filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id }
252 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100253 } catch (e) {
Skyler Greyad002172022-08-16 18:48:26 +0100254 innerTimedOut = true;
255 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100256 }
TheCodedProf21c08592022-09-13 14:14:43 -0400257 if ((i.component as Component).customId === "template") {
pineafan63fc5e22022-08-04 22:04:10 +0100258 i.deferUpdate();
pineafan3a02ea32022-08-11 21:35:04 +0100259 await interaction.channel!.send({
Skyler Grey75ea9172022-08-06 10:22:23 +0100260 embeds: [
261 new EmojiEmbed()
pineafan3a02ea32022-08-11 21:35:04 +0100262 .setTitle(verifyMessages[parseInt((i as SelectMenuInteraction).values[0]!)]!.label)
Skyler Grey75ea9172022-08-06 10:22:23 +0100263 .setDescription(
pineafan3a02ea32022-08-11 21:35:04 +0100264 verifyMessages[parseInt((i as SelectMenuInteraction).values[0]!)]!.description
Skyler Grey75ea9172022-08-06 10:22:23 +0100265 )
266 .setStatus("Success")
267 .setEmoji("CONTROL.BLOCKTICK")
268 ],
269 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400270 new ActionRowBuilder().addComponents([
271 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100272 .setLabel("Verify")
Skyler Grey11236ba2022-08-08 21:13:33 +0100273 .setEmoji(getEmojiByName("CONTROL.TICK", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400274 .setStyle(ButtonStyle.Success)
Skyler Grey75ea9172022-08-06 10:22:23 +0100275 .setCustomId("verifybutton")
276 ])
277 ]
278 });
Skyler Greyad002172022-08-16 18:48:26 +0100279 templateSelected = true;
280 continue;
TheCodedProf21c08592022-09-13 14:14:43 -0400281 } else if ((i.component as Component).customId === "blank") {
Skyler Grey75ea9172022-08-06 10:22:23 +0100282 i.deferUpdate();
pineafan3a02ea32022-08-11 21:35:04 +0100283 await interaction.channel!.send({
Skyler Grey75ea9172022-08-06 10:22:23 +0100284 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400285 new ActionRowBuilder().addComponents([
286 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100287 .setLabel("Verify")
Skyler Grey11236ba2022-08-08 21:13:33 +0100288 .setEmoji(getEmojiByName("CONTROL.TICK", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400289 .setStyle(ButtonStyle.Success)
Skyler Grey75ea9172022-08-06 10:22:23 +0100290 .setCustomId("verifybutton")
291 ])
292 ]
293 });
Skyler Greyad002172022-08-16 18:48:26 +0100294 templateSelected = true;
295 continue;
TheCodedProf21c08592022-09-13 14:14:43 -0400296 } else if ((i.component as Component).customId === "custom") {
Skyler Grey75ea9172022-08-06 10:22:23 +0100297 await i.showModal(
298 new Discord.Modal()
299 .setCustomId("modal")
300 .setTitle("Enter embed details")
301 .addComponents(
TheCodedProf21c08592022-09-13 14:14:43 -0400302 new ActionRowBuilder<TextInputComponent>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100303 new TextInputComponent()
304 .setCustomId("title")
305 .setLabel("Title")
306 .setMaxLength(256)
307 .setRequired(true)
308 .setStyle("SHORT")
309 ),
TheCodedProf21c08592022-09-13 14:14:43 -0400310 new ActionRowBuilder<TextInputComponent>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100311 new TextInputComponent()
312 .setCustomId("description")
313 .setLabel("Description")
314 .setMaxLength(4000)
315 .setRequired(true)
316 .setStyle("PARAGRAPH")
317 )
318 )
319 );
pineafan41d93562022-07-30 22:10:15 +0100320 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100321 embeds: [
322 new EmojiEmbed()
323 .setTitle("Verify Button")
Skyler Grey11236ba2022-08-08 21:13:33 +0100324 .setDescription("Modal opened. If you can't see it, click back and try again.")
Skyler Grey75ea9172022-08-06 10:22:23 +0100325 .setStatus("Success")
326 .setEmoji("GUILD.TICKET.OPEN")
327 ],
328 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400329 new ActionRowBuilder().addComponents([
330 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100331 .setLabel("Back")
Skyler Grey11236ba2022-08-08 21:13:33 +0100332 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400333 .setStyle(ButtonStyle.Primary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100334 .setCustomId("back")
335 ])
336 ]
pineafan41d93562022-07-30 22:10:15 +0100337 });
338 let out;
339 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100340 out = await modalInteractionCollector(
341 m,
pineafan3a02ea32022-08-11 21:35:04 +0100342 (m: Interaction) =>
343 (m as MessageComponentInteraction | ModalSubmitInteraction).channelId ===
344 interaction.channelId,
Skyler Grey75ea9172022-08-06 10:22:23 +0100345 (m) => m.customId === "modify"
346 );
347 } catch (e) {
Skyler Greyad002172022-08-16 18:48:26 +0100348 innerTimedOut = true;
pineafan3a02ea32022-08-11 21:35:04 +0100349 continue;
Skyler Greyad002172022-08-16 18:48:26 +0100350 }
351 if (out !== null && out instanceof ModalSubmitInteraction) {
pineafan63fc5e22022-08-04 22:04:10 +0100352 const title = out.fields.getTextInputValue("title");
Skyler Grey11236ba2022-08-08 21:13:33 +0100353 const description = out.fields.getTextInputValue("description");
pineafan3a02ea32022-08-11 21:35:04 +0100354 await interaction.channel!.send({
Skyler Grey75ea9172022-08-06 10:22:23 +0100355 embeds: [
356 new EmojiEmbed()
357 .setTitle(title)
358 .setDescription(description)
359 .setStatus("Success")
360 .setEmoji("CONTROL.BLOCKTICK")
361 ],
362 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400363 new ActionRowBuilder().addComponents([
364 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100365 .setLabel("Verify")
Skyler Grey11236ba2022-08-08 21:13:33 +0100366 .setEmoji(getEmojiByName("CONTROL.TICK", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400367 .setStyle(ButtonStyle.Success)
Skyler Grey75ea9172022-08-06 10:22:23 +0100368 .setCustomId("verifybutton")
369 ])
370 ]
371 });
Skyler Greyad002172022-08-16 18:48:26 +0100372 templateSelected = true;
Skyler Grey75ea9172022-08-06 10:22:23 +0100373 }
pineafan41d93562022-07-30 22:10:15 +0100374 }
375 }
pineafan6702cef2022-06-13 17:52:37 +0100376 } else {
pineafan63fc5e22022-08-04 22:04:10 +0100377 i.deferUpdate();
pineafan41d93562022-07-30 22:10:15 +0100378 break;
pineafan6702cef2022-06-13 17:52:37 +0100379 }
380 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100381 await interaction.editReply({
382 embeds: [m.embeds[0]!.setFooter({ text: "Message closed" })],
383 components: []
384 });
pineafan63fc5e22022-08-04 22:04:10 +0100385};
pineafan4f164f32022-02-26 22:07:12 +0000386
Skyler Grey1a67e182022-08-04 23:05:44 +0100387const check = (interaction: CommandInteraction) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100388 const member = interaction.member as Discord.GuildMember;
PineaFana00db1b2023-01-02 15:32:54 +0000389 if (!member.permissions.has("ManageGuild"))
PineaFan0d06edc2023-01-17 22:10:31 +0000390 return "You must have the *Manage Server* permission to use this command";
pineafan4f164f32022-02-26 22:07:12 +0000391 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100392};
pineafan4f164f32022-02-26 22:07:12 +0000393
394export { command };
395export { callback };
pineafan6702cef2022-06-13 17:52:37 +0100396export { check };