/[sudobot]/trunk/src/automod/Logger.ts
ViewVC logotype

Contents of /trunk/src/automod/Logger.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 559 - (show annotations)
Mon Jul 29 17:30:49 2024 UTC (8 months, 1 week ago) by rakin
File MIME type: application/typescript
File size: 16905 byte(s)
feat(logging): show who banned a user
1 /**
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 { roleMention } from '@discordjs/builders';
21 import { formatDuration, intervalToDuration } from 'date-fns';
22 import { BanOptions, CommandInteraction, FileOptions, Guild, GuildBan, GuildMember, Message, MessageEmbed, MessageOptions, MessagePayload, TextChannel, User } from 'discord.js';
23 import ms from 'ms';
24 import DiscordClient from '../client/Client';
25 import { IPunishment } from '../models/Punishment';
26 import { timeSince } from '../utils/util';
27
28 class Logger {
29 client: DiscordClient;
30 pause = false;
31 pauseBan = false;
32
33 pauseAll(p = true) {
34 this.pause = p;
35 }
36
37 constructor(client: DiscordClient) {
38 this.client = client;
39 }
40
41 channel(callback: (channel: TextChannel) => any, msg: any) {
42 if (this.pause) {
43 return;
44 }
45
46 let channelID = this.client.config.props[msg.guild!.id].logging_channel;
47 let channel = msg.guild!.channels.cache.find((c: any) => c.id === channelID) as TextChannel;
48
49 if (channel) {
50 return callback(channel);
51 }
52 }
53
54 channelJoinLeft(callback: (channel: TextChannel) => any, msg: any) {
55 let channelID = this.client.config.props[msg.guild!.id].logging_channel_join_leave;
56 let channel = msg.guild!.channels.cache.find((c: any) => c.id === channelID) as TextChannel;
57
58 if (channel) {
59 return callback(channel);
60 }
61 }
62
63 async send(guild: Guild, messageOptions: MessageOptions | MessagePayload | string) {
64 let channelID = this.client.config.props[guild!.id].logging_channel;
65 let channel = guild!.channels.cache.find((c: any) => c.id === channelID) as TextChannel;
66
67 if (channel) {
68 return await channel.send(messageOptions);
69 }
70 }
71
72 log(guild: Guild, callback: (channel: TextChannel) => any) {
73 this.channel(callback, { guild });
74 }
75
76 logEdit(oldMsg: Message, newMsg: Message) {
77 this.channel(async (channel) => {
78 await channel.send({
79 embeds: [
80 new MessageEmbed()
81 .setColor('#007bff')
82 .setTitle('Message Edited in #' + (newMsg.channel as TextChannel).name + " (" + newMsg.channel.id + ")")
83 .setDescription('**-+-+Before**\n' + oldMsg.content + '\n\n**-+-+After**\n' + newMsg.content)
84 .addField('ID', newMsg.id)
85 .setAuthor({
86 name: newMsg.author.tag,
87 iconURL: newMsg.author.displayAvatarURL(),
88 })
89 .setFooter({
90 text: "Edited",
91 })
92 .setTimestamp()
93 ]
94 });
95 }, newMsg);
96 }
97
98 logDelete(msg: Message) {
99 this.channel(async (channel) => {
100 const embed = new MessageEmbed()
101 .setColor('#f14a60')
102 .setTitle('Message Deleted in #' + (msg.channel as TextChannel).name + " (" + msg.channel.id + ")")
103 .setDescription(msg.content)
104 .setAuthor({
105 name: msg.author.tag,
106 iconURL: msg.author.displayAvatarURL(),
107 })
108 .addField('ID', msg.id)
109 .setFooter({
110 text: "Deleted",
111 })
112 .setTimestamp();
113
114 const files: FileOptions[] = [];
115
116 if (msg.attachments.size > 0) {
117 let str = '';
118
119 msg.attachments.forEach(a => {
120 str += `${a.name}\n`;
121 files.push({
122 name: a.name!,
123 attachment: a.proxyURL
124 });
125 });
126
127 embed.addField('Attachments (top)', str);
128 }
129
130 await channel.send({
131 embeds: [
132 embed
133 ],
134 files
135 });
136 }, msg);
137 }
138
139 logBanned(ban: GuildBan) {
140 this.channel(async (channel) => {
141 let r = '*No reason provided*';
142
143 const auditLog = (await ban.guild.fetchAuditLogs({
144 limit: 1,
145 type: 'MEMBER_BAN_ADD',
146 })).entries.first();
147
148 if (ban.reason) {
149 r = ban.reason;
150 }
151 else if (auditLog) {
152 console.log(auditLog);
153 const { target, reason } = await auditLog;
154
155 if (target!.id === ban.user.id && reason) {
156 r = reason.replace(/^\[BAN\]/, '');
157 }
158
159 if (auditLog.executor?.id === this.client.user!.id || (r.startsWith("[TEMPBAN]") || r.startsWith("[SOFTBAN]"))) {
160 return;
161 }
162 }
163
164 await channel.send({
165 embeds: [
166 new MessageEmbed()
167 .setColor('#f14a60')
168 .setTitle("A user was banned")
169 .setAuthor({
170 name: ban.user.tag,
171 iconURL: ban.user.displayAvatarURL(),
172 })
173 .addField('Reason', r)
174 .addField('User ID', ban.user.id)
175 .addFields({
176 name: 'Banned by',
177 value: auditLog?.executor ? `${auditLog.executor.tag} (${auditLog.executor.id})` : 'Unknown'
178 })
179 .setFooter({
180 text: "Banned",
181 })
182 .setTimestamp()
183 ]
184 });
185 }, ban);
186 }
187
188 logSoftBan(banOptions: BanOptions, guild: Guild, user: User, model: IPunishment) {
189 this.channel(async (channel) => {
190 let r = '*No reason provided*';
191
192 const auditLog = (await guild.fetchAuditLogs({
193 limit: 1,
194 type: 'MEMBER_BAN_ADD',
195 })).entries.first();
196
197 if (banOptions.reason) {
198 r = banOptions.reason;
199 }
200 else if (auditLog) {
201 console.log(auditLog);
202 const { target, reason } = await auditLog;
203
204 if (target!.id === user.id && reason) {
205 r = reason.replace(/^\[SOFTBAN\]/, '');
206 }
207 }
208
209 await channel.send({
210 embeds: [
211 new MessageEmbed()
212 .setColor('#f14a60')
213 .setTitle("A user was softbanned")
214 .setAuthor({
215 name: user.tag,
216 iconURL: user.displayAvatarURL(),
217 })
218 .addField('Reason', r)
219 .addField('Softbanned by', model.mod_tag)
220 .addField('User ID', user.id)
221 .setFooter({
222 text: "Softbanned",
223 })
224 .setTimestamp()
225 ]
226 });
227 }, {
228 guild
229 });
230 }
231
232 logTempBan(banOptions: BanOptions, guild: Guild, user: User, model: IPunishment) {
233 this.channel(async (channel) => {
234 let r = '*No reason provided*';
235
236 const auditLog = (await guild.fetchAuditLogs({
237 limit: 1,
238 type: 'MEMBER_BAN_ADD',
239 })).entries.first();
240
241 if (banOptions.reason) {
242 r = banOptions.reason;
243 }
244 else if (auditLog) {
245 console.log(auditLog);
246 const { target, reason } = await auditLog;
247
248 if (target!.id === user.id && reason) {
249 r = reason.replace(/^\[TEMPBAN\]/, '');
250 }
251 }
252
253 await channel.send({
254 embeds: [
255 new MessageEmbed()
256 .setColor('#f14a60')
257 .setTitle("A user was temporarily banned")
258 .setAuthor({
259 name: user.tag,
260 iconURL: user.displayAvatarURL(),
261 })
262 .addField('Reason', r)
263 .addField('Banned by', model.mod_tag)
264 .addField('User ID', user.id)
265 .addField('Duration', ms((model.meta as any).time))
266 .setFooter({
267 text: "Temporarily banned",
268 })
269 .setTimestamp()
270 ]
271 });
272 }, {
273 guild
274 });
275 }
276
277 logUnbanned(ban: GuildBan) {
278 this.channel(async (channel) => {
279 await channel.send({
280 embeds: [
281 new MessageEmbed()
282 .setColor('#f14a60')
283 .setTitle("A user was unbanned")
284 .setAuthor({
285 name: ban.user.tag,
286 iconURL: ban.user.displayAvatarURL(),
287 })
288 .addField('User ID', ban.user.id)
289 .setFooter({
290 text: "Unbanned",
291 })
292 .setTimestamp()
293 ]
294 });
295 }, ban);
296 }
297
298 logJoined(member: GuildMember) {
299 this.channelJoinLeft(async (channel) => {
300 await channel.send({
301 embeds: [
302 new MessageEmbed()
303 .setColor('#007bff')
304 .setTitle("New member joined")
305 .setAuthor({
306 name: member.user.tag,
307 iconURL: member.user.displayAvatarURL(),
308 })
309 .setDescription(`<@${member.user.id}> just joined the server!`)
310 .addField('Account Created', `${member.user.createdAt.toLocaleString()} (${timeSince(member.user.createdAt.getTime())})`)
311 .addField('New Account?', (new Date().getTime() - member.user.createdAt.getTime()) <= 3 * 24 * 60 * 60 * 1000 ? ":warning: Yes :warning:" : "No")
312 .addField('Bot?', member.user.bot === true ? 'Yes' : 'No')
313 .addField('User ID', member.user.id)
314 .setFooter({
315 text: "Joined",
316 })
317 .setTimestamp()
318 ]
319 });
320 }, member);
321 }
322
323 logLeft(member: GuildMember) {
324 this.channelJoinLeft(async (channel) => {
325 const roles = await member.roles.cache.filter(role => role.id !== member.guild.id).reduce((acc, val) => ` ${acc} ${roleMention(val.id)}`, '');
326
327 await channel.send({
328 embeds: [
329 new MessageEmbed()
330 .setColor('#f14a60')
331 .setTitle("Member left")
332 .setAuthor({
333 name: member.user.tag,
334 iconURL: member.user.displayAvatarURL(),
335 })
336 .setDescription(`**Roles**\n${roles}`)
337 .addField('Joined at', `${member.joinedAt!.toLocaleString()} (${timeSince(member.joinedAt!.getTime())})`)
338 .addField('User ID', member.user.id)
339 .addField('Bot?', member.user.bot === true ? 'Yes' : 'No')
340 .setFooter({
341 text: "Left",
342 })
343 .setTimestamp()
344 ]
345 });
346 }, member);
347 }
348
349 logBeaned(member: GuildMember, r: string, d: User) {
350 this.channel(async (channel) => {
351 await channel.send({
352 embeds: [
353 new MessageEmbed()
354 .setColor('#007bff')
355 .setTitle("Member beaned")
356 .setAuthor({
357 name: member.user.tag,
358 iconURL: member.user.displayAvatarURL(),
359 })
360 .addField('Reason', r)
361 .addField('Beaned by', d.tag)
362 .addField('User ID', member.user.id)
363 .setFooter({
364 text: "Beaned",
365 })
366 .setTimestamp()
367 ]
368 });
369 }, member);
370 }
371
372 logMute(member: GuildMember, reason: string, duration: number | null | undefined, d: User, hard: boolean = true) {
373 this.channel(async (channel) => {
374 await channel.send({
375 embeds: [
376 new MessageEmbed()
377 .setColor('#f14a60')
378 .setTitle("Member muted")
379 .setAuthor({
380 name: member.user.tag,
381 iconURL: member.user.displayAvatarURL(),
382 })
383 .addField('Reason', reason)
384 .addField('Muted by', d.tag)
385 .addField('Duration Until', duration ? `${(new Date(Date.now() + duration)).toLocaleString()} (${formatDuration(intervalToDuration({ start: 0, end: duration }))})` : "*No duration set*")
386 .addField('User ID', member.user.id)
387 .addField('Hardmute', hard ? 'Yes' : 'No')
388 .setFooter({
389 text: "Muted",
390 })
391 .setTimestamp()
392 ]
393 });
394 }, member);
395 }
396
397 logUnmute(member: GuildMember, d: User) {
398 this.channel(async (channel) => {
399 await channel.send({
400 embeds: [
401 new MessageEmbed()
402 .setColor('#007bff')
403 .setTitle("Member unmuted")
404 .setAuthor({
405 name: member.user.tag,
406 iconURL: member.user.displayAvatarURL(),
407 })
408 .addField('Unmuted by', d.tag)
409 .addField('User ID', member.user.id)
410 .setFooter({
411 text: "Unmuted",
412 })
413 .setTimestamp()
414 ]
415 });
416 }, member);
417 }
418
419 logWarn(msg: Message | CommandInteraction, member: GuildMember | User, d: User, reason: string | undefined, id: number | string) {
420 if ((member as GuildMember).user)
421 member = (member as GuildMember).user;
422
423 this.channel(async (channel) => {
424 await channel.send({
425 embeds: [
426 new MessageEmbed()
427 .setColor('GOLD')
428 .setTitle("Member warned")
429 .setAuthor({
430 name: (member as User).tag,
431 iconURL: member.displayAvatarURL(),
432 })
433 .addField('Reason', reason ?? '*No reason provided*')
434 .addField('Warned by', d.tag)
435 .addField('User ID', member.id)
436 .addField('Case ID', id + '')
437 .setFooter({
438 text: "Warned",
439 })
440 .setTimestamp()
441 ]
442 });
443 }, msg);
444 }
445
446 logWarndel(msg: Message, member: GuildMember, warn: any, d: User) {
447 this.channel(async (channel) => {
448 await channel.send({
449 embeds: [
450 new MessageEmbed()
451 .setColor('GOLD')
452 .setTitle("Warning deleted")
453 .setAuthor({
454 name: member.user.tag,
455 iconURL: member.user.displayAvatarURL(),
456 })
457 .addField('Warned by', d.tag + '')
458 .addField('Warning ID', warn.id + '')
459 .addField('User ID', member.user.id)
460 .setFooter({
461 text: "Warning Deleted",
462 })
463 .setTimestamp()
464 ]
465 });
466 }, msg);
467 }
468 }
469
470 export default Logger;

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26