diff --git a/bot.js b/bot.js index 1fa71ad..4bcf2f2 100644 --- a/bot.js +++ b/bot.js @@ -71,6 +71,8 @@ class Bot { .registerCommandModule(require('./lib/commands/AnilistApiCommands').module, {}); await this.messageHandler .registerCommandModule(require('./lib/commands/UtilityCommands').module, {bot: this, logger: logger, config: config}); + await this.messageHandler + .registerCommandModule(require('./lib/commands/InfoCommands').module, {client: this.client}); //this.registerCommands(); this.registerCallbacks(); cmd.init(prefix); diff --git a/lib/CommandLib.js b/lib/CommandLib.js index 5381a3a..07ad8e1 100644 --- a/lib/CommandLib.js +++ b/lib/CommandLib.js @@ -130,8 +130,8 @@ class CommandHandler { * @param name {String} * @param command {Command} */ - registerCommand(name, command) { - this.commands[name] = command; + registerCommand(command) { + this.commands[command.name] = command; } } diff --git a/lib/MessageLib.js b/lib/MessageLib.js index 588e32e..8545021 100644 --- a/lib/MessageLib.js +++ b/lib/MessageLib.js @@ -58,7 +58,7 @@ class MessageHandler { _registerEvents() { this.logger.debug('Registering message event...'); this.discordClient.on('message', async (msg) => { - this.logger.debug(`<${msg.channel.name || 'PRIVATE'}> ${msg.author.name}: ${msg.content}`); + this.logger.debug(`<${msg.guild? msg.channel.name+'@'+msg.guild.name : 'PRIVATE'}> ${msg.author.tag}: ${msg.content}`); if (msg.author !== this.discordClient.user) { let sequence = this._parseSyntax(msg); this.logger.debug(`Syntax parsing returned: ${JSON.stringify(sequence)}`); @@ -78,12 +78,12 @@ class MessageHandler { this.logger.debug('Parsing command sequence...'); let commandSequence = []; let content = message.content; - let strings = content.match(/".+?"/g); + let strings = content.match(/".+?"/g) || []; - for (let string in strings) - content.replace(string, string // escape all special chars - .replace(';', '\\;')) - .replace('&', '\\&'); + for (let string of strings) + content = content.replace(string, string // escape all special chars + .replace(';', '\\;') + .replace('&', '\\&')); let independentCommands = content // independent command sequende with ; .split(/(? x.replace(/^ +/, '')); diff --git a/lib/commands/AnilistApiCommands/index.js b/lib/commands/AnilistApiCommands/index.js index de844ef..160b645 100644 --- a/lib/commands/AnilistApiCommands/index.js +++ b/lib/commands/AnilistApiCommands/index.js @@ -78,8 +78,8 @@ class AniListCommandModule extends cmdLib.CommandModule { ); // registering commands - commandHandler.registerCommand(this.template.anime_search.name, animeSearch); - commandHandler.registerCommand(this.template.manga_search.name, mangaSearch); + commandHandler.registerCommand(animeSearch); + commandHandler.registerCommand(mangaSearch); } } diff --git a/lib/commands/InfoCommands/index.js b/lib/commands/InfoCommands/index.js index e69de29..3063fe5 100644 --- a/lib/commands/InfoCommands/index.js +++ b/lib/commands/InfoCommands/index.js @@ -0,0 +1,72 @@ +const cmdLib = require('../../CommandLib'), + utils = require('../../utils'), + location = './lib/commands/InfoCommands'; + +/** + * Info commands provide information about the bot. These informations are + * not process specific but access the discord client instance of the bot. + */ + +class InfoCommandModule extends cmdLib.CommandModule { + + /** + * @param opts {Object} properties: + * client - the instance of the discord client. + */ + constructor(opts) { + super(cmdLib.CommandScopes.Global); + this.templateFile = location + '/InfoCommandsTemplate.yaml'; + this.client = opts.client; + } + + async register(commandHandler) { + await this._loadTemplate(); + + let about = new cmdLib.Command( + this.template.about, + new cmdLib.Answer(() => { + return new cmdLib.ExtendedRichEmbed('About') + .setDescription(this.template.about.response.about_creator) + .addField('Icon', this.template.about.response.about_icon); + }) + ); + + let ping = new cmdLib.Command( + this.template.ping, + new cmdLib.Answer(() => { + return `Current average ping: \`${this.client.ping} ms\``; + }) + ); + + let uptime = new cmdLib.Command( + this.template.uptime, + new cmdLib.Answer(() => { + let uptime = utils.getSplitDuration(this.client.uptime); + return new cmdLib.ExtendedRichEmbed('Uptime').setDescription(` + **${uptime.days}** days + **${uptime.hours}** hours + **${uptime.minutes}** minutes + **${uptime.seconds}** seconds + **${uptime.milliseconds}** milliseconds + `).setTitle('Uptime'); + }) + ); + + let guilds = new cmdLib.Command( + this.template.guilds, + new cmdLib.Answer(() => { + return `Number of guilds: \`${this.client.guilds.size}\``; + }) + ); + + // register commands + commandHandler.registerCommand(about); + commandHandler.registerCommand(ping); + commandHandler.registerCommand(uptime); + commandHandler.registerCommand(guilds); + } +} + +Object.assign(exports, { + 'module': InfoCommandModule +}); diff --git a/lib/commands/UtilityCommands/index.js b/lib/commands/UtilityCommands/index.js index e69de29..e2c198c 100644 --- a/lib/commands/UtilityCommands/index.js +++ b/lib/commands/UtilityCommands/index.js @@ -0,0 +1,113 @@ +const cmdLib = require('../../CommandLib'), + location = './lib/commands/UtilityCommands'; + +/** + * Utility commands are all commands that allow the user to control the behaviour of the + * bot. Utility commands for example are allowed to: + * - manipulate the main database + * - manipulate the bot's presences + * - manipulate the process (e.g. shutdown) + */ + +class UtilityCommandModule extends cmdLib.CommandModule { + + /** + * @param opts {Object} properties: + * bot - the instance of the bot. + * logger - the instance of the logger. + * config - the config object + */ + constructor(opts) { + super(cmdLib.CommandScopes.User); + this.templateFile = location + '/UtilityCommandsTemplate.yaml'; + this.bot = opts.bot; + this.logger = opts.logger; + this.config = opts.config; + } + + async register(commandHandler) { + await this._loadTemplate(); + + let addPresence = new cmdLib.Command( + this.template.add_presence, + new cmdLib.Answer(async (m, k, s) => { + this.bot.presences.push(s); + await this.bot.maindb.run('INSERT INTO presences (text) VALUES (?)', [s]); + return `Added Presence \`${s}\``; + }) + ); + + let rotatePresence = new cmdLib.Command( + this.template.rotate_presence, + new cmdLib.Answer(() => { + try { + this.bot.client.clearInterval(this.rotator); + this.bot.rotatePresence(); + this.bot.rotator = this.bot.client.setInterval(() => this.bot.rotatePresence(), + this.config.presence_duration); + } catch (error) { + this.logger.warn(error.message); + } + }) + ); + + let shutdown = new cmdLib.Command( + this.template.shutdown, + new cmdLib.Answer(async (m) => { + try { + await m.reply('Shutting down...'); + this.logger.debug('Destroying client...'); + } catch (err) { + this.logger.error(err.message); + this.logger.debug(err.stack); + } + try { + await this.bot.client.destroy(); + this.logger.debug('Exiting server...'); + } catch (err) { + this.logger.error(err.message); + this.logger.debug(err.stack); + } + try { + await this.bot.webServer.stop(); + this.logger.debug(`Exiting Process...`); + process.exit(0); + } catch (err) { + this.logger.error(err.message); + this.logger.debug(err.stack); + } + }) + ); + + let createUser = new cmdLib.Command( + this.template.create_user, + new cmdLib.Answer(async (m, k) => { + if (k.username &&k.password && k.scope) { + this.logger.debug(`Creating user entry for ${k.username}`); + let token = await this.bot.webServer.createUser( + k.username, k.password, k.scope, false); + return `${k.username}'s token is ${token}`; + } + }) + ); + + let bugReport = new cmdLib.Command( + this.template.bugreport, + new cmdLib.Answer(() => { + return new cmdLib.ExtendedRichEmbed(this.template.bugreport.response.title) + .setDescription(this.template.bugreport.response.bug_report); + }) + ); + + // register commands + commandHandler.registerCommand(addPresence); + commandHandler.registerCommand(rotatePresence); + commandHandler.registerCommand(shutdown); + commandHandler.registerCommand(createUser); + commandHandler.registerCommand(bugReport); + } +} + +Object.assign(exports, { + 'module': UtilityCommandModule +});