diff --git a/.gitignore b/.gitignore index b3112e0..0852168 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ logs emojis.json # API -api \ No newline at end of file +src/middleware/api \ No newline at end of file diff --git a/src/middleware/BaseClient.js b/src/middleware/BaseClient.js index 3139d64..7e18c29 100644 --- a/src/middleware/BaseClient.js +++ b/src/middleware/BaseClient.js @@ -1,4 +1,5 @@ const { EventEmitter } = require('events'); +const os = require('os'); const SlashCommandManager = require('./rest/SlashCommandManager.js'); const { ShardingManager } = require('./shard/'); @@ -16,6 +17,7 @@ class BaseClient extends EventEmitter { this.logger = new Logger(this, options.logger); this.version = version; + this.readyAt = null; this._options = options; this._built = false; @@ -26,7 +28,20 @@ class BaseClient extends EventEmitter { async build() { - await this.shardingManager.spawn(); + await this.shardingManager.spawn().catch((err) => { + this.error(`Fatal error during shard spawning:\n${err.stack}`); + // eslint-disable-next-line no-process-exit + process.exit(); // Prevent a boot loop when shards die due to an error in the client + }); + + const API = await import('./api/index.js').catch((err) => this.warn(`Error importing API files:\n${err.stack}`)); + if (API) { + this.info('Booting up API'); + const { default: APIManager } = API; + this.api = new APIManager(this); + await this.api.init(); + this.info('API ready.'); + } await this.slashCommandManager.global([ { @@ -35,11 +50,86 @@ class BaseClient extends EventEmitter { } ]); + this._built = true; + this.readyAt = Date.now(); + } _handleMessage(shard, message) { - if(message._logger) return this.logger._handleMessage(shard, message); - if(message._commands) return this.slashCommandManager._handleMessage(message); + if (message._logger) return this.logger._handleMessage(shard, message); + if (message._commands) return this.slashCommandManager._handleMessage(message); + if (message._api) return this.apiRequest(shard, message); + } + + apiRequest(shard, message) { + + const { type } = message; + switch (type) { + case 'stats': + this.aggregateStatistics(shard, message); + break; + } + + } + + async aggregateStatistics(shard, message) { + console.log('AGGREGATE STATS!'); + + const managerData = { + memory: process.memoryUsage().heapUsed, // Bytes + uptime: Date.now() - this.readyAt, + managedShards: this.shardingManager.shards.size + }; + + const CPU = os.cpus(); + const freeMemory = os.freemem(); + const totalMemory = os.totalmem(); + const systemData = { + cpu: CPU[0].model.trim(), + threads: CPU.length, + memory: { + used: totalMemory - freeMemory, + total: totalMemory + }, + osType: os.type(), + uptime: os.uptime(), + hostname: os.hostname() + }; + + const clientData = { + library: { + name: 'Discord.js', + version: require('discord.js').version + }, + shardData: [] + }; + + const databaseData = { + + }; + + const data = { + systemData, + clientData, + databaseData, + managerData, + timestamp: Date.now() + }; + + shard.send({ success: true, id: message.id, data }); + + } + + warn(message) { + this.logger.write('warn', message); + } + + info(message) { + this.logger.write('info', message); + } + + error(message) { + this.logger.write('error', message); } } diff --git a/src/middleware/Logger.js b/src/middleware/Logger.js index 12fed75..7c9e25d 100644 --- a/src/middleware/Logger.js +++ b/src/middleware/Logger.js @@ -43,14 +43,14 @@ class Logger { } - write(type = 'info', string = '', shard = null) { + write(type = 'info', string = '', shard = null, api = false) { type = type.toLowerCase(); let color = Constants.Colors[type]; if(!color) color = Constants.Colors.info; - const header = `${chalk[color](`[${Util.date}][${shard ? `shard${this._shardId(shard)}` : 'manager'}]`)}`; + const header = `${chalk[color](`[${Util.date}][${shard ? `${api ? 'api-' : ''}shard${this._shardId(shard)}` : `${api ? 'api-' : ''}manager`}]`)}`; const maximumCharacters = Math.max(...Constants.Types.map((t) => t.length)); const spacers = maximumCharacters - type.length; @@ -97,7 +97,7 @@ class Logger { //Messages coming from the shards process.send functions. _handleMessage(shard, message) { - this.write(message.type, message.message, shard); + this.write(message.type, message.message, shard, message._api); } _shardId(shard) {