From c418cbbc903dbab78eb71e5edd193929328d7514 Mon Sep 17 00:00:00 2001 From: Daryl Ronningen Date: Sat, 19 Jun 2021 15:54:25 -0700 Subject: [PATCH] feat: added checking of config JSON schema in startup --- config/default.json.example | 2 +- config/tests.json | 2 +- src/index.ts | 42 +++++++++++++++++++++++++++++---- src/lib/utils/defaults.ts | 46 +++++++++++++++++++++++++++++++++++++ src/lib/utils/logger.ts | 4 +--- src/lib/utils/types.ts | 2 ++ 6 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 src/lib/utils/defaults.ts diff --git a/config/default.json.example b/config/default.json.example index be9820e..ab13c68 100644 --- a/config/default.json.example +++ b/config/default.json.example @@ -1,4 +1,4 @@ { "token": "", - "loglevel": "info" + "logLevel": "info" } \ No newline at end of file diff --git a/config/tests.json b/config/tests.json index 362164b..60520ee 100644 --- a/config/tests.json +++ b/config/tests.json @@ -1,3 +1,3 @@ { - "loglevel": "verbose" + "logLevel": "verbose" } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 32444bb..780def7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,19 +16,44 @@ */ require('module-alias/register'); +import process from 'process'; import { Client } from 'discord.js'; import figlet from 'figlet'; import gradient from 'gradient-string'; -// import config from 'config'; -import { debug, error, info } from '@utils/logger'; +import config from 'config'; +import { Validator } from 'jsonschema'; +import { DateTime } from 'luxon'; +import chalk from 'chalk'; +import { debug, error, info, verbose } from '@utils/logger'; import { ELoggingScope } from '@utils/types'; +import { Defaults } from '@utils/defaults'; -debug('Starting bot... Please wait!', ELoggingScope.Startup); +info('Starting bot... Please wait!', ELoggingScope.Startup); +debug('Checking config JSON schema', ELoggingScope.Startup); + +const mergedConfig = config.util.extendDeep(Defaults.config, config.util.loadFileConfigs(`${process.cwd()}/config`)); + +const schemaValidator = new Validator(); +const validate = schemaValidator.validate(mergedConfig, Defaults.configSchema); + +if (validate.valid) { + debug('Config matches JSON schema', ELoggingScope.Startup); +} else { + // Manually send fatal message in case someone messes up the logLevel JSON schema + const message = `Found some errors with the config! Please check errors below.\n${validate.errors}`; + + const date = DateTime.now().toLocal().setLocale(Intl.DateTimeFormat().resolvedOptions().locale).toFormat('yyyy-LL-dd HH:mm:ss'); + const splitMultiline = message.split('\n'); + + splitMultiline.forEach((val) => { + console.log(chalk`{grey (${date})} {magenta.bold ${ELoggingScope.Startup}} {red.bold.underline [FATAL]}: {red.underline ${val}}`); + }); +} figlet('Argon Bot', (err, data) => { if (err) error(`Figlet encountered an error!\n${err.message}`); - info(gradient.rainbow.multiline(`\n${data}`)); + info(gradient.rainbow.multiline(`\n${data}`), ELoggingScope.Startup); }); const client = new Client({ @@ -36,7 +61,14 @@ const client = new Client({ }); client.on('ready', () => { + debug(`Total number of Servers: ${client.guilds.cache.size}`, ELoggingScope.Startup); + debug(`Total number of Users: ${client.users.cache.size}`, ELoggingScope.Startup); + info('Bot is ready!', ELoggingScope.Startup); }); -//client.login(token); +client.on('raw', (payload) => { + verbose(JSON.stringify(payload, null, 2), ELoggingScope.Payload); +}); + +client.login(config.get('token')); diff --git a/src/lib/utils/defaults.ts b/src/lib/utils/defaults.ts new file mode 100644 index 0000000..6d06d76 --- /dev/null +++ b/src/lib/utils/defaults.ts @@ -0,0 +1,46 @@ +/* + * This file is part of ArgonBot + * + * ArgonBot is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ArgonBot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ArgonBot. If not, see . + */ +export const Defaults = { + config: { + logLevel: 'info', + }, + configSchema: { + $id: 'http://example.com/example.json', + $schema: 'http://json-schema.org/draft-07/schema', + required: ['token', 'logLevel'], + type: 'object', + properties: { + token: { + $id: '#/properties/token', + type: 'string', + }, + logLevel: { + $id: '#/properties/logLevel', + type: 'string', + enum: [ + 'verbose', + 'debug', + 'info', + 'warn', + 'error', + 'fatal', + ], + }, + }, + additionalProperties: false, + }, +}; diff --git a/src/lib/utils/logger.ts b/src/lib/utils/logger.ts index 222b9d1..a704aba 100644 --- a/src/lib/utils/logger.ts +++ b/src/lib/utils/logger.ts @@ -20,8 +20,6 @@ import { DateTime } from 'luxon'; import type { ELoggingScope } from './types'; -chalk.Level = 3; - let verboseLevel = false; let debugLevel = false; let infoLevel = false; @@ -29,7 +27,7 @@ let warnLevel = false; let errorLevel = false; let fatalLevel = false; -switch ((config.get('loglevel') as string).toLowerCase()) { +switch ((config.get('logLevel') as string).toLowerCase()) { case 'verbose': verboseLevel = true; debugLevel = true; diff --git a/src/lib/utils/types.ts b/src/lib/utils/types.ts index 3ee5a99..1b3a7f1 100644 --- a/src/lib/utils/types.ts +++ b/src/lib/utils/types.ts @@ -18,6 +18,8 @@ export enum ELoggingScope { Startup = 'STARTUP', Command = 'COMMAND', + Payload = 'PAYLOAD', + Query = 'QUERY', } // Interfaces