AutoMod/src/bot/commands/warns.ts
2022-01-05 20:20:55 +01:00

133 lines
6.6 KiB
TypeScript

import Command from "../../struct/Command";
import { client } from "../..";
import Infraction from "../../struct/antispam/Infraction";
import InfractionType from "../../struct/antispam/InfractionType";
import { isModerator, NO_MANAGER_MSG, parseUserOrId, uploadFile } from "../util";
import Day from 'dayjs';
import RelativeTime from 'dayjs/plugin/relativeTime';
import Xlsx from 'xlsx';
import { fetchUsername } from "../modules/mod_logs";
import MessageCommandContext from "../../struct/MessageCommandContext";
Day.extend(RelativeTime);
export default {
name: 'warns',
aliases: [ 'warnings', 'infractions', 'infraction' ],
description: 'Show all user infractions',
syntax: '/warns; /warns @username ["export-csv"]; /warns rm [ID]',
category: 'moderation',
run: async (message: MessageCommandContext, args: string[]) => {
if (!await isModerator(message.member!, message.serverContext)) return message.reply(NO_MANAGER_MSG);
let collection = client.db.get('infractions');
let infractions: Array<Infraction> = await collection.find({
server: message.serverContext._id,
});
let userInfractions: Map<string, Infraction[]> = new Map();
infractions.forEach(i => {
if (!userInfractions.get(i.user)) userInfractions.set(i.user, [ i ]);
else userInfractions.set(i.user, [ i, ...userInfractions.get(i.user)! ]);
});
if (!args[0]) {
// Show top most warned users
let msg = `## Most warned users in ${message.serverContext.name}\n\u200b\n`;
for (let inf of Array.from(userInfractions.values()).sort((a, b) => b.length - a.length).slice(0, 9)) {
inf = inf.sort((a, b) => b.date - a.date);
msg += `**${await fetchUsername(inf[0].user)}** (${inf[0].user}): **${inf.length}** infractions\n`;
msg += `\u200b \u200b \u200b \u200b \u200b ↳ Most recent infraction: ${getInfEmoji(inf[0])}\`${inf[0].reason}\` `
+ `${inf[0].type == InfractionType.Manual ? `(${await fetchUsername(inf[0].createdBy ?? '')})` : ''}\n`;
};
message.reply(msg.substring(0, 1999));
} else {
switch(args[0]?.toLowerCase()) {
case 'delete':
case 'remove':
case 'rm':
case 'del':
let id = args[1];
if (!id) return message.reply('No infraction ID provided.');
let inf: Infraction|null = await client.db.get('infractions').findOneAndDelete({
_id: { $eq: id.toUpperCase() },
server: message.serverContext._id
});
if (!inf) return message.reply('I can\'t find that ID.');
message.reply(`## Infraction deleted\n`
+ `ID: \`${inf._id}\`\n`
+ `Reason: ${getInfEmoji(inf)}\`${inf.reason}\` `
+ `(${inf.type == InfractionType.Manual ? await fetchUsername(inf.createdBy ?? '') : 'System'})\n`
+ `Created ${Day(inf.date).fromNow()}`);
break;
default:
let user = await parseUserOrId(args[0]);
if (!user?._id) return message.reply('I can\'t find this user.');
let infs = userInfractions.get(user._id);
if (!infs) return message.reply(`There are no infractions stored for \`${await fetchUsername(user._id)}\`.`);
else {
let msg = `## ${infs.length} infractions stored for ${await fetchUsername(user._id)}\n\u200b\n`;
let attachSpreadsheet = false;
for (const i in infs) {
let inf = infs[i];
let toAdd = '';
toAdd += `#${Number(i)+1}: ${getInfEmoji(inf)} \`${inf.reason}\` (${inf.type == InfractionType.Manual ? await fetchUsername(inf.createdBy!) : 'System'})\n`;
toAdd += `\u200b \u200b \u200b \u200b \u200b ↳ ${Day(inf.date).fromNow()} (Infraction ID: \`${inf._id}\`)\n`;
if ((msg + toAdd).length > 1900 || Number(i) > 5) {
msg += `\u200b\n[${infs.length - Number(i) + 1} more, check attached file]`;
attachSpreadsheet = true;
break;
}
else msg += toAdd;
}
if (args[1]?.toLowerCase() == 'export-csv' ||
args[1]?.toLowerCase() == 'csv' ||
args[1]?.toLowerCase() == 'export') attachSpreadsheet = true;
if (attachSpreadsheet) {
try {
let csv_data = [
[`Warns for ${await fetchUsername(user._id)} (${user._id}) - ${Day().toString()}`],
[],
['Date', 'Reason', 'Created By', 'Type', 'Action Type', 'ID'],
];
for (const inf of infs) {
csv_data.push([
Day(inf.date).toString(),
inf.reason,
inf.type == InfractionType.Manual ? `${await fetchUsername(inf.createdBy!)} (${inf.createdBy})` : 'SYSTEM',
inf.type == InfractionType.Automatic ? 'Automatic' : 'Manual',
inf.actionType || 'warn',
inf._id,
]);
}
let sheet = Xlsx.utils.aoa_to_sheet(csv_data);
let csv = Xlsx.utils.sheet_to_csv(sheet);
message.reply({ content: msg, attachments: [ await uploadFile(csv, `${user._id}.csv`) ] });
} catch(e) {
console.error(e);
message.reply(msg);
}
} else message.reply(msg);
}
break;
}
}
}
} as Command;
function getInfEmoji(inf: Infraction) {
switch(inf.actionType) {
case 'kick': return ':mans_shoe: ';
case 'ban': return ':hammer: ';
default: return '';
}
}