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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/src/Logger.js revision 25 by rakin, Mon Jul 29 17:28:16 2024 UTC trunk/src/automod/Logger.ts revision 559 by rakin, Mon Jul 29 17:30:49 2024 UTC
# Line 1  Line 1 
1  const { MessageEmbed } = require('discord.js');  /**
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 {  class Logger {
29      constructor() {      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, msg) {      channel(callback: (channel: TextChannel) => any, msg: any) {
42          let channelID = app.config.props[msg.guild.id].logging_channel;          if (this.pause) {
43          let channel = msg.guild.channels.cache.find(c => c.id === channelID);              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) {          if (channel) {
50              return callback(channel);              return callback(channel);
51          }          }
52      }      }
53    
54      logEdit(oldMsg, newMsg) {      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) => {          this.channel(async (channel) => {
78              await channel.send({              await channel.send({
79                  embeds: [                  embeds: [
80                      new MessageEmbed()                      new MessageEmbed()
81                      .setColor('#007bff')                      .setColor('#007bff')
82                      .setTitle('Message Edited in #' + newMsg.channel.name + " (" + newMsg.channel.id + ")")                      .setTitle('Message Edited in #' + (newMsg.channel as TextChannel).name + " (" + newMsg.channel.id + ")")
83                      .setDescription('**-+-+Before**\n' + oldMsg.content + '\n\n**-+-+After**\n' + newMsg.content)                      .setDescription('**-+-+Before**\n' + oldMsg.content + '\n\n**-+-+After**\n' + newMsg.content)
84                      .addField('ID', newMsg.id)                      .addField('ID', newMsg.id)
85                      .setAuthor({                      .setAuthor({
# Line 36  class Logger { Line 95  class Logger {
95          }, newMsg);          }, newMsg);
96      }      }
97    
98      logDelete(msg) {      logDelete(msg: Message) {
99          this.channel(async (channel) => {          this.channel(async (channel) => {
100              const embed = new MessageEmbed()              const embed = new MessageEmbed()
101                  .setColor('#f14a60')                  .setColor('#f14a60')
102                  .setTitle('Message Deleted in #' + msg.channel.name + " (" + msg.channel.id + ")")                  .setTitle('Message Deleted in #' + (msg.channel as TextChannel).name + " (" + msg.channel.id + ")")
103                  .setDescription(msg.content)                  .setDescription(msg.content)
104                  .setAuthor({                  .setAuthor({
105                      name: msg.author.tag,                      name: msg.author.tag,
# Line 51  class Logger { Line 110  class Logger {
110                      text: "Deleted",                      text: "Deleted",
111                  })                  })
112                  .setTimestamp();                  .setTimestamp();
113                
114                const files: FileOptions[] = [];
115    
116              if (msg.attachments.size > 0) {              if (msg.attachments.size > 0) {
117                  let str = '';                  let str = '';
118    
119                  msg.attachments.forEach(a => {                  msg.attachments.forEach(a => {
120                      str += `**${a.name}** ${a.proxyURL}\n`;                      str += `${a.name}\n`;
121                        files.push({
122                            name: a.name!,
123                            attachment: a.proxyURL
124                        });
125                  });                  });
126    
127                  embed.addField('Attachments', str);                  embed.addField('Attachments (top)', str);
128              }              }
129    
130              await channel.send({              await channel.send({
131                  embeds: [                  embeds: [
132                      embed                      embed
133                  ]                  ],
134                    files
135              });              });
136          }, msg);          }, msg);
137      }      }
138    
139      logBanned(ban) {      logBanned(ban: GuildBan) {
140          this.channel(async (channel) => {          this.channel(async (channel) => {
141              let r = '*No reason provided*';              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) {              if (ban.reason) {
149                  r = ban.reason;                  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({              await channel.send({
165                  embeds: [                  embeds: [
# Line 89  class Logger { Line 172  class Logger {
172                      })                      })
173                      .addField('Reason', r)                      .addField('Reason', r)
174                      .addField('User ID', ban.user.id)                      .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({                      .setFooter({
180                          text: "Banned",                          text: "Banned",
181                      })                      })
# Line 98  class Logger { Line 185  class Logger {
185          }, ban);          }, ban);
186      }      }
187    
188      logUnbanned(ban) {      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) => {          this.channel(async (channel) => {
279              await channel.send({              await channel.send({
280                  embeds: [                  embeds: [
# Line 119  class Logger { Line 295  class Logger {
295          }, ban);          }, ban);
296      }      }
297    
298      logJoined(member) {      logJoined(member: GuildMember) {
299          this.channel(async (channel) => {          this.channelJoinLeft(async (channel) => {
300              await channel.send({              await channel.send({
301                  embeds: [                  embeds: [
302                      new MessageEmbed()                      new MessageEmbed()
# Line 131  class Logger { Line 307  class Logger {
307                          iconURL: member.user.displayAvatarURL(),                          iconURL: member.user.displayAvatarURL(),
308                      })                      })
309                      .setDescription(`<@${member.user.id}> just joined the server!`)                      .setDescription(`<@${member.user.id}> just joined the server!`)
310                      .addField('Account Created', member.user.createdAt.toLocaleString())                      .addField('Account Created', `${member.user.createdAt.toLocaleString()} (${timeSince(member.user.createdAt.getTime())})`)
311                      .addField('New Account?', (new Date().getTime() - member.user.createdAt.getTime()) <= 24 * 60 * 60 * 1000 ? ":warning: Yes :warning:" : "No")                      .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)                      .addField('User ID', member.user.id)
314                      .setFooter({                      .setFooter({
315                          text: "Joined",                          text: "Joined",
# Line 143  class Logger { Line 320  class Logger {
320          }, member);          }, member);
321      }      }
322    
323      logLeft(member) {      logLeft(member: GuildMember) {
324          this.channel(async (channel) => {          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({              await channel.send({
328                  embeds: [                  embeds: [
329                      new MessageEmbed()                      new MessageEmbed()
# Line 154  class Logger { Line 333  class Logger {
333                          name: member.user.tag,                          name: member.user.tag,
334                          iconURL: member.user.displayAvatarURL(),                          iconURL: member.user.displayAvatarURL(),
335                      })                      })
336                      .addField('Joined at', member.joinedAt.toLocaleString())                      .setDescription(`**Roles**\n${roles}`)
337                        .addField('Joined at', `${member.joinedAt!.toLocaleString()} (${timeSince(member.joinedAt!.getTime())})`)
338                      .addField('User ID', member.user.id)                      .addField('User ID', member.user.id)
339                        .addField('Bot?', member.user.bot === true ? 'Yes' : 'No')
340                      .setFooter({                      .setFooter({
341                          text: "Left",                          text: "Left",
342                      })                      })
# Line 165  class Logger { Line 346  class Logger {
346          }, member);          }, member);
347      }      }
348    
349      logBeaned(member, r, d) {      logBeaned(member: GuildMember, r: string, d: User) {
350          this.channel(async (channel) => {          this.channel(async (channel) => {
351              await channel.send({              await channel.send({
352                  embeds: [                  embeds: [
# Line 188  class Logger { Line 369  class Logger {
369          }, member);          }, member);
370      }      }
371    
372      logMute(member, reason, timeMs, d) {      logMute(member: GuildMember, reason: string, duration: number | null | undefined, d: User, hard: boolean = true) {
373          this.channel(async (channel) => {          this.channel(async (channel) => {
374              await channel.send({              await channel.send({
375                  embeds: [                  embeds: [
# Line 201  class Logger { Line 382  class Logger {
382                      })                      })
383                      .addField('Reason', reason)                      .addField('Reason', reason)
384                      .addField('Muted by', d.tag)                      .addField('Muted by', d.tag)
385                      .addField('Duration Until', typeof timeMs === 'number' ? new Date((timeMs / 1000) + Date.now()).toLocaleString() : "*No duration set*")                      .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)                      .addField('User ID', member.user.id)
387                        .addField('Hardmute', hard ? 'Yes' : 'No')
388                      .setFooter({                      .setFooter({
389                          text: "Muted",                          text: "Muted",
390                      })                      })
# Line 212  class Logger { Line 394  class Logger {
394          }, member);          }, member);
395      }      }
396    
397      logUnmute(member, d) {      logUnmute(member: GuildMember, d: User) {
398          this.channel(async (channel) => {          this.channel(async (channel) => {
399              await channel.send({              await channel.send({
400                  embeds: [                  embeds: [
# Line 234  class Logger { Line 416  class Logger {
416          }, member);          }, member);
417      }      }
418    
419      logWarn(msg, member, d, reason) {      logWarn(msg: Message | CommandInteraction, member: GuildMember | User, d: User, reason: string | undefined, id: number | string) {
420          if (member.user)          if ((member as GuildMember).user)
421              member = member.user;              member = (member as GuildMember).user;
422    
423          this.channel(async (channel) => {          this.channel(async (channel) => {            
424              await channel.send({              await channel.send({
425                  embeds: [                  embeds: [
426                      new MessageEmbed()                      new MessageEmbed()
427                      .setColor('GOLD')                      .setColor('GOLD')
428                      .setTitle("Member warned")                      .setTitle("Member warned")
429                      .setAuthor({                      .setAuthor({
430                          name: member.tag,                          name: (member as User).tag,
431                          iconURL: member.displayAvatarURL(),                          iconURL: member.displayAvatarURL(),
432                      })                      })
433                      .addField('Reason', reason)                      .addField('Reason', reason ?? '*No reason provided*')
434                      .addField('Warned by', d.tag)                      .addField('Warned by', d.tag)
435                      .addField('User ID', member.id)                      .addField('User ID', member.id)
436                        .addField('Case ID', id + '')
437                      .setFooter({                      .setFooter({
438                          text: "Warned",                          text: "Warned",
439                      })                      })
# Line 260  class Logger { Line 443  class Logger {
443          }, msg);          }, msg);
444      }      }
445    
446      logWarndel(msg, member, warn, d) {      logWarndel(msg: Message, member: GuildMember, warn: any, d: User) {
447          this.channel(async (channel) => {          this.channel(async (channel) => {
448              await channel.send({              await channel.send({
449                  embeds: [                  embeds: [
# Line 284  class Logger { Line 467  class Logger {
467      }      }
468  }  }
469    
 module.exports = Logger;  
470    export default Logger;

Legend:
Removed from v.25  
changed lines
  Added in v.559

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26