blob: bc95dd8cac7210cac61b9f35e5b8388dc114bedf [file] [log] [blame]
pineafan63fc5e22022-08-04 22:04:10 +01001import * as Discord from "discord.js";
2import getEmojiByName from "./getEmojiByName.js";
3import { toHexArray } from "./calculate.js";
4import { promisify } from "util";
5import generateKeyValueList from "./generateKeyValueList.js";
6import client from "./client.js";
Skyler Grey1b669632023-03-05 10:58:11 +00007import {DiscordAPIError} from "discord.js";
pineafan32767212022-03-14 21:27:39 +00008
9const wait = promisify(setTimeout);
10
TheCodedProf6ec331b2023-02-20 12:13:06 -050011export interface LoggerOptions {
12 meta: {
13 type: string;
14 displayName: string;
15 calculateType: string;
16 color: number;
17 emoji: string;
18 timestamp: number;
19 };
20 // eslint-disable-next-line @typescript-eslint/no-explicit-any
21 list: any;
22 hidden: {
23 guild: string;
Skyler Greyda16adf2023-03-05 10:22:12 +000024 };
TheCodedProf6ec331b2023-02-20 12:13:06 -050025 separate?: {
26 start?: string;
27 end?: string;
Skyler Greyda16adf2023-03-05 10:22:12 +000028 };
TheCodedProf6ec331b2023-02-20 12:13:06 -050029}
30
31async function isLogging(guild: string, type: string): Promise<boolean> {
32 const config = await client.database.guilds.read(guild);
33 if (!config.logging.logs.enabled) return false;
34 if (!config.logging.logs.channel) return false;
Skyler Greyda16adf2023-03-05 10:22:12 +000035 if (!toHexArray(config.logging.logs.toLog).includes(type)) {
36 return false;
37 }
TheCodedProf6ec331b2023-02-20 12:13:06 -050038 return true;
39}
PineaFan64486c42022-12-28 09:21:04 +000040
41export const Logger = {
pineafane625d782022-05-09 18:04:32 +010042 renderUser(user: Discord.User | string) {
PineaFanb0d0c242023-02-05 10:59:45 +000043 if (typeof user === "string") user = client.users.cache.get(user)!;
pineafane625d782022-05-09 18:04:32 +010044 return `${user.username} [<@${user.id}>]`;
PineaFan64486c42022-12-28 09:21:04 +000045 },
pineafane625d782022-05-09 18:04:32 +010046 renderTime(t: number) {
Skyler Grey75ea9172022-08-06 10:22:23 +010047 t = Math.floor((t /= 1000));
pineafane625d782022-05-09 18:04:32 +010048 return `<t:${t}:D> at <t:${t}:T>`;
PineaFan64486c42022-12-28 09:21:04 +000049 },
pineafane625d782022-05-09 18:04:32 +010050 renderDelta(t: number) {
Skyler Grey75ea9172022-08-06 10:22:23 +010051 t = Math.floor((t /= 1000));
pineafane625d782022-05-09 18:04:32 +010052 return `<t:${t}:R> (<t:${t}:D> at <t:${t}:T>)`;
PineaFan64486c42022-12-28 09:21:04 +000053 },
pineafanbd02b4a2022-08-05 22:01:38 +010054 renderNumberDelta(num1: number, num2: number) {
pineafan63fc5e22022-08-04 22:04:10 +010055 const delta = num2 - num1;
56 return `${num1} -> ${num2} (${delta > 0 ? "+" : ""}${delta})`;
PineaFan64486c42022-12-28 09:21:04 +000057 },
Skyler Greyda16adf2023-03-05 10:22:12 +000058 entry(
59 value: string | number | boolean | null | (string | boolean)[],
60 displayValue: string
61 ): { value: string | boolean | null | (string | boolean | number)[]; displayValue: string } {
PineaFan0d06edc2023-01-17 22:10:31 +000062 if (typeof value === "number") value = value.toString();
pineafan63fc5e22022-08-04 22:04:10 +010063 return { value: value, displayValue: displayValue };
PineaFan64486c42022-12-28 09:21:04 +000064 },
TheCodedProf4a6d5712023-01-19 15:54:40 -050065 renderChannel(channel: Discord.GuildChannel | Discord.ThreadChannel | string) {
Skyler Greyda16adf2023-03-05 10:22:12 +000066 if (typeof channel === "string")
67 channel = client.channels.cache.get(channel) as Discord.GuildChannel | Discord.ThreadChannel;
pineafane625d782022-05-09 18:04:32 +010068 return `${channel.name} [<#${channel.id}>]`;
PineaFan64486c42022-12-28 09:21:04 +000069 },
TheCodedProf486bca32023-02-02 16:49:44 -050070 renderRole(role: Discord.Role | string, guild?: Discord.Guild | string) {
Skyler Greyda16adf2023-03-05 10:22:12 +000071 if (typeof role === "string")
72 role = (typeof guild === "string" ? client.guilds.cache.get(guild) : guild)!.roles.cache.get(role)!;
pineafane625d782022-05-09 18:04:32 +010073 return `${role.name} [<@&${role.id}>]`;
PineaFan64486c42022-12-28 09:21:04 +000074 },
pineafane625d782022-05-09 18:04:32 +010075 renderEmoji(emoji: Discord.GuildEmoji) {
Skyler Grey11236ba2022-08-08 21:13:33 +010076 return `<${emoji.animated ? "a" : ""}:${emoji.name}:${emoji.id}> [\`:${emoji.name}:\`]`;
PineaFan64486c42022-12-28 09:21:04 +000077 },
78 NucleusColors: {
Skyler Grey75ea9172022-08-06 10:22:23 +010079 red: 0xf27878,
80 yellow: 0xf2d478,
81 green: 0x68d49e
PineaFan64486c42022-12-28 09:21:04 +000082 },
Skyler Greyda16adf2023-03-05 10:22:12 +000083 async getAuditLog(
84 guild: Discord.Guild,
85 event: Discord.GuildAuditLogsResolvable,
86 delay?: number
87 ): Promise<Discord.GuildAuditLogsEntry[]> {
Skyler Grey1b669632023-03-05 10:58:11 +000088 if (!guild.members.me?.permissions.has("ViewAuditLog")) return [];
TheCodedProf686829f2023-02-22 15:08:01 -050089 await wait(delay ?? 250);
Skyler Grey1b669632023-03-05 10:58:11 +000090 try {
91 const auditLog = (await guild.fetchAuditLogs({ type: event })).entries.map((m) => m);
92 return auditLog as Discord.GuildAuditLogsEntry[];
93 } catch (e) {
94 if (e instanceof DiscordAPIError) return [];
95 throw e;
96 }
PineaFan64486c42022-12-28 09:21:04 +000097 },
TheCodedProf6ec331b2023-02-20 12:13:06 -050098 async log(log: LoggerOptions): Promise<void> {
Skyler Greyda16adf2023-03-05 10:22:12 +000099 if (!(await isLogging(log.hidden.guild, log.meta.calculateType))) return;
100 console.log(log.hidden.guild);
pineafan63fc5e22022-08-04 22:04:10 +0100101 const config = await client.database.guilds.read(log.hidden.guild);
Skyler Greyda16adf2023-03-05 10:22:12 +0000102 console.log(config.logging.logs.channel);
Samuel Shuerta1511f92023-03-04 13:55:33 -0500103
pineafane625d782022-05-09 18:04:32 +0100104 if (config.logging.logs.channel) {
Skyler Grey11236ba2022-08-08 21:13:33 +0100105 const channel = (await client.channels.fetch(config.logging.logs.channel)) as Discord.TextChannel | null;
pineafanbd02b4a2022-08-05 22:01:38 +0100106 const description: Record<string, string> = {};
Skyler Grey75ea9172022-08-06 10:22:23 +0100107 Object.entries(log.list).map((entry) => {
pineafanbd02b4a2022-08-05 22:01:38 +0100108 const key: string = entry[0];
pineafan63fc5e22022-08-04 22:04:10 +0100109 // eslint-disable-next-line @typescript-eslint/no-explicit-any
110 const value: any = entry[1];
Skyler Grey75ea9172022-08-06 10:22:23 +0100111 if (value.displayValue) {
pineafane625d782022-05-09 18:04:32 +0100112 description[key] = value.displayValue;
113 } else {
114 description[key] = value;
115 }
pineafan63fc5e22022-08-04 22:04:10 +0100116 });
pineafane625d782022-05-09 18:04:32 +0100117 if (channel) {
TheCodedProf1807fb32023-02-20 14:33:48 -0500118 log.separate = log.separate ?? {};
TheCodedProf21c08592022-09-13 14:14:43 -0400119 const embed = new Discord.EmbedBuilder()
Skyler Grey11236ba2022-08-08 21:13:33 +0100120 .setTitle(`${getEmojiByName(log.meta.emoji)} ${log.meta.displayName}`)
pineafane625d782022-05-09 18:04:32 +0100121 .setDescription(
122 (log.separate.start ? log.separate.start + "\n" : "") +
Skyler Greyda16adf2023-03-05 10:22:12 +0000123 generateKeyValueList(description) +
124 (log.separate.end ? "\n" + log.separate.end : "")
pineafane625d782022-05-09 18:04:32 +0100125 )
126 .setTimestamp(log.meta.timestamp)
127 .setColor(log.meta.color);
Skyler Grey75ea9172022-08-06 10:22:23 +0100128 channel.send({ embeds: [embed] });
pineafane625d782022-05-09 18:04:32 +0100129 }
130 }
TheCodedProf6ec331b2023-02-20 12:13:06 -0500131 },
132 isLogging
PineaFan64486c42022-12-28 09:21:04 +0000133};
134
pineafan63fc5e22022-08-04 22:04:10 +0100135export default {};