From 474bb8bb3136469b1fefbe15a19ad58a0feda60a Mon Sep 17 00:00:00 2001 From: IRONM00N <64110067+IRONM00N@users.noreply.github.com> Date: Tue, 28 Nov 2023 18:02:28 -0500 Subject: [PATCH] add more options for logging config, timeout user fetch for level --- .eslintrc.json | 3 +- config/Config.ts | 10 +++++ lib/utils/Logger.ts | 78 ++++++++++++++++++++++++++++------ src/commands/leveling/level.ts | 7 ++- 4 files changed, 83 insertions(+), 15 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 0dfcaea6..d6c915a4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -58,6 +58,7 @@ "@typescript-eslint/prefer-as-const": "warn", "@typescript-eslint/ban-types": "off", "@typescript-eslint/no-inferrable-types": "off", - "@typescript-eslint/no-unsafe-declaration-merging": "off" + "@typescript-eslint/no-unsafe-declaration-merging": "off", + "prefer-const": "warn" } } diff --git a/config/Config.ts b/config/Config.ts index 90d44283..52355f59 100644 --- a/config/Config.ts +++ b/config/Config.ts @@ -256,6 +256,11 @@ export type Logging = { * Whether or not to log database queries, verbose logs, or informational logs */ [Key in LoggingType]: boolean; +} & { + /** + * Override default behavior + */ + [Key in OverrideLog]?: boolean; }; /** @@ -263,6 +268,11 @@ export type Logging = { */ export type LoggingType = 'db' | 'verbose' | 'info'; +/** + * Override the default logging behavior + */ +export type OverrideLog = 'success' | 'error' | 'warn' | 'veryVerbose' | 'debug' | 'noMessage' | 'noRaw'; + /** * Information regarding the bot's support server. */ diff --git a/lib/utils/Logger.ts b/lib/utils/Logger.ts index cb19522b..9f3bde98 100644 --- a/lib/utils/Logger.ts +++ b/lib/utils/Logger.ts @@ -1,5 +1,13 @@ import chalk from 'chalk'; -import { EmbedBuilder, bold, escapeMarkdown, type Client, type Message, type PartialTextBasedChannelFields } from 'discord.js'; +import { + BitField, + EmbedBuilder, + bold, + escapeMarkdown, + type Client, + type Message, + type PartialTextBasedChannelFields +} from 'discord.js'; import repl, { REPL_MODE_STRICT, type REPLServer } from 'node:repl'; import type { WriteStream } from 'node:tty'; import { stripVTControlCharacters as stripColor } from 'node:util'; @@ -117,14 +125,51 @@ function pad(num: number) { return num.toString().padStart(2, '0'); } +/** + * The flags representing what forms of the logger are enabled, allows for default logging behavior to be overridden + * by the config. + */ +export enum LoggingFlags { + None = 0, + Info = 1 << 0, + Success = 1 << 1, + Error = 1 << 2, + Warn = 1 << 3, + Verbose = 1 << 4, + VeryVerbose = 1 << 5, + Debug = 1 << 6, + NoMessage = 1 << 7, + NoRaw = 1 << 8 +} + +export type LoggingFlagsKeys = keyof typeof LoggingFlags; + /** * Custom logging utility for the bot. */ export class Logger { + private flags: BitField; + /** * @param client The client. */ - public constructor(public client: Client) {} + public constructor(public client: Client) { + let flags = LoggingFlags.None; + + const l = client.config.logging; + + if (l.info) flags |= LoggingFlags.Info; + if ('success' in l ? l.success : true) flags |= LoggingFlags.Success; + if ('error' in l ? l.error : true) flags |= LoggingFlags.Error; + if ('warn' in l ? l.warn : true) flags |= LoggingFlags.Warn; + if (l.verbose) flags |= LoggingFlags.Verbose; + if ('veryVerbose' in l ? l.veryVerbose : l.verbose) flags |= LoggingFlags.VeryVerbose; + if ('debug' in l ? l.debug : client.config.isDevelopment) flags |= LoggingFlags.Debug; + if ('noMessage' in l ? l.noMessage : false) flags |= LoggingFlags.NoMessage; + if ('noRaw' in l ? l.noRaw : false) flags |= LoggingFlags.NoRaw; + + this.flags = new BitField(flags); + } /** * Logs information. Highlight information by surrounding it in `<<>>`. @@ -174,7 +219,7 @@ export class Logger { * @param depth The depth the content will inspected. Defaults to `0`. */ public debug(content: any, depth = 0): void { - if (!this.client.config.isDevelopment) return; + if (!this.flags.has('Debug')) return; const newContent = inspectContent(content, depth, true); console.log(`${chalk.bgMagenta(getTimeStamp())} ${chalk.magenta('[Debug]')} ${newContent}`); } @@ -184,7 +229,7 @@ export class Logger { * @param content The content to log. */ public debugRaw(...content: any): void { - if (!this.client.config.isDevelopment) return; + if (!this.flags.has('Debug') || this.flags.has('NoRaw')) return; console.log(`${chalk.bgMagenta(getTimeStamp())} ${chalk.magenta('[Debug]')}`, ...content); } @@ -196,10 +241,11 @@ export class Logger { * @param depth The depth the content will inspected. Defaults to `0`. */ public async verbose(header: string, content: any, sendChannel = false, depth = 0): Promise { - if (!this.client.config.logging.verbose) return; + if (!this.flags.has('Verbose')) return; const newContent = inspectContent(content, depth, true); console.log(`${chalk.bgGrey(getTimeStamp())} ${chalk.grey(`[${header}]`)} ${parseFormatting(newContent, 'blackBright')}`); - if (!sendChannel) return; + + if (!sendChannel || this.flags.has('NoMessage')) return; const embed = new EmbedBuilder() .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`) .setColor(colors.gray) @@ -214,7 +260,7 @@ export class Logger { * @param depth The depth the content will inspected. Defaults to `0`. */ public async superVerbose(header: string, content: any, depth = 0): Promise { - if (!this.client.config.logging.verbose) return; + if (!this.flags.has('VeryVerbose')) return; const newContent = inspectContent(content, depth, true); console.log( `${chalk.bgHex('#949494')(getTimeStamp())} ${chalk.hex('#949494')(`[${header}]`)} ${chalk.hex('#b3b3b3')(newContent)}` @@ -227,7 +273,7 @@ export class Logger { * @param content The content to log. */ public async superVerboseRaw(header: string, ...content: any[]): Promise { - if (!this.client.config.logging.verbose) return; + if (!this.flags.has('VeryVerbose') || this.flags.has('NoRaw')) return; console.log(`${chalk.bgHex('#a3a3a3')(getTimeStamp())} ${chalk.hex('#a3a3a3')(`[${header}]`)}`, ...content); } @@ -239,10 +285,11 @@ export class Logger { * @param depth The depth the content will inspected. Defaults to `0`. */ public async info(header: string, content: any, sendChannel = true, depth = 0): Promise { - if (!this.client.config.logging.info) return; + if (!this.flags.has('Info')) return; const newContent = inspectContent(content, depth, true); console.log(`${chalk.bgCyan(getTimeStamp())} ${chalk.cyan(`[${header}]`)} ${parseFormatting(newContent, 'blueBright')}`); - if (!sendChannel) return; + + if (!sendChannel || this.flags.has('NoMessage')) return; const embed = new EmbedBuilder() .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`) .setColor(colors.info) @@ -258,12 +305,13 @@ export class Logger { * @param depth The depth the content will inspected. Defaults to `0`. */ public async warn(header: string, content: any, sendChannel = true, depth = 0): Promise { + if (!this.flags.has('Warn')) return; const newContent = inspectContent(content, depth, true); console.warn( `${chalk.bgYellow(getTimeStamp())} ${chalk.yellow(`[${header}]`)} ${parseFormatting(newContent, 'yellowBright')}` ); - if (!sendChannel) return; + if (!sendChannel || this.flags.has('NoMessage')) return; const embed = new EmbedBuilder() .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`) .setColor(colors.warn) @@ -279,11 +327,13 @@ export class Logger { * @param depth The depth the content will inspected. Defaults to `0`. */ public async error(header: string, content: any, sendChannel = true, depth = 0): Promise { + if (!this.flags.has('Error')) return; const newContent = inspectContent(content, depth, true); console.warn( `${chalk.bgRedBright(getTimeStamp())} ${chalk.redBright(`[${header}]`)} ${parseFormatting(newContent, 'redBright')}` ); - if (!sendChannel) return; + + if (!sendChannel || this.flags.has('NoMessage')) return; const embed = new EmbedBuilder() .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`) .setColor(colors.error) @@ -300,11 +350,13 @@ export class Logger { * @param depth The depth the content will inspected. Defaults to `0`. */ public async success(header: string, content: any, sendChannel = true, depth = 0): Promise { + if (!this.flags.has('Success')) return; const newContent = inspectContent(content, depth, true); console.log( `${chalk.bgGreen(getTimeStamp())} ${chalk.greenBright(`[${header}]`)} ${parseFormatting(newContent, 'greenBright')}` ); - if (!sendChannel) return; + + if (!sendChannel || this.flags.has('NoMessage')) return; const embed = new EmbedBuilder() .setDescription(`**[${header}]** ${parseFormatting(stripColor(newContent), '', true)}`) .setColor(colors.success) diff --git a/src/commands/leveling/level.ts b/src/commands/leveling/level.ts index 6764f296..df357145 100644 --- a/src/commands/leveling/level.ts +++ b/src/commands/leveling/level.ts @@ -3,7 +3,9 @@ import { BotCommand, CanvasProgressBar, Level, + Time, emojis, + sleep, type CommandMessage, type OptArgType, type SlashMessage @@ -151,7 +153,10 @@ export default class LevelCommand extends BotCommand { this.logger.debug(`hexAccentColor: ${user.hexAccentColor}`); - await user.fetch(true); // get accent color + await Promise.race([ + user.fetch(true), // get accent color + sleep(2 * Time.Second) // timeout request after 2 seconds + ]); mark(`image:fetch`);