blob: 4d850a9825dc359909004e60b4bb45014940b74d [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed } from "../../utils/defaults.js";
Skyler Greyda16adf2023-03-05 10:22:12 +00002import Discord, {
3 CommandInteraction,
4 ActionRowBuilder,
5 ButtonBuilder,
6 ButtonStyle,
7 ButtonComponent,
8 TextInputBuilder,
9 RoleSelectMenuBuilder
10} from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +010011import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
12import getEmojiByName from "../../utils/getEmojiByName.js";
TheCodedProff86ba092023-01-27 17:10:07 -050013import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +010014import client from "../../utils/client.js";
15import { modalInteractionCollector } from "../../utils/dualCollector.js";
pineafan0bc04162022-07-25 17:22:26 +010016
17const command = (builder: SlashCommandSubcommandBuilder) =>
18 builder
TheCodedProf1f675042023-02-16 17:01:29 -050019 .setName("moderation")
Skyler Greyda16adf2023-03-05 10:22:12 +000020 .setDescription("Links and text shown to a user after a moderator action is performed");
pineafan0bc04162022-07-25 17:22:26 +010021
TheCodedProf1f675042023-02-16 17:01:29 -050022const callback = async (interaction: CommandInteraction): Promise<void> => {
TheCodedProf01cba762023-02-18 15:55:05 -050023 const m = await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010024 embeds: LoadingEmbed,
25 ephemeral: true,
26 fetchReply: true
27 });
Skyler Greyad002172022-08-16 18:48:26 +010028 let timedOut = false;
29 while (!timedOut) {
TheCodedProfd9636e82023-01-17 22:13:06 -050030 const config = await client.database.guilds.read(interaction.guild!.id);
PineaFan9b2ac4d2023-01-18 14:41:07 +000031 const moderation = config.moderation;
TheCodedProf01cba762023-02-18 15:55:05 -050032 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +010033 embeds: [
34 new EmojiEmbed()
35 .setTitle("Moderation Commands")
36 .setEmoji("PUNISH.BAN.GREEN")
37 .setStatus("Success")
38 .setDescription(
39 "These links are shown below the message sent in a user's DM when they are punished.\n\n" +
Skyler Greyda16adf2023-03-05 10:22:12 +000040 "**Mute Role:** " +
41 (moderation.mute.role ? `<@&${moderation.mute.role}>` : "*None set*")
Skyler Grey75ea9172022-08-06 10:22:23 +010042 )
43 ],
44 components: [
TheCodedProfd9636e82023-01-17 22:13:06 -050045 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040046 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010047 .setLabel("Warn")
48 .setEmoji(getEmojiByName("PUNISH.WARN.YELLOW", "id"))
49 .setCustomId("warn")
TheCodedProf21c08592022-09-13 14:14:43 -040050 .setStyle(ButtonStyle.Secondary),
51 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010052 .setLabel("Mute")
53 .setEmoji(getEmojiByName("PUNISH.MUTE.YELLOW", "id"))
54 .setCustomId("mute")
TheCodedProf21c08592022-09-13 14:14:43 -040055 .setStyle(ButtonStyle.Secondary),
56 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010057 .setLabel("Nickname")
58 .setEmoji(getEmojiByName("PUNISH.NICKNAME.GREEN", "id"))
59 .setCustomId("nickname")
TheCodedProf21c08592022-09-13 14:14:43 -040060 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010061 ]),
TheCodedProfd9636e82023-01-17 22:13:06 -050062 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040063 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010064 .setLabel("Kick")
65 .setEmoji(getEmojiByName("PUNISH.KICK.RED", "id"))
66 .setCustomId("kick")
TheCodedProf21c08592022-09-13 14:14:43 -040067 .setStyle(ButtonStyle.Secondary),
68 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010069 .setLabel("Softban")
70 .setEmoji(getEmojiByName("PUNISH.BAN.YELLOW", "id"))
71 .setCustomId("softban")
TheCodedProf21c08592022-09-13 14:14:43 -040072 .setStyle(ButtonStyle.Secondary),
73 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010074 .setLabel("Ban")
75 .setEmoji(getEmojiByName("PUNISH.BAN.RED", "id"))
76 .setCustomId("ban")
TheCodedProf21c08592022-09-13 14:14:43 -040077 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010078 ]),
TheCodedProfd9636e82023-01-17 22:13:06 -050079 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040080 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010081 .setCustomId("timeout")
Skyler Grey11236ba2022-08-08 21:13:33 +010082 .setLabel("Mute timeout " + (moderation.mute.timeout ? "Enabled" : "Disabled"))
TheCodedProf21c08592022-09-13 14:14:43 -040083 .setStyle(moderation.mute.timeout ? ButtonStyle.Success : ButtonStyle.Danger)
Skyler Grey11236ba2022-08-08 21:13:33 +010084 .setEmoji(getEmojiByName("CONTROL." + (moderation.mute.timeout ? "TICK" : "CROSS"), "id"))
TheCodedProf1f675042023-02-16 17:01:29 -050085 ]),
86 new ActionRowBuilder<RoleSelectMenuBuilder>().addComponents(
Skyler Greyda16adf2023-03-05 10:22:12 +000087 new RoleSelectMenuBuilder().setCustomId("muteRole").setPlaceholder("Select a new mute role")
TheCodedProf1f675042023-02-16 17:01:29 -050088 )
Skyler Grey75ea9172022-08-06 10:22:23 +010089 ]
90 });
pineafan0bc04162022-07-25 17:22:26 +010091 let i;
92 try {
PineaFan0d06edc2023-01-17 22:10:31 +000093 i = await m.awaitMessageComponent({
94 time: 300000,
Skyler Greyda16adf2023-03-05 10:22:12 +000095 filter: (i) => {
96 return (
97 i.user.id === interaction.user.id &&
98 i.channel!.id === interaction.channel!.id &&
99 i.message.id === m.id
100 );
101 }
PineaFan0d06edc2023-01-17 22:10:31 +0000102 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100103 } catch (e) {
Skyler Greyad002172022-08-16 18:48:26 +0100104 timedOut = true;
105 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100106 }
TheCodedProfd9636e82023-01-17 22:13:06 -0500107 type modIDs = "mute" | "kick" | "ban" | "softban" | "warn" | "role";
PineaFan9b2ac4d2023-01-18 14:41:07 +0000108 let chosen = moderation[i.customId as modIDs];
TheCodedProf1f675042023-02-16 17:01:29 -0500109 if (i.isRoleSelectMenu()) {
TheCodedProf267563a2023-01-21 17:00:57 -0500110 await i.deferUpdate();
TheCodedProf1f675042023-02-16 17:01:29 -0500111 await client.database.guilds.write(interaction.guild!.id, {
112 "moderation.mute.role": i.values[0]!
113 });
pineafan63fc5e22022-08-04 22:04:10 +0100114 continue;
TheCodedProf1f675042023-02-16 17:01:29 -0500115 } else if ((i.component as ButtonComponent).customId === "timeout") {
pineafan63fc5e22022-08-04 22:04:10 +0100116 await i.deferUpdate();
TheCodedProfd9636e82023-01-17 22:13:06 -0500117 await client.database.guilds.write(interaction.guild!.id, {
Skyler Grey75ea9172022-08-06 10:22:23 +0100118 "moderation.mute.timeout": !moderation.mute.timeout
119 });
pineafan63fc5e22022-08-04 22:04:10 +0100120 continue;
pineafan0bc04162022-07-25 17:22:26 +0100121 } else if (i.customId) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100122 await i.showModal(
TheCodedProfd9636e82023-01-17 22:13:06 -0500123 new Discord.ModalBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100124 .setCustomId("modal")
125 .setTitle(`Options for ${i.customId}`)
126 .addComponents(
Skyler Greyda16adf2023-03-05 10:22:12 +0000127 new ActionRowBuilder<TextInputBuilder>()
128 .addComponents(
129 new TextInputBuilder()
130 .setCustomId("name")
131 .setLabel("Button text")
132 .setMaxLength(100)
133 .setRequired(false)
134 .setStyle(Discord.TextInputStyle.Short)
135 .setValue(chosen.text ?? "")
136 )
137 .toJSON(),
138 new ActionRowBuilder<TextInputBuilder>()
139 .addComponents(
140 new TextInputBuilder()
141 .setCustomId("url")
142 .setLabel("URL - Type {id} to insert the user's ID")
143 .setMaxLength(2000)
144 .setRequired(false)
145 .setStyle(Discord.TextInputStyle.Short)
146 .setValue(chosen.link ?? "")
147 )
148 .toJSON()
Skyler Grey75ea9172022-08-06 10:22:23 +0100149 )
150 );
pineafan0bc04162022-07-25 17:22:26 +0100151 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100152 embeds: [
153 new EmojiEmbed()
154 .setTitle("Moderation Links")
Skyler Grey11236ba2022-08-08 21:13:33 +0100155 .setDescription("Modal opened. If you can't see it, click back and try again.")
Skyler Grey75ea9172022-08-06 10:22:23 +0100156 .setStatus("Success")
157 .setEmoji("GUILD.TICKET.OPEN")
158 ],
159 components: [
TheCodedProfd9636e82023-01-17 22:13:06 -0500160 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -0400161 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100162 .setLabel("Back")
163 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400164 .setStyle(ButtonStyle.Primary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100165 .setCustomId("back")
166 ])
167 ]
pineafan0bc04162022-07-25 17:22:26 +0100168 });
PineaFan9b2ac4d2023-01-18 14:41:07 +0000169 let out: Discord.ModalSubmitInteraction | null;
pineafan0bc04162022-07-25 17:22:26 +0100170 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000171 out = (await modalInteractionCollector(m, interaction.user)) as Discord.ModalSubmitInteraction | null;
Skyler Grey75ea9172022-08-06 10:22:23 +0100172 } catch (e) {
173 continue;
174 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000175 if (!out || out.isButton()) continue;
PineaFan9b2ac4d2023-01-18 14:41:07 +0000176 const buttonText = out.fields.getTextInputValue("name");
177 const buttonLink = out.fields.getTextInputValue("url").replace(/{id}/gi, "{id}");
178 const current = chosen;
179 if (current.text !== buttonText || current.link !== buttonLink) {
180 chosen = { text: buttonText, link: buttonLink };
181 await client.database.guilds.write(interaction.guild!.id, {
182 ["moderation." + i.customId]: {
183 text: buttonText,
184 link: buttonLink
185 }
186 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100187 }
pineafan0bc04162022-07-25 17:22:26 +0100188 }
189 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000190 await interaction.deleteReply();
pineafan63fc5e22022-08-04 22:04:10 +0100191};
pineafan0bc04162022-07-25 17:22:26 +0100192
TheCodedProff86ba092023-01-27 17:10:07 -0500193const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100194 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000195 if (!member.permissions.has("ManageGuild"))
196 return "You must have the *Manage Server* permission to use this command";
pineafan0bc04162022-07-25 17:22:26 +0100197 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100198};
pineafan0bc04162022-07-25 17:22:26 +0100199
200export { command };
201export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100202export { check };