blob: 39c9e5e28e4daff8a66242f5c80a9e064ac9e6a6 [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LinkWarningFooter, LoadingEmbed } from "../../utils/defaults.js";
PineaFan5bea7e12023-01-05 21:20:04 +00002import Discord, { CommandInteraction, GuildMember, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
TheCodedProff86ba092023-01-27 17:10:07 -05003import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan4edb7762022-06-26 19:21:04 +01004import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan8b4b17f2022-02-27 20:42:52 +00005import getEmojiByName from "../../utils/getEmojiByName.js";
6import confirmationMessage from "../../utils/confirmationMessage.js";
7import keyValueList from "../../utils/generateKeyValueList.js";
pineafan62ce1922022-08-25 20:34:45 +01008// @ts-expect-error
pineafan8b4b17f2022-02-27 20:42:52 +00009import humanizeDuration from "humanize-duration";
pineafan6702cef2022-06-13 17:52:37 +010010import client from "../../utils/client.js";
Skyler Grey11236ba2022-08-08 21:13:33 +010011import { areTicketsEnabled, create } from "../../actions/createModActionTicket.js";
pineafan8b4b17f2022-02-27 20:42:52 +000012
13const command = (builder: SlashCommandSubcommandBuilder) =>
14 builder
pineafan63fc5e22022-08-04 22:04:10 +010015 .setName("mute")
PineaFan538d3752023-01-12 21:48:23 +000016 // .setNameLocalizations({"ru": "silence"})
Skyler Grey11236ba2022-08-08 21:13:33 +010017 .setDescription("Mutes a member, stopping them from talking in the server")
18 .addUserOption((option) => option.setName("user").setDescription("The user to mute").setRequired(true))
Skyler Grey75ea9172022-08-06 10:22:23 +010019 .addIntegerOption((option) =>
20 option
21 .setName("days")
Skyler Grey11236ba2022-08-08 21:13:33 +010022 .setDescription("The number of days to mute the user for | Default: 0")
Skyler Grey75ea9172022-08-06 10:22:23 +010023 .setMinValue(0)
24 .setMaxValue(27)
25 .setRequired(false)
26 )
27 .addIntegerOption((option) =>
28 option
29 .setName("hours")
Skyler Grey11236ba2022-08-08 21:13:33 +010030 .setDescription("The number of hours to mute the user for | Default: 0")
Skyler Grey75ea9172022-08-06 10:22:23 +010031 .setMinValue(0)
32 .setMaxValue(23)
33 .setRequired(false)
34 )
35 .addIntegerOption((option) =>
36 option
37 .setName("minutes")
Skyler Grey11236ba2022-08-08 21:13:33 +010038 .setDescription("The number of minutes to mute the user for | Default: 0")
Skyler Grey75ea9172022-08-06 10:22:23 +010039 .setMinValue(0)
40 .setMaxValue(59)
41 .setRequired(false)
42 )
43 .addIntegerOption((option) =>
44 option
45 .setName("seconds")
Skyler Grey11236ba2022-08-08 21:13:33 +010046 .setDescription("The number of seconds to mute the user for | Default: 0")
Skyler Grey75ea9172022-08-06 10:22:23 +010047 .setMinValue(0)
48 .setMaxValue(59)
49 .setRequired(false)
50 );
pineafan8b4b17f2022-02-27 20:42:52 +000051
Skyler Greyc634e2b2022-08-06 17:50:48 +010052const callback = async (interaction: CommandInteraction): Promise<unknown> => {
PineaFana00db1b2023-01-02 15:32:54 +000053 if (!interaction.guild) return;
Skyler Grey11236ba2022-08-08 21:13:33 +010054 const { log, NucleusColors, renderUser, entry, renderDelta } = client.logger;
PineaFan5bea7e12023-01-05 21:20:04 +000055 const member = interaction.options.getMember("user") as GuildMember;
Skyler Greyda16adf2023-03-05 10:22:12 +000056 const time: { days: number; hours: number; minutes: number; seconds: number } = {
PineaFan5bea7e12023-01-05 21:20:04 +000057 days: (interaction.options.get("days")?.value as number | null) ?? 0,
58 hours: (interaction.options.get("hours")?.value as number | null) ?? 0,
59 minutes: (interaction.options.get("minutes")?.value as number | null) ?? 0,
60 seconds: (interaction.options.get("seconds")?.value as number | null) ?? 0
pineafan63fc5e22022-08-04 22:04:10 +010061 };
PineaFana00db1b2023-01-02 15:32:54 +000062 const config = await client.database.guilds.read(interaction.guild.id);
Skyler Grey11236ba2022-08-08 21:13:33 +010063 let serverSettingsDescription = config.moderation.mute.timeout ? "given a timeout" : "";
Skyler Grey75ea9172022-08-06 10:22:23 +010064 if (config.moderation.mute.role)
65 serverSettingsDescription +=
Skyler Grey11236ba2022-08-08 21:13:33 +010066 (serverSettingsDescription ? " and " : "") + `given the <@&${config.moderation.mute.role}> role`;
pineafane625d782022-05-09 18:04:32 +010067
Skyler Grey11236ba2022-08-08 21:13:33 +010068 let muteTime = time.days * 24 * 60 * 60 + time.hours * 60 * 60 + time.minutes * 60 + time.seconds;
pineafane23c4ec2022-07-27 21:56:27 +010069 if (muteTime === 0) {
PineaFan5bea7e12023-01-05 21:20:04 +000070 const m = await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010071 embeds: [
72 new EmojiEmbed()
73 .setEmoji("PUNISH.MUTE.GREEN")
74 .setTitle("Mute")
PineaFan5bea7e12023-01-05 21:20:04 +000075 .setDescription("How long should the user be muted for?")
Skyler Grey75ea9172022-08-06 10:22:23 +010076 .setStatus("Success")
77 ],
78 components: [
PineaFan5bea7e12023-01-05 21:20:04 +000079 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040080 new Discord.ButtonBuilder().setCustomId("1m").setLabel("1 Minute").setStyle(ButtonStyle.Secondary),
Skyler Greyda16adf2023-03-05 10:22:12 +000081 new Discord.ButtonBuilder()
82 .setCustomId("10m")
83 .setLabel("10 Minutes")
84 .setStyle(ButtonStyle.Secondary),
85 new Discord.ButtonBuilder()
86 .setCustomId("30m")
87 .setLabel("30 Minutes")
88 .setStyle(ButtonStyle.Secondary),
TheCodedProf21c08592022-09-13 14:14:43 -040089 new Discord.ButtonBuilder().setCustomId("1h").setLabel("1 Hour").setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010090 ]),
PineaFan5bea7e12023-01-05 21:20:04 +000091 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040092 new Discord.ButtonBuilder().setCustomId("6h").setLabel("6 Hours").setStyle(ButtonStyle.Secondary),
93 new Discord.ButtonBuilder().setCustomId("12h").setLabel("12 Hours").setStyle(ButtonStyle.Secondary),
94 new Discord.ButtonBuilder().setCustomId("1d").setLabel("1 Day").setStyle(ButtonStyle.Secondary),
95 new Discord.ButtonBuilder().setCustomId("1w").setLabel("1 Week").setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +010096 ]),
PineaFan5bea7e12023-01-05 21:20:04 +000097 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040098 new Discord.ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +010099 .setCustomId("cancel")
100 .setLabel("Cancel")
TheCodedProf21c08592022-09-13 14:14:43 -0400101 .setStyle(ButtonStyle.Danger)
Skyler Grey75ea9172022-08-06 10:22:23 +0100102 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
103 ])
104 ],
105 ephemeral: true,
106 fetchReply: true
PineaFan5bea7e12023-01-05 21:20:04 +0000107 });
pineafan8b4b17f2022-02-27 20:42:52 +0000108 let component;
109 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100110 component = await m.awaitMessageComponent({
Skyler Greyda16adf2023-03-05 10:22:12 +0000111 filter: (i) => {
112 return i.user.id === interaction.user.id && i.channelId === interaction.channelId;
113 },
Skyler Grey75ea9172022-08-06 10:22:23 +0100114 time: 300000
115 });
116 } catch {
117 return;
118 }
pineafan8b4b17f2022-02-27 20:42:52 +0000119 component.deferUpdate();
Skyler Grey75ea9172022-08-06 10:22:23 +0100120 if (component.customId === "cancel")
121 return interaction.editReply({
122 embeds: [
123 new EmojiEmbed()
124 .setEmoji("PUNISH.MUTE.RED")
125 .setTitle("Mute")
126 .setDescription("Mute cancelled")
127 .setStatus("Danger")
128 ]
129 });
pineafan8b4b17f2022-02-27 20:42:52 +0000130 switch (component.customId) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100131 case "1m": {
132 muteTime = 60;
133 break;
134 }
135 case "10m": {
136 muteTime = 60 * 10;
137 break;
138 }
139 case "30m": {
140 muteTime = 60 * 30;
141 break;
142 }
143 case "1h": {
144 muteTime = 60 * 60;
145 break;
146 }
147 case "6h": {
148 muteTime = 60 * 60 * 6;
149 break;
150 }
151 case "12h": {
152 muteTime = 60 * 60 * 12;
153 break;
154 }
155 case "1d": {
156 muteTime = 60 * 60 * 24;
157 break;
158 }
159 case "1w": {
160 muteTime = 60 * 60 * 24 * 7;
161 break;
162 }
pineafan8b4b17f2022-02-27 20:42:52 +0000163 }
164 } else {
Skyler Grey75ea9172022-08-06 10:22:23 +0100165 await interaction.reply({
166 embeds: LoadingEmbed,
167 ephemeral: true,
168 fetchReply: true
169 });
pineafan8b4b17f2022-02-27 20:42:52 +0000170 }
pineafan5d1908e2022-02-28 21:34:47 +0000171 // TODO:[Modals] Replace this with a modal
pineafan62ce1922022-08-25 20:34:45 +0100172 let reason: string | null = null;
pineafan02ba0232022-07-24 22:16:15 +0100173 let notify = true;
174 let createAppealTicket = false;
pineafan73a7c4a2022-07-24 10:38:04 +0100175 let confirmation;
Skyler Greyad002172022-08-16 18:48:26 +0100176 let timedOut = false;
177 let success = false;
pineafan62ce1922022-08-25 20:34:45 +0100178 do {
pineafan73a7c4a2022-07-24 10:38:04 +0100179 confirmation = await new confirmationMessage(interaction)
180 .setEmoji("PUNISH.MUTE.RED")
181 .setTitle("Mute")
Skyler Grey75ea9172022-08-06 10:22:23 +0100182 .setDescription(
183 keyValueList({
PineaFan5bea7e12023-01-05 21:20:04 +0000184 user: renderUser(member.user),
Skyler Grey75ea9172022-08-06 10:22:23 +0100185 time: `${humanizeDuration(muteTime * 1000, {
186 round: true
187 })}`,
Skyler Greyda16adf2023-03-05 10:22:12 +0000188 reason: reason ? "\n> " + reason.replaceAll("\n", "\n> ") : "*No reason provided*"
Skyler Grey75ea9172022-08-06 10:22:23 +0100189 }) +
190 "The user will be " +
191 serverSettingsDescription +
PineaFan5bea7e12023-01-05 21:20:04 +0000192 "\n\n" +
193 `Are you sure you want to mute <@!${member.id}>?`
Skyler Grey75ea9172022-08-06 10:22:23 +0100194 )
pineafan73a7c4a2022-07-24 10:38:04 +0100195 .setColor("Danger")
196 .addCustomBoolean(
Skyler Grey75ea9172022-08-06 10:22:23 +0100197 "appeal",
198 "Create appeal ticket",
PineaFana00db1b2023-01-02 15:32:54 +0000199 !(await areTicketsEnabled(interaction.guild.id)),
Skyler Greyda16adf2023-03-05 10:22:12 +0000200 async () =>
201 await create(interaction.guild!, interaction.options.getUser("user")!, interaction.user, reason),
Skyler Grey75ea9172022-08-06 10:22:23 +0100202 "An appeal ticket will be created when Confirm is clicked",
PineaFana34d04b2023-01-03 22:05:42 +0000203 null,
Skyler Grey75ea9172022-08-06 10:22:23 +0100204 "CONTROL.TICKET",
205 createAppealTicket
206 )
207 .addCustomBoolean(
208 "notify",
209 "Notify user",
210 false,
Skyler Grey75ea9172022-08-06 10:22:23 +0100211 null,
PineaFan5bea7e12023-01-05 21:20:04 +0000212 "The user will be sent a DM",
PineaFana34d04b2023-01-03 22:05:42 +0000213 null,
Skyler Grey75ea9172022-08-06 10:22:23 +0100214 "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
215 notify
216 )
pineafan73a7c4a2022-07-24 10:38:04 +0100217 .addReasonButton(reason ?? "")
PineaFan1dee28f2023-01-16 22:09:07 +0000218 .setFailedMessage("No changes were made", "Success", "PUNISH.MUTE.GREEN")
pineafan63fc5e22022-08-04 22:04:10 +0100219 .send(true);
220 reason = reason ?? "";
Skyler Greyad002172022-08-16 18:48:26 +0100221 if (confirmation.cancelled) timedOut = true;
PineaFan5bea7e12023-01-05 21:20:04 +0000222 else if (confirmation.success) success = true;
223 else if (confirmation.newReason) reason = confirmation.newReason;
224 else if (confirmation.components) {
pineafan62ce1922022-08-25 20:34:45 +0100225 notify = confirmation.components["notify"]!.active;
226 createAppealTicket = confirmation.components["appeal"]!.active;
pineafan02ba0232022-07-24 22:16:15 +0100227 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000228 } while (!timedOut && !success);
PineaFan1dee28f2023-01-16 22:09:07 +0000229 if (timedOut || !confirmation.success) return;
Skyler Greyda16adf2023-03-05 10:22:12 +0000230 const status: { timeout: boolean | null; role: boolean | null; dm: boolean | null } = {
231 timeout: null,
232 role: null,
233 dm: null
234 };
PineaFan5bea7e12023-01-05 21:20:04 +0000235 let dmMessage;
236 try {
237 if (notify) {
Skyler Greyda16adf2023-03-05 10:22:12 +0000238 if (reason) {
239 reason = reason
240 .split("\n")
241 .map((line) => "> " + line)
242 .join("\n");
243 }
PineaFan5bea7e12023-01-05 21:20:04 +0000244 const messageData: {
245 embeds: EmojiEmbed[];
246 components: ActionRowBuilder<ButtonBuilder>[];
247 } = {
248 embeds: [
249 new EmojiEmbed()
250 .setEmoji("PUNISH.MUTE.RED")
251 .setTitle("Muted")
252 .setDescription(
253 `You have been muted in ${interaction.guild.name}` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000254 (reason ? ` for:\n${reason}` : ".\n*No reason was provided*") +
255 "\n\n" +
256 `You will be unmuted at: <t:${Math.round(Date.now() / 1000) + muteTime}:D> at ` +
257 `<t:${Math.round(Date.now() / 1000) + muteTime}:T> (<t:${
258 Math.round(Date.now() / 1000) + muteTime
259 }:R>)` +
260 "\n\n" +
261 (createAppealTicket
262 ? `You can appeal this in the ticket created in <#${
263 confirmation.components!["appeal"]!.response
264 }>`
265 : "")
PineaFan5bea7e12023-01-05 21:20:04 +0000266 )
267 .setStatus("Danger")
268 ],
269 components: []
Skyler Greyda16adf2023-03-05 10:22:12 +0000270 };
PineaFan5bea7e12023-01-05 21:20:04 +0000271 if (config.moderation.mute.text && config.moderation.mute.link) {
272 messageData.embeds[0]!.setFooter(LinkWarningFooter);
Skyler Greyda16adf2023-03-05 10:22:12 +0000273 messageData.components.push(
274 new ActionRowBuilder<Discord.ButtonBuilder>().addComponents(
275 new ButtonBuilder()
276 .setStyle(ButtonStyle.Link)
277 .setLabel(config.moderation.mute.text)
278 .setURL(
279 config.moderation.mute.link.replaceAll(
280 "{id}",
281 (interaction.options.getMember("user") as GuildMember).id
282 )
283 )
PineaFan5bea7e12023-01-05 21:20:04 +0000284 )
Skyler Greyda16adf2023-03-05 10:22:12 +0000285 );
286 }
PineaFan5bea7e12023-01-05 21:20:04 +0000287 dmMessage = await member.send(messageData);
288 status.dm = true;
289 }
290 } catch {
291 status.dm = false;
292 }
293 try {
294 if (config.moderation.mute.timeout) {
295 await member.timeout(muteTime * 1000, reason || "*No reason provided*");
296 if (config.moderation.mute.role !== null) {
297 await member.roles.add(config.moderation.mute.role);
Skyler Greyda16adf2023-03-05 10:22:12 +0000298 await client.database.eventScheduler.schedule(
299 "naturalUnmute",
300 (Date.now() + muteTime * 1000).toString(),
301 {
302 guild: interaction.guild.id,
303 user: member.id,
304 expires: Date.now() + muteTime * 1000
305 }
306 );
PineaFan5bea7e12023-01-05 21:20:04 +0000307 }
308 } else {
309 status.timeout = true;
310 }
311 } catch {
312 status.timeout = false;
313 }
314 try {
315 if (config.moderation.mute.role !== null) {
316 await member.roles.add(config.moderation.mute.role);
TheCodedProf6ec331b2023-02-20 12:13:06 -0500317 await client.database.eventScheduler.schedule("unmuteRole", (Date.now() + muteTime * 1000).toString(), {
PineaFan5bea7e12023-01-05 21:20:04 +0000318 guild: interaction.guild.id,
319 user: member.id,
320 role: config.moderation.mute.role
321 });
322 } else {
323 status.role = true;
324 }
325 } catch {
326 status.role = false;
327 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000328 const countTrue = (items: (boolean | null)[]) => items.filter((item) => item === true).length;
PineaFan5bea7e12023-01-05 21:20:04 +0000329 const requiredPunishments = countTrue([config.moderation.mute.timeout, config.moderation.mute.role !== null]);
330 const actualPunishments = countTrue([status.timeout, status.role]);
331
332 await client.database.history.create("mute", interaction.guild.id, member.user, interaction.user, reason);
333 if (requiredPunishments !== actualPunishments) {
334 const messages = [];
335 if (config.moderation.mute.timeout) messages.push(`The member was ${status.timeout ? "" : "not "}timed out`);
Skyler Greyda16adf2023-03-05 10:22:12 +0000336 if (config.moderation.mute.role !== null)
337 messages.push(`The member was ${status.role ? "" : "not "}given the mute role`);
PineaFan5bea7e12023-01-05 21:20:04 +0000338 messages.push(`The member was not sent a DM`);
339 if (dmMessage && actualPunishments === 0) await dmMessage.delete();
340 await interaction.editReply({
341 embeds: [
342 new EmojiEmbed()
343 .setEmoji("PUNISH.MUTE." + (actualPunishments > 0 ? "YELLOW" : "RED"))
344 .setTitle("Mute")
345 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000346 "Mute " +
347 (actualPunishments > 0 ? "partially" : "failed") +
348 ":\n" +
349 messages.map((message) => `> ${message}`).join("\n")
PineaFan5bea7e12023-01-05 21:20:04 +0000350 )
351 .setStatus(actualPunishments > 0 ? "Warning" : "Danger")
352 ],
353 components: []
354 });
355 }
356 const data = {
357 meta: {
358 type: "memberMute",
359 displayName: "Member Muted",
360 calculateType: "guildMemberPunish",
361 color: NucleusColors.yellow,
362 emoji: "PUNISH.WARN.YELLOW",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500363 timestamp: Date.now()
PineaFan5bea7e12023-01-05 21:20:04 +0000364 },
365 list: {
366 memberId: entry(member.user.id, `\`${member.user.id}\``),
367 name: entry(member.user.id, renderUser(member.user)),
Skyler Greyda16adf2023-03-05 10:22:12 +0000368 mutedUntil: entry((Date.now() + muteTime * 1000).toString(), renderDelta(Date.now() + muteTime * 1000)),
TheCodedProf6ec331b2023-02-20 12:13:06 -0500369 muted: entry(new Date().getTime.toString(), renderDelta(Date.now() - 1000)),
PineaFan5bea7e12023-01-05 21:20:04 +0000370 mutedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as Discord.User)),
371 reason: entry(reason, reason ? reason : "*No reason provided*")
372 },
TheCodedProf94ff6de2023-02-22 17:47:26 -0500373 separate: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000374 end:
375 getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) +
376 ` The user was ${notify ? "" : "not "}notified`
TheCodedProf94ff6de2023-02-22 17:47:26 -0500377 },
PineaFan5bea7e12023-01-05 21:20:04 +0000378 hidden: {
379 guild: interaction.guild.id
380 }
381 };
382 log(data);
383 const failed = !status.dm && notify;
384 await interaction.editReply({
385 embeds: [
386 new EmojiEmbed()
387 .setEmoji(`PUNISH.MUTE.${failed ? "YELLOW" : "GREEN"}`)
388 .setTitle("Mute")
389 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000390 "The member was muted" +
391 (failed ? ", but could not be notified" : "") +
392 (createAppealTicket
393 ? ` and an appeal ticket was opened in <#${confirmation.components!["appeal"]!.response}>`
394 : "")
PineaFan5bea7e12023-01-05 21:20:04 +0000395 )
396 .setStatus(failed ? "Warning" : "Success")
397 ],
398 components: []
399 });
pineafan63fc5e22022-08-04 22:04:10 +0100400};
pineafan8b4b17f2022-02-27 20:42:52 +0000401
TheCodedProff86ba092023-01-27 17:10:07 -0500402const check = async (interaction: CommandInteraction, partial: boolean = false) => {
PineaFana00db1b2023-01-02 15:32:54 +0000403 if (!interaction.guild) return;
Skyler Grey75ea9172022-08-06 10:22:23 +0100404 const member = interaction.member as GuildMember;
TheCodedProff86ba092023-01-27 17:10:07 -0500405 // Check if the user has moderate_members permission
406 if (!member.permissions.has("ModerateMembers")) return "You do not have the *Moderate Members* permission";
407 if (partial) return true;
PineaFan5bea7e12023-01-05 21:20:04 +0000408 const me = interaction.guild.members.me!;
Skyler Grey75ea9172022-08-06 10:22:23 +0100409 const apply = interaction.options.getMember("user") as GuildMember;
pineafan62ce1922022-08-25 20:34:45 +0100410 const memberPos = member.roles.cache.size > 1 ? member.roles.highest.position : 0;
411 const mePos = me.roles.cache.size > 1 ? me.roles.highest.position : 0;
412 const applyPos = apply.roles.cache.size > 1 ? apply.roles.highest.position : 0;
pineafanc1c18792022-08-03 21:41:36 +0100413 // Do not allow muting the owner
PineaFan0d06edc2023-01-17 22:10:31 +0000414 if (member.id === interaction.guild.ownerId) return "You cannot mute the owner of the server";
pineafan8b4b17f2022-02-27 20:42:52 +0000415 // Check if Nucleus can mute the member
TheCodedProf0941da42023-02-18 20:28:04 -0500416 if (!(mePos > applyPos)) return `I do not have a role higher than <@${apply.id}>`;
pineafan8b4b17f2022-02-27 20:42:52 +0000417 // Check if Nucleus has permission to mute
PineaFan0d06edc2023-01-17 22:10:31 +0000418 if (!me.permissions.has("ModerateMembers")) return "I do not have the *Moderate Members* permission";
pineafan8b4b17f2022-02-27 20:42:52 +0000419 // Do not allow muting Nucleus
PineaFan0d06edc2023-01-17 22:10:31 +0000420 if (member.id === me.id) return "I cannot mute myself";
pineafan8b4b17f2022-02-27 20:42:52 +0000421 // Allow the owner to mute anyone
PineaFana00db1b2023-01-02 15:32:54 +0000422 if (member.id === interaction.guild.ownerId) return true;
pineafan8b4b17f2022-02-27 20:42:52 +0000423 // Check if the user is below on the role list
TheCodedProf0941da42023-02-18 20:28:04 -0500424 if (!(memberPos > applyPos)) return `You do not have a role higher than <@${apply.id}>`;
pineafan8b4b17f2022-02-27 20:42:52 +0000425 // Allow mute
pineafan63fc5e22022-08-04 22:04:10 +0100426 return true;
427};
pineafan8b4b17f2022-02-27 20:42:52 +0000428
Skyler Grey75ea9172022-08-06 10:22:23 +0100429export { command, callback, check };
TheCodedProfa112f612023-01-28 18:06:45 -0500430export const metadata = {
Skyler Greyda16adf2023-03-05 10:22:12 +0000431 longDescription:
432 "Stops a member from being able to send messages or join voice channels for a specified amount of time.",
433 premiumOnly: true
434};