blob: 46e28713b3808dd89b9a994ea6b59047d8ceb293 [file] [log] [blame]
pineafan5d1908e2022-02-28 21:34:47 +00001import Discord, { CommandInteraction, GuildMember, MessageActionRow } from "discord.js";
pineafan4f164f32022-02-26 22:07:12 +00002import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
3import { WrappedCheck } from "jshaiku";
pineafan8b4b17f2022-02-27 20:42:52 +00004import confirmationMessage from "../../utils/confirmationMessage.js";
pineafan377794f2022-04-18 19:01:01 +01005import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan8b4b17f2022-02-27 20:42:52 +00006import keyValueList from "../../utils/generateKeyValueList.js";
pineafan377794f2022-04-18 19:01:01 +01007import { create, areTicketsEnabled } from "../../automations/createModActionTicket.js";
pineafan4f164f32022-02-26 22:07:12 +00008
9const command = (builder: SlashCommandSubcommandBuilder) =>
10 builder
11 .setName("warn")
12 .setDescription("Warns a user")
pineafan8b4b17f2022-02-27 20:42:52 +000013 .addUserOption(option => option.setName("user").setDescription("The user to warn").setRequired(true))
14 .addStringOption(option => option.setName("reason").setDescription("The reason for the warn").setRequired(false))
15 .addStringOption(option => option.setName("notify").setDescription("If the user should get a message when they are warned | Default yes").setRequired(false)
16 .addChoices([["Yes", "yes"], ["No", "no"]])
17 )
pineafan4f164f32022-02-26 22:07:12 +000018
pineafan6702cef2022-06-13 17:52:37 +010019const callback = async (interaction: CommandInteraction): Promise<any> => {
pineafan1dc15722022-03-14 21:27:34 +000020 // @ts-ignore
pineafan377794f2022-04-18 19:01:01 +010021 const { log, NucleusColors, renderUser, entry } = interaction.client.logger
pineafan8b4b17f2022-02-27 20:42:52 +000022 // TODO:[Modals] Replace this with a modal
pineafan377794f2022-04-18 19:01:01 +010023 let confirmation = await new confirmationMessage(interaction)
pineafan8b4b17f2022-02-27 20:42:52 +000024 .setEmoji("PUNISH.WARN.RED")
25 .setTitle("Warn")
26 .setDescription(keyValueList({
27 "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
28 "reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
29 })
pineafan1dc15722022-03-14 21:27:34 +000030 + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`
31 + `Are you sure you want to warn <@!${(interaction.options.getMember("user") as GuildMember).id}>?`)
pineafan8b4b17f2022-02-27 20:42:52 +000032 .setColor("Danger")
pineafan4092b862022-05-20 19:27:23 +010033 .addCustomBoolean(
pineafan377794f2022-04-18 19:01:01 +010034 "Create appeal ticket", !(await areTicketsEnabled(interaction.guild.id)),
pineafan6702cef2022-06-13 17:52:37 +010035 async () => await create(interaction.guild, interaction.options.getUser("user"), interaction.user, interaction.options.getString("reason")),
pineafan4092b862022-05-20 19:27:23 +010036 "An appeal ticket will be created when Confirm is clicked")
pineafan377794f2022-04-18 19:01:01 +010037 .send()
38 if (confirmation.success) {
pineafan8b4b17f2022-02-27 20:42:52 +000039 let dmd = false
40 try {
41 if (interaction.options.getString("notify") != "no") {
42 await (interaction.options.getMember("user") as GuildMember).send({
pineafan377794f2022-04-18 19:01:01 +010043 embeds: [new generateEmojiEmbed()
pineafan8b4b17f2022-02-27 20:42:52 +000044 .setEmoji("PUNISH.WARN.RED")
45 .setTitle("Warned")
46 .setDescription(`You have been warned in ${interaction.guild.name}` +
pineafan377794f2022-04-18 19:01:01 +010047 (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : ".") + "\n\n" +
PineappleFan30b5fda2022-05-22 15:41:47 +010048 (confirmation.buttonClicked ? `You can appeal this here ticket: <#${confirmation.response}>` : ``))
pineafan8b4b17f2022-02-27 20:42:52 +000049 .setStatus("Danger")
50 ]
51 })
52 dmd = true
53 }
pineafan8b4b17f2022-02-27 20:42:52 +000054 } catch {
pineafan377794f2022-04-18 19:01:01 +010055 await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan8b4b17f2022-02-27 20:42:52 +000056 .setEmoji("PUNISH.WARN.RED")
57 .setTitle(`Warn`)
58 .setDescription("Something went wrong and the user was not warned")
59 .setStatus("Danger")
60 ], components: []})
61 }
pineafan1dc15722022-03-14 21:27:34 +000062 let data = {
63 meta:{
64 type: 'memberWarn',
65 displayName: 'Member warned',
66 calculateType: 'guildMemberPunish',
67 color: NucleusColors.yellow,
68 emoji: 'PUNISH.WARN.YELLOW',
69 timestamp: new Date().getTime()
70 },
71 list: {
pineafan377794f2022-04-18 19:01:01 +010072 user: entry((interaction.options.getMember("user") as GuildMember).user.id, renderUser((interaction.options.getMember("user") as GuildMember).user)),
73 warnedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)),
pineafan1dc15722022-03-14 21:27:34 +000074 reason: (interaction.options.getString("reason") ? `\n> ${interaction.options.getString("reason")}` : "No reason provided")
75 },
76 hidden: {
77 guild: interaction.guild.id
78 }
79 }
80 log(data, interaction.client);
pineafan5d1908e2022-02-28 21:34:47 +000081 let failed = (dmd == false && interaction.options.getString("notify") != "no")
82 if (!failed) {
pineafan377794f2022-04-18 19:01:01 +010083 await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +000084 .setEmoji(`PUNISH.WARN.GREEN`)
85 .setTitle(`Warn`)
pineafan4092b862022-05-20 19:27:23 +010086 .setDescription("The user was warned" + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
pineafan5d1908e2022-02-28 21:34:47 +000087 .setStatus("Success")
88 ], components: []})
89 } else {
90 let m = await interaction.editReply({
pineafan377794f2022-04-18 19:01:01 +010091 embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +000092 .setEmoji(`PUNISH.WARN.RED`)
93 .setTitle(`Warn`)
94 .setDescription("The user's DMs are not open\n\nWhat would you like to do?")
95 .setStatus("Danger")
96 ], components: [
97 new MessageActionRow().addComponents([
98 new Discord.MessageButton()
99 .setCustomId("log")
100 .setLabel("Ignore and log")
101 .setStyle("SECONDARY"),
102 new Discord.MessageButton()
103 .setCustomId("here")
104 .setLabel("Warn here")
105 .setStyle("SECONDARY")
106 .setDisabled((interaction.options.getMember("user") as GuildMember).permissionsIn(interaction.channel as Discord.TextChannel).has("VIEW_CHANNEL") === false),
107 ])
108 ],
109 })
110 let component;
111 try {
112 component = await (m as Discord.Message).awaitMessageComponent({filter: (m) => m.user.id === interaction.user.id, time: 2.5 * 60 * 1000});
113 } catch (e) {
pineafan377794f2022-04-18 19:01:01 +0100114 return await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000115 .setEmoji(`PUNISH.WARN.GREEN`)
116 .setTitle(`Warn`)
117 .setDescription("No changes were made")
118 .setStatus("Success")
119 ], components: []})
120 }
121 if ( component.customId == "here" ) {
122 await interaction.channel.send({
pineafan377794f2022-04-18 19:01:01 +0100123 embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000124 .setEmoji(`PUNISH.WARN.RED`)
125 .setTitle(`Warn`)
126 .setDescription(`You have been warned` +
pineafan1dc15722022-03-14 21:27:34 +0000127 (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : "."))
pineafan5d1908e2022-02-28 21:34:47 +0000128 .setStatus("Danger")
129 ],
130 content: `<@!${(interaction.options.getMember("user") as GuildMember).id}>`,
131 allowedMentions: {users: [(interaction.options.getMember("user") as GuildMember).id]}
132 })
pineafan377794f2022-04-18 19:01:01 +0100133 return await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000134 .setEmoji(`PUNISH.WARN.GREEN`)
135 .setTitle(`Warn`)
pineafan4092b862022-05-20 19:27:23 +0100136 .setDescription("The user was warned" + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
pineafan5d1908e2022-02-28 21:34:47 +0000137 .setStatus("Success")
138 ], components: []})
139 } else {
pineafan377794f2022-04-18 19:01:01 +0100140 await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000141 .setEmoji(`PUNISH.WARN.GREEN`)
142 .setTitle(`Warn`)
143 .setDescription("The warn was logged")
144 .setStatus("Success")
145 ], components: []})
146 }
147 }
pineafan8b4b17f2022-02-27 20:42:52 +0000148 } else {
pineafan377794f2022-04-18 19:01:01 +0100149 await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan8b4b17f2022-02-27 20:42:52 +0000150 .setEmoji("PUNISH.WARN.GREEN")
151 .setTitle(`Warn`)
152 .setDescription("No changes were made")
153 .setStatus("Success")
154 ], components: []})
155 }
pineafan4f164f32022-02-26 22:07:12 +0000156}
157
158const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
pineafan5d1908e2022-02-28 21:34:47 +0000159 let member = (interaction.member as GuildMember)
160 let me = (interaction.guild.me as GuildMember)
161 let apply = (interaction.options.getMember("user") as GuildMember)
162 if (member == null || me == null || apply == null) throw "That member is not in the server"
163 let memberPos = member.roles ? member.roles.highest.position : 0
164 let mePos = me.roles ? me.roles.highest.position : 0
165 let applyPos = apply.roles ? apply.roles.highest.position : 0
pineafan8b4b17f2022-02-27 20:42:52 +0000166 // Do not allow warning bots
pineafan663dc472022-05-10 18:13:47 +0100167 if (member.user.bot) throw "I cannot warn bots"
pineafan8b4b17f2022-02-27 20:42:52 +0000168 // Allow the owner to warn anyone
pineafan663dc472022-05-10 18:13:47 +0100169 if (member.id == interaction.guild.ownerId) return true
pineafan8b4b17f2022-02-27 20:42:52 +0000170 // Check if the user has moderate_members permission
pineafan663dc472022-05-10 18:13:47 +0100171 if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the `moderate_members` permission";
pineafan8b4b17f2022-02-27 20:42:52 +0000172 // Check if the user is below on the role list
pineafan5d1908e2022-02-28 21:34:47 +0000173 if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
pineafan8b4b17f2022-02-27 20:42:52 +0000174 // Allow warn
175 return true
pineafan4f164f32022-02-26 22:07:12 +0000176}
177
pineafan8b4b17f2022-02-27 20:42:52 +0000178export { command, callback, check };