diff --git a/borgil.js b/borgil.js index fbd5bd6..a95b118 100644 --- a/borgil.js +++ b/borgil.js @@ -1,7 +1,8 @@ var Bot = require('./bot/bot'); - +var repl = require('repl'); var borgil = new Bot('config.json'); +repl.start('Borgil> ').context.bot = borgil; //borgil.use('echo'); //borgil.use('errortest'); @@ -12,5 +13,7 @@ borgil.use('rss'); borgil.use('sed'); borgil.use('url'); borgil.use('youtube'); -borgil.use('eightball'); +//borgil.use('eightball'); +//borgil.use('ircutil'); +borgil.use('plugin-manager'); diff --git a/bot/api.js b/bot/api.js index 04e298c..b8b7dee 100644 --- a/bot/api.js +++ b/bot/api.js @@ -7,6 +7,8 @@ var API = module.exports = function (bot, plugin_name) { this.config = bot.config; this.memory = bot.memory; +; + this.command_listeners = {}; require('../plugins/' + plugin_name).call(this, this); }; @@ -64,13 +66,11 @@ API.prototype.addCommand = function (command, callback, ignorePrivate, ignorePub else if (ignorePublic) type = 'pm'; if (!command) return; - var commands = [].concat(command).filter(function (cmd) { - return typeof cmd == 'string' && cmd; - }); - - this._bot.addListener(type, function (client, nick, target, text, msg) { + + api.command_listeners[command] = function (client, nick, target, text, msg) { var match = api.matchCommand(text); - if (match && commands.indexOf(match[1]) > -1) { + if (typeof match !== 'object') return; + if (match && api.command_listeners[match[1]]) { callPlugin(api, callback, { network: client.__network, nick: nick, @@ -81,7 +81,16 @@ API.prototype.addCommand = function (command, callback, ignorePrivate, ignorePub args: (match[2] || '').split(/\s+/) }); } - }); + }; + + this._bot.addListener(type, api.command_listeners[command]); +}; + + +// Remove a command listener. +API.prototype.removeCommand = function (command, plugin_name) { + var type = 'message'; + this._bot.removeListener(type, this._bot.plugins[plugin_name].command_listeners[command]); }; @@ -94,6 +103,30 @@ API.prototype.say = function (network, target) { }; +// Join a channel +API.prototype.join = function (network, channel) { + if (!this._bot.clients[network]) return; + + this._bot.clients[network].join(channel); +}; + + +// Leave a channel +API.prototype.part = function (network, channel) { + if (!this._bot.clients[network]) return; + + var msg = util.format.apply(null, Array.prototype.slice.call(arguments, 2)); + this._bot.clients[network].part(channel, msg); +}; + + +// Get whois info for a nickname +API.prototype.whois = function (network, nick, callback) { + if (!this._bot.clients[network]) return; + this._bot.clients[network].whois(nick, function (info) { callback(info); }); +}; + + // Add a line to the log API.prototype.log = function () { this._bot.log.info('%s:', this._plugin, util.format.apply(null, arguments)); diff --git a/bot/bot.js b/bot/bot.js index 5f168c4..92ca0de 100644 --- a/bot/bot.js +++ b/bot/bot.js @@ -7,6 +7,7 @@ var API = require('./api'); var Bot = module.exports = function (configfile) { this.clients = {}; this.plugins = {}; + this.memory = {}; // run the event emitter constructor @@ -27,3 +28,16 @@ util.inherits(Bot, EventEmitter); Bot.prototype.use = function (plugin_name) { this.plugins[plugin_name] = new API(this, plugin_name); }; + +// cut a plugin from the herd, leave it for dead +Bot.prototype.unlinkPlugin = function (plugin_name) { + if (this.plugins[plugin_name]) { + // get list of commands in plugin + // then remove their listeners + for (var cmd in this.plugins[plugin_name].command_listeners) { + this.plugins[plugin_name].removeCommand(cmd, plugin_name); + } + + delete this.plugins[plugin_name]; + } +}; diff --git a/plugins/eightball.js b/plugins/eightball.js index f497cb2..82950c3 100644 --- a/plugins/eightball.js +++ b/plugins/eightball.js @@ -1,5 +1,6 @@ var fs = require('fs'); + module.exports = function (bot) { var resps = []; diff --git a/plugins/ircutil.js b/plugins/ircutil.js new file mode 100644 index 0000000..e9988b9 --- /dev/null +++ b/plugins/ircutil.js @@ -0,0 +1,50 @@ +// Callback function (admin) {} +function checkForAdmin(nick, network, bot, callback) { + var admin = false; + var adminlist = bot.config.get('admins'); + var registered = false; + + bot.whois(network, nick, function (info) { + if (network === "oftc") { + var oftcre = /.*\.oftc\.net$/ + registered = oftcre.test(info.host); + } + if (registered) { + for (i = 0; i < adminlist.length; i++) { + if (adminlist[i] === nick) { + admin = true; + break; + } + } + } + callback(admin); + }); +} + +module.exports = function (bot) { + bot.addCommand('join', function (cmd) { + checkForAdmin(cmd.nick, cmd.network, bot, function (admin) { + if (admin) { + var chan = cmd.args[0]; + var p = cmd.args[1]; + + if (!chan) return bot.say(cmd.network, cmd.replyto, 'Usage: .join '); + if (p) { chan += ' '; chan += p; } + bot.join(cmd.network, chan); + } else { + bot.say(cmd.network, cmd.replyto, 'You\'re not my supervisor!'); + } + }); + }); + + bot.addCommand('part', function (cmd) { + checkForAdmin(cmd.nick, cmd.network, bot, function (admin) { + if (admin) { + var partmsg = cmd.args[0] || 'I\'ll show you.'; + bot.part(cmd.network, cmd.replyto, partmsg); + } else { + bot.say(cmd.network, cmd.replyto, 'You\'re not my supervisor!'); + } + }); + }); +}; diff --git a/plugins/plugin-manager.js b/plugins/plugin-manager.js new file mode 100644 index 0000000..b0848dd --- /dev/null +++ b/plugins/plugin-manager.js @@ -0,0 +1,25 @@ +module.exports = function (bot) { + bot.addCommand('plugin', function (cmd) { + var usage = "Usage: .plugin {load | unload | reload} "; + + if (!(cmd.args[0] && cmd.args[1])) { + bot.say(cmd.network, cmd.replyto, usage); + return; + } + + switch (cmd.args[0]) { + case 'unload': + bot._bot.unlinkPlugin(cmd.args[1]); + break; + case 'load': + bot._bot.use(cmd.args[1]); + break; + case 'reload': + bot._bot.unlinkPlugin(cmd.args[1]); + bot._bot.use(cmd.args[1]); + break; + default: + bot.say(cmd.network, cmd.replyto, usage); + } + }); +};