/[sudobot]/branches/4.x/src/commands/moderation/MuteCommand.ts
ViewVC logotype

Annotation of /branches/4.x/src/commands/moderation/MuteCommand.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (hide annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months, 1 week ago) by rakinar2
File MIME type: application/typescript
File size: 11814 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 rakinar2 577 /**
2     * This file is part of SudoBot.
3     *
4     * Copyright (C) 2021-2022 OSN Inc.
5     *
6     * SudoBot is free software; you can redistribute it and/or modify it
7     * under the terms of the GNU Affero General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * SudoBot is distributed in the hope that it will be useful, but
12     * WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU Affero General Public License for more details.
15     *
16     * You should have received a copy of the GNU Affero General Public License
17     * along with SudoBot. If not, see <https://www.gnu.org/licenses/>.
18     */
19    
20     import { CommandInteraction, Guild, GuildMember, Message, Permissions, User } from 'discord.js';
21     import BaseCommand from '../../utils/structures/BaseCommand';
22     import DiscordClient from '../../client/Client';
23     import CommandOptions from '../../types/CommandOptions';
24     import InteractionOptions from '../../types/InteractionOptions';
25     import MessageEmbed from '../../client/MessageEmbed';
26     import getMember from '../../utils/getMember';
27     import ms from 'ms';
28     import PunishmentType from '../../types/PunishmentType';
29     import { generateInfractionDescription, hasPermission, shouldNotModerate } from '../../utils/util';
30     import UnmuteQueue from '../../queues/UnmuteQueue';
31     import { formatDistanceToNowStrict } from 'date-fns';
32    
33     export async function mute(client: DiscordClient, dateTime: number | undefined, user: GuildMember, msg: Message | CommandInteraction | { guild: Guild, member: GuildMember, editReply?: undefined }, timeInterval: number | undefined, reason: string | undefined, hard: boolean = false, mod?: User) {
34     try {
35     const { default: Punishment } = await import('../../models/Punishment');
36    
37     const { getTimeouts, clearTimeoutv2 } = await import('../../utils/setTimeout');
38    
39     const timeouts = getTimeouts();
40    
41     for (const timeout of timeouts.values()) {
42     if (timeout.row.params) {
43     try {
44     const json = JSON.parse(timeout.row.params);
45    
46     if (json) {
47     if (json[1] === user.id && timeout.row.filePath.endsWith('unmute-job')) {
48     await clearTimeoutv2(timeout);
49     }
50     }
51     }
52     catch (e) {
53     console.log(e);
54     }
55     }
56     }
57    
58     if (dateTime && timeInterval) {
59     // await setTimeoutv2('unmute-job', timeInterval, msg.guild!.id, `unmute ${user.id}`, msg.guild!.id, user.id);
60     for await (const queue of client.queueManager.queues.values()) {
61     if (queue instanceof UnmuteQueue && queue.data!.memberID === user.id && queue.data!.guildID === msg.guild!.id) {
62     await queue.cancel();
63     }
64     }
65    
66     await client.queueManager.addQueue(UnmuteQueue, {
67     data: {
68     guildID: msg.guild!.id,
69     memberID: user.id
70     },
71     runAt: new Date(Date.now() + timeInterval),
72     guild: msg.guild!.id
73     });
74     }
75    
76     if (hard) {
77     const { default: Hardmute } = await import("../../models/Hardmute");
78     const roles = await user.roles.cache.filter(r => r.id !== msg.guild!.id);
79     await user.roles.remove(roles, reason);
80    
81     await Hardmute.create({
82     user_id: user.id,
83     roles: roles.map(role => role.id),
84     guild_id: msg.guild!.id,
85     createdAt: new Date()
86     });
87     }
88    
89     const role = await msg.guild!.roles.fetch(client.config.props[msg.guild!.id].mute_role);
90     await user.roles.add(role!, reason);
91    
92     const { numericId: id } = await Punishment.create({
93     type: hard ? PunishmentType.HARDMUTE : PunishmentType.MUTE,
94     user_id: user.id,
95     guild_id: msg.guild!.id,
96     mod_id: (mod ?? msg.member!.user).id,
97     mod_tag: ((mod ?? msg.member!.user) as User).tag,
98     reason,
99     meta: {
100     time: timeInterval ? ms(timeInterval) : undefined
101     },
102     createdAt: new Date()
103     });
104    
105     await client.logger.onMemberMute(user, timeInterval, reason === undefined || reason.trim() === '' ? "*No reason provided*" : reason, (mod ?? msg.member!.user) as User, hard, id!.toString());
106    
107     try {
108     await user.send({
109     embeds: [
110     new MessageEmbed({
111     description: generateInfractionDescription(client, msg.guild!.id, 'mute_message')
112     })
113     .setAuthor({
114     iconURL: <string> msg.guild!.iconURL(),
115     name: `\tYou have been muted in ${msg.guild!.name}`
116     })
117     .setColor('#f14a60')
118     .addField("Reason", reason === undefined || reason.trim() === '' ? "*No reason provided*" : reason)
119     .addFields({
120     name: 'Duration',
121     value: `${timeInterval ? `${formatDistanceToNowStrict(new Date(Date.now() + timeInterval))}` : '*No duration specified*'}`
122     })
123     .addFields({
124     name: 'Infraction ID',
125     value: id?.toString() ?? '*Unavailable*'
126     })
127     ]
128     });
129     }
130     catch (e) {
131     console.log(e);
132     }
133     }
134     catch (e) {
135     console.log(e);
136    
137     if (msg instanceof Message)
138     await msg.reply({
139     embeds: [
140     new MessageEmbed()
141     .setColor('#f14a60')
142     .setDescription("Failed to assign the muted role to this user. Maybe missing permisions/roles or I'm not allowed to assign roles this user?")
143     ]
144     });
145     else if (msg.editReply)
146     await msg.editReply({
147     embeds: [
148     new MessageEmbed()
149     .setColor('#f14a60')
150     .setDescription("Failed to assign the muted role to this user. Maybe missing permisions/roles or I'm not allowed to assign roles this user?")
151     ]
152     });
153    
154     return;
155     }
156     }
157    
158     export default class MuteCommand extends BaseCommand {
159     supportsInteractions: boolean = true;
160     permissions = [Permissions.FLAGS.MODERATE_MEMBERS];
161    
162     constructor() {
163     super('mute', 'moderation', []);
164     }
165    
166     async run(client: DiscordClient, msg: Message | CommandInteraction, options: CommandOptions | InteractionOptions) {
167     if (!options.isInteraction && typeof options.args[0] === 'undefined') {
168     await msg.reply({
169     embeds: [
170     new MessageEmbed()
171     .setColor('#f14a60')
172     .setDescription(`This command requires at least one argument.`)
173     ]
174     });
175    
176     return;
177     }
178    
179     if (msg instanceof CommandInteraction)
180     await msg.deferReply();
181    
182     let user: GuildMember;
183     let reason: string | undefined;
184     let time: string | undefined;
185     let timeInterval: number | undefined;
186     let dateTime: number | undefined;
187     let hard: boolean = false;
188    
189     if (options.isInteraction) {
190     user = await <GuildMember> options.options.getMember('member');
191    
192     if (options.options.getString('reason')) {
193     reason = await <string> options.options.getString('reason');
194     }
195    
196     if (options.options.getBoolean('hardmute')) {
197     hard = await <boolean> options.options.getBoolean('hardmute');
198     }
199    
200     if (options.options.getString('time')) {
201     time = await options.options.getString('time') as string;
202     timeInterval = await ms(time);
203    
204     if (!timeInterval) {
205     await this.deferReply(msg, {
206     embeds: [
207     new MessageEmbed()
208     .setColor('#f14a60')
209     .setDescription(`Option \`-t\` (time) requires an argument which must be a valid time interval.`)
210     ]
211     });
212    
213     return;
214     }
215     }
216     }
217     else {
218     const user2 = await getMember((msg as Message), options);
219    
220     if (!user2) {
221     await this.deferReply(msg, {
222     embeds: [
223     new MessageEmbed()
224     .setColor('#f14a60')
225     .setDescription(`Invalid user given.`)
226     ]
227     });
228    
229     return;
230     }
231    
232     user = user2;
233    
234     const index = await options.args.indexOf('-t');
235    
236     if (options.args[1]) {
237     const args = [...options.args];
238     args.shift();
239    
240     if (index !== -1) {
241     args.splice(index - 1, 2);
242     }
243    
244     reason = await args.join(' ');
245     }
246    
247     if (index !== -1) {
248     time = await options.args[index + 1];
249    
250     if (time === undefined) {
251     await this.deferReply(msg, {
252     embeds: [
253     new MessageEmbed()
254     .setColor('#f14a60')
255     .setDescription(`Option \`-t\` (time) requires an argument.`)
256     ]
257     });
258    
259     return;
260     }
261    
262     if (!ms(time)) {
263     await this.deferReply(msg, {
264     embeds: [
265     new MessageEmbed()
266     .setColor('#f14a60')
267     .setDescription(`Option \`-t\` (time) requires an argument which must be a valid time interval.`)
268     ]
269     });
270    
271     return;
272     }
273    
274     timeInterval = await ms(time);
275     }
276     }
277    
278     if (timeInterval) {
279     dateTime = Date.now() + timeInterval;
280     }
281    
282     if (!(await hasPermission(client, user, msg, null, "You don't have permission to mute this user."))) {
283     return;
284     }
285    
286     if (shouldNotModerate(client, user)) {
287     await msg.reply({
288     embeds: [
289     {
290     description: "This user cannot be muted."
291     }
292     ]
293     });
294    
295     return;
296     }
297    
298     await mute(client, dateTime, user, msg, timeInterval, reason, hard);
299    
300     const fields = [
301     {
302     name: "Muted by",
303     value: (msg.member!.user as User).tag
304     },
305     {
306     name: "Reason",
307     value: reason === undefined || reason.trim() === '' ? "*No reason provided*" : reason
308     },
309     {
310     name: "Duration",
311     value: time === undefined ? "*No duration set*" : (time + '')
312     },
313     {
314     name: "Role Takeout",
315     value: hard ? 'Yes' : 'No'
316     }
317     ];
318    
319     console.log(fields);
320    
321     await this.deferReply(msg, {
322     embeds: [
323     new MessageEmbed()
324     .setAuthor({
325     name: user.user.tag,
326     iconURL: user.displayAvatarURL(),
327     })
328     .setDescription(user.user.tag + " has been muted.")
329     .addFields(fields)
330     ]
331     });
332     }
333     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26