AutoMod/bot/src/bot/commands/ban.ts
2022-01-22 20:21:57 +01:00

125 lines
5.2 KiB
TypeScript

import { ulid } from "ulid";
import { client } from "../../index";
import Infraction from "../../struct/antispam/Infraction";
import InfractionType from "../../struct/antispam/InfractionType";
import Command from "../../struct/Command";
import MessageCommandContext from "../../struct/MessageCommandContext";
import TempBan from "../../struct/TempBan";
import { fetchUsername, logModAction } from "../modules/mod_logs";
import { storeTempBan } from "../modules/tempbans";
import { isModerator, NO_MANAGER_MSG, parseUser, storeInfraction } from "../util";
import Day from 'dayjs';
import RelativeTime from 'dayjs/plugin/relativeTime';
Day.extend(RelativeTime);
export default {
name: 'ban',
aliases: null,
description: 'Ban a member from the server',
syntax: '/ban @username [10m|1h|...?] [reason?]',
removeEmptyArgs: true,
category: 'moderation',
run: async (message: MessageCommandContext, args: string[]) => {
if (!await isModerator(message))
return message.reply(NO_MANAGER_MSG);
if (args.length == 0)
return message.reply(`You need to provide a target user!`);
let targetUser = await parseUser(args.shift()!);
if (!targetUser) return message.reply('Sorry, I can\'t find that user.');
if (targetUser._id == message.author_id) {
return message.reply('nah');
}
if (targetUser._id == client.user!._id) {
return message.reply('lol no');
}
let banDuration = 0;
let durationStr = args.shift();
if (durationStr && /([0-9]{1,3}[smhdwy])+/g.test(durationStr)) {
let pieces = durationStr.match(/([0-9]{1,3}[smhdwy])/g) ?? [];
// Being able to specify the same letter multiple times
// (e.g. 1s1s) and having their values stack is a feature
for (const piece of pieces) {
let [ num, letter ] = [ Number(piece.slice(0, piece.length - 1)), piece.slice(piece.length - 1) ];
let multiplier = 0;
switch(letter) {
case 's': multiplier = 1000; break;
case 'm': multiplier = 1000 * 60; break;
case 'h': multiplier = 1000 * 60 * 60; break;
case 'd': multiplier = 1000 * 60 * 60 * 24; break;
case 'w': multiplier = 1000 * 60 * 60 * 24 * 7; break;
case 'y': multiplier = 1000 * 60 * 60 * 24 * 365; break;
}
banDuration += num * multiplier;
}
} else if (durationStr) args.splice(0, 0, durationStr);
let reason = args.join(' ') || 'No reason provided';
if (banDuration == 0) {
let infId = ulid();
let infraction: Infraction = {
_id: infId,
createdBy: message.author_id,
date: Date.now(),
reason: reason,
server: message.serverContext._id,
type: InfractionType.Manual,
user: targetUser._id,
actionType: 'ban',
}
let { userWarnCount } = await storeInfraction(infraction);
message.serverContext.banUser(targetUser._id, {
reason: reason + ` (by ${await fetchUsername(message.author_id)} ${message.author_id})`
})
.catch(e => message.reply(`Failed to ban user: \`${e}\``));
await Promise.all([
message.reply(`### @${targetUser.username} has been banned.\n`
+ `Infraction ID: \`${infId}\` (**#${userWarnCount}** for this user)`),
logModAction('ban', message.serverContext, message.member!, targetUser._id, reason, infraction, `Ban duration: **Permanent**`),
]);
} else {
let banUntil = Date.now() + banDuration;
let infId = ulid();
let infraction: Infraction = {
_id: infId,
createdBy: message.author_id,
date: Date.now(),
reason: reason + ` (${durationStr})`,
server: message.serverContext._id,
type: InfractionType.Manual,
user: targetUser._id,
actionType: 'ban',
}
let { userWarnCount } = await storeInfraction(infraction);
message.serverContext.banUser(targetUser._id, {
reason: reason + ` (by ${await fetchUsername(message.author_id)} ${message.author_id}) (${durationStr})`
})
.catch(e => message.reply(`Failed to ban user: \`${e}\``));
await storeTempBan({
id: infId,
bannedUser: targetUser._id,
server: message.serverContext._id,
until: banUntil,
} as TempBan);
await Promise.all([
message.reply(`### ${targetUser.username} has been temporarily banned.\n`
+ `Infraction ID: \`${infId}\` (**#${userWarnCount}** for this user)`),
logModAction('ban', message.serverContext, message.member!, targetUser._id, reason, infraction, `Ban duration: **${Day(banUntil).fromNow(true)}**`),
]);
}
}
} as Command;