/[sudobot]/branches/4.x/src/automod/Logger.ts
ViewVC logotype

Contents of /branches/4.x/src/automod/Logger.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (show annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 40859 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
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 { formatDistanceStrict, formatDistanceToNowStrict, formatDuration, intervalToDuration } from "date-fns";
22 import {
23 Message,
24 MessageEmbedOptions,
25 MessageEmbed as MessageEmbedDiscord,
26 TextChannel,
27 MessageActionRow,
28 MessageButton,
29 FileOptions,
30 GuildBan,
31 BanOptions,
32 Guild,
33 User,
34 GuildMember,
35 Util,
36 GuildChannel,
37 Role,
38 Collection,
39 } from "discord.js";
40 import ms from "ms";
41 import BaseMessageEmbed from "../client/MessageEmbed";
42 import { IGuildInfo } from "../models/GuildInfo";
43 import Punishment, { IPunishment } from "../models/Punishment";
44 import PunishmentType from "../types/PunishmentType";
45 import Service from "../utils/structures/Service";
46 import { timeSince } from "../utils/util";
47
48 class MessageEmbed extends BaseMessageEmbed {
49 constructor(options?: MessageEmbedDiscord | MessageEmbedOptions) {
50 super(options);
51 this.setTimestamp();
52 }
53 }
54
55 export default class Logger extends Service {
56 loggingChannel(id: string) {
57 return this.client.guilds.cache.get(id)?.channels.cache.get(this.client.config.props[id].logging_channel) as TextChannel | null;
58 }
59
60 loggingChannelBoosts(id: string) {
61 return this.client.guilds.cache
62 .get(id)
63 ?.channels.cache.get(
64 this.client.config.props[id].logging_channel_boosts ?? this.client.config.props[id].logging_channel
65 ) as TextChannel | null;
66 }
67
68 loggingChannelJoinLeave(id: string) {
69 return this.client.guilds.cache.get(id)?.channels.cache.get(this.client.config.props[id].logging_channel_join_leave) as TextChannel | null;
70 }
71
72 async onRoleCreate(role: Role) {
73 this.loggingChannel(role.guild.id)?.send({
74 embeds: [
75 new MessageEmbed({
76 title: "Role created",
77 fields: [
78 {
79 name: "Role",
80 value: `Name: ${role.name}\nID: ${role.id}\nMention: ${role.toString()}`
81 }
82 ],
83 footer: {
84 text: "Created"
85 },
86 color: 0x007bff
87 })
88 .setTimestamp()
89 ],
90 allowedMentions: {
91 roles: []
92 }
93 });
94 }
95
96
97 async onRoleDelete(role: Role) {
98 this.loggingChannel(role.guild.id)?.send({
99 embeds: [
100 new MessageEmbed({
101 title: "Role deleted",
102 fields: [
103 {
104 name: "Role",
105 value: `Name: ${role.name}\nID: ${role.id}\nMention: ${role.toString()}`
106 }
107 ],
108 footer: {
109 text: "Deleted"
110 },
111 color: 0xf14a60
112 })
113 .setTimestamp()
114 ],
115 allowedMentions: {
116 roles: []
117 }
118 });
119 }
120
121
122 async onRoleUpdate(oldRole: Role, newRole: Role) {
123 this.loggingChannel(newRole.guild.id)?.send({
124 embeds: [
125 new MessageEmbed({
126 title: "Role updated",
127 fields: [
128 ...(newRole.name !== oldRole.name ? [
129 {
130 name: "Name",
131 value: `New Name: ${newRole.name}\nOld Name: ${oldRole.name}`
132 }
133 ] : [
134 {
135 name: "Name",
136 value: `${newRole.name}`
137 }
138 ]),
139 ...(newRole.color !== oldRole.color ? [
140 {
141 name: "Color",
142 value: `New Color: ${newRole.hexColor}\nOld Color: ${oldRole.hexColor}`
143 }
144 ] : []),
145 ...(!newRole.permissions.equals(oldRole.permissions) ? [
146 {
147 name: "New Permissions",
148 value: `\`${newRole.permissions.toArray().join('`, `')}\``
149 }
150 ] : []),
151 ...(oldRole.icon !== newRole.icon ? [
152 {
153 name: "Icon",
154 value: `New Icon: ${newRole.iconURL()}\nOld Icon: ${oldRole.iconURL()}`
155 }
156 ] : []),
157 {
158 name: "ID",
159 value: `${newRole.id}`
160 }
161 ],
162 footer: {
163 text: "Updated"
164 },
165 })
166 .setTimestamp()
167 .setColor("GREEN")
168 ],
169 allowedMentions: {
170 roles: []
171 }
172 });
173 }
174
175 async onChannelCreate(channel: GuildChannel) {
176 this.loggingChannel(channel.guild.id)?.send({
177 embeds: [
178 new MessageEmbed({
179 title: `Channel${channel.type === "GUILD_CATEGORY" ? " Category" : ""} Created`,
180 color: 0x07bff,
181 fields: [
182 {
183 name: "Channel",
184 value: `#${channel.name} (${channel.toString()}, ${channel.id})`
185 },
186 {
187 name: "Type",
188 value: channel.type.replace("GUILD_", '')
189 }
190 ],
191 footer: {
192 text: 'Created'
193 }
194 }).setTimestamp()
195 ]
196 }).catch(console.error);
197 }
198
199 async onChannelDelete(channel: GuildChannel) {
200 this.loggingChannel(channel.guild.id)?.send({
201 embeds: [
202 new MessageEmbed({
203 title: `Channel${channel.type === "GUILD_CATEGORY" ? " Category" : ""} Deleted`,
204 color: 0xf14a60,
205 fields: [
206 {
207 name: "Channel",
208 value: `#${channel.name} (${channel.id})`
209 },
210 {
211 name: "Type",
212 value: channel.type.replace("GUILD_", '')
213 }
214 ],
215 footer: {
216 text: 'Deleted'
217 }
218 }).setTimestamp()
219 ]
220 }).catch(console.error);
221 }
222
223 async onMemberRoleAdd(member: GuildMember, roles: Role[]) {
224 this.loggingChannel(member.guild.id)?.send({
225 embeds: [
226 new MessageEmbed({
227 title: `Roles added to member`,
228 color: 0xf14a60,
229 fields: [
230 {
231 name: "Member",
232 value: `${member.user.toString()} (${member.user.id})`
233 },
234 {
235 name: "Roles",
236 value: `${roles.map(r => r.toString()).join(', ')}`
237 }
238 ],
239 footer: {
240 text: 'Roles Added'
241 }
242 }).setTimestamp()
243 ],
244 allowedMentions: {
245 roles: [],
246 users: []
247 }
248 }).catch(console.error);
249 }
250
251 async onMemberRoleUpdate(newMember: GuildMember, oldMember: GuildMember) {
252 this.loggingChannel(newMember.guild.id)?.send({
253 embeds: [
254 new MessageEmbed({
255 author: {
256 name: newMember.user.username,
257 icon_url: newMember.displayAvatarURL()
258 },
259 title: `Roles modified`,
260 color: 0xf14a60,
261 fields: [
262 {
263 name: "Member",
264 value: `${newMember.user.toString()} (${newMember.user.id})`
265 },
266 {
267 name: "Old Roles",
268 value: `${oldMember.roles.cache.map(r => r.toString()).join(', ')}`
269 },
270 {
271 name: "New Roles",
272 value: `${newMember.roles.cache.map(r => r.toString()).join(', ')}`
273 }
274 ],
275 footer: {
276 text: 'Roles Updated'
277 }
278 }).setTimestamp()
279 ],
280 allowedMentions: {
281 roles: [],
282 users: []
283 }
284 }).catch(console.error);
285 }
286
287 async onMemberRoleRemove(member: GuildMember, roles: Role[]) {
288 this.loggingChannel(member.guild.id)?.send({
289 embeds: [
290 new MessageEmbed({
291 title: `Roles removed from member`,
292 color: 0xf14a60,
293 fields: [
294 {
295 name: "Member",
296 value: `${member.user.toString()} (${member.user.id})`
297 },
298 {
299 name: "Roles",
300 value: `${roles.map(r => r.toString()).join(', ')}`
301 }
302 ],
303 footer: {
304 text: 'Roles Removed'
305 }
306 }).setTimestamp()
307 ],
308 allowedMentions: {
309 roles: [],
310 users: []
311 }
312 }).catch(console.error);
313 }
314
315
316 async onBulkDelete(messages: Collection<string, Message>) {
317 this.loggingChannel(messages.at(0)?.guildId!)?.send({
318 embeds: [
319 new MessageEmbed({
320 title: `Messages deleted in bulk`,
321 color: 0xf14a60,
322 fields: [
323 {
324 name: "Channel",
325 value: `${messages.at(0)?.channel.toString()} (${messages.at(0)?.channelId})`
326 },
327 {
328 name: "Count",
329 value: `${messages.size}`
330 }
331 ],
332 footer: {
333 text: 'Deleted'
334 }
335 }).setTimestamp()
336 ]
337 }).catch(console.error);
338 }
339
340 async onAIModMessageDelete(message: Message, config: any, response: any, meta: any) {
341 const toxicScore = response.data.attributeScores.TOXICITY.summaryScore.value * 100;
342 const severeToxicScore = response.data.attributeScores.SEVERE_TOXICITY.summaryScore.value * 100;
343 const threatScore = response.data.attributeScores.THREAT.summaryScore.value * 100;
344
345 let conf = meta.toxic ? `Toxicity score is ${toxicScore}%, which is higher than or equal to the given maximum value in the configuration (${config.toxicity * 100}%)` : (
346 meta.severeToxic ? `Severe Toxicity score is ${severeToxicScore}%, which is higher than or equal to the given maximum value in the configuration (${config.severe_toxicity * 100}%)` : (
347 meta.threat ? `Threat score is ${threatScore}%, which is higher than or equal to the given maximum value in the configuration (${config.threat * 100}%)` : `Unknown`
348 )
349 );
350
351 await this.loggingChannel(message.guildId!)?.send({
352 embeds: [
353 new MessageEmbed({
354 title: "AI Moderator has deleted this message",
355 author: {
356 name: message.author.tag,
357 iconURL: message.author.displayAvatarURL(),
358 },
359 color: 0xf14a60,
360 description: message.content,
361 fields: [
362 {
363 name: "User ID",
364 value: message.author.id,
365 },
366 {
367 name: "Message Analysis Results",
368 value: `Toxicity: ${toxicScore}%\nSevere Toxicity: ${severeToxicScore}%\nThreat: ${threatScore}%`,
369 },
370 {
371 name: "Reason",
372 value: `Deleted the message because of the following configuration:\n\`\`\`${conf}\`\`\``
373 }
374 ],
375 footer: {
376 text: 'Deleted'
377 }
378 })
379 .setTimestamp(),
380 ],
381 });
382 }
383
384 async onServerBoost(member: GuildMember, level: number) {
385 const distance = formatDistanceToNowStrict(member.premiumSince!);
386
387 await this.loggingChannelBoosts(member.guild.id)?.send({
388 embeds: [
389 new MessageEmbed({
390 title: "Server Boosted",
391 author: {
392 name: member.user.tag,
393 iconURL: member.user.displayAvatarURL(),
394 },
395 description: `${member.user.toString()} has boosted the server!${level > 0 ? ` The server has reached level **${level}**!` : ""}`,
396 fields: [
397 {
398 name: "Boosting Since",
399 value: `${member.premiumSince!.toUTCString()} (${distance.startsWith("0 second") ? "just now" : distance})`,
400 },
401 ],
402 footer: {
403 text: "Boosted",
404 },
405 }).setTimestamp(),
406 ],
407 });
408 }
409
410 async onServerUnboost(oldMember: GuildMember, newMember: GuildMember) {
411 await this.loggingChannelBoosts(oldMember.guild.id)?.send({
412 embeds: [
413 new MessageEmbed({
414 title: "Server Unboosted",
415 author: {
416 name: newMember.user.tag,
417 iconURL: newMember.user.displayAvatarURL(),
418 },
419 description: `${newMember.user.toString()} has unboosted the server.`,
420 fields: [
421 {
422 name: "Boosting Since",
423 value: `${oldMember.premiumSince!.toUTCString()} (${formatDistanceToNowStrict(oldMember.premiumSince!)})`,
424 },
425 ],
426 footer: {
427 text: "Unboosted",
428 },
429 })
430 .setColor("PURPLE")
431 .setTimestamp(),
432 ],
433 });
434 }
435
436 async onNicknameChange(oldMember: GuildMember, newMember: GuildMember) {
437 await this.loggingChannel(oldMember.guild.id)?.send({
438 embeds: [
439 new MessageEmbed({
440 title: "Nickname Updated",
441 author: {
442 name: oldMember.user.tag,
443 iconURL: oldMember.user.displayAvatarURL(),
444 },
445 color: 0xf14a60,
446 fields: [
447 {
448 name: "Old Nickname",
449 value: oldMember.nickname ? Util.escapeMarkdown(oldMember.nickname) : "*No nickname was set*",
450 },
451 {
452 name: "New Nickname",
453 value: newMember.nickname ? Util.escapeMarkdown(newMember.nickname) : "*Nickname was removed*",
454 },
455 {
456 name: "User ID",
457 value: newMember.user.id,
458 },
459 ],
460 footer: {
461 text: "Updated",
462 },
463 }).setTimestamp(),
464 ],
465 });
466 }
467
468 async onMessageUpdate(oldMessage: Message, newMessage: Message) {
469 const row = new MessageActionRow().addComponents(new MessageButton().setLabel("Go to context").setStyle("LINK").setURL(newMessage.url));
470
471 if (newMessage.type === "REPLY") {
472 row.addComponents(
473 new MessageButton()
474 .setLabel("Go to referenced message")
475 .setStyle("LINK")
476 .setURL(`https://discord.com/channels/${newMessage.guildId!}/${newMessage.channelId!}/${newMessage.reference!.messageId}`)
477 );
478 }
479
480 await this.loggingChannel(newMessage.guild!.id)?.send({
481 embeds: [
482 new MessageEmbed({
483 title: "Message Updated",
484 author: {
485 name: oldMessage.author.tag,
486 iconURL: oldMessage.author.displayAvatarURL(),
487 },
488 description: "**-+-+Before**\n" + oldMessage.content + "\n\n**-+-+After**\n" + newMessage.content,
489 fields: [
490 {
491 name: "Message ID",
492 value: newMessage.id,
493 },
494 {
495 name: "User ID",
496 value: oldMessage.author.id,
497 },
498 {
499 name: "Channel",
500 value: `${oldMessage.channel} (${oldMessage.channelId})`,
501 },
502 ],
503 footer: {
504 text: `Updated • ${newMessage.id}`,
505 },
506 }),
507 ],
508 components: [row],
509 });
510 }
511
512 async onMessageDelete(message: Message) {
513 const embed = new MessageEmbed({
514 title: "Message Deleted",
515 color: 0xf14a60,
516 author: {
517 name: message.author.tag,
518 iconURL: message.author.displayAvatarURL(),
519 },
520 description: message.content,
521 fields: [
522 {
523 name: "Message ID",
524 value: message.id,
525 },
526 {
527 name: "User ID",
528 value: message.author.id,
529 },
530 {
531 name: "Channel",
532 value: `${message.channel} (${message.channelId})`,
533 },
534 ],
535 footer: {
536 text: `Deleted • ${message.id}`,
537 },
538 });
539
540 const files: FileOptions[] = [];
541
542 if (message.attachments.size > 0) {
543 let str = "";
544
545 message.attachments.forEach((a) => {
546 str += `${a.name}\n`;
547 files.push({
548 name: a.name!,
549 attachment: a.proxyURL,
550 });
551 });
552
553 embed.addFields({
554 name: "Attachments (top)",
555 value: str,
556 });
557 }
558
559 const row = new MessageActionRow().addComponents(new MessageButton().setLabel("Go to context").setStyle("LINK").setURL(message.url));
560
561 if (message.type === "REPLY") {
562 row.addComponents(
563 new MessageButton()
564 .setLabel("Go to referenced message")
565 .setStyle("LINK")
566 .setURL(`https://discord.com/channels/${message.guildId!}/${message.channelId!}/${message.reference!.messageId}`)
567 );
568 }
569
570 await this.loggingChannel(message.guild!.id)?.send({
571 embeds: [embed],
572 components: [row],
573 files,
574 });
575 }
576
577 async onGuildBanAdd(ban: GuildBan, _executor?: User, id?: string | number) {
578 const auditLog = (
579 await ban.guild.fetchAuditLogs({
580 limit: 1,
581 type: "MEMBER_BAN_ADD",
582 })
583 ).entries.first();
584
585 const executor = _executor ?? auditLog?.executor;
586
587 if (executor?.id === this.client.user!.id) {
588 console.log("Action taken by bot");
589 return;
590 }
591
592 const guildBan = await ban.guild.bans.fetch(ban.user.id);
593 const reason = ban.reason ?? guildBan.reason ?? "*No reason provided*";
594
595 await this.loggingChannel(ban.guild.id)?.send({
596 embeds: [
597 new MessageEmbed()
598 .setColor("#f14a60")
599 .setTitle("A user was banned")
600 .setAuthor({
601 name: guildBan.user.tag,
602 iconURL: guildBan.user.displayAvatarURL(),
603 })
604 .addField("Reason", reason)
605 .addField("User ID", guildBan.user.id)
606 .addFields(
607 {
608 name: "Banned by",
609 value: executor ? `${executor.tag} (${executor.id})` : "Unknown",
610 },
611 {
612 name: "Infraction ID",
613 value: id?.toString() ?? "*Unavailable*",
614 }
615 )
616 .setFooter({
617 text: "Banned",
618 }),
619 ],
620 });
621 }
622
623 async onGuildBanRemove(ban: GuildBan, _executor?: User) {
624 const auditLog = (
625 await ban.guild.fetchAuditLogs({
626 limit: 1,
627 type: "MEMBER_BAN_REMOVE",
628 })
629 ).entries.first();
630
631 const executor = _executor ?? auditLog?.executor;
632
633 await this.loggingChannel(ban.guild.id)?.send({
634 embeds: [
635 new MessageEmbed()
636 .setColor("#f14a60")
637 .setTitle("A user was unbanned")
638 .setAuthor({
639 name: ban.user.tag,
640 iconURL: ban.user.displayAvatarURL(),
641 })
642 .addField("User ID", ban.user.id)
643 .addFields({
644 name: "Unbanned By",
645 value: executor ? `${executor.tag} (${executor.id})` : "Unknown",
646 })
647 .setFooter({
648 text: "Unbanned",
649 })
650 .setTimestamp(),
651 ],
652 });
653 }
654
655 async onSoftban(banOptions: BanOptions, guild: Guild, user: User, model: IPunishment) {
656 let r = banOptions.reason ?? "*No reason provided*";
657
658 await this.loggingChannel(guild.id)?.send({
659 embeds: [
660 new MessageEmbed()
661 .setColor("#f14a60")
662 .setTitle("A user was softbanned")
663 .setAuthor({
664 name: user.tag,
665 iconURL: user.displayAvatarURL(),
666 })
667 .addField("Reason", r)
668 .addField("Softbanned by", `${model.mod_tag} (${model.mod_id})`)
669 .addField("User ID", user.id)
670 .addFields({
671 name: "Case ID",
672 value: model.numericId + "",
673 })
674 .setFooter({
675 text: "Softbanned",
676 })
677 .setTimestamp(),
678 ],
679 });
680 }
681
682 async onTempBan(banOptions: BanOptions, guild: Guild, user: User, model: IPunishment) {
683 let r = banOptions.reason ?? "*No reason provided*";
684
685 await this.loggingChannel(guild.id)?.send({
686 embeds: [
687 new MessageEmbed()
688 .setColor("#f14a60")
689 .setTitle("A user was temporarily banned")
690 .setAuthor({
691 name: user.tag,
692 iconURL: user.displayAvatarURL(),
693 })
694 .addField("Reason", r)
695 .addField("Banned by", `${model.mod_tag} (${model.mod_id})`)
696 .addField("User ID", user.id)
697 .addField("Duration", ms((model.meta as any).time))
698 .addFields({
699 name: "Case ID",
700 value: model.numericId + "",
701 })
702 .setFooter({
703 text: "Temporarily banned",
704 })
705 .setTimestamp(),
706 ],
707 });
708 }
709
710 async onGuildMemberAdd(member: GuildMember, info?: IGuildInfo) {
711 let members = 0,
712 bots = 0;
713
714 for (const m of member.guild!.members.cache.values()) {
715 if (m.user.bot) bots++;
716 else members++;
717 }
718
719 const invite = member.user.bot ? null : await this.client.inviteTracker.getInviteInfo(member);
720
721 await this.loggingChannelJoinLeave(member.guild.id)?.send({
722 embeds: [
723 new MessageEmbed()
724 .setColor("#007bff")
725 .setTitle("New member joined")
726 .setAuthor({
727 name: member.user.tag,
728 iconURL: member.user.displayAvatarURL(),
729 })
730 .setDescription(`<@${member.user.id}> just joined the server! Their position is ${members + bots}th.`)
731 .addField("Account Created", `${member.user.createdAt.toLocaleString()} (${timeSince(member.user.createdAt.getTime())})`)
732 .addField(
733 "New Account?",
734 new Date().getTime() - member.user.createdAt.getTime() <= 3 * 24 * 60 * 60 * 1000 ? ":warning: Yes :warning:" : "No"
735 )
736 .addField("Bot?", member.user.bot === true ? "Yes" : "No")
737 .addField("User ID", member.user.id)
738 .addFields(
739 {
740 name: "Total Members Joined",
741 value: info?.totalMembersJoined?.toString() ?? "*Information unavailable*",
742 },
743 {
744 name: "Positions",
745 value: `Among All members: ${members + bots}th\n${
746 member.user.bot ? `Among bots: ${bots}th` : `Among human members: ${members}th`
747 }`,
748 },
749 {
750 name: "Invite Information",
751 value: invite
752 ? `Inviter: ${invite.inviter ?? "*Unavailable*"}\nInvite URL: [https://discord.gg/${
753 invite.code
754 }](https://discord.gg/${invite.code})`
755 : "*Unavailable*",
756 }
757 )
758 .setFooter({
759 text: `Joined • ${members + bots} members total`,
760 })
761 .setTimestamp(),
762 ],
763 });
764 }
765
766 async onGuildMemberRemove(member: GuildMember) {
767 const roles = member.roles.cache.filter((role) => role.id !== member.guild.id).reduce((acc, val) => ` ${acc} ${roleMention(val.id)}`, "");
768
769 await this.loggingChannelJoinLeave(member.guild.id)?.send({
770 embeds: [
771 new MessageEmbed()
772 .setColor("#f14a60")
773 .setTitle("Member left")
774 .setAuthor({
775 name: member.user.tag,
776 iconURL: member.user.displayAvatarURL(),
777 })
778 .setDescription(`**Roles**\n${roles}`)
779 .addField("Joined at", `${member.joinedAt!.toLocaleString()} (${timeSince(member.joinedAt!.getTime())})`)
780 .addField("User ID", member.user.id)
781 .addField("Bot?", member.user.bot === true ? "Yes" : "No")
782 .setFooter({
783 text: `Left • ${member.guild.memberCount} members total`,
784 })
785 .setTimestamp(),
786 ],
787 });
788 }
789
790 async onMemberShot(member: GuildMember, moderator: User, reason?: string, id?: string) {
791 await this.loggingChannel(member.guild.id)?.send({
792 embeds: [
793 new MessageEmbed()
794 .setColor("#007bff")
795 .setTitle("Member got shot")
796 .setAuthor({
797 name: member.user.tag,
798 iconURL: member.user.displayAvatarURL(),
799 })
800 .addField("Reason", reason ?? "*No reason provided*")
801 .addField("Doctor 💉", moderator.tag)
802 .addField("User ID", member.user.id)
803 .addFields({
804 name: "Infraction ID",
805 value: id ?? "*Unavailable*",
806 })
807 .setFooter({
808 text: "Shot delivered",
809 })
810 .setTimestamp(),
811 ],
812 });
813 }
814
815 async onMemberKick(member: GuildMember, reason?: string, executor?: User, id?: string) {
816 await this.loggingChannel(member.guild.id)?.send({
817 embeds: [
818 new MessageEmbed({
819 author: {
820 name: member.user.tag,
821 iconURL: member.user.displayAvatarURL(),
822 },
823 title: "Member Kicked",
824 description: "This user has left the server, probably due to a kick.",
825 fields: [
826 {
827 name: "Kicked by",
828 value: executor?.tag ?? "Unknown",
829 },
830 {
831 name: "Reason",
832 value: reason ?? "*No reason provided*",
833 },
834 {
835 name: "Infraction ID",
836 value: id ?? "*Unavailable*",
837 },
838 ],
839 footer: {
840 text: "Kicked",
841 },
842 }).setTimestamp(),
843 ],
844 });
845 }
846
847 async onMemberMute(member: GuildMember, duration?: number, reason?: string, executor?: User, hard = false, id?: string) {
848 await this.loggingChannel(member.guild.id)?.send({
849 embeds: [
850 new MessageEmbed()
851 .setColor("#f14a60")
852 .setTitle("Member muted")
853 .setAuthor({
854 name: member.user.tag,
855 iconURL: member.user.displayAvatarURL(),
856 })
857 .addField("Reason", reason ?? "*No reason provided*")
858 .addField("Muted by", executor?.tag ?? "Unknown")
859 .addField(
860 "Duration Until",
861 duration
862 ? `${new Date(Date.now() + duration).toLocaleString()} (${formatDuration(
863 intervalToDuration({ start: 0, end: duration })
864 )})`
865 : "*No duration set*"
866 )
867 .addField("User ID", member.user.id)
868 .addField("Hardmute", hard ? "Yes" : "No")
869 .addFields({
870 name: "Infraction ID",
871 value: id ?? "*Unavailable*",
872 })
873 .setFooter({
874 text: "Muted",
875 })
876 .setTimestamp(),
877 ],
878 });
879 }
880
881 async onMemberUnmute(member: GuildMember, executor?: User) {
882 await this.loggingChannel(member.guild.id)?.send({
883 embeds: [
884 new MessageEmbed()
885 .setColor("#007bff")
886 .setTitle("Member unmuted")
887 .setAuthor({
888 name: member.user.tag,
889 iconURL: member.user.displayAvatarURL(),
890 })
891 .addField("Unmuted by", executor?.tag ?? "Unknown")
892 .addField("User ID", member.user.id)
893 .setFooter({
894 text: "Unmuted",
895 })
896 .setTimestamp(),
897 ],
898 });
899 }
900
901 async onMemberWarn(user: User, guildID: string, id: string, reason?: string, moderator?: User) {
902 await this.loggingChannel(guildID)?.send({
903 embeds: [
904 new MessageEmbed()
905 .setColor("GOLD")
906 .setTitle("Member warned")
907 .setAuthor({
908 name: user.tag,
909 iconURL: user.displayAvatarURL(),
910 })
911 .addField("Reason", reason ?? "*No reason provided*")
912 .addField("Warned by", moderator?.tag ?? "*No reason provided*")
913 .addField("User ID", user.id)
914 .addField("Infraction ID", id + "")
915 .setFooter({
916 text: "Warned",
917 })
918 .setTimestamp(),
919 ],
920 });
921 }
922
923 async onMemberWarningDelete(member: GuildMember, id: string, reason?: string, moderator?: User) {
924 await this.loggingChannel(member.guild.id)?.send({
925 embeds: [
926 new MessageEmbed()
927 .setColor("GOLD")
928 .setTitle("Warning deleted")
929 .setAuthor({
930 name: member.user.tag,
931 iconURL: member.user.displayAvatarURL(),
932 })
933 .addField("Warned by", moderator?.tag ?? "Unknown")
934 .addField("Infraction ID", id + "")
935 .addField("User ID", member.user.id)
936 .setFooter({
937 text: "Warning Deleted",
938 })
939 .setTimestamp(),
940 ],
941 });
942 }
943
944 async onMemberUpdate(oldMember: GuildMember, newMember: GuildMember) {
945 if (oldMember.isCommunicationDisabled() && !newMember.isCommunicationDisabled()) {
946 setTimeout(async () => {
947 const auditLog = await newMember.guild.fetchAuditLogs({
948 type: "MEMBER_UPDATE",
949 limit: 1,
950 });
951
952 const data = auditLog?.entries.first();
953
954 console.log(data);
955
956 Punishment.create({
957 createdAt: new Date(),
958 guild_id: newMember.guild.id,
959 mod_id: data?.executor?.id,
960 mod_tag: data?.executor?.tag,
961 user_id: newMember.user.id,
962 type: PunishmentType.TIMEOUT_REMOVE,
963 }).catch(console.error);
964
965 await this.loggingChannel(newMember.guild.id)?.send({
966 embeds: [
967 new MessageEmbed()
968 .setColor("GOLD")
969 .setTitle("Member Timeout Removed")
970 .setAuthor({
971 name: newMember.user.tag,
972 iconURL: newMember.user.displayAvatarURL(),
973 })
974 .addField(
975 "Removed by",
976 data?.target?.id === newMember.user.id && data?.executor?.tag
977 ? `${data?.executor?.tag} (${data?.executor?.id})`
978 : "*Timeout expired automatically*"
979 )
980 .addField("User ID", oldMember.user.id)
981 .setFooter({
982 text: "Timeout Removed",
983 })
984 .setTimestamp(),
985 ],
986 });
987 }, 2000);
988 } else if (!oldMember.isCommunicationDisabled() && newMember.isCommunicationDisabled()) {
989 setTimeout(async () => {
990 const auditLog = await newMember.guild.fetchAuditLogs({
991 type: "MEMBER_UPDATE",
992 limit: 1,
993 });
994
995 const data = auditLog?.entries.first();
996
997 console.log(data);
998
999 Punishment.create({
1000 createdAt: new Date(),
1001 guild_id: newMember.guild.id,
1002 mod_id: data?.executor?.id,
1003 mod_tag: data?.executor?.tag,
1004 reason: data?.reason,
1005 user_id: newMember.user.id,
1006 type: PunishmentType.TIMEOUT,
1007 meta: {
1008 time: ms(newMember.communicationDisabledUntilTimestamp - Date.now()),
1009 },
1010 }).catch(console.error);
1011
1012 await this.loggingChannel(newMember.guild.id)?.send({
1013 embeds: [
1014 new MessageEmbed()
1015 .setColor("#f14a60")
1016 .setTitle("Member Timed Out")
1017 .setAuthor({
1018 name: newMember.user.tag,
1019 iconURL: newMember.user.displayAvatarURL(),
1020 })
1021 .addFields(
1022 {
1023 name: "Reason",
1024 value: data?.reason ?? "*No reason provided*",
1025 },
1026 {
1027 name: "Duration",
1028 value: newMember.communicationDisabledUntil
1029 ? `${newMember.communicationDisabledUntil.toUTCString()} (${formatDistanceStrict(
1030 newMember.communicationDisabledUntil,
1031 new Date()
1032 )})`
1033 : "Unknown",
1034 }
1035 )
1036 .addField(
1037 "Action taken by",
1038 data?.target?.id === newMember.user.id && data?.executor?.tag
1039 ? `${data?.executor?.tag} (${data?.executor?.id})`
1040 : "Unknown"
1041 )
1042 .addField("User ID", oldMember.user.id)
1043 .setFooter({
1044 text: "Timed-out",
1045 })
1046 .setTimestamp(),
1047 ],
1048 });
1049 }, 2000);
1050 }
1051 }
1052 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26