diff --git a/structure/client/DiscordClient.js b/structure/client/DiscordClient.js index 5b8ccd3..7b4334d 100644 --- a/structure/client/DiscordClient.js +++ b/structure/client/DiscordClient.js @@ -130,6 +130,10 @@ class DiscordClient extends Client { return this._options.prefix; } + get storage() { + return this.storageManager; + } + } module.exports = DiscordClient; diff --git a/structure/client/components/commands/developer/Stats.js b/structure/client/components/commands/developer/Stats.js index 316117d..9e54d78 100644 --- a/structure/client/components/commands/developer/Stats.js +++ b/structure/client/components/commands/developer/Stats.js @@ -1,15 +1,14 @@ const { Command } = require('../../../../interfaces/'); +const os = require('os'); class StatsCommand extends Command { constructor(client) { super(client, { - name: 'about', + name: 'stats', module: 'developer', aliases: [ - 'stats', - 'info' ], usage: '', restricted: true, @@ -26,12 +25,12 @@ class StatsCommand extends Command { } - async execute(message, { params, args }) { + async execute(message) { // TODO: // Add some stuff that only shows when a dev runs the command, for instance amount of cached messages etc - const { guild } = message; + const { guild, author } = message; const { shard } = this.client; const evalFunc = (thisArg) => { @@ -54,20 +53,18 @@ class StatsCommand extends Command { const shardResults = await shard.broadcastEval(evalFunc).catch((error) => this.client.logger.error(error)); const managerResult = await this.client.managerEval(`(${mEvalFunc})(this)`).catch((error) => this.client.logger.error(error)); - const descValues = { - devs: await this.client.resolveUsers(this.client._options.bot.owners).then((owners) => { - return owners.map((o) => o.tag).join(', '); - }), - uptime: this.client.resolver.timeAgo(Math.floor(managerResult.uptime/1000)), + const mainValues = { + uptime: this.client.resolver.timeAgo(Math.floor(managerResult.uptime / 1000), true, true, true), memory: managerResult.memory, - shards: shard.count + shards: shard.count, + library: require('discord.js').version }; const shardValues = { cachedUsers: this.client.users.cache.size, guilds: this.client.guilds.cache.size, channels: this.client.channels.cache.size, - uptime: this.client.resolver.timeAgo(Math.floor(this.client.uptime/1000)), + uptime: this.client.resolver.timeAgo(Math.floor(this.client.uptime / 1000), true, true, true), memory: Math.floor(process.memoryUsage().heapUsed / 1024 / 1024) }; @@ -78,28 +75,83 @@ class StatsCommand extends Command { }); return acc; }, {}); - totalValues.uptime = this.client.resolver.timeAgo(Math.floor(totalValues.uptime / 1000)); + totalValues.uptime = this.client.resolver.timeAgo(Math.floor(totalValues.uptime / 1000), true, true, true); + + const CPU = os.cpus(); + const memoryFree = (os.freemem() / 1024 / 1024 / 1024).toFixed(1); + const memoryTotal = (os.totalmem() / 1024 / 1024 / 1024).toFixed(1); + + const sysInfo = { + devs: await this.client.resolveUsers(this.client._options.bot.owners).then((owners) => { + return owners.map((o) => o.tag).join(', '); + }), + cpu: CPU[0].model, + cores: CPU.length, + memoryUsed: memoryTotal - memoryFree, + memoryTotal, + osType: os.type(), + uptime: this.client.resolver.timeAgo(os.uptime(), true, true, true), + hostname: os.hostname() + }; + + const commands = this.client.registry.components.filter((comp) => comp.type === 'command'); + + const commandValues = { + invokes: commands.reduce((acc, cmd) => acc + cmd._invokes.success + cmd._invokes.fail, 0), + success: commands.reduce((acc, cmd) => acc + cmd._invokes.success, 0), + fail: commands.reduce((acc, cmd) => acc + cmd._invokes.fail, 0) + }; const embed = { title: message.format('C_STATS_TITLE', { client: this.client.user.tag, version: require('../../../../../package.json').version }), - description: message.format('C_STATS_DESC', descValues), + description: message.format('C_STATS_SYSTEM_VALUE', sysInfo), fields: [ + { + name: message.format('C_STATS_MAIN'), + value: message.format('C_STATS_MAIN_VALUE', mainValues), + inline: true + }, { name: message.format('C_STATS_CURRENT_SHARD', { shard: guild.shardID }), value: message.format('C_STATS_CURRENT_SHARDS_VALUE', shardValues), inline: true }, { - name: message.format('C_STATS_TOTAL', { shards: shard.count }), + name: message.format('C_STATS_TOTAL'), value: message.format('C_STATS_TOTAL_VALUE', totalValues), inline: true + }, + { + name: message.format('C_STATS_COMMANDS'), + value: message.format('C_STATS_COMMANDS_VALUE', commandValues), + inline: true } ] }; + if (author.developer) { + + //Mongo DB + const stats = await this.client.storage.mongodb.stats(); + const dbStats = { + db: stats.db, + collections: stats.collections, + objects: stats.objects, + avgObjSize: (stats.avgObjSize / 1024 / 1024).toFixed(1), + totalSize: (stats.dataSize / 1024 / 1024 / 1024).toFixed(2) + }; + + embed.fields.push({ + name: message.format('C_STATS_MONGODB'), + value: message.format('C_STATS_MONGODB_VALUE', dbStats), + inline: true + }); + + } + message.embed(embed); } diff --git a/structure/client/components/commands/information/Guild.js b/structure/client/components/commands/information/Guild.js index c40c54d..9a77328 100644 --- a/structure/client/components/commands/information/Guild.js +++ b/structure/client/components/commands/information/Guild.js @@ -92,6 +92,9 @@ class GuildCommand extends Command { ], thumbnail: { url: guild.iconURL() + }, + footer: { + text: `• Server ID: ${guild.id} • Shard ID: ${guild.shardID}` } }; diff --git a/structure/extensions/Message.js b/structure/extensions/Message.js index 02d2c41..a203af2 100644 --- a/structure/extensions/Message.js +++ b/structure/extensions/Message.js @@ -70,9 +70,11 @@ const Message = Structures.extend('Message', (Message) => { params: this.parameters, args: this.arguments }); + this.command._invokes.success++; if(resolved instanceof Promise) await resolved; return { error: false }; - } catch(error) { + } catch (error) { + this.command._invokes.fail++; return { error: true, message: error }; } diff --git a/structure/interfaces/Command.js b/structure/interfaces/Command.js index fa0e622..76210f3 100644 --- a/structure/interfaces/Command.js +++ b/structure/interfaces/Command.js @@ -43,6 +43,10 @@ class Command extends Component { }; this._throttles = new Map(); + this._invokes = { + success: 0, + fail: 0 + }; } diff --git a/structure/language/languages/en_us/commands/en_us_developer.lang b/structure/language/languages/en_us/commands/en_us_developer.lang index 80fd1f4..3c25482 100644 --- a/structure/language/languages/en_us/commands/en_us_developer.lang +++ b/structure/language/languages/en_us/commands/en_us_developer.lang @@ -5,10 +5,22 @@ Evaluates javascript code. Reloads components and language files. [C_STATS_TITLE] -Statistics for {client} ({version}). +Statistics for {client} ({version}) -[C_STATS_DESC] +[C_STATS_MAIN] +__**Main Process**__ + +[C_STATS_SYSTEM_VALUE] **Developers:** {devs} +**Hostname:** {hostname} +**CPU:** {cpu} +**Threads:** {cores} +**Memory:** {memoryUsed}/{memoryTotal}GB +**OS Type:** {osType} +**System Uptime:** {uptime} + +[C_STATS_MAIN_VALUE] +**Library:** {library} **Manager Uptime:** {uptime} **Managed Shards:** {shards} **Manager Memory Consumption:** {memory}MB @@ -31,4 +43,22 @@ __**All shards**__ **Guilds:** {guilds} **Channels:** {channels} **Average Uptime:** {uptime} -**Total Memory Consumption:** {memory}MB \ No newline at end of file +**Total Memory Consumption:** {memory}MB + +[C_STATS_COMMANDS] +__**Command usage since start**__ + +[C_STATS_COMMANDS_VALUE] +**Invokes:** {invokes} +**Succeeds:** {success} +**Fails:** {fail} + +[C_STATS_MONGODB] +__**MongoDB**__ + +[C_STATS_MONGODB_VALUE] +**Database:** {db} +**Collections:** {collections} +**Entries:** {objects} +**Average Entry Size:** {avgObjSize}MB +**Total DB Size:** {totalSize}GB diff --git a/structure/language/languages/en_us/commands/en_us_information.lang b/structure/language/languages/en_us/commands/en_us_information.lang index e2f09fa..51711a2 100644 --- a/structure/language/languages/en_us/commands/en_us_information.lang +++ b/structure/language/languages/en_us/commands/en_us_information.lang @@ -117,14 +117,12 @@ __Server information for **{name}**__ {emoji_booster3} **Boosters:** {boosters} {emoji_calendar} **Date created:** {createdAt} {emoji_region} **Voice region:** {region} -{emoji_id} **Server ID:** {id} -{emoji_id} **Shard ID:** {shard} [C_GUILD_MEMBERS_NAME] __Members__ [C_GUILD_MEMBERS] -{emoji_member} **Count:** +{emoji_members} **Count:** {memberCount}/{maxMembers} {emoji_online} **Online:** {approxPresences}/{maxPresences} diff --git a/structure/storage/interfaces/MongodbTable.js b/structure/storage/interfaces/MongodbTable.js index 94aee32..a0da0f2 100644 --- a/structure/storage/interfaces/MongodbTable.js +++ b/structure/storage/interfaces/MongodbTable.js @@ -124,7 +124,7 @@ class MongodbTable { } //Statistics - statistics(options = {}) { + stats(options = {}) { return new Promise((resolve, reject) => { if(!this.provider._initialized) return reject(new Error('MongoDB is not connected.')); this.collection.stats(options, (error, statistics) => { diff --git a/structure/storage/providers/Mongodb.js b/structure/storage/providers/Mongodb.js index 7ba8b4f..b88a126 100644 --- a/structure/storage/providers/Mongodb.js +++ b/structure/storage/providers/Mongodb.js @@ -25,6 +25,20 @@ class MongoDBProvider extends Provider { } + stats(options = {}) { + + return new Promise((resolve, reject) => { + + if (!this._initialized) return reject(new Error('MongoDB is not connected.')); + this.db.stats(options, (error, result) => { + if (error) reject(error); + resolve(result); + }); + + }); + + } + get guilds() { return this.tables.guilds; }