blob: f3c475e29fe2212dfc18ed5033e64217f771f7e1 [file] [log] [blame]
Skyler Grey75ea9172022-08-06 10:22:23 +01001import {
2 CommandInteraction,
3 GuildMember,
4 MessageActionRow,
5 MessageButton
6} from "discord.js";
pineafan4f164f32022-02-26 22:07:12 +00007import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
pineafan8b4b17f2022-02-27 20:42:52 +00008import confirmationMessage from "../../utils/confirmationMessage.js";
pineafan4edb7762022-06-26 19:21:04 +01009import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan8b4b17f2022-02-27 20:42:52 +000010import keyValueList from "../../utils/generateKeyValueList.js";
pineafan6702cef2022-06-13 17:52:37 +010011import client from "../../utils/client.js";
12import addPlural from "../../utils/plurals.js";
pineafan4f164f32022-02-26 22:07:12 +000013
14const command = (builder: SlashCommandSubcommandBuilder) =>
15 builder
pineafan63fc5e22022-08-04 22:04:10 +010016 .setName("softban")
17 .setDescription("Kicks a user and deletes their messages")
Skyler Grey75ea9172022-08-06 10:22:23 +010018 .addUserOption((option) =>
19 option
20 .setName("user")
21 .setDescription("The user to softban")
22 .setRequired(true)
23 )
24 .addIntegerOption((option) =>
25 option
26 .setName("delete")
27 .setDescription("The days of messages to delete | Default: 0")
28 .setMinValue(0)
29 .setMaxValue(7)
30 .setRequired(false)
31 );
pineafan4f164f32022-02-26 22:07:12 +000032
Skyler Grey75ea9172022-08-06 10:22:23 +010033const callback = async (
34 interaction: CommandInteraction
35): Promise<void | unknown> => {
pineafan63fc5e22022-08-04 22:04:10 +010036 const { renderUser } = client.logger;
pineafan8b4b17f2022-02-27 20:42:52 +000037 // TODO:[Modals] Replace this with a modal
pineafan73a7c4a2022-07-24 10:38:04 +010038 let reason = null;
pineafan02ba0232022-07-24 22:16:15 +010039 let notify = true;
pineafan73a7c4a2022-07-24 10:38:04 +010040 let confirmation;
41 while (true) {
pineafan63fc5e22022-08-04 22:04:10 +010042 const confirmation = await new confirmationMessage(interaction)
pineafan73a7c4a2022-07-24 10:38:04 +010043 .setEmoji("PUNISH.BAN.RED")
44 .setTitle("Softban")
Skyler Grey75ea9172022-08-06 10:22:23 +010045 .setDescription(
46 keyValueList({
47 user: renderUser(interaction.options.getUser("user")),
48 reason: reason
49 ? "\n> " + (reason ?? "").replaceAll("\n", "\n> ")
50 : "*No reason provided*"
51 }) +
52 `The user **will${notify ? "" : " not"}** be notified\n` +
53 `${addPlural(
54 interaction.options.getInteger("delete")
55 ? interaction.options.getInteger("delete")
56 : 0,
57 "day"
58 )} of messages will be deleted\n\n` +
59 `Are you sure you want to softban <@!${
60 (interaction.options.getMember("user") as GuildMember)
61 .id
62 }>?`
63 )
pineafan73a7c4a2022-07-24 10:38:04 +010064 .setColor("Danger")
Skyler Grey75ea9172022-08-06 10:22:23 +010065 .addCustomBoolean(
66 "notify",
67 "Notify user",
68 false,
69 null,
70 null,
71 "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
72 notify
73 )
pineafan73a7c4a2022-07-24 10:38:04 +010074 .addReasonButton(reason ?? "")
pineafan63fc5e22022-08-04 22:04:10 +010075 .send(reason !== null);
76 reason = reason ?? "";
77 if (confirmation.cancelled) return;
78 if (confirmation.success) break;
79 if (confirmation.newReason) reason = confirmation.newReason;
pineafan02ba0232022-07-24 22:16:15 +010080 if (confirmation.components) {
pineafan63fc5e22022-08-04 22:04:10 +010081 notify = confirmation.components.notify.active;
pineafan02ba0232022-07-24 22:16:15 +010082 }
pineafan73a7c4a2022-07-24 10:38:04 +010083 }
pineafan377794f2022-04-18 19:01:01 +010084 if (confirmation.success) {
85 let dmd = false;
pineafan63fc5e22022-08-04 22:04:10 +010086 const config = await client.database.guilds.read(interaction.guild.id);
pineafan8b4b17f2022-02-27 20:42:52 +000087 try {
pineafan02ba0232022-07-24 22:16:15 +010088 if (notify) {
Skyler Grey75ea9172022-08-06 10:22:23 +010089 await (
90 interaction.options.getMember("user") as GuildMember
91 ).send({
92 embeds: [
93 new EmojiEmbed()
94 .setEmoji("PUNISH.BAN.RED")
95 .setTitle("Softbanned")
96 .setDescription(
97 `You have been softbanned from ${interaction.guild.name}` +
98 (reason ? ` for:\n> ${reason}` : ".")
99 )
100 .setStatus("Danger")
pineafan377794f2022-04-18 19:01:01 +0100101 ],
Skyler Grey75ea9172022-08-06 10:22:23 +0100102 components: [
103 new MessageActionRow().addComponents(
104 config.moderation.ban.text
105 ? [
106 new MessageButton()
107 .setStyle("LINK")
108 .setLabel(config.moderation.ban.text)
109 .setURL(config.moderation.ban.link)
110 ]
111 : []
112 )
113 ]
pineafan63fc5e22022-08-04 22:04:10 +0100114 });
115 dmd = true;
pineafan8b4b17f2022-02-27 20:42:52 +0000116 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100117 } catch {
118 dmd = false;
119 }
120 const member = interaction.options.getMember("user") as GuildMember;
pineafan8b4b17f2022-02-27 20:42:52 +0000121 try {
pineafan4edb7762022-06-26 19:21:04 +0100122 await member.ban({
pineafan8b4b17f2022-02-27 20:42:52 +0000123 days: Number(interaction.options.getInteger("delete") ?? 0),
pineafan73a7c4a2022-07-24 10:38:04 +0100124 reason: reason
pineafan5d1908e2022-02-28 21:34:47 +0000125 });
pineafan4edb7762022-06-26 19:21:04 +0100126 await interaction.guild.members.unban(member, "Softban");
pineafan8b4b17f2022-02-27 20:42:52 +0000127 } catch {
Skyler Grey75ea9172022-08-06 10:22:23 +0100128 await interaction.editReply({
129 embeds: [
130 new EmojiEmbed()
131 .setEmoji("PUNISH.BAN.RED")
132 .setTitle("Softban")
133 .setDescription(
134 "Something went wrong and the user was not softbanned"
135 )
136 .setStatus("Danger")
137 ],
138 components: []
139 });
pineafan8b4b17f2022-02-27 20:42:52 +0000140 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100141 await client.database.history.create(
142 "softban",
143 interaction.guild.id,
144 member.user,
145 reason
146 );
147 const failed = !dmd && notify;
148 await interaction.editReply({
149 embeds: [
150 new EmojiEmbed()
151 .setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`)
152 .setTitle("Softban")
153 .setDescription(
154 "The member was softbanned" +
155 (failed ? ", but could not be notified" : "")
156 )
157 .setStatus(failed ? "Warning" : "Success")
158 ],
159 components: []
160 });
pineafan8b4b17f2022-02-27 20:42:52 +0000161 } else {
Skyler Grey75ea9172022-08-06 10:22:23 +0100162 await interaction.editReply({
163 embeds: [
164 new EmojiEmbed()
165 .setEmoji("PUNISH.BAN.GREEN")
166 .setTitle("Softban")
167 .setDescription("No changes were made")
168 .setStatus("Success")
169 ],
170 components: []
171 });
pineafan8b4b17f2022-02-27 20:42:52 +0000172 }
pineafan63fc5e22022-08-04 22:04:10 +0100173};
pineafan4f164f32022-02-26 22:07:12 +0000174
pineafanbd02b4a2022-08-05 22:01:38 +0100175const check = (interaction: CommandInteraction) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100176 const member = interaction.member as GuildMember;
177 const me = interaction.guild.me!;
178 const apply = interaction.options.getMember("user") as GuildMember;
179 if (member === null || me === null || apply === null)
180 throw "That member is not in the server";
pineafan63fc5e22022-08-04 22:04:10 +0100181 const memberPos = member.roles ? member.roles.highest.position : 0;
182 const mePos = me.roles ? me.roles.highest.position : 0;
183 const applyPos = apply.roles ? apply.roles.highest.position : 0;
pineafanc1c18792022-08-03 21:41:36 +0100184 // Do not allow softbanning the owner
Skyler Grey75ea9172022-08-06 10:22:23 +0100185 if (member.id === interaction.guild.ownerId)
186 throw "You cannot softban the owner of the server";
pineafan8b4b17f2022-02-27 20:42:52 +0000187 // Check if Nucleus can ban the member
Skyler Grey75ea9172022-08-06 10:22:23 +0100188 if (!(mePos > applyPos))
189 throw "I do not have a role higher than that member";
pineafan8b4b17f2022-02-27 20:42:52 +0000190 // Check if Nucleus has permission to ban
Skyler Grey75ea9172022-08-06 10:22:23 +0100191 if (!me.permissions.has("BAN_MEMBERS"))
192 throw "I do not have the *Ban Members* permission";
pineafan8b4b17f2022-02-27 20:42:52 +0000193 // Do not allow softbanning Nucleus
pineafan63fc5e22022-08-04 22:04:10 +0100194 if (member.id === me.id) throw "I cannot softban myself";
pineafanc1c18792022-08-03 21:41:36 +0100195 // Allow the owner to softban anyone
pineafan63fc5e22022-08-04 22:04:10 +0100196 if (member.id === interaction.guild.ownerId) return true;
pineafan8b4b17f2022-02-27 20:42:52 +0000197 // Check if the user has ban_members permission
Skyler Grey75ea9172022-08-06 10:22:23 +0100198 if (!member.permissions.has("BAN_MEMBERS"))
199 throw "You do not have the *Ban Members* permission";
pineafan8b4b17f2022-02-27 20:42:52 +0000200 // Check if the user is below on the role list
Skyler Grey75ea9172022-08-06 10:22:23 +0100201 if (!(memberPos > applyPos))
202 throw "You do not have a role higher than that member";
pineafan8b4b17f2022-02-27 20:42:52 +0000203 // Allow softban
pineafan63fc5e22022-08-04 22:04:10 +0100204 return true;
205};
pineafan4f164f32022-02-26 22:07:12 +0000206
Skyler Grey75ea9172022-08-06 10:22:23 +0100207export { command, callback, check };