Shasha/cmds/moderation/mute.js
2021-07-21 11:28:21 +07:00

185 lines
No EOL
9.5 KiB
JavaScript

'use strict';
const commando = require("@iceprod/discord.js-commando");
const { trySend, findMemberRegEx, cleanMentionID, findChannelRegEx, findRoleRegEx, defaultImageEmbed, parseDoubleDash, parseComa, getRole, defaultEventLogEmbed } = require("../../resources/functions");
const { database } = require("../../database/mongo");
const col = database.collection("Guild");
const schedule = database.collection("Schedule");
const { scheduler } = require("../../resources/scheduler");
const { DateTime, Settings, Interval } = require("luxon");
const muteSetting = require("./src/muteSetting");
const fn = require("./src/duration");
const durationFn = fn.duration;
const targetUser = require("./src/targetUser");
const configureMuteRole = require("./src/configureMuteRole");
const { makeJSONMessage } = require("../../resources/debug");
Settings.defaultZone = "utc";
/*{
footer: {
text: undefined,
icon: undefined
},
timestamp: false
};
{
mute: {
role: undefined,
duration: {
date: undefined,
string: undefined
},
log: undefined,
publicLog: undefined
},
ban: {
duration: {
date: undefined,
string: undefined
},
log: undefined,
publicLog: undefined
},
kick: {
log: undefined,
publicLog: undefined
}
}
*/
module.exports = class mute extends commando.Command {
constructor(client) {
super(client, {
name: "mute",
memberName: "mute",
group: "moderation",
description: "Mute.",
details: `Run \`${client.commandPrefix}mute --s -r role_[name|ID|mention] -d [duration]\` to set up a mute role.\n` +
`Or if you're too lazy you can run \`${client.commandPrefix}mute --cmr -n [name] -c color_[name|hex|number]\` to make a new mute role and let me set it up for you. ` +
`You can view server as the newly created mute role and override my default settings later.\n` +
`Example:\`\`\`\n--s -r muted -d 69y420mo36w49d69h4m420s\n` +
`--s -r none -d 0\n--cmr -n Muted -c black\`\`\``,
guildOnly: true,
userPermissions: ['MANAGE_ROLES'],
clientPermissions: ['MANAGE_ROLES']
});
}
/**
* @param {commando.CommandoMessage} msg
* @param {*} arg
* @returns
*/
async run(msg, arg) {
msg.channel.startTyping();
if (!msg.guild.DB) await msg.guild.dbLoad();
const MOD = msg.guild.DB.moderation.settings,
MUTE = MOD.mute || {},
args = parseDoubleDash(arg),
mentions = parseComa(args?.shift());
if (!MOD.mute) msg.guild.DB.moderation.settings.mute = {};
let reason = "No reason provided", duration = {}, resultMsg = "", targetUsers = [];
if (args?.[1]) {
for (const ARG of args) {
const U = ARG.slice(2).trim();
if (/^cmr(\s|$)/.test(ARG)) return configureMuteRole(msg, ARG.slice(3).trim());
if (/^s(\s|$)/.test(ARG)) return muteSetting(msg, U);
if (/^[\-\+]?\d{1,16}(?![^ymwdhs])[ymwdhs]?o?/i.test(ARG.trim())) {
duration = durationFn(msg.editedAt || msg.createdAt, ARG.trim());
} else if (!ARG || ARG === "--" || ARG.trim().length === 0) continue; else reason = ARG.trim();
}
} else if (!MUTE.role || !msg.guild.roles.cache.get(MUTE.role)) {
return trySend(this.client, msg, `No mute role configured!\n\n**[ADMINISTRATOR]**\nRun \`${msg.guild.commandPrefix + this.name} --s -r role_[name|ID|mention] -d [duration]\` to set it up.\n` +
`Or if you're too lazy you can run \`${msg.guild.commandPrefix + this.name} --cmr -n [name] -c color_[name|hex|number]\` to make a new mute role and let me set it up for you. ` +
`You can view server as the new mute role and override my default settings later.\n` +
`Example:\`\`\`\n--s -r muted -d 69y420mo36w49d69h4m420s\n` +
`--s -r none -d 0\n--cmr -n Muted -c black\`\`\``);
}
if (!duration.invoked) duration.invoked = DateTime.fromJSDate(msg.editedAt || msg.createdAt);
if (!duration.until && MUTE.defaultDuration?.duration) duration.until = duration.invoked.plus(MUTE.defaultDuration.duration.object);
if (duration.until?.invalid) duration.until = undefined; else if (duration.until && !duration.duration) {
duration.interval = Interval.fromDateTimes(duration.invoked, duration.until);
duration.duration = fn.intervalToDuration(duration.interval);
}
if (mentions?.length > 0) {
const FR = await targetUser(msg, mentions, targetUsers, resultMsg);
targetUsers = FR.targetUser;
resultMsg = FR.resultMsg;
} else return trySend(this.client, msg, "Args: `<[user_[mention|ID|name]]> -- [reason] -- [duration]`. Use `,` to provide multiple user. `--s` to view settings.\nExample:```js\n" + `${msg.guild.commandPrefix + this.name} 580703409934696449, @Shasha#1234, ur mom,#6969,^yuck\\s(ur)?\\s.{5}#\\d+69$--69y69mo69w420d420h420m420s -- Saying "joe"\`\`\``);
let infractionToDoc;
if (targetUsers.length > 0) {
let infractionCase = msg.guild.DB.moderation.infractions?.length,
muted = [], cant = [], already = [], infractionN = [];
infractionToDoc = {
infraction: infractionCase ? infractionCase++ : 1,
by: targetUsers,
moderator: msg.author,
punishment: "mute",
reason: reason,
msg: msg.toJSON()
}
for (const EXEC of targetUsers) {
try {
const RES = await EXEC.mute(msg.guild, { duration: duration, infraction: infractionToDoc.infraction, moderator: msg.member }, reason);
if (RES.infraction) infractionN.push(RES.infraction);
muted.push(EXEC.id);
} catch (e) {
if (/Missing Permissions|someone with higher position/.test(e.message)) cant.push(EXEC.id);
else if (/already muted/.test(e.message)) already.push(EXEC.id); else trySend(msg.client, msg, e.message); continue;
}
const emb = defaultEventLogEmbed(msg.guild);
emb.setTitle("You have been muted")
.setDescription("**Reason**\n" + reason)
.addField("At", duration.invoked.toFormat(fn.DT_PRINT_FORMAT), true)
.addField("For", duration.duration?.strings.join(" ") || "Indefinite", true)
.addField("Until", duration.until?.toFormat(fn.DT_PRINT_FORMAT) || "Never", true);
EXEC.createDM().then(r => trySend(msg.client, r, emb));
}
if (muted.length > 0) {
infractionToDoc.executed = muted;
infractionToDoc.aborted = already;
infractionToDoc.failed = cant;
msg.guild.addInfraction(infractionToDoc);
}
const NAME = msg.guild.id + "/" + infractionToDoc.infraction,
newUnmuteSchedule = {
name: NAME,
path: "./scheduler/unmute.js",
worker: {
argv: [NAME]
},
date: duration.until?.toJSDate()
};
let emb = defaultImageEmbed(msg, null, "Infraction #" + infractionToDoc.infraction);
if (cant.length > 0) emb.addField("Can't mute", "<@" + cant.join(">, <@") + ">\n\n**You can't mute someone with higher position than you <:nekokekLife:852865942530949160>**");
if (already.length > 0) emb.addField("Already muted", "<@" + already.join(">, <@") + ">\n\nDuration updated for these users");
let mutedStr = "", mutedArr = [];
if (muted.length > 0) for (const U of muted) {
const tU = "<@" + U + ">\n";
if ((mutedStr + tU).length < 1000) mutedStr += tU; else mutedArr.push(U);
}
if (mutedArr.length > 0) mutedStr += `and ${mutedArr.length} more...`;
emb.setDescription("**Reason**\n" + reason)
.addField("Muted", mutedStr || "`[NONE]`")
.addField("At", duration.invoked.toFormat(fn.DT_PRINT_FORMAT), true)
.addField("For", duration.duration?.strings.join(" ") || "Indefinite", true)
.addField("Until", duration.until?.toFormat(fn.DT_PRINT_FORMAT) || "Never", true)
.addField("Reason", reason);
return trySend(msg.client, msg, { content: resultMsg, embed: emb });
}
return trySend(msg.client, msg, resultMsg);
resultMsg += `Result:\`\`\`js\nUsers: ${targetUsers.map(r => r?.tag).join(", ")}\nReason: ${reason}\nAt: ${duration.invoked.toFormat("DDD',' cccc',' tt")}\nFor: ${duration.duration?.strings?.join(" ")}\nUntil: ${duration.until?.toFormat("DDD',' cccc',' tt")}\`\`\``;
return trySend(this.client, msg, { content: resultMsg + "```js\n" + JSON.stringify(infractionToDoc, null, 2) + "```", split: { maxLength: 2000, append: ",```", prepend: "```js\n", char: "," } });
}
};