blob: 67ecdd69bd12efa5585a24cb8f255cf947ea51ba [file] [log] [blame]
Skyler Grey11236ba2022-08-08 21:13:33 +01001import { CommandInteraction, GuildMember, MessageActionRow, MessageButton } from "discord.js";
pineafan4f164f32022-02-26 22:07:12 +00002import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
pineafan8b4b17f2022-02-27 20:42:52 +00003import confirmationMessage from "../../utils/confirmationMessage.js";
pineafan4edb7762022-06-26 19:21:04 +01004import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan8b4b17f2022-02-27 20:42:52 +00005import keyValueList from "../../utils/generateKeyValueList.js";
pineafan6702cef2022-06-13 17:52:37 +01006import client from "../../utils/client.js";
7import addPlural from "../../utils/plurals.js";
pineafan4f164f32022-02-26 22:07:12 +00008
9const command = (builder: SlashCommandSubcommandBuilder) =>
10 builder
pineafan63fc5e22022-08-04 22:04:10 +010011 .setName("softban")
12 .setDescription("Kicks a user and deletes their messages")
Skyler Grey11236ba2022-08-08 21:13:33 +010013 .addUserOption((option) => option.setName("user").setDescription("The user to softban").setRequired(true))
Skyler Grey75ea9172022-08-06 10:22:23 +010014 .addIntegerOption((option) =>
15 option
16 .setName("delete")
17 .setDescription("The days of messages to delete | Default: 0")
18 .setMinValue(0)
19 .setMaxValue(7)
20 .setRequired(false)
21 );
pineafan4f164f32022-02-26 22:07:12 +000022
pineafan3a02ea32022-08-11 21:35:04 +010023const callback = async (interaction: CommandInteraction): Promise<unknown> => {
pineafan63fc5e22022-08-04 22:04:10 +010024 const { renderUser } = client.logger;
pineafan8b4b17f2022-02-27 20:42:52 +000025 // TODO:[Modals] Replace this with a modal
pineafan73a7c4a2022-07-24 10:38:04 +010026 let reason = null;
pineafan02ba0232022-07-24 22:16:15 +010027 let notify = true;
pineafan73a7c4a2022-07-24 10:38:04 +010028 let confirmation;
29 while (true) {
pineafan63fc5e22022-08-04 22:04:10 +010030 const confirmation = await new confirmationMessage(interaction)
pineafan73a7c4a2022-07-24 10:38:04 +010031 .setEmoji("PUNISH.BAN.RED")
32 .setTitle("Softban")
Skyler Grey75ea9172022-08-06 10:22:23 +010033 .setDescription(
34 keyValueList({
35 user: renderUser(interaction.options.getUser("user")),
Skyler Grey11236ba2022-08-08 21:13:33 +010036 reason: reason ? "\n> " + (reason ?? "").replaceAll("\n", "\n> ") : "*No reason provided*"
Skyler Grey75ea9172022-08-06 10:22:23 +010037 }) +
38 `The user **will${notify ? "" : " not"}** be notified\n` +
39 `${addPlural(
Skyler Grey11236ba2022-08-08 21:13:33 +010040 interaction.options.getInteger("delete") ? interaction.options.getInteger("delete") : 0,
Skyler Grey75ea9172022-08-06 10:22:23 +010041 "day"
42 )} of messages will be deleted\n\n` +
Skyler Grey11236ba2022-08-08 21:13:33 +010043 `Are you sure you want to softban <@!${(interaction.options.getMember("user") as GuildMember).id}>?`
Skyler Grey75ea9172022-08-06 10:22:23 +010044 )
pineafan73a7c4a2022-07-24 10:38:04 +010045 .setColor("Danger")
Skyler Grey75ea9172022-08-06 10:22:23 +010046 .addCustomBoolean(
47 "notify",
48 "Notify user",
49 false,
50 null,
51 null,
52 "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
53 notify
54 )
pineafan73a7c4a2022-07-24 10:38:04 +010055 .addReasonButton(reason ?? "")
pineafan63fc5e22022-08-04 22:04:10 +010056 .send(reason !== null);
57 reason = reason ?? "";
58 if (confirmation.cancelled) return;
59 if (confirmation.success) break;
60 if (confirmation.newReason) reason = confirmation.newReason;
pineafan02ba0232022-07-24 22:16:15 +010061 if (confirmation.components) {
pineafan63fc5e22022-08-04 22:04:10 +010062 notify = confirmation.components.notify.active;
pineafan02ba0232022-07-24 22:16:15 +010063 }
pineafan73a7c4a2022-07-24 10:38:04 +010064 }
pineafan377794f2022-04-18 19:01:01 +010065 if (confirmation.success) {
66 let dmd = false;
pineafan63fc5e22022-08-04 22:04:10 +010067 const config = await client.database.guilds.read(interaction.guild.id);
pineafan8b4b17f2022-02-27 20:42:52 +000068 try {
pineafan02ba0232022-07-24 22:16:15 +010069 if (notify) {
Skyler Grey11236ba2022-08-08 21:13:33 +010070 await (interaction.options.getMember("user") as GuildMember).send({
Skyler Grey75ea9172022-08-06 10:22:23 +010071 embeds: [
72 new EmojiEmbed()
73 .setEmoji("PUNISH.BAN.RED")
74 .setTitle("Softbanned")
75 .setDescription(
76 `You have been softbanned from ${interaction.guild.name}` +
77 (reason ? ` for:\n> ${reason}` : ".")
78 )
79 .setStatus("Danger")
pineafan377794f2022-04-18 19:01:01 +010080 ],
Skyler Grey75ea9172022-08-06 10:22:23 +010081 components: [
82 new MessageActionRow().addComponents(
83 config.moderation.ban.text
84 ? [
85 new MessageButton()
86 .setStyle("LINK")
87 .setLabel(config.moderation.ban.text)
88 .setURL(config.moderation.ban.link)
89 ]
90 : []
91 )
92 ]
pineafan63fc5e22022-08-04 22:04:10 +010093 });
94 dmd = true;
pineafan8b4b17f2022-02-27 20:42:52 +000095 }
Skyler Grey75ea9172022-08-06 10:22:23 +010096 } catch {
97 dmd = false;
98 }
99 const member = interaction.options.getMember("user") as GuildMember;
pineafan8b4b17f2022-02-27 20:42:52 +0000100 try {
pineafan4edb7762022-06-26 19:21:04 +0100101 await member.ban({
pineafan8b4b17f2022-02-27 20:42:52 +0000102 days: Number(interaction.options.getInteger("delete") ?? 0),
pineafan73a7c4a2022-07-24 10:38:04 +0100103 reason: reason
pineafan5d1908e2022-02-28 21:34:47 +0000104 });
pineafan4edb7762022-06-26 19:21:04 +0100105 await interaction.guild.members.unban(member, "Softban");
pineafan8b4b17f2022-02-27 20:42:52 +0000106 } catch {
Skyler Grey75ea9172022-08-06 10:22:23 +0100107 await interaction.editReply({
108 embeds: [
109 new EmojiEmbed()
110 .setEmoji("PUNISH.BAN.RED")
111 .setTitle("Softban")
Skyler Grey11236ba2022-08-08 21:13:33 +0100112 .setDescription("Something went wrong and the user was not softbanned")
Skyler Grey75ea9172022-08-06 10:22:23 +0100113 .setStatus("Danger")
114 ],
115 components: []
116 });
pineafan8b4b17f2022-02-27 20:42:52 +0000117 }
Skyler Grey11236ba2022-08-08 21:13:33 +0100118 await client.database.history.create("softban", interaction.guild.id, member.user, reason);
Skyler Grey75ea9172022-08-06 10:22:23 +0100119 const failed = !dmd && notify;
120 await interaction.editReply({
121 embeds: [
122 new EmojiEmbed()
123 .setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`)
124 .setTitle("Softban")
Skyler Grey11236ba2022-08-08 21:13:33 +0100125 .setDescription("The member was softbanned" + (failed ? ", but could not be notified" : ""))
Skyler Grey75ea9172022-08-06 10:22:23 +0100126 .setStatus(failed ? "Warning" : "Success")
127 ],
128 components: []
129 });
pineafan8b4b17f2022-02-27 20:42:52 +0000130 } else {
Skyler Grey75ea9172022-08-06 10:22:23 +0100131 await interaction.editReply({
132 embeds: [
133 new EmojiEmbed()
134 .setEmoji("PUNISH.BAN.GREEN")
135 .setTitle("Softban")
136 .setDescription("No changes were made")
137 .setStatus("Success")
138 ],
139 components: []
140 });
pineafan8b4b17f2022-02-27 20:42:52 +0000141 }
pineafan63fc5e22022-08-04 22:04:10 +0100142};
pineafan4f164f32022-02-26 22:07:12 +0000143
pineafanbd02b4a2022-08-05 22:01:38 +0100144const check = (interaction: CommandInteraction) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100145 const member = interaction.member as GuildMember;
146 const me = interaction.guild.me!;
147 const apply = interaction.options.getMember("user") as GuildMember;
pineafan3a02ea32022-08-11 21:35:04 +0100148 if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
pineafan63fc5e22022-08-04 22:04:10 +0100149 const memberPos = member.roles ? member.roles.highest.position : 0;
150 const mePos = me.roles ? me.roles.highest.position : 0;
151 const applyPos = apply.roles ? apply.roles.highest.position : 0;
pineafanc1c18792022-08-03 21:41:36 +0100152 // Do not allow softbanning the owner
pineafan3a02ea32022-08-11 21:35:04 +0100153 if (member.id === interaction.guild.ownerId) throw new Error("You cannot softban the owner of the server");
pineafan8b4b17f2022-02-27 20:42:52 +0000154 // Check if Nucleus can ban the member
pineafan3a02ea32022-08-11 21:35:04 +0100155 if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member");
pineafan8b4b17f2022-02-27 20:42:52 +0000156 // Check if Nucleus has permission to ban
pineafan3a02ea32022-08-11 21:35:04 +0100157 if (!me.permissions.has("BAN_MEMBERS")) throw new Error("I do not have the *Ban Members* permission");
pineafan8b4b17f2022-02-27 20:42:52 +0000158 // Do not allow softbanning Nucleus
pineafan3a02ea32022-08-11 21:35:04 +0100159 if (member.id === me.id) throw new Error("I cannot softban myself");
pineafanc1c18792022-08-03 21:41:36 +0100160 // Allow the owner to softban anyone
pineafan63fc5e22022-08-04 22:04:10 +0100161 if (member.id === interaction.guild.ownerId) return true;
pineafan8b4b17f2022-02-27 20:42:52 +0000162 // Check if the user has ban_members permission
pineafan3a02ea32022-08-11 21:35:04 +0100163 if (!member.permissions.has("BAN_MEMBERS")) throw new Error("You do not have the *Ban Members* permission");
pineafan8b4b17f2022-02-27 20:42:52 +0000164 // Check if the user is below on the role list
pineafan3a02ea32022-08-11 21:35:04 +0100165 if (!(memberPos > applyPos)) throw new Error("You do not have a role higher than that member");
pineafan8b4b17f2022-02-27 20:42:52 +0000166 // Allow softban
pineafan63fc5e22022-08-04 22:04:10 +0100167 return true;
168};
pineafan4f164f32022-02-26 22:07:12 +0000169
Skyler Grey75ea9172022-08-06 10:22:23 +0100170export { command, callback, check };