blob: d5f420595e76abe7e2c8843d2ff971b693298a0d [file] [log] [blame]
pineafan5d1908e2022-02-28 21:34:47 +00001import { CommandInteraction, GuildMember } from "discord.js";
pineafan4f164f32022-02-26 22:07:12 +00002import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
3import { WrappedCheck } from "jshaiku";
pineafan5d1908e2022-02-28 21:34:47 +00004import confirmationMessage from "../../utils/confirmationMessage.js";
pineafan4edb7762022-06-26 19:21:04 +01005import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan5d1908e2022-02-28 21:34:47 +00006import keyValueList from "../../utils/generateKeyValueList.js";
pineafan4edb7762022-06-26 19:21:04 +01007import client from "../../utils/client.js";
pineafan4f164f32022-02-26 22:07:12 +00008
9const command = (builder: SlashCommandSubcommandBuilder) =>
10 builder
pineafan8b4b17f2022-02-27 20:42:52 +000011 .setName("unmute")
pineafan5d1908e2022-02-28 21:34:47 +000012 .setDescription("Unmutes a user")
13 .addUserOption(option => option.setName("user").setDescription("The user to unmute").setRequired(true))
pineafan73a7c4a2022-07-24 10:38:04 +010014 .addStringOption(option => option.setName("notify").setDescription("If the user should get a message when they are unmuted | Default: No").setRequired(false)
pineafan5d1908e2022-02-28 21:34:47 +000015 .addChoices([["Yes", "yes"], ["No", "no"]])
16 )
pineafan4f164f32022-02-26 22:07:12 +000017
pineafan4edb7762022-06-26 19:21:04 +010018const callback = async (interaction: CommandInteraction): Promise<any> => {
pineafan73a7c4a2022-07-24 10:38:04 +010019 const { log, NucleusColors, renderUser, entry, renderDelta } = client.logger
pineafan5d1908e2022-02-28 21:34:47 +000020 // TODO:[Modals] Replace this with a modal
pineafan73a7c4a2022-07-24 10:38:04 +010021 let reason = null;
22 let confirmation;
23 while (true) {
24 confirmation = await new confirmationMessage(interaction)
25 .setEmoji("PUNISH.MUTE.RED")
26 .setTitle("Unmute")
27 .setDescription(keyValueList({
28 "user": renderUser(interaction.options.getUser("user")),
29 "reason": `\n> ${reason ? reason : "*No reason provided*"}`
30 })
31 + `The user **will${interaction.options.getString("notify") === "yes" ? '' : ' not'}** be notified\n\n`
32 + `Are you sure you want to unmute <@!${(interaction.options.getMember("user") as GuildMember).id}>?`)
33 .setColor("Danger")
34 .addReasonButton(reason ?? "")
35 .send(reason !== null)
36 reason = reason ?? ""
37 if (confirmation.newReason === undefined) break
38 reason = confirmation.newReason
39 }
pineafan377794f2022-04-18 19:01:01 +010040 if (confirmation.success) {
pineafan5d1908e2022-02-28 21:34:47 +000041 let dmd = false
42 let dm;
43 try {
44 if (interaction.options.getString("notify") != "no") {
45 dm = await (interaction.options.getMember("user") as GuildMember).send({
pineafan4edb7762022-06-26 19:21:04 +010046 embeds: [new EmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +000047 .setEmoji("PUNISH.MUTE.GREEN")
48 .setTitle("Unmuted")
49 .setDescription(`You have been unmuted in ${interaction.guild.name}` +
pineafan73a7c4a2022-07-24 10:38:04 +010050 (reason ? ` for:\n> ${reason}` : " with no reason provided."))
pineafan5d1908e2022-02-28 21:34:47 +000051 .setStatus("Success")
52 ]
53 })
54 dmd = true
55 }
56 } catch {}
pineafan73a7c4a2022-07-24 10:38:04 +010057 let member = (interaction.options.getMember("user") as GuildMember)
pineafan5d1908e2022-02-28 21:34:47 +000058 try {
pineafan73a7c4a2022-07-24 10:38:04 +010059 member.timeout(0, reason || "No reason provided")
pineafan5d1908e2022-02-28 21:34:47 +000060 } catch {
pineafan4edb7762022-06-26 19:21:04 +010061 await interaction.editReply({embeds: [new EmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +000062 .setEmoji("PUNISH.MUTE.RED")
63 .setTitle(`Unmute`)
64 .setDescription("Something went wrong and the user was not unmuted")
65 .setStatus("Danger")
66 ], components: []})
67 if (dmd) await dm.delete()
68 return
69 }
pineafan73a7c4a2022-07-24 10:38:04 +010070 try { await client.database.history.create("unmute", interaction.guild.id, (interaction.options.getMember("user") as GuildMember).user, interaction.user, reason) } catch {}
71 let data = {
72 meta: {
73 type: 'memberUnmute',
74 displayName: 'Unmuted',
75 calculateType: 'guildMemberPunish',
76 color: NucleusColors.green,
77 emoji: "PUNISH.MUTE.GREEN",
78 timestamp: new Date().getTime()
79 },
80 list: {
81 memberId: entry(member.user.id, `\`${member.user.id}\``),
82 name: entry(member.user.id, renderUser(member.user)),
83 unmuted: entry(new Date().getTime(), renderDelta(new Date().getTime())),
84 unmutedBy: entry(interaction.user.id, renderUser(interaction.user)),
85 },
86 hidden: {
87 guild: interaction.guild.id
88 }
89 }
90 log(data);
pineafan5d1908e2022-02-28 21:34:47 +000091 let failed = (dmd == false && interaction.options.getString("notify") != "no")
pineafan4edb7762022-06-26 19:21:04 +010092 await interaction.editReply({embeds: [new EmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +000093 .setEmoji(`PUNISH.MUTE.${failed ? "YELLOW" : "GREEN"}`)
94 .setTitle(`Unmute`)
95 .setDescription("The member was unmuted" + (failed ? ", but could not be notified" : ""))
96 .setStatus(failed ? "Warning" : "Success")
97 ], components: []})
98 } else {
pineafan4edb7762022-06-26 19:21:04 +010099 await interaction.editReply({embeds: [new EmojiEmbed()
pineafan5d1908e2022-02-28 21:34:47 +0000100 .setEmoji("PUNISH.MUTE.GREEN")
101 .setTitle(`Unmute`)
102 .setDescription("No changes were made")
103 .setStatus("Success")
104 ], components: []})
105 }
pineafan4f164f32022-02-26 22:07:12 +0000106}
107
108const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
pineafan5d1908e2022-02-28 21:34:47 +0000109 let member = (interaction.member as GuildMember)
110 let me = (interaction.guild.me as GuildMember)
111 let apply = (interaction.options.getMember("user") as GuildMember)
112 if (member == null || me == null || apply == null) throw "That member is not in the server"
113 let memberPos = member.roles ? member.roles.highest.position : 0
114 let mePos = me.roles ? me.roles.highest.position : 0
115 let applyPos = apply.roles ? apply.roles.highest.position : 0
116 // Check if Nucleus can unmute the member
117 if (! (mePos > applyPos)) throw "I do not have a role higher than that member"
118 // Check if Nucleus has permission to unmute
pineafan4edb7762022-06-26 19:21:04 +0100119 if (! me.permissions.has("MODERATE_MEMBERS")) throw "I do not have the Moderate members permission";
pineafan5d1908e2022-02-28 21:34:47 +0000120 // Do not allow the user to have admin or be the owner
PineappleFan5fe720d2022-05-19 12:01:49 +0100121 if (apply.permissions.has("ADMINISTRATOR") || apply.id == interaction.guild.ownerId) throw "You cannot unmute an admin or the owner"
pineafan5d1908e2022-02-28 21:34:47 +0000122 // Allow the owner to unmute anyone
pineafan663dc472022-05-10 18:13:47 +0100123 if (member.id == interaction.guild.ownerId) return true
pineafan5d1908e2022-02-28 21:34:47 +0000124 // Check if the user has moderate_members permission
pineafan4edb7762022-06-26 19:21:04 +0100125 if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the Moderate members permission";
pineafan5d1908e2022-02-28 21:34:47 +0000126 // Check if the user is below on the role list
127 if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
128 // Allow unmute
129 return true
pineafan4f164f32022-02-26 22:07:12 +0000130}
131
pineafan8b4b17f2022-02-27 20:42:52 +0000132export { command, callback, check };