blob: 6345ec36db86068c128b4447ff05babe7a9e839f [file] [log] [blame]
pineafan63fc5e22022-08-04 22:04:10 +01001import { LoadingEmbed } from "./../../utils/defaultEmbeds.js";
Skyler Grey11236ba2022-08-08 21:13:33 +01002import Discord, { CommandInteraction, MessageActionRow, MessageButton, TextInputComponent } from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +01003import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
4import getEmojiByName from "../../utils/getEmojiByName.js";
5import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
6import { 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 = "";
26 if (interaction.options.getRole("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({
32 role: `<@&${interaction.options.getRole("role").id}>`
33 })
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) {
Skyler Grey75ea9172022-08-06 10:22:23 +010039 await client.database.guilds.write(interaction.guild.id, {
40 ["moderation.mute.role"]: interaction.options.getRole("role").id
41 });
pineafan0bc04162022-07-25 17:22:26 +010042 }
43 }
Skyler Greyad002172022-08-16 18:48:26 +010044 let timedOut = false;
45 while (!timedOut) {
pineafan63fc5e22022-08-04 22:04:10 +010046 const config = await client.database.guilds.read(interaction.guild.id);
47 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: [
61 new MessageActionRow().addComponents([
62 new MessageButton()
63 .setLabel("Warn")
64 .setEmoji(getEmojiByName("PUNISH.WARN.YELLOW", "id"))
65 .setCustomId("warn")
66 .setStyle("SECONDARY"),
67 new MessageButton()
68 .setLabel("Mute")
69 .setEmoji(getEmojiByName("PUNISH.MUTE.YELLOW", "id"))
70 .setCustomId("mute")
71 .setStyle("SECONDARY"),
72 new MessageButton()
73 .setLabel("Nickname")
74 .setEmoji(getEmojiByName("PUNISH.NICKNAME.GREEN", "id"))
75 .setCustomId("nickname")
76 .setStyle("SECONDARY")
77 ]),
78 new MessageActionRow().addComponents([
79 new MessageButton()
80 .setLabel("Kick")
81 .setEmoji(getEmojiByName("PUNISH.KICK.RED", "id"))
82 .setCustomId("kick")
83 .setStyle("SECONDARY"),
84 new MessageButton()
85 .setLabel("Softban")
86 .setEmoji(getEmojiByName("PUNISH.BAN.YELLOW", "id"))
87 .setCustomId("softban")
88 .setStyle("SECONDARY"),
89 new MessageButton()
90 .setLabel("Ban")
91 .setEmoji(getEmojiByName("PUNISH.BAN.RED", "id"))
92 .setCustomId("ban")
93 .setStyle("SECONDARY")
94 ]),
95 new MessageActionRow().addComponents([
96 new MessageButton()
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")
100 .setStyle("DANGER")
101 .setDisabled(!moderation.mute.role),
102 new MessageButton()
103 .setCustomId("timeout")
Skyler Grey11236ba2022-08-08 21:13:33 +0100104 .setLabel("Mute timeout " + (moderation.mute.timeout ? "Enabled" : "Disabled"))
105 .setStyle(moderation.mute.timeout ? "SUCCESS" : "DANGER")
106 .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(
143 new MessageActionRow<TextInputComponent>().addComponents(
144 new TextInputComponent()
145 .setCustomId("name")
146 .setLabel("Button text")
147 .setMaxLength(100)
148 .setRequired(false)
149 .setStyle("SHORT")
150 .setValue(chosen.text ?? "")
151 ),
152 new MessageActionRow<TextInputComponent>().addComponents(
153 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: [
172 new MessageActionRow().addComponents([
173 new MessageButton()
174 .setLabel("Back")
175 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
176 .setStyle("PRIMARY")
177 .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 };