aboutsummaryrefslogtreecommitdiff
path: root/src/commands/moderation/BanCommand.ts
blob: 300101ba07eb1e1d68e7a8ce327a0f2a236bf161 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { User } from 'discord.js';
import { BotCommand } from '../../lib/extensions/BotCommand';
import { BotMessage } from '../../lib/extensions/BotMessage';
import { Ban, Modlog, ModlogType } from '../../lib/types/Models';
import moment from 'moment';

const durationAliases: Record<string, string[]> = {
	weeks: ['w', 'weeks', 'week', 'wk', 'wks'],
	days: ['d', 'days', 'day'],
	hours: ['h', 'hours', 'hour', 'hr', 'hrs'],
	minutes: ['m', 'min', 'mins', 'minutes', 'minute'],
	months: ['mo', 'month', 'months']
};
const durationRegex = /(?:(\d+)(d(?:ays?)?|h(?:ours?|rs?)?|m(?:inutes?|ins?)?|mo(?:nths?)?|w(?:eeks?|ks?)?)(?: |$))/g;

export default class PrefixCommand extends BotCommand {
	constructor() {
		super('ban', {
			aliases: ['ban'],
			args: [
				{
					id: 'user',
					type: 'user',
					prompt: {
						start: 'What user would you like to ban?',
						retry: 'Invalid response. What user would you like to ban?'
					}
				},
				{
					id: 'reason'
				},
				{
					id: 'time',
					match: 'option',
					flag: '--time'
				}
			],
			clientPermissions: ['BAN_MEMBERS'],
			userPermissions: ['BAN_MEMBERS']
		});
	}
	async exec(
		message: BotMessage,
		{ user, reason, time }: { user: User; reason?: string; time?: string }
	): Promise<void> {
		const duration = moment.duration();
		let modlogEnry: Modlog;
		let banEntry: Ban;
		const translatedTime: string[] = [];
		try {
			try {
				if (time) {
					const parsed = [...time.matchAll(durationRegex)];
					if (parsed.length < 1) {
						await message.util.send('Invalid time.');
						return;
					}
					for (const part of parsed) {
						const translated = Object.keys(durationAliases).find((k) =>
							durationAliases[k].includes(part[2])
						);
						translatedTime.push(part[1] + ' ' + translated);
						duration.add(
							Number(part[1]),
							translated as 'weeks' | 'days' | 'hours' | 'months' | 'minutes'
						);
					}
					modlogEnry = Modlog.build({
						user: user.id,
						guild: message.guild.id,
						reason,
						type: ModlogType.TEMPBAN,
						duration: duration.asMilliseconds(),
						moderator: message.author.id
					});
					banEntry = Ban.build({
						user: user.id,
						guild: message.guild.id,
						reason,
						expires: new Date(new Date().getTime() + duration.asMilliseconds()),
						modlog: modlogEnry.id
					});
				} else {
					modlogEnry = Modlog.build({
						user: user.id,
						guild: message.guild.id,
						reason,
						type: ModlogType.BAN,
						moderator: message.author.id
					});
					banEntry = Ban.build({
						user: user.id,
						guild: message.guild.id,
						reason,
						modlog: modlogEnry.id
					});
				}
				await modlogEnry.save();
				await banEntry.save();
			} catch (e) {
				console.error(e);
				await message.util.send(
					'Error saving to database. Please report this to a developer.'
				);
				return;
			}
			try {
				await user.send(
					`You were banned in ${message.guild.name} ${
						translatedTime.length >= 1
							? `for ${translatedTime.join(', ')}`
							: 'permanently'
					} with reason \`${reason || 'No reason given'}\``
				);
			} catch (e) {
				await message.channel.send('Error sending message to user');
			}
			await message.guild.members.ban(user, {
				reason: `Banned by ${message.author.tag} with ${
					reason ? `reason ${reason}` : 'no reason'
				}`
			});
			await message.util.send(
				`Banned <@!${user.id}> ${
					translatedTime.length >= 1
						? `for ${translatedTime.join(', ')}`
						: 'permanently'
				} with reason \`${reason || 'No reason given'}\``
			);
		} catch {
			await message.util.send('Error banning :/');
			await modlogEnry.destroy();
			await banEntry.destroy();
			return;
		}
	}
}