blob: 0cfe660d60c64a7becb88d8b7042286cced450be [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LinkWarningFooter, LoadingEmbed } from "../../utils/defaults.js";
pineafan1e462ab2023-03-07 21:34:06 +00002import Discord, {
3 CommandInteraction,
4 GuildMember,
5 ActionRowBuilder,
6 ButtonBuilder,
7 ButtonStyle,
8 ButtonInteraction
9} from "discord.js";
TheCodedProff86ba092023-01-27 17:10:07 -050010import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan4edb7762022-06-26 19:21:04 +010011import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan8b4b17f2022-02-27 20:42:52 +000012import getEmojiByName from "../../utils/getEmojiByName.js";
13import confirmationMessage from "../../utils/confirmationMessage.js";
14import keyValueList from "../../utils/generateKeyValueList.js";
pineafan62ce1922022-08-25 20:34:45 +010015// @ts-expect-error
pineafan8b4b17f2022-02-27 20:42:52 +000016import humanizeDuration from "humanize-duration";
pineafan6702cef2022-06-13 17:52:37 +010017import client from "../../utils/client.js";
Skyler Grey11236ba2022-08-08 21:13:33 +010018import { areTicketsEnabled, create } from "../../actions/createModActionTicket.js";
pineafan8b4b17f2022-02-27 20:42:52 +000019
20const command = (builder: SlashCommandSubcommandBuilder) =>
21 builder
pineafan63fc5e22022-08-04 22:04:10 +010022 .setName("mute")
PineaFan538d3752023-01-12 21:48:23 +000023 // .setNameLocalizations({"ru": "silence"})
Skyler Grey11236ba2022-08-08 21:13:33 +010024 .setDescription("Mutes a member, stopping them from talking in the server")
25 .addUserOption((option) => option.setName("user").setDescription("The user to mute").setRequired(true))
Skyler Grey75ea9172022-08-06 10:22:23 +010026 .addIntegerOption((option) =>
27 option
28 .setName("days")
Skyler Grey11236ba2022-08-08 21:13:33 +010029 .setDescription("The number of days to mute the user for | Default: 0")
Skyler Grey75ea9172022-08-06 10:22:23 +010030 .setMinValue(0)
31 .setMaxValue(27)
32 .setRequired(false)
33 )
34 .addIntegerOption((option) =>
35 option
36 .setName("hours")
Skyler Grey11236ba2022-08-08 21:13:33 +010037 .setDescription("The number of hours to mute the user for | Default: 0")
Skyler Grey75ea9172022-08-06 10:22:23 +010038 .setMinValue(0)
39 .setMaxValue(23)
40 .setRequired(false)
41 )
42 .addIntegerOption((option) =>
43 option
44 .setName("minutes")
Skyler Grey11236ba2022-08-08 21:13:33 +010045 .setDescription("The number of minutes to mute the user for | Default: 0")
Skyler Grey75ea9172022-08-06 10:22:23 +010046 .setMinValue(0)
47 .setMaxValue(59)
48 .setRequired(false)
49 )
50 .addIntegerOption((option) =>
51 option
52 .setName("seconds")
Skyler Grey11236ba2022-08-08 21:13:33 +010053 .setDescription("The number of seconds to mute the user for | Default: 0")
Skyler Grey75ea9172022-08-06 10:22:23 +010054 .setMinValue(0)
55 .setMaxValue(59)
56 .setRequired(false)
57 );
pineafan8b4b17f2022-02-27 20:42:52 +000058
pineafan1e462ab2023-03-07 21:34:06 +000059const callback = async (
60 interaction: CommandInteraction | ButtonInteraction,
61 member?: GuildMember
62): Promise<unknown> => {
PineaFana00db1b2023-01-02 15:32:54 +000063 if (!interaction.guild) return;
Skyler Grey11236ba2022-08-08 21:13:33 +010064 const { log, NucleusColors, renderUser, entry, renderDelta } = client.logger;
pineafan6de4da52023-03-07 20:43:44 +000065 let time: { days: number; hours: number; minutes: number; seconds: number } | null = null;
66 if (!interaction.isButton()) {
67 member = interaction.options.getMember("user") as GuildMember;
68 time = {
69 days: (interaction.options.get("days")?.value as number | null) ?? 0,
70 hours: (interaction.options.get("hours")?.value as number | null) ?? 0,
71 minutes: (interaction.options.get("minutes")?.value as number | null) ?? 0,
72 seconds: (interaction.options.get("seconds")?.value as number | null) ?? 0
73 };
74 } else {
pineafan1e462ab2023-03-07 21:34:06 +000075 time = { days: 0, hours: 0, minutes: 0, seconds: 0 };
pineafan6de4da52023-03-07 20:43:44 +000076 }
77 if (!member) return;
PineaFana00db1b2023-01-02 15:32:54 +000078 const config = await client.database.guilds.read(interaction.guild.id);
Skyler Grey11236ba2022-08-08 21:13:33 +010079 let serverSettingsDescription = config.moderation.mute.timeout ? "given a timeout" : "";
Skyler Grey75ea9172022-08-06 10:22:23 +010080 if (config.moderation.mute.role)
81 serverSettingsDescription +=
Skyler Grey11236ba2022-08-08 21:13:33 +010082 (serverSettingsDescription ? " and " : "") + `given the <@&${config.moderation.mute.role}> role`;
pineafane625d782022-05-09 18:04:32 +010083
Skyler Grey11236ba2022-08-08 21:13:33 +010084 let muteTime = time.days * 24 * 60 * 60 + time.hours * 60 * 60 + time.minutes * 60 + time.seconds;
pineafane23c4ec2022-07-27 21:56:27 +010085 if (muteTime === 0) {
PineaFan5bea7e12023-01-05 21:20:04 +000086 const m = await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010087 embeds: [
88 new EmojiEmbed()
89 .setEmoji("PUNISH.MUTE.GREEN")
90 .setTitle("Mute")
PineaFan5bea7e12023-01-05 21:20:04 +000091 .setDescription("How long should the user be muted for?")
Skyler Grey75ea9172022-08-06 10:22:23 +010092 .setStatus("Success")
93 ],
94 components: [
PineaFan5bea7e12023-01-05 21:20:04 +000095 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -040096 new Discord.ButtonBuilder().setCustomId("1m").setLabel("1 Minute").setStyle(ButtonStyle.Secondary),
Skyler Greyda16adf2023-03-05 10:22:12 +000097 new Discord.ButtonBuilder()
98 .setCustomId("10m")
99 .setLabel("10 Minutes")
100 .setStyle(ButtonStyle.Secondary),
101 new Discord.ButtonBuilder()
102 .setCustomId("30m")
103 .setLabel("30 Minutes")
104 .setStyle(ButtonStyle.Secondary),
TheCodedProf21c08592022-09-13 14:14:43 -0400105 new Discord.ButtonBuilder().setCustomId("1h").setLabel("1 Hour").setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100106 ]),
PineaFan5bea7e12023-01-05 21:20:04 +0000107 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -0400108 new Discord.ButtonBuilder().setCustomId("6h").setLabel("6 Hours").setStyle(ButtonStyle.Secondary),
109 new Discord.ButtonBuilder().setCustomId("12h").setLabel("12 Hours").setStyle(ButtonStyle.Secondary),
110 new Discord.ButtonBuilder().setCustomId("1d").setLabel("1 Day").setStyle(ButtonStyle.Secondary),
111 new Discord.ButtonBuilder().setCustomId("1w").setLabel("1 Week").setStyle(ButtonStyle.Secondary)
Skyler Grey75ea9172022-08-06 10:22:23 +0100112 ]),
PineaFan5bea7e12023-01-05 21:20:04 +0000113 new ActionRowBuilder<ButtonBuilder>().addComponents([
TheCodedProf21c08592022-09-13 14:14:43 -0400114 new Discord.ButtonBuilder()
Skyler Grey75ea9172022-08-06 10:22:23 +0100115 .setCustomId("cancel")
116 .setLabel("Cancel")
TheCodedProf21c08592022-09-13 14:14:43 -0400117 .setStyle(ButtonStyle.Danger)
Skyler Grey75ea9172022-08-06 10:22:23 +0100118 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
119 ])
120 ],
121 ephemeral: true,
122 fetchReply: true
PineaFan5bea7e12023-01-05 21:20:04 +0000123 });
pineafan8b4b17f2022-02-27 20:42:52 +0000124 let component;
125 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100126 component = await m.awaitMessageComponent({
Skyler Greyda16adf2023-03-05 10:22:12 +0000127 filter: (i) => {
128 return i.user.id === interaction.user.id && i.channelId === interaction.channelId;
129 },
Skyler Grey75ea9172022-08-06 10:22:23 +0100130 time: 300000
131 });
132 } catch {
133 return;
134 }
Skyler Greyf4f21c42023-03-08 14:36:29 +0000135 await component.deferUpdate();
Skyler Grey75ea9172022-08-06 10:22:23 +0100136 if (component.customId === "cancel")
137 return interaction.editReply({
138 embeds: [
139 new EmojiEmbed()
140 .setEmoji("PUNISH.MUTE.RED")
141 .setTitle("Mute")
142 .setDescription("Mute cancelled")
143 .setStatus("Danger")
144 ]
145 });
pineafan8b4b17f2022-02-27 20:42:52 +0000146 switch (component.customId) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100147 case "1m": {
148 muteTime = 60;
149 break;
150 }
151 case "10m": {
152 muteTime = 60 * 10;
153 break;
154 }
155 case "30m": {
156 muteTime = 60 * 30;
157 break;
158 }
159 case "1h": {
160 muteTime = 60 * 60;
161 break;
162 }
163 case "6h": {
164 muteTime = 60 * 60 * 6;
165 break;
166 }
167 case "12h": {
168 muteTime = 60 * 60 * 12;
169 break;
170 }
171 case "1d": {
172 muteTime = 60 * 60 * 24;
173 break;
174 }
175 case "1w": {
176 muteTime = 60 * 60 * 24 * 7;
177 break;
178 }
pineafan8b4b17f2022-02-27 20:42:52 +0000179 }
180 } else {
Skyler Grey75ea9172022-08-06 10:22:23 +0100181 await interaction.reply({
182 embeds: LoadingEmbed,
183 ephemeral: true,
184 fetchReply: true
185 });
pineafan8b4b17f2022-02-27 20:42:52 +0000186 }
pineafan5d1908e2022-02-28 21:34:47 +0000187 // TODO:[Modals] Replace this with a modal
pineafan62ce1922022-08-25 20:34:45 +0100188 let reason: string | null = null;
pineafan02ba0232022-07-24 22:16:15 +0100189 let notify = true;
190 let createAppealTicket = false;
pineafan73a7c4a2022-07-24 10:38:04 +0100191 let confirmation;
Skyler Greyad002172022-08-16 18:48:26 +0100192 let timedOut = false;
193 let success = false;
pineafan62ce1922022-08-25 20:34:45 +0100194 do {
pineafan73a7c4a2022-07-24 10:38:04 +0100195 confirmation = await new confirmationMessage(interaction)
196 .setEmoji("PUNISH.MUTE.RED")
197 .setTitle("Mute")
Skyler Grey75ea9172022-08-06 10:22:23 +0100198 .setDescription(
199 keyValueList({
PineaFan5bea7e12023-01-05 21:20:04 +0000200 user: renderUser(member.user),
Skyler Grey75ea9172022-08-06 10:22:23 +0100201 time: `${humanizeDuration(muteTime * 1000, {
202 round: true
203 })}`,
Skyler Greyda16adf2023-03-05 10:22:12 +0000204 reason: reason ? "\n> " + reason.replaceAll("\n", "\n> ") : "*No reason provided*"
Skyler Grey75ea9172022-08-06 10:22:23 +0100205 }) +
206 "The user will be " +
207 serverSettingsDescription +
PineaFan5bea7e12023-01-05 21:20:04 +0000208 "\n\n" +
209 `Are you sure you want to mute <@!${member.id}>?`
Skyler Grey75ea9172022-08-06 10:22:23 +0100210 )
pineafan73a7c4a2022-07-24 10:38:04 +0100211 .setColor("Danger")
212 .addCustomBoolean(
Skyler Grey75ea9172022-08-06 10:22:23 +0100213 "appeal",
214 "Create appeal ticket",
PineaFana00db1b2023-01-02 15:32:54 +0000215 !(await areTicketsEnabled(interaction.guild.id)),
pineafan1e462ab2023-03-07 21:34:06 +0000216 async () => await create(interaction.guild!, member!.user, interaction.user, reason),
Skyler Grey75ea9172022-08-06 10:22:23 +0100217 "An appeal ticket will be created when Confirm is clicked",
PineaFana34d04b2023-01-03 22:05:42 +0000218 null,
Skyler Grey75ea9172022-08-06 10:22:23 +0100219 "CONTROL.TICKET",
220 createAppealTicket
221 )
222 .addCustomBoolean(
223 "notify",
224 "Notify user",
225 false,
Skyler Grey75ea9172022-08-06 10:22:23 +0100226 null,
PineaFan5bea7e12023-01-05 21:20:04 +0000227 "The user will be sent a DM",
PineaFana34d04b2023-01-03 22:05:42 +0000228 null,
Skyler Grey75ea9172022-08-06 10:22:23 +0100229 "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
230 notify
231 )
pineafan73a7c4a2022-07-24 10:38:04 +0100232 .addReasonButton(reason ?? "")
PineaFan1dee28f2023-01-16 22:09:07 +0000233 .setFailedMessage("No changes were made", "Success", "PUNISH.MUTE.GREEN")
pineafan63fc5e22022-08-04 22:04:10 +0100234 .send(true);
235 reason = reason ?? "";
Skyler Greyad002172022-08-16 18:48:26 +0100236 if (confirmation.cancelled) timedOut = true;
PineaFan5bea7e12023-01-05 21:20:04 +0000237 else if (confirmation.success) success = true;
238 else if (confirmation.newReason) reason = confirmation.newReason;
239 else if (confirmation.components) {
pineafan62ce1922022-08-25 20:34:45 +0100240 notify = confirmation.components["notify"]!.active;
241 createAppealTicket = confirmation.components["appeal"]!.active;
pineafan02ba0232022-07-24 22:16:15 +0100242 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000243 } while (!timedOut && !success);
PineaFan1dee28f2023-01-16 22:09:07 +0000244 if (timedOut || !confirmation.success) return;
Skyler Greyda16adf2023-03-05 10:22:12 +0000245 const status: { timeout: boolean | null; role: boolean | null; dm: boolean | null } = {
246 timeout: null,
247 role: null,
248 dm: null
249 };
PineaFan5bea7e12023-01-05 21:20:04 +0000250 let dmMessage;
251 try {
252 if (notify) {
Skyler Greyda16adf2023-03-05 10:22:12 +0000253 if (reason) {
254 reason = reason
255 .split("\n")
256 .map((line) => "> " + line)
257 .join("\n");
258 }
PineaFan5bea7e12023-01-05 21:20:04 +0000259 const messageData: {
260 embeds: EmojiEmbed[];
261 components: ActionRowBuilder<ButtonBuilder>[];
262 } = {
263 embeds: [
264 new EmojiEmbed()
265 .setEmoji("PUNISH.MUTE.RED")
266 .setTitle("Muted")
267 .setDescription(
268 `You have been muted in ${interaction.guild.name}` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000269 (reason ? ` for:\n${reason}` : ".\n*No reason was provided*") +
270 "\n\n" +
271 `You will be unmuted at: <t:${Math.round(Date.now() / 1000) + muteTime}:D> at ` +
272 `<t:${Math.round(Date.now() / 1000) + muteTime}:T> (<t:${
273 Math.round(Date.now() / 1000) + muteTime
274 }:R>)` +
275 "\n\n" +
276 (createAppealTicket
277 ? `You can appeal this in the ticket created in <#${
278 confirmation.components!["appeal"]!.response
279 }>`
280 : "")
PineaFan5bea7e12023-01-05 21:20:04 +0000281 )
282 .setStatus("Danger")
283 ],
284 components: []
Skyler Greyda16adf2023-03-05 10:22:12 +0000285 };
PineaFan5bea7e12023-01-05 21:20:04 +0000286 if (config.moderation.mute.text && config.moderation.mute.link) {
287 messageData.embeds[0]!.setFooter(LinkWarningFooter);
Skyler Greyda16adf2023-03-05 10:22:12 +0000288 messageData.components.push(
289 new ActionRowBuilder<Discord.ButtonBuilder>().addComponents(
290 new ButtonBuilder()
291 .setStyle(ButtonStyle.Link)
292 .setLabel(config.moderation.mute.text)
pineafan6de4da52023-03-07 20:43:44 +0000293 .setURL(config.moderation.mute.link.replaceAll("{id}", member.id))
PineaFan5bea7e12023-01-05 21:20:04 +0000294 )
Skyler Greyda16adf2023-03-05 10:22:12 +0000295 );
296 }
PineaFan5bea7e12023-01-05 21:20:04 +0000297 dmMessage = await member.send(messageData);
298 status.dm = true;
299 }
300 } catch {
301 status.dm = false;
302 }
303 try {
304 if (config.moderation.mute.timeout) {
305 await member.timeout(muteTime * 1000, reason || "*No reason provided*");
306 if (config.moderation.mute.role !== null) {
307 await member.roles.add(config.moderation.mute.role);
Skyler Greyda16adf2023-03-05 10:22:12 +0000308 await client.database.eventScheduler.schedule(
309 "naturalUnmute",
310 (Date.now() + muteTime * 1000).toString(),
311 {
312 guild: interaction.guild.id,
313 user: member.id,
314 expires: Date.now() + muteTime * 1000
315 }
316 );
PineaFan5bea7e12023-01-05 21:20:04 +0000317 }
318 } else {
319 status.timeout = true;
320 }
321 } catch {
322 status.timeout = false;
323 }
324 try {
325 if (config.moderation.mute.role !== null) {
326 await member.roles.add(config.moderation.mute.role);
TheCodedProf6ec331b2023-02-20 12:13:06 -0500327 await client.database.eventScheduler.schedule("unmuteRole", (Date.now() + muteTime * 1000).toString(), {
PineaFan5bea7e12023-01-05 21:20:04 +0000328 guild: interaction.guild.id,
329 user: member.id,
330 role: config.moderation.mute.role
331 });
332 } else {
333 status.role = true;
334 }
335 } catch {
336 status.role = false;
337 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000338 const countTrue = (items: (boolean | null)[]) => items.filter((item) => item === true).length;
PineaFan5bea7e12023-01-05 21:20:04 +0000339 const requiredPunishments = countTrue([config.moderation.mute.timeout, config.moderation.mute.role !== null]);
340 const actualPunishments = countTrue([status.timeout, status.role]);
341
342 await client.database.history.create("mute", interaction.guild.id, member.user, interaction.user, reason);
343 if (requiredPunishments !== actualPunishments) {
344 const messages = [];
345 if (config.moderation.mute.timeout) messages.push(`The member was ${status.timeout ? "" : "not "}timed out`);
Skyler Greyda16adf2023-03-05 10:22:12 +0000346 if (config.moderation.mute.role !== null)
347 messages.push(`The member was ${status.role ? "" : "not "}given the mute role`);
PineaFan5bea7e12023-01-05 21:20:04 +0000348 messages.push(`The member was not sent a DM`);
349 if (dmMessage && actualPunishments === 0) await dmMessage.delete();
350 await interaction.editReply({
351 embeds: [
352 new EmojiEmbed()
353 .setEmoji("PUNISH.MUTE." + (actualPunishments > 0 ? "YELLOW" : "RED"))
354 .setTitle("Mute")
355 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000356 "Mute " +
357 (actualPunishments > 0 ? "partially" : "failed") +
358 ":\n" +
359 messages.map((message) => `> ${message}`).join("\n")
PineaFan5bea7e12023-01-05 21:20:04 +0000360 )
361 .setStatus(actualPunishments > 0 ? "Warning" : "Danger")
362 ],
363 components: []
364 });
365 }
366 const data = {
367 meta: {
368 type: "memberMute",
369 displayName: "Member Muted",
370 calculateType: "guildMemberPunish",
371 color: NucleusColors.yellow,
372 emoji: "PUNISH.WARN.YELLOW",
TheCodedProf6ec331b2023-02-20 12:13:06 -0500373 timestamp: Date.now()
PineaFan5bea7e12023-01-05 21:20:04 +0000374 },
375 list: {
376 memberId: entry(member.user.id, `\`${member.user.id}\``),
377 name: entry(member.user.id, renderUser(member.user)),
Skyler Greyda16adf2023-03-05 10:22:12 +0000378 mutedUntil: entry((Date.now() + muteTime * 1000).toString(), renderDelta(Date.now() + muteTime * 1000)),
TheCodedProf6ec331b2023-02-20 12:13:06 -0500379 muted: entry(new Date().getTime.toString(), renderDelta(Date.now() - 1000)),
PineaFan5bea7e12023-01-05 21:20:04 +0000380 mutedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as Discord.User)),
381 reason: entry(reason, reason ? reason : "*No reason provided*")
382 },
TheCodedProf94ff6de2023-02-22 17:47:26 -0500383 separate: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000384 end:
385 getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) +
386 ` The user was ${notify ? "" : "not "}notified`
TheCodedProf94ff6de2023-02-22 17:47:26 -0500387 },
PineaFan5bea7e12023-01-05 21:20:04 +0000388 hidden: {
389 guild: interaction.guild.id
390 }
391 };
Skyler Greyf4f21c42023-03-08 14:36:29 +0000392 await log(data);
PineaFan5bea7e12023-01-05 21:20:04 +0000393 const failed = !status.dm && notify;
394 await interaction.editReply({
395 embeds: [
396 new EmojiEmbed()
397 .setEmoji(`PUNISH.MUTE.${failed ? "YELLOW" : "GREEN"}`)
398 .setTitle("Mute")
399 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000400 "The member was muted" +
401 (failed ? ", but could not be notified" : "") +
402 (createAppealTicket
403 ? ` and an appeal ticket was opened in <#${confirmation.components!["appeal"]!.response}>`
404 : "")
PineaFan5bea7e12023-01-05 21:20:04 +0000405 )
406 .setStatus(failed ? "Warning" : "Success")
407 ],
408 components: []
409 });
pineafan63fc5e22022-08-04 22:04:10 +0100410};
pineafan8b4b17f2022-02-27 20:42:52 +0000411
pineafan6de4da52023-03-07 20:43:44 +0000412const check = (interaction: CommandInteraction | ButtonInteraction, partial: boolean = false, target?: GuildMember) => {
PineaFana00db1b2023-01-02 15:32:54 +0000413 if (!interaction.guild) return;
Skyler Grey75ea9172022-08-06 10:22:23 +0100414 const member = interaction.member as GuildMember;
TheCodedProff86ba092023-01-27 17:10:07 -0500415 // Check if the user has moderate_members permission
416 if (!member.permissions.has("ModerateMembers")) return "You do not have the *Moderate Members* permission";
417 if (partial) return true;
PineaFan5bea7e12023-01-05 21:20:04 +0000418 const me = interaction.guild.members.me!;
pineafan6de4da52023-03-07 20:43:44 +0000419 let apply;
420 if (interaction.isButton()) {
421 apply = target!;
422 } else {
423 apply = interaction.options.getMember("user") as GuildMember;
424 }
pineafan62ce1922022-08-25 20:34:45 +0100425 const memberPos = member.roles.cache.size > 1 ? member.roles.highest.position : 0;
426 const mePos = me.roles.cache.size > 1 ? me.roles.highest.position : 0;
427 const applyPos = apply.roles.cache.size > 1 ? apply.roles.highest.position : 0;
pineafanc1c18792022-08-03 21:41:36 +0100428 // Do not allow muting the owner
PineaFan0d06edc2023-01-17 22:10:31 +0000429 if (member.id === interaction.guild.ownerId) return "You cannot mute the owner of the server";
pineafan8b4b17f2022-02-27 20:42:52 +0000430 // Check if Nucleus can mute the member
TheCodedProf0941da42023-02-18 20:28:04 -0500431 if (!(mePos > applyPos)) return `I do not have a role higher than <@${apply.id}>`;
pineafan8b4b17f2022-02-27 20:42:52 +0000432 // Check if Nucleus has permission to mute
PineaFan0d06edc2023-01-17 22:10:31 +0000433 if (!me.permissions.has("ModerateMembers")) return "I do not have the *Moderate Members* permission";
pineafan8b4b17f2022-02-27 20:42:52 +0000434 // Do not allow muting Nucleus
PineaFan0d06edc2023-01-17 22:10:31 +0000435 if (member.id === me.id) return "I cannot mute myself";
pineafan8b4b17f2022-02-27 20:42:52 +0000436 // Allow the owner to mute anyone
PineaFana00db1b2023-01-02 15:32:54 +0000437 if (member.id === interaction.guild.ownerId) return true;
pineafan8b4b17f2022-02-27 20:42:52 +0000438 // Check if the user is below on the role list
TheCodedProf0941da42023-02-18 20:28:04 -0500439 if (!(memberPos > applyPos)) return `You do not have a role higher than <@${apply.id}>`;
pineafan8b4b17f2022-02-27 20:42:52 +0000440 // Allow mute
pineafan63fc5e22022-08-04 22:04:10 +0100441 return true;
442};
pineafan8b4b17f2022-02-27 20:42:52 +0000443
Skyler Grey75ea9172022-08-06 10:22:23 +0100444export { command, callback, check };
TheCodedProfa112f612023-01-28 18:06:45 -0500445export const metadata = {
Skyler Greyda16adf2023-03-05 10:22:12 +0000446 longDescription:
447 "Stops a member from being able to send messages or join voice channels for a specified amount of time.",
448 premiumOnly: true
449};