const { EventEmitter } = require('events'); // eslint-disable-next-line no-unused-vars const { inspect } = require('util'); const os = require('os'); const ShardManager = require('./middleware/ShardManager.js'); const Logger = require('./middleware/logger/Logger.js'); class Manager extends EventEmitter { constructor(options) { super(); this.shardManager = new ShardManager('./structure/client/DiscordClient.js', options); this.logger = new Logger(this); this._built = false; this.readyAt = null; this.shardManager.on('message', this._handleMessage.bind(this)); // this.on('built', () => { // this.shardManager.broadcast({ _built: true }); // }); } _handleMessage(shard, message) { if (message._mEval) return this.eval(shard, message); // Messages coming from the API that have the _logger flag will be caught here, i.e. both flags should be on if (message._logger) return this.logger._handleMessage(shard, message); if (message._webhook) return undefined; //todo if (message._api) return this.apiRequest(shard, message); } async build() { this.info('Spawning shards...'); await this.shardManager.spawn(); // G:\Documents\My programs\GBot\New GBot\api\index.cjs this.info('Shards done, booting up API...'); const API = await import('./api/index.js').catch(() => this.warn(`Import of API Manager failed. Skipping API.`)); if (API) { const { default: APIManager } = API; this.apiManager = new APIManager(this); await this.apiManager.init(); this.info('API done. Manager built.'); } else this.info('Missing API source, skipping'); this._built = true; this.emit('built'); this.readyAt = Date.now(); } /** * * * @param {*} shard The shard from which the eval came and to which it will be returned * @param {*} script The script to be executed * @memberof Manager * @private */ async eval(shard, { script }) { this.info(`Incoming manager eval from shard ${shard.id}:\n${script}`); let result = null, error = null; try { // eslint-disable-next-line no-eval result = eval(script); if (result instanceof Promise) result = await result; //if(typeof result !== 'string') result = inspect(result); } catch (err) { error = err.stack || err; } return shard.send({ _evalResult: true, script, result, error }); } async apiRequest(shard, message) { const { type } = message; switch (type) { case 'statsQuery': break; // TODO: Figure out best strategy for stats querying - push/pull, prometheus, simple polling //return this.aggregateStatistics(); } } async aggregateStatistics() { const managerData = { memory: process.memoryUsage().heapUsed, // Bytes uptime: Date.now() - this.readyAt, library: { name: 'Discord.js', versionersion: require('discord.js').version }, managedShards: this.shardManager.shards.size }; const CPU = os.cpus(); const freeMemory = os.freemem(); const totalMemory = os.totalmem(); const systemData = { cpu: CPU[0].model, cores: CPU.length, memory: { used: totalMemory - freeMemory, total: totalMemory }, osType: os.type(), uptime: os.uptime(), hostname: os.hostname() }; } get uptime() { return this.readyAt !== null ? Date.now() - this.readyAt : 0; } info(message) { this.logger.write('info', message); } warn(message) { this.logger.write('warn', message); } error(message) { this.logger.write('error', message); } } module.exports = Manager;