125 lines
5.2 KiB
TypeScript
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;
|