blob: c7f0dd0dffd585966b689b5f42a87c6a0f7e7ceb [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed } from "../../utils/defaults.js";
TheCodedProf01cba762023-02-18 15:55:05 -05002import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ButtonComponent, TextInputBuilder, RoleSelectMenuBuilder } from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +01003import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
4import getEmojiByName from "../../utils/getEmojiByName.js";
TheCodedProff86ba092023-01-27 17:10:07 -05005import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +01006import client from "../../utils/client.js";
7import { modalInteractionCollector } from "../../utils/dualCollector.js";
pineafan0bc04162022-07-25 17:22:26 +01008
9const command = (builder: SlashCommandSubcommandBuilder) =>
10 builder
TheCodedProf1f675042023-02-16 17:01:29 -050011 .setName("moderation")
Skyler Grey11236ba2022-08-08 21:13:33 +010012 .setDescription("Links and text shown to a user after a moderator action is performed")
pineafan0bc04162022-07-25 17:22:26 +010013
TheCodedProf1f675042023-02-16 17:01:29 -050014const callback = async (interaction: CommandInteraction): Promise<void> => {
TheCodedProf01cba762023-02-18 15:55:05 -050015 const m = await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010016 embeds: LoadingEmbed,
17 ephemeral: true,
18 fetchReply: true
19 });
Skyler Greyad002172022-08-16 18:48:26 +010020 let timedOut = false;
21 while (!timedOut) {
TheCodedProfd9636e82023-01-17 22:13:06 -050022 const config = await client.database.guilds.read(interaction.guild!.id);
PineaFan9b2ac4d2023-01-18 14:41:07 +000023 const moderation = config.moderation;
TheCodedProf01cba762023-02-18 15:55:05 -050024 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +010025 embeds: [
26 new EmojiEmbed()
27 .setTitle("Moderation Commands")
28 .setEmoji("PUNISH.BAN.GREEN")
29 .setStatus("Success")
30 .setDescription(
31 "These links are shown below the message sent in a user's DM when they are punished.\n\n" +
TheCodedProf1f675042023-02-16 17:01:29 -050032 "**Mute Role:** " + (moderation.mute.role ? `<@&${moderation.mute.role}>` : "*None set*")
Skyler Grey75ea9172022-08-06 10:22:23 +010033 )
34 ],
35 components: [
TheCodedProfd9636e82023-01-17 22:13:06 -050036 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040037 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010038 .setLabel("Warn")
39 .setEmoji(getEmojiByName("PUNISH.WARN.YELLOW", "id"))
40 .setCustomId("warn")
TheCodedProf21c08592022-09-13 14:14:43 -040041 .setStyle(ButtonStyle.Secondary),
42 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010043 .setLabel("Mute")
44 .setEmoji(getEmojiByName("PUNISH.MUTE.YELLOW", "id"))
45 .setCustomId("mute")
TheCodedProf21c08592022-09-13 14:14:43 -040046 .setStyle(ButtonStyle.Secondary),
47 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010048 .setLabel("Nickname")
49 .setEmoji(getEmojiByName("PUNISH.NICKNAME.GREEN", "id"))
50 .setCustomId("nickname")
TheCodedProf21c08592022-09-13 14:14:43 -040051 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010052 ]),
TheCodedProfd9636e82023-01-17 22:13:06 -050053 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040054 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010055 .setLabel("Kick")
56 .setEmoji(getEmojiByName("PUNISH.KICK.RED", "id"))
57 .setCustomId("kick")
TheCodedProf21c08592022-09-13 14:14:43 -040058 .setStyle(ButtonStyle.Secondary),
59 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010060 .setLabel("Softban")
61 .setEmoji(getEmojiByName("PUNISH.BAN.YELLOW", "id"))
62 .setCustomId("softban")
TheCodedProf21c08592022-09-13 14:14:43 -040063 .setStyle(ButtonStyle.Secondary),
64 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010065 .setLabel("Ban")
66 .setEmoji(getEmojiByName("PUNISH.BAN.RED", "id"))
67 .setCustomId("ban")
TheCodedProf21c08592022-09-13 14:14:43 -040068 .setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010069 ]),
TheCodedProfd9636e82023-01-17 22:13:06 -050070 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040071 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010072 .setCustomId("timeout")
Skyler Grey11236ba2022-08-08 21:13:33 +010073 .setLabel("Mute timeout " + (moderation.mute.timeout ? "Enabled" : "Disabled"))
TheCodedProf21c08592022-09-13 14:14:43 -040074 .setStyle(moderation.mute.timeout ? ButtonStyle.Success : ButtonStyle.Danger)
Skyler Grey11236ba2022-08-08 21:13:33 +010075 .setEmoji(getEmojiByName("CONTROL." + (moderation.mute.timeout ? "TICK" : "CROSS"), "id"))
TheCodedProf1f675042023-02-16 17:01:29 -050076 ]),
77 new ActionRowBuilder<RoleSelectMenuBuilder>().addComponents(
78 new RoleSelectMenuBuilder()
79 .setCustomId("muteRole")
80 .setPlaceholder("Select a new mute role")
81 )
Skyler Grey75ea9172022-08-06 10:22:23 +010082 ]
83 });
pineafan0bc04162022-07-25 17:22:26 +010084 let i;
85 try {
PineaFan0d06edc2023-01-17 22:10:31 +000086 i = await m.awaitMessageComponent({
87 time: 300000,
TheCodedProf267563a2023-01-21 17:00:57 -050088 filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id }
PineaFan0d06edc2023-01-17 22:10:31 +000089 });
Skyler Grey75ea9172022-08-06 10:22:23 +010090 } catch (e) {
Skyler Greyad002172022-08-16 18:48:26 +010091 timedOut = true;
92 continue;
Skyler Grey75ea9172022-08-06 10:22:23 +010093 }
TheCodedProfd9636e82023-01-17 22:13:06 -050094 type modIDs = "mute" | "kick" | "ban" | "softban" | "warn" | "role";
PineaFan9b2ac4d2023-01-18 14:41:07 +000095 let chosen = moderation[i.customId as modIDs];
TheCodedProf1f675042023-02-16 17:01:29 -050096 if (i.isRoleSelectMenu()) {
TheCodedProf267563a2023-01-21 17:00:57 -050097 await i.deferUpdate();
TheCodedProf1f675042023-02-16 17:01:29 -050098 await client.database.guilds.write(interaction.guild!.id, {
99 "moderation.mute.role": i.values[0]!
100 });
pineafan63fc5e22022-08-04 22:04:10 +0100101 continue;
TheCodedProf1f675042023-02-16 17:01:29 -0500102 } else if ((i.component as ButtonComponent).customId === "timeout") {
pineafan63fc5e22022-08-04 22:04:10 +0100103 await i.deferUpdate();
TheCodedProfd9636e82023-01-17 22:13:06 -0500104 await client.database.guilds.write(interaction.guild!.id, {
Skyler Grey75ea9172022-08-06 10:22:23 +0100105 "moderation.mute.timeout": !moderation.mute.timeout
106 });
pineafan63fc5e22022-08-04 22:04:10 +0100107 continue;
pineafan0bc04162022-07-25 17:22:26 +0100108 } else if (i.customId) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100109 await i.showModal(
TheCodedProfd9636e82023-01-17 22:13:06 -0500110 new Discord.ModalBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100111 .setCustomId("modal")
112 .setTitle(`Options for ${i.customId}`)
113 .addComponents(
TheCodedProfd9636e82023-01-17 22:13:06 -0500114 new ActionRowBuilder<TextInputBuilder>().addComponents(
115 new TextInputBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100116 .setCustomId("name")
117 .setLabel("Button text")
118 .setMaxLength(100)
119 .setRequired(false)
TheCodedProfd9636e82023-01-17 22:13:06 -0500120 .setStyle(Discord.TextInputStyle.Short)
Skyler Grey75ea9172022-08-06 10:22:23 +0100121 .setValue(chosen.text ?? "")
TheCodedProfd9636e82023-01-17 22:13:06 -0500122 ).toJSON(),
123 new ActionRowBuilder<TextInputBuilder>().addComponents(
124 new TextInputBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100125 .setCustomId("url")
Skyler Grey11236ba2022-08-08 21:13:33 +0100126 .setLabel("URL - Type {id} to insert the user's ID")
Skyler Grey75ea9172022-08-06 10:22:23 +0100127 .setMaxLength(2000)
128 .setRequired(false)
TheCodedProfd9636e82023-01-17 22:13:06 -0500129 .setStyle(Discord.TextInputStyle.Short)
Skyler Grey75ea9172022-08-06 10:22:23 +0100130 .setValue(chosen.link ?? "")
TheCodedProfd9636e82023-01-17 22:13:06 -0500131 ).toJSON()
Skyler Grey75ea9172022-08-06 10:22:23 +0100132 )
133 );
pineafan0bc04162022-07-25 17:22:26 +0100134 await interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100135 embeds: [
136 new EmojiEmbed()
137 .setTitle("Moderation Links")
Skyler Grey11236ba2022-08-08 21:13:33 +0100138 .setDescription("Modal opened. If you can't see it, click back and try again.")
Skyler Grey75ea9172022-08-06 10:22:23 +0100139 .setStatus("Success")
140 .setEmoji("GUILD.TICKET.OPEN")
141 ],
142 components: [
TheCodedProfd9636e82023-01-17 22:13:06 -0500143 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -0400144 new ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100145 .setLabel("Back")
146 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
TheCodedProf21c08592022-09-13 14:14:43 -0400147 .setStyle(ButtonStyle.Primary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100148 .setCustomId("back")
149 ])
150 ]
pineafan0bc04162022-07-25 17:22:26 +0100151 });
PineaFan9b2ac4d2023-01-18 14:41:07 +0000152 let out: Discord.ModalSubmitInteraction | null;
pineafan0bc04162022-07-25 17:22:26 +0100153 try {
TheCodedProf01cba762023-02-18 15:55:05 -0500154 out = await modalInteractionCollector(m, interaction.user) as Discord.ModalSubmitInteraction | null;
Skyler Grey75ea9172022-08-06 10:22:23 +0100155 } catch (e) {
156 continue;
157 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500158 if (!out || out.isButton()) continue
PineaFan9b2ac4d2023-01-18 14:41:07 +0000159 const buttonText = out.fields.getTextInputValue("name");
160 const buttonLink = out.fields.getTextInputValue("url").replace(/{id}/gi, "{id}");
161 const current = chosen;
162 if (current.text !== buttonText || current.link !== buttonLink) {
163 chosen = { text: buttonText, link: buttonLink };
164 await client.database.guilds.write(interaction.guild!.id, {
165 ["moderation." + i.customId]: {
166 text: buttonText,
167 link: buttonLink
168 }
169 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100170 }
pineafan0bc04162022-07-25 17:22:26 +0100171 }
172 }
TheCodedProf01cba762023-02-18 15:55:05 -0500173 await interaction.deleteReply()
pineafan63fc5e22022-08-04 22:04:10 +0100174};
pineafan0bc04162022-07-25 17:22:26 +0100175
TheCodedProff86ba092023-01-27 17:10:07 -0500176const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100177 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000178 if (!member.permissions.has("ManageGuild"))
179 return "You must have the *Manage Server* permission to use this command";
pineafan0bc04162022-07-25 17:22:26 +0100180 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100181};
pineafan0bc04162022-07-25 17:22:26 +0100182
183export { command };
184export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100185export { check };