blob: 5260858437cd614466d50c2fdb03de90ee863b10 [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 { WrappedCheck } from "jshaiku";
7import client from "../../utils/client.js";
8import { modalInteractionCollector } from "../../utils/dualCollector.js";
9import confirmationMessage from "../../utils/confirmationMessage.js";
10import keyValueList from "../../utils/generateKeyValueList.js";
11
12const command = (builder: SlashCommandSubcommandBuilder) =>
13 builder
pineafan63fc5e22022-08-04 22:04:10 +010014 .setName("commands")
Skyler Grey11236ba2022-08-08 21:13:33 +010015 .setDescription("Links and text shown to a user after a moderator action is performed")
16 .addRoleOption((o) => o.setName("role").setDescription("The role given when a member is muted"));
pineafan0bc04162022-07-25 17:22:26 +010017
pineafan3a02ea32022-08-11 21:35:04 +010018const callback = async (interaction: CommandInteraction): Promise<unknown> => {
Skyler Grey75ea9172022-08-06 10:22:23 +010019 await interaction.reply({
20 embeds: LoadingEmbed,
21 ephemeral: true,
22 fetchReply: true
23 });
pineafan0bc04162022-07-25 17:22:26 +010024 let m;
25 let clicked = "";
TheCodedProf21c08592022-09-13 14:14:43 -040026 if (interaction.options.get("role")) {
pineafan63fc5e22022-08-04 22:04:10 +010027 const confirmation = await new confirmationMessage(interaction)
pineafan0bc04162022-07-25 17:22:26 +010028 .setEmoji("GUILD.ROLES.DELETE")
29 .setTitle("Moderation Commands")
Skyler Grey75ea9172022-08-06 10:22:23 +010030 .setDescription(
31 keyValueList({
TheCodedProf21c08592022-09-13 14:14:43 -040032 role: `<@&${(interaction.options.get("role") as unknown as Role).id}>`
Skyler Grey75ea9172022-08-06 10:22:23 +010033 })
34 )
pineafan0bc04162022-07-25 17:22:26 +010035 .setColor("Danger")
pineafan63fc5e22022-08-04 22:04:10 +010036 .send(true);
pineafan62ce1922022-08-25 20:34:45 +010037 if (confirmation.cancelled) return
pineafan0bc04162022-07-25 17:22:26 +010038 if (confirmation.success) {
TheCodedProf21c08592022-09-13 14:14:43 -040039 await client.database.guilds.write(interaction!.guild.id, {
40 ["moderation.mute.role"]: (interaction.options.get("role") as unknown as Role).id
Skyler Grey75ea9172022-08-06 10:22:23 +010041 });
pineafan0bc04162022-07-25 17:22:26 +010042 }
43 }
Skyler Greyad002172022-08-16 18:48:26 +010044 let timedOut = false;
45 while (!timedOut) {
TheCodedProf21c08592022-09-13 14:14:43 -040046 const config = await client.database.guilds.read(interaction!.guild.id);
pineafan63fc5e22022-08-04 22:04:10 +010047 const moderation = config.getKey("moderation");
Skyler Grey75ea9172022-08-06 10:22:23 +010048 m = await interaction.editReply({
49 embeds: [
50 new EmojiEmbed()
51 .setTitle("Moderation Commands")
52 .setEmoji("PUNISH.BAN.GREEN")
53 .setStatus("Success")
54 .setDescription(
55 "These links are shown below the message sent in a user's DM when they are punished.\n\n" +
56 "**Mute Role:** " +
Skyler Grey11236ba2022-08-08 21:13:33 +010057 (moderation.mute.role ? `<@&${moderation.mute.role}>` : "*None set*")
Skyler Grey75ea9172022-08-06 10:22:23 +010058 )
59 ],
60 components: [
TheCodedProf21c08592022-09-13 14:14:43 -040061 new ActionRowBuilder().addComponents([
62 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010063 .setLabel("Warn")
64 .setEmoji(getEmojiByName("PUNISH.WARN.YELLOW", "id"))
65 .setCustomId("warn")
TheCodedProf21c08592022-09-13 14:14:43 -040066 .setStyle(ButtonStyle.Secondary),
67 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010068 .setLabel("Mute")
69 .setEmoji(getEmojiByName("PUNISH.MUTE.YELLOW", "id"))
70 .setCustomId("mute")
TheCodedProf21c08592022-09-13 14:14:43 -040071 .setStyle(ButtonStyle.Secondary),
72 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010073 .setLabel("Nickname")
74 .setEmoji(getEmojiByName("PUNISH.NICKNAME.GREEN", "id"))
75 .setCustomId("nickname")
TheCodedProf21c08592022-09-13 14:14:43 -040076 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010077 ]),
TheCodedProf21c08592022-09-13 14:14:43 -040078 new ActionRowBuilder().addComponents([
79 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010080 .setLabel("Kick")
81 .setEmoji(getEmojiByName("PUNISH.KICK.RED", "id"))
82 .setCustomId("kick")
TheCodedProf21c08592022-09-13 14:14:43 -040083 .setStyle(ButtonStyle.Secondary),
84 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010085 .setLabel("Softban")
86 .setEmoji(getEmojiByName("PUNISH.BAN.YELLOW", "id"))
87 .setCustomId("softban")
TheCodedProf21c08592022-09-13 14:14:43 -040088 .setStyle(ButtonStyle.Secondary),
89 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010090 .setLabel("Ban")
91 .setEmoji(getEmojiByName("PUNISH.BAN.RED", "id"))
92 .setCustomId("ban")
TheCodedProf21c08592022-09-13 14:14:43 -040093 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010094 ]),
TheCodedProf21c08592022-09-13 14:14:43 -040095 new ActionRowBuilder().addComponents([
96 new ButtonBuilder()
Skyler Grey11236ba2022-08-08 21:13:33 +010097 .setLabel(clicked === "clearMuteRole" ? "Click again to confirm" : "Clear mute role")
Skyler Grey75ea9172022-08-06 10:22:23 +010098 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
99 .setCustomId("clearMuteRole")
TheCodedProf21c08592022-09-13 14:14:43 -0400100 .setStyle(ButtonStyle.Danger)
Skyler Grey75ea9172022-08-06 10:22:23 +0100101 .setDisabled(!moderation.mute.role),
TheCodedProf21c08592022-09-13 14:14:43 -0400102 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100103 .setCustomId("timeout")
Skyler Grey11236ba2022-08-08 21:13:33 +0100104 .setLabel("Mute timeout " + (moderation.mute.timeout ? "Enabled" : "Disabled"))
TheCodedProf21c08592022-09-13 14:14:43 -0400105 .setStyle(moderation.mute.timeout ? ButtonStyle.Success : ButtonStyle.Danger)
Skyler Grey11236ba2022-08-08 21:13:33 +0100106 .setEmoji(getEmojiByName("CONTROL." + (moderation.mute.timeout ? "TICK" : "CROSS"), "id"))
Skyler Grey75ea9172022-08-06 10:22:23 +0100107 ])
108 ]
109 });
pineafan0bc04162022-07-25 17:22:26 +0100110 let i;
111 try {
112 i = await m.awaitMessageComponent({ time: 300000 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100113 } catch (e) {
Skyler Greyad002172022-08-16 18:48:26 +0100114 timedOut = true;
115 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100116 }
117 let chosen = moderation[i.customId] ?? { text: null, url: null };
pineafan0bc04162022-07-25 17:22:26 +0100118 if (i.component.customId === "clearMuteRole") {
pineafan63fc5e22022-08-04 22:04:10 +0100119 i.deferUpdate();
pineafan0bc04162022-07-25 17:22:26 +0100120 if (clicked === "clearMuteRole") {
Skyler Grey75ea9172022-08-06 10:22:23 +0100121 await client.database.guilds.write(interaction.guild.id, {
122 "moderation.mute.role": null
123 });
124 } else {
125 clicked = "clearMuteRole";
126 }
pineafan63fc5e22022-08-04 22:04:10 +0100127 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100128 } else {
129 clicked = "";
130 }
pineafan0bc04162022-07-25 17:22:26 +0100131 if (i.component.customId === "timeout") {
pineafan63fc5e22022-08-04 22:04:10 +0100132 await i.deferUpdate();
Skyler Grey75ea9172022-08-06 10:22:23 +0100133 await client.database.guilds.write(interaction.guild.id, {
134 "moderation.mute.timeout": !moderation.mute.timeout
135 });
pineafan63fc5e22022-08-04 22:04:10 +0100136 continue;
pineafan0bc04162022-07-25 17:22:26 +0100137 } else if (i.customId) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100138 await i.showModal(
139 new Discord.Modal()
140 .setCustomId("modal")
141 .setTitle(`Options for ${i.customId}`)
142 .addComponents(
TheCodedProf21c08592022-09-13 14:14:43 -0400143 new ActionRowBuilder<TextInputComponent>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100144 new TextInputComponent()
145 .setCustomId("name")
146 .setLabel("Button text")
147 .setMaxLength(100)
148 .setRequired(false)
149 .setStyle("SHORT")
150 .setValue(chosen.text ?? "")
151 ),
TheCodedProf21c08592022-09-13 14:14:43 -0400152 new ActionRowBuilder<TextInputComponent>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100153 new TextInputComponent()
154 .setCustomId("url")
Skyler Grey11236ba2022-08-08 21:13:33 +0100155 .setLabel("URL - Type {id} to insert the user's ID")
Skyler Grey75ea9172022-08-06 10:22:23 +0100156 .setMaxLength(2000)
157 .setRequired(false)
158 .setStyle("SHORT")
159 .setValue(chosen.link ?? "")
160 )
161 )
162 );
pineafan0bc04162022-07-25 17:22:26 +0100163 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100164 embeds: [
165 new EmojiEmbed()
166 .setTitle("Moderation Links")
Skyler Grey11236ba2022-08-08 21:13:33 +0100167 .setDescription("Modal opened. If you can't see it, click back and try again.")
Skyler Grey75ea9172022-08-06 10:22:23 +0100168 .setStatus("Success")
169 .setEmoji("GUILD.TICKET.OPEN")
170 ],
171 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400172 new ActionRowBuilder().addComponents([
173 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100174 .setLabel("Back")
175 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400176 .setStyle(ButtonStyle.Primary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100177 .setCustomId("back")
178 ])
179 ]
pineafan0bc04162022-07-25 17:22:26 +0100180 });
181 let out;
182 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100183 out = await modalInteractionCollector(
184 m,
185 (m) => m.channel.id === interaction.channel.id,
186 (_) => true
187 );
188 } catch (e) {
189 continue;
190 }
pineafan0bc04162022-07-25 17:22:26 +0100191 if (out.fields) {
pineafan63fc5e22022-08-04 22:04:10 +0100192 const buttonText = out.fields.getTextInputValue("name");
Skyler Grey11236ba2022-08-08 21:13:33 +0100193 const buttonLink = out.fields.getTextInputValue("url").replace(/{id}/gi, "{id}");
pineafan63fc5e22022-08-04 22:04:10 +0100194 const current = chosen;
Skyler Grey11236ba2022-08-08 21:13:33 +0100195 if (current.text !== buttonText || current.link !== buttonLink) {
pineafan0bc04162022-07-25 17:22:26 +0100196 chosen = { text: buttonText, link: buttonLink };
Skyler Grey75ea9172022-08-06 10:22:23 +0100197 await client.database.guilds.write(interaction.guild.id, {
198 ["moderation." + i.customId]: {
199 text: buttonText,
200 link: buttonLink
201 }
202 });
pineafan0bc04162022-07-25 17:22:26 +0100203 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100204 } else {
205 continue;
206 }
pineafan0bc04162022-07-25 17:22:26 +0100207 }
208 }
pineafan63fc5e22022-08-04 22:04:10 +0100209};
pineafan0bc04162022-07-25 17:22:26 +0100210
Skyler Grey11236ba2022-08-08 21:13:33 +0100211const check = (interaction: CommandInteraction, _defaultCheck: WrappedCheck) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100212 const member = interaction.member as Discord.GuildMember;
213 if (!member.permissions.has("MANAGE_GUILD"))
pineafan3a02ea32022-08-11 21:35:04 +0100214 throw new Error("You must have the *Manage Server* permission to use this command");
pineafan0bc04162022-07-25 17:22:26 +0100215 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100216};
pineafan0bc04162022-07-25 17:22:26 +0100217
218export { command };
219export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100220export { check };