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
|
import {
Arg,
BanResponse,
banResponse,
BotCommand,
clientSendAndPermCheck,
colors,
emojis,
overflowEmbed,
regex,
TanzaniteEvent,
type ArgType,
type CommandMessage,
type OptArgType,
type SlashMessage
} from '#lib';
import assert from 'assert/strict';
import { ApplicationCommandOptionType, Collection, PermissionFlagsBits } from 'discord.js';
export default class MassBanCommand extends BotCommand {
public constructor() {
super('massBan', {
aliases: ['mass-ban', 'mass-dban'],
category: 'moderation',
description: 'Ban multiple users at once.',
usage: ['mass-ban <...users> [--reason "<reason>"] [--days <days>]'],
examples: ['mass-ban 311294982898057217 792202575851814942 792199864510447666 792201010118131713 --reason "too many alts"'],
args: [
{
id: 'users',
description: 'The ids of users to ban.',
type: 'string',
match: 'rest',
prompt: 'What are the ids of all the users you would like to ban?',
retry: '{error} Choose a valid list of user ids to ban.',
slashType: ApplicationCommandOptionType.String
},
{
id: 'reason',
description: 'The reason for the bans.',
flag: ['--reason'],
match: 'option',
prompt: 'Why should these users be banned?',
retry: '{error} Choose a valid ban reason.',
optional: true,
slashType: ApplicationCommandOptionType.String
},
{
id: 'days',
description: 'The number of days of messages to delete when the user is banned, defaults to 0.',
flag: ['--days', '--delete'],
match: 'option',
prompt: "How many days of the user's messages would you like to delete?",
retry: '{error} Choose between 0 and 7 days to delete messages from the user for.',
type: Arg.range('integer', 0, 7, true),
optional: true,
slashType: ApplicationCommandOptionType.Integer,
choices: [...Array(8).keys()].map((v) => ({ name: v.toString(), value: v }))
}
],
quoted: true,
slash: true,
channel: 'guild',
clientPermissions: (m) => clientSendAndPermCheck(m),
userPermissions: [PermissionFlagsBits.BanMembers],
lock: 'user'
});
}
public override async exec(
message: CommandMessage | SlashMessage,
args: { users: ArgType<'string'>; reason: OptArgType<'string'>; days: OptArgType<'integer'> }
) {
assert(message.inGuild());
args.days ??= message.util.parsed?.alias?.includes('dban') ? 1 : 0;
const ids = args.users.split(/\n| /).filter((id) => id.length > 0);
if (ids.length === 0) return message.util.send(`${emojis.error} You must provide at least one user id.`);
for (const id of ids) {
if (!regex.snowflake.test(id)) return message.util.send(`${emojis.error} ${id} is not a valid snowflake.`);
}
if (!Number.isInteger(args.days) || args.days! < 0 || args.days! > 7) {
return message.util.reply(`${emojis.error} The delete days must be an integer between 0 and 7.`);
}
const promises = ids.map((id) =>
message.guild.massBanOne({
user: id,
moderator: message.author.id,
reason: `[MassBan] ${args.reason ? args.reason.trim() : 'No reason provided.'}`,
deleteDays: args.days ?? 0
})
);
const res = await Promise.all(promises);
const map = new Collection(res.map((r, i) => [ids[i], r]));
this.client.emit(
TanzaniteEvent.MassBan,
message.member!,
message.guild!,
args.reason ? args.reason.trim() : 'No reason provided.',
map
);
const success = (res: BanResponse): boolean => [banResponse.SUCCESS, banResponse.DM_ERROR].includes(res as any);
const lines = res.map((_, i) => {
const id = ids[i];
const status = res[i];
const isSuccess = success(status);
const emoji = isSuccess ? emojis.success : emojis.error;
return `${emoji} ${id}${isSuccess ? '' : ` - ${status}`}`;
});
const embeds = overflowEmbed(
{
color: colors.DarkRed,
title: 'Mass Ban Results'
},
lines
);
return message.util.send({ embeds });
}
}
|