blob: 34a197b124aa8427368833ba00a69a6588500981 [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed } from "../../utils/defaults.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 {
PineaFan0d06edc2023-01-17 22:10:31 +0000111 i = await m.awaitMessageComponent({
112 time: 300000,
113 filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id }
114 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100115 } catch (e) {
Skyler Greyad002172022-08-16 18:48:26 +0100116 timedOut = true;
117 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100118 }
119 let chosen = moderation[i.customId] ?? { text: null, url: null };
pineafan0bc04162022-07-25 17:22:26 +0100120 if (i.component.customId === "clearMuteRole") {
pineafan63fc5e22022-08-04 22:04:10 +0100121 i.deferUpdate();
pineafan0bc04162022-07-25 17:22:26 +0100122 if (clicked === "clearMuteRole") {
Skyler Grey75ea9172022-08-06 10:22:23 +0100123 await client.database.guilds.write(interaction.guild.id, {
124 "moderation.mute.role": null
125 });
126 } else {
127 clicked = "clearMuteRole";
128 }
pineafan63fc5e22022-08-04 22:04:10 +0100129 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100130 } else {
131 clicked = "";
132 }
pineafan0bc04162022-07-25 17:22:26 +0100133 if (i.component.customId === "timeout") {
pineafan63fc5e22022-08-04 22:04:10 +0100134 await i.deferUpdate();
Skyler Grey75ea9172022-08-06 10:22:23 +0100135 await client.database.guilds.write(interaction.guild.id, {
136 "moderation.mute.timeout": !moderation.mute.timeout
137 });
pineafan63fc5e22022-08-04 22:04:10 +0100138 continue;
pineafan0bc04162022-07-25 17:22:26 +0100139 } else if (i.customId) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100140 await i.showModal(
141 new Discord.Modal()
142 .setCustomId("modal")
143 .setTitle(`Options for ${i.customId}`)
144 .addComponents(
TheCodedProf21c08592022-09-13 14:14:43 -0400145 new ActionRowBuilder<TextInputComponent>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100146 new TextInputComponent()
147 .setCustomId("name")
148 .setLabel("Button text")
149 .setMaxLength(100)
150 .setRequired(false)
151 .setStyle("SHORT")
152 .setValue(chosen.text ?? "")
153 ),
TheCodedProf21c08592022-09-13 14:14:43 -0400154 new ActionRowBuilder<TextInputComponent>().addComponents(
Skyler Grey75ea9172022-08-06 10:22:23 +0100155 new TextInputComponent()
156 .setCustomId("url")
Skyler Grey11236ba2022-08-08 21:13:33 +0100157 .setLabel("URL - Type {id} to insert the user's ID")
Skyler Grey75ea9172022-08-06 10:22:23 +0100158 .setMaxLength(2000)
159 .setRequired(false)
160 .setStyle("SHORT")
161 .setValue(chosen.link ?? "")
162 )
163 )
164 );
pineafan0bc04162022-07-25 17:22:26 +0100165 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100166 embeds: [
167 new EmojiEmbed()
168 .setTitle("Moderation Links")
Skyler Grey11236ba2022-08-08 21:13:33 +0100169 .setDescription("Modal opened. If you can't see it, click back and try again.")
Skyler Grey75ea9172022-08-06 10:22:23 +0100170 .setStatus("Success")
171 .setEmoji("GUILD.TICKET.OPEN")
172 ],
173 components: [
TheCodedProf21c08592022-09-13 14:14:43 -0400174 new ActionRowBuilder().addComponents([
175 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100176 .setLabel("Back")
177 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400178 .setStyle(ButtonStyle.Primary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100179 .setCustomId("back")
180 ])
181 ]
pineafan0bc04162022-07-25 17:22:26 +0100182 });
183 let out;
184 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100185 out = await modalInteractionCollector(
186 m,
187 (m) => m.channel.id === interaction.channel.id,
188 (_) => true
189 );
190 } catch (e) {
191 continue;
192 }
pineafan0bc04162022-07-25 17:22:26 +0100193 if (out.fields) {
pineafan63fc5e22022-08-04 22:04:10 +0100194 const buttonText = out.fields.getTextInputValue("name");
Skyler Grey11236ba2022-08-08 21:13:33 +0100195 const buttonLink = out.fields.getTextInputValue("url").replace(/{id}/gi, "{id}");
pineafan63fc5e22022-08-04 22:04:10 +0100196 const current = chosen;
Skyler Grey11236ba2022-08-08 21:13:33 +0100197 if (current.text !== buttonText || current.link !== buttonLink) {
pineafan0bc04162022-07-25 17:22:26 +0100198 chosen = { text: buttonText, link: buttonLink };
Skyler Grey75ea9172022-08-06 10:22:23 +0100199 await client.database.guilds.write(interaction.guild.id, {
200 ["moderation." + i.customId]: {
201 text: buttonText,
202 link: buttonLink
203 }
204 });
pineafan0bc04162022-07-25 17:22:26 +0100205 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100206 } else {
207 continue;
208 }
pineafan0bc04162022-07-25 17:22:26 +0100209 }
210 }
pineafan63fc5e22022-08-04 22:04:10 +0100211};
pineafan0bc04162022-07-25 17:22:26 +0100212
PineaFan64486c42022-12-28 09:21:04 +0000213const check = (interaction: CommandInteraction) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100214 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000215 if (!member.permissions.has("ManageGuild"))
216 return "You must have the *Manage Server* permission to use this command";
pineafan0bc04162022-07-25 17:22:26 +0100217 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100218};
pineafan0bc04162022-07-25 17:22:26 +0100219
220export { command };
221export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100222export { check };