blob: 092fdaa724f16effd9833e6a8bc6f558a09ef3b3 [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> => {
PineappleFanb3dd83c2022-06-17 10:53:48 +010020 const { log, NucleusColors, renderUser, entry } = client.logger
pineafan8b4b17f2022-02-27 20:42:52 +000021 // TODO:[Modals] Replace this with a modal
pineafan377794f2022-04-18 19:01:01 +010022 let confirmation = await new confirmationMessage(interaction)
pineafan8b4b17f2022-02-27 20:42:52 +000023 .setEmoji("PUNISH.WARN.RED")
24 .setTitle("Warn")
25 .setDescription(keyValueList({
26 "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
27 "reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
28 })
pineafan1dc15722022-03-14 21:27:34 +000029 + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`
30 + `Are you sure you want to warn <@!${(interaction.options.getMember("user") as GuildMember).id}>?`)
pineafan8b4b17f2022-02-27 20:42:52 +000031 .setColor("Danger")
pineafan4092b862022-05-20 19:27:23 +010032 .addCustomBoolean(
pineafan377794f2022-04-18 19:01:01 +010033 "Create appeal ticket", !(await areTicketsEnabled(interaction.guild.id)),
pineafan6702cef2022-06-13 17:52:37 +010034 async () => await create(interaction.guild, interaction.options.getUser("user"), interaction.user, interaction.options.getString("reason")),
pineafan4092b862022-05-20 19:27:23 +010035 "An appeal ticket will be created when Confirm is clicked")
pineafan377794f2022-04-18 19:01:01 +010036 .send()
37 if (confirmation.success) {
pineafan8b4b17f2022-02-27 20:42:52 +000038 let dmd = false
39 try {
40 if (interaction.options.getString("notify") != "no") {
41 await (interaction.options.getMember("user") as GuildMember).send({
pineafan377794f2022-04-18 19:01:01 +010042 embeds: [new generateEmojiEmbed()
pineafan8b4b17f2022-02-27 20:42:52 +000043 .setEmoji("PUNISH.WARN.RED")
44 .setTitle("Warned")
45 .setDescription(`You have been warned in ${interaction.guild.name}` +
pineafan377794f2022-04-18 19:01:01 +010046 (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : ".") + "\n\n" +
PineappleFan30b5fda2022-05-22 15:41:47 +010047 (confirmation.buttonClicked ? `You can appeal this here ticket: <#${confirmation.response}>` : ``))
pineafan8b4b17f2022-02-27 20:42:52 +000048 .setStatus("Danger")
49 ]
50 })
51 dmd = true
52 }
pineafan8b4b17f2022-02-27 20:42:52 +000053 } catch {
pineafan377794f2022-04-18 19:01:01 +010054 await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan8b4b17f2022-02-27 20:42:52 +000055 .setEmoji("PUNISH.WARN.RED")
56 .setTitle(`Warn`)
57 .setDescription("Something went wrong and the user was not warned")
58 .setStatus("Danger")
59 ], components: []})
60 }
pineafan1dc15722022-03-14 21:27:34 +000061 let data = {
62 meta:{
63 type: 'memberWarn',
64 displayName: 'Member warned',
65 calculateType: 'guildMemberPunish',
66 color: NucleusColors.yellow,
67 emoji: 'PUNISH.WARN.YELLOW',
68 timestamp: new Date().getTime()
69 },
70 list: {
pineafan377794f2022-04-18 19:01:01 +010071 user: entry((interaction.options.getMember("user") as GuildMember).user.id, renderUser((interaction.options.getMember("user") as GuildMember).user)),
72 warnedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)),
pineafan1dc15722022-03-14 21:27:34 +000073 reason: (interaction.options.getString("reason") ? `\n> ${interaction.options.getString("reason")}` : "No reason provided")
74 },
75 hidden: {
76 guild: interaction.guild.id
77 }
78 }
PineappleFanb3dd83c2022-06-17 10:53:48 +010079 log(data, client);
pineafan5d1908e2022-02-28 21:34:47 +000080 let failed = (dmd == false && interaction.options.getString("notify") != "no")
81 if (!failed) {
pineafan377794f2022-04-18 19:01:01 +010082 await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +000083 .setEmoji(`PUNISH.WARN.GREEN`)
84 .setTitle(`Warn`)
pineafan4092b862022-05-20 19:27:23 +010085 .setDescription("The user was warned" + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
pineafan5d1908e2022-02-28 21:34:47 +000086 .setStatus("Success")
87 ], components: []})
88 } else {
89 let m = await interaction.editReply({
pineafan377794f2022-04-18 19:01:01 +010090 embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +000091 .setEmoji(`PUNISH.WARN.RED`)
92 .setTitle(`Warn`)
93 .setDescription("The user's DMs are not open\n\nWhat would you like to do?")
94 .setStatus("Danger")
95 ], components: [
96 new MessageActionRow().addComponents([
97 new Discord.MessageButton()
98 .setCustomId("log")
99 .setLabel("Ignore and log")
100 .setStyle("SECONDARY"),
101 new Discord.MessageButton()
102 .setCustomId("here")
103 .setLabel("Warn here")
104 .setStyle("SECONDARY")
105 .setDisabled((interaction.options.getMember("user") as GuildMember).permissionsIn(interaction.channel as Discord.TextChannel).has("VIEW_CHANNEL") === false),
106 ])
107 ],
108 })
109 let component;
110 try {
111 component = await (m as Discord.Message).awaitMessageComponent({filter: (m) => m.user.id === interaction.user.id, time: 2.5 * 60 * 1000});
112 } catch (e) {
pineafan377794f2022-04-18 19:01:01 +0100113 return await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000114 .setEmoji(`PUNISH.WARN.GREEN`)
115 .setTitle(`Warn`)
116 .setDescription("No changes were made")
117 .setStatus("Success")
118 ], components: []})
119 }
120 if ( component.customId == "here" ) {
121 await interaction.channel.send({
pineafan377794f2022-04-18 19:01:01 +0100122 embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000123 .setEmoji(`PUNISH.WARN.RED`)
124 .setTitle(`Warn`)
125 .setDescription(`You have been warned` +
pineafan1dc15722022-03-14 21:27:34 +0000126 (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : "."))
pineafan5d1908e2022-02-28 21:34:47 +0000127 .setStatus("Danger")
128 ],
129 content: `<@!${(interaction.options.getMember("user") as GuildMember).id}>`,
130 allowedMentions: {users: [(interaction.options.getMember("user") as GuildMember).id]}
131 })
pineafan377794f2022-04-18 19:01:01 +0100132 return await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000133 .setEmoji(`PUNISH.WARN.GREEN`)
134 .setTitle(`Warn`)
pineafan4092b862022-05-20 19:27:23 +0100135 .setDescription("The user was warned" + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
pineafan5d1908e2022-02-28 21:34:47 +0000136 .setStatus("Success")
137 ], components: []})
138 } else {
pineafan377794f2022-04-18 19:01:01 +0100139 await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000140 .setEmoji(`PUNISH.WARN.GREEN`)
141 .setTitle(`Warn`)
142 .setDescription("The warn was logged")
143 .setStatus("Success")
144 ], components: []})
145 }
146 }
pineafan8b4b17f2022-02-27 20:42:52 +0000147 } else {
pineafan377794f2022-04-18 19:01:01 +0100148 await interaction.editReply({embeds: [new generateEmojiEmbed()
pineafan8b4b17f2022-02-27 20:42:52 +0000149 .setEmoji("PUNISH.WARN.GREEN")
150 .setTitle(`Warn`)
151 .setDescription("No changes were made")
152 .setStatus("Success")
153 ], components: []})
154 }
pineafan4f164f32022-02-26 22:07:12 +0000155}
156
157const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
pineafan5d1908e2022-02-28 21:34:47 +0000158 let member = (interaction.member as GuildMember)
159 let me = (interaction.guild.me as GuildMember)
160 let apply = (interaction.options.getMember("user") as GuildMember)
161 if (member == null || me == null || apply == null) throw "That member is not in the server"
162 let memberPos = member.roles ? member.roles.highest.position : 0
163 let mePos = me.roles ? me.roles.highest.position : 0
164 let applyPos = apply.roles ? apply.roles.highest.position : 0
pineafan8b4b17f2022-02-27 20:42:52 +0000165 // Do not allow warning bots
pineafan663dc472022-05-10 18:13:47 +0100166 if (member.user.bot) throw "I cannot warn bots"
pineafan8b4b17f2022-02-27 20:42:52 +0000167 // Allow the owner to warn anyone
pineafan663dc472022-05-10 18:13:47 +0100168 if (member.id == interaction.guild.ownerId) return true
pineafan8b4b17f2022-02-27 20:42:52 +0000169 // Check if the user has moderate_members permission
pineafan663dc472022-05-10 18:13:47 +0100170 if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the `moderate_members` permission";
pineafan8b4b17f2022-02-27 20:42:52 +0000171 // Check if the user is below on the role list
pineafan5d1908e2022-02-28 21:34:47 +0000172 if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
pineafan8b4b17f2022-02-27 20:42:52 +0000173 // Allow warn
174 return true
pineafan4f164f32022-02-26 22:07:12 +0000175}
176
pineafan8b4b17f2022-02-27 20:42:52 +0000177export { command, callback, check };