blob: 4493f79b9968ce1fc5aa438ed002a33ad6c05a94 [file] [log] [blame]
pineafan63fc5e22022-08-04 22:04:10 +01001import { LoadingEmbed } from "./../../utils/defaultEmbeds.js";
TheCodedProf21c08592022-09-13 14:14:43 -04002import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, TextInputComponent, Role, ButtonStyle } from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +01003import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
4import getEmojiByName from "../../utils/getEmojiByName.js";
TheCodedProf21c08592022-09-13 14:14:43 -04005import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
pineafan0bc04162022-07-25 17:22:26 +01006import client from "../../utils/client.js";
7import { modalInteractionCollector } from "../../utils/dualCollector.js";
8import confirmationMessage from "../../utils/confirmationMessage.js";
9import keyValueList from "../../utils/generateKeyValueList.js";
10
11const command = (builder: SlashCommandSubcommandBuilder) =>
12 builder
pineafan63fc5e22022-08-04 22:04:10 +010013 .setName("commands")
Skyler Grey11236ba2022-08-08 21:13:33 +010014 .setDescription("Links and text shown to a user after a moderator action is performed")
15 .addRoleOption((o) => o.setName("role").setDescription("The role given when a member is muted"));
pineafan0bc04162022-07-25 17:22:26 +010016
pineafan3a02ea32022-08-11 21:35:04 +010017const callback = async (interaction: CommandInteraction): Promise<unknown> => {
Skyler Grey75ea9172022-08-06 10:22:23 +010018 await interaction.reply({
19 embeds: LoadingEmbed,
20 ephemeral: true,
21 fetchReply: true
22 });
pineafan0bc04162022-07-25 17:22:26 +010023 let m;
24 let clicked = "";
TheCodedProf21c08592022-09-13 14:14:43 -040025 if (interaction.options.get("role")) {
pineafan63fc5e22022-08-04 22:04:10 +010026 const confirmation = await new confirmationMessage(interaction)
pineafan0bc04162022-07-25 17:22:26 +010027 .setEmoji("GUILD.ROLES.DELETE")
28 .setTitle("Moderation Commands")
Skyler Grey75ea9172022-08-06 10:22:23 +010029 .setDescription(
30 keyValueList({
TheCodedProf21c08592022-09-13 14:14:43 -040031 role: `<@&${(interaction.options.get("role") as unknown as Role).id}>`
Skyler Grey75ea9172022-08-06 10:22:23 +010032 })
33 )
pineafan0bc04162022-07-25 17:22:26 +010034 .setColor("Danger")
pineafan63fc5e22022-08-04 22:04:10 +010035 .send(true);
pineafan62ce1922022-08-25 20:34:45 +010036 if (confirmation.cancelled) return
pineafan0bc04162022-07-25 17:22:26 +010037 if (confirmation.success) {
TheCodedProf21c08592022-09-13 14:14:43 -040038 await client.database.guilds.write(interaction!.guild.id, {
39 ["moderation.mute.role"]: (interaction.options.get("role") as unknown as Role).id
Skyler Grey75ea9172022-08-06 10:22:23 +010040 });
pineafan0bc04162022-07-25 17:22:26 +010041 }
42 }
Skyler Greyad002172022-08-16 18:48:26 +010043 let timedOut = false;
44 while (!timedOut) {
TheCodedProf21c08592022-09-13 14:14:43 -040045 const config = await client.database.guilds.read(interaction!.guild.id);
pineafan63fc5e22022-08-04 22:04:10 +010046 const moderation = config.getKey("moderation");
Skyler Grey75ea9172022-08-06 10:22:23 +010047 m = await interaction.editReply({
48 embeds: [
49 new EmojiEmbed()
50 .setTitle("Moderation Commands")
51 .setEmoji("PUNISH.BAN.GREEN")
52 .setStatus("Success")
53 .setDescription(
54 "These links are shown below the message sent in a user's DM when they are punished.\n\n" +
55 "**Mute Role:** " +
Skyler Grey11236ba2022-08-08 21:13:33 +010056 (moderation.mute.role ? `<@&${moderation.mute.role}>` : "*None set*")
Skyler Grey75ea9172022-08-06 10:22:23 +010057 )
58 ],
59 components: [
TheCodedProf21c08592022-09-13 14:14:43 -040060 new ActionRowBuilder().addComponents([
61 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010062 .setLabel("Warn")
63 .setEmoji(getEmojiByName("PUNISH.WARN.YELLOW", "id"))
64 .setCustomId("warn")
TheCodedProf21c08592022-09-13 14:14:43 -040065 .setStyle(ButtonStyle.Secondary),
66 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010067 .setLabel("Mute")
68 .setEmoji(getEmojiByName("PUNISH.MUTE.YELLOW", "id"))
69 .setCustomId("mute")
TheCodedProf21c08592022-09-13 14:14:43 -040070 .setStyle(ButtonStyle.Secondary),
71 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010072 .setLabel("Nickname")
73 .setEmoji(getEmojiByName("PUNISH.NICKNAME.GREEN", "id"))
74 .setCustomId("nickname")
TheCodedProf21c08592022-09-13 14:14:43 -040075 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010076 ]),
TheCodedProf21c08592022-09-13 14:14:43 -040077 new ActionRowBuilder().addComponents([
78 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010079 .setLabel("Kick")
80 .setEmoji(getEmojiByName("PUNISH.KICK.RED", "id"))
81 .setCustomId("kick")
TheCodedProf21c08592022-09-13 14:14:43 -040082 .setStyle(ButtonStyle.Secondary),
83 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010084 .setLabel("Softban")
85 .setEmoji(getEmojiByName("PUNISH.BAN.YELLOW", "id"))
86 .setCustomId("softban")
TheCodedProf21c08592022-09-13 14:14:43 -040087 .setStyle(ButtonStyle.Secondary),
88 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010089 .setLabel("Ban")
90 .setEmoji(getEmojiByName("PUNISH.BAN.RED", "id"))
91 .setCustomId("ban")
TheCodedProf21c08592022-09-13 14:14:43 -040092 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010093 ]),
TheCodedProf21c08592022-09-13 14:14:43 -040094 new ActionRowBuilder().addComponents([
95 new ButtonBuilder()
Skyler Grey11236ba2022-08-08 21:13:33 +010096 .setLabel(clicked === "clearMuteRole" ? "Click again to confirm" : "Clear mute role")
Skyler Grey75ea9172022-08-06 10:22:23 +010097 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
98 .setCustomId("clearMuteRole")
TheCodedProf21c08592022-09-13 14:14:43 -040099 .setStyle(ButtonStyle.Danger)
Skyler Grey75ea9172022-08-06 10:22:23 +0100100 .setDisabled(!moderation.mute.role),
TheCodedProf21c08592022-09-13 14:14:43 -0400101 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100102 .setCustomId("timeout")
Skyler Grey11236ba2022-08-08 21:13:33 +0100103 .setLabel("Mute timeout " + (moderation.mute.timeout ? "Enabled" : "Disabled"))
TheCodedProf21c08592022-09-13 14:14:43 -0400104 .setStyle(moderation.mute.timeout ? ButtonStyle.Success : ButtonStyle.Danger)
Skyler Grey11236ba2022-08-08 21:13:33 +0100105 .setEmoji(getEmojiByName("CONTROL." + (moderation.mute.timeout ? "TICK" : "CROSS"), "id"))
Skyler Grey75ea9172022-08-06 10:22:23 +0100106 ])
107 ]
108 });
pineafan0bc04162022-07-25 17:22:26 +0100109 let i;
110 try {
111 i = await m.awaitMessageComponent({ time: 300000 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100112 } catch (e) {
Skyler Greyad002172022-08-16 18:48:26 +0100113 timedOut = true;
114 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100115 }
116 let chosen = moderation[i.customId] ?? { text: null, url: null };
pineafan0bc04162022-07-25 17:22:26 +0100117 if (i.component.customId === "clearMuteRole") {
pineafan63fc5e22022-08-04 22:04:10 +0100118 i.deferUpdate();
pineafan0bc04162022-07-25 17:22:26 +0100119 if (clicked === "clearMuteRole") {
Skyler Grey75ea9172022-08-06 10:22:23 +0100120 await client.database.guilds.write(interaction.guild.id, {
121 "moderation.mute.role": null
122 });
123 } else {
124 clicked = "clearMuteRole";
125 }
pineafan63fc5e22022-08-04 22:04:10 +0100126 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100127 } else {
128 clicked = "";
129 }
pineafan0bc04162022-07-25 17:22:26 +0100130 if (i.component.customId === "timeout") {
pineafan63fc5e22022-08-04 22:04:10 +0100131 await i.deferUpdate();
Skyler Grey75ea9172022-08-06 10:22:23 +0100132 await client.database.guilds.write(interaction.guild.id, {
133 "moderation.mute.timeout": !moderation.mute.timeout
134 });
pineafan63fc5e22022-08-04 22:04:10 +0100135 continue;
pineafan0bc04162022-07-25 17:22:26 +0100136 } else if (i.customId) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100137 await i.showModal(
138 new Discord.Modal()
139 .setCustomId("modal")
140 .setTitle(`Options for ${i.customId}`)
141 .addComponents(
TheCodedProf21c08592022-09-13 14:14:43 -0400142 new ActionRowBuilder<TextInputComponent>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100143 new TextInputComponent()
144 .setCustomId("name")
145 .setLabel("Button text")
146 .setMaxLength(100)
147 .setRequired(false)
148 .setStyle("SHORT")
149 .setValue(chosen.text ?? "")
150 ),
TheCodedProf21c08592022-09-13 14:14:43 -0400151 new ActionRowBuilder<TextInputComponent>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100152 new TextInputComponent()
153 .setCustomId("url")
Skyler Grey11236ba2022-08-08 21:13:33 +0100154 .setLabel("URL - Type {id} to insert the user's ID")
Skyler Grey75ea9172022-08-06 10:22:23 +0100155 .setMaxLength(2000)
156 .setRequired(false)
157 .setStyle("SHORT")
158 .setValue(chosen.link ?? "")
159 )
160 )
161 );
pineafan0bc04162022-07-25 17:22:26 +0100162 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100163 embeds: [
164 new EmojiEmbed()
165 .setTitle("Moderation Links")
Skyler Grey11236ba2022-08-08 21:13:33 +0100166 .setDescription("Modal opened. If you can't see it, click back and try again.")
Skyler Grey75ea9172022-08-06 10:22:23 +0100167 .setStatus("Success")
168 .setEmoji("GUILD.TICKET.OPEN")
169 ],
170 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400171 new ActionRowBuilder().addComponents([
172 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100173 .setLabel("Back")
174 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400175 .setStyle(ButtonStyle.Primary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100176 .setCustomId("back")
177 ])
178 ]
pineafan0bc04162022-07-25 17:22:26 +0100179 });
180 let out;
181 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100182 out = await modalInteractionCollector(
183 m,
184 (m) => m.channel.id === interaction.channel.id,
185 (_) => true
186 );
187 } catch (e) {
188 continue;
189 }
pineafan0bc04162022-07-25 17:22:26 +0100190 if (out.fields) {
pineafan63fc5e22022-08-04 22:04:10 +0100191 const buttonText = out.fields.getTextInputValue("name");
Skyler Grey11236ba2022-08-08 21:13:33 +0100192 const buttonLink = out.fields.getTextInputValue("url").replace(/{id}/gi, "{id}");
pineafan63fc5e22022-08-04 22:04:10 +0100193 const current = chosen;
Skyler Grey11236ba2022-08-08 21:13:33 +0100194 if (current.text !== buttonText || current.link !== buttonLink) {
pineafan0bc04162022-07-25 17:22:26 +0100195 chosen = { text: buttonText, link: buttonLink };
Skyler Grey75ea9172022-08-06 10:22:23 +0100196 await client.database.guilds.write(interaction.guild.id, {
197 ["moderation." + i.customId]: {
198 text: buttonText,
199 link: buttonLink
200 }
201 });
pineafan0bc04162022-07-25 17:22:26 +0100202 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100203 } else {
204 continue;
205 }
pineafan0bc04162022-07-25 17:22:26 +0100206 }
207 }
pineafan63fc5e22022-08-04 22:04:10 +0100208};
pineafan0bc04162022-07-25 17:22:26 +0100209
PineaFan64486c42022-12-28 09:21:04 +0000210const check = (interaction: CommandInteraction) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100211 const member = interaction.member as Discord.GuildMember;
212 if (!member.permissions.has("MANAGE_GUILD"))
pineafan3a02ea32022-08-11 21:35:04 +0100213 throw new Error("You must have the *Manage Server* permission to use this command");
pineafan0bc04162022-07-25 17:22:26 +0100214 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100215};
pineafan0bc04162022-07-25 17:22:26 +0100216
217export { command };
218export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100219export { check };