diff --git a/config.json.sample b/config.json.sample index 1f1501e..be6de54 100644 --- a/config.json.sample +++ b/config.json.sample @@ -13,7 +13,7 @@ }, "admins": [ "batman" ], "moderators": [ "whatever" ], - "moduleNames": [ "ignore", "admin", "command", "dice", "js", "kick", "quotes", "spelling", "youare", "stats", "users" ], + "moduleNames": [ "ignore", "admin", "command", "dice", "js", "kick", "quotes", "spelling", "youare", "stats", "users", "link" ], "language": "en", "debugMode": true, "version": "Depressionbot IRC bot 0.4-dev - Lovingly crafted by The DepressionBot Foundation (a charity arm of the Official Aberystwyth Open Source International Development League)." diff --git a/install.sh b/install.sh index 8a8d85d..d175afb 100755 --- a/install.sh +++ b/install.sh @@ -3,6 +3,17 @@ cat LICENCE git submodule init git submodule update +if [ ! -e /usr/bin/node ] && [ ! -e /usr/local/bin/node ]; +then + echo 'node.js is not installed. Please install it before running install.sh.' + exit 1 +fi +if [ ! -e /usr/bin/npm ] && [ ! -e /usr/local/bin/npm ]; +then + echo 'npm is not installed. Please install it before running install.sh' + exit 1 +fi + npm install underscore request sandbox express moment jade@0.25 cd public/ diff --git a/modules/admin/commands.js b/modules/admin/commands.js index c648760..b272d8f 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -23,10 +23,10 @@ var commands = function(dbot) { return false; } } - } + } var currentOption; - if(configKey.length != 1) { + if(configKey && configKey.length != 1) { configKey = _.last(configKey); if(_.has(userConfigPath, configKey) && !_.isUndefined(userConfigPath[configKey])) { currentOption = userConfigPath[configKey]; @@ -173,8 +173,10 @@ var commands = function(dbot) { var moduleName = event.params[1]; if(_.include(moduleNames, moduleName)) { var moduleDir = '../' + moduleName + '/'; - var cacheKey = require.resolve(moduleDir + moduleName); - delete require.cache[cacheKey]; + try { + var cacheKey = require.resolve(moduleDir + moduleName); + delete require.cache[cacheKey]; + } catch(err) { } dbot.config.moduleNames = _.without(dbot.config.moduleNames, moduleName); dbot.reloadModules(); @@ -184,32 +186,6 @@ var commands = function(dbot) { } }, - // Ban user from command or * - 'ban': function(event) { - var username = event.params[1]; - var command = event.params[2]; - - if(!_.has(dbot.db.bans, command)) { - dbot.db.bans[command] = [ ]; - } - dbot.db.bans[command].push(username); - event.reply(dbot.t('banned', {'user': username, 'command': command})); - }, - - // Unban a user from command or * - 'unban': function(event) { - var username = event.params[1]; - var command = event.params[2]; - if(_.has(dbot.db.bans, command) && _.include(dbot.db.bans[command], username)) { - _.reject(dbot.db.bans[command], function(bans) { - return bans == username; - }, this); - event.reply(dbot.t('unbanned', {'user': username, 'command': command})); - } else { - event.reply(dbot.t('unban_error', {'user': username})); - } - }, - /*** Config options ***/ 'setconfig': function(event) { @@ -291,19 +267,15 @@ var commands = function(dbot) { } }; - commands['greload'].access = 'admin'; - commands['reload'].access = 'admin'; - commands['unload'].access = 'admin'; - commands['load'].access = 'admin'; - commands['version'].access = 'admin'; - commands['setconfig'].access = 'admin'; + _.each(commands, function(command) { + command.access = 'admin'; + }); + commands['showconfig'].access = 'moderator'; commands['join'].access = 'moderator'; commands['part'].access = 'moderator'; commands['opme'].access = 'moderator'; commands['say'].access = 'moderator'; - commands['ban'].access = 'moderator'; - commands['unban'].access = 'moderator'; return commands; }; diff --git a/modules/admin/config.json b/modules/admin/config.json index 009fb85..f87d4b9 100644 --- a/modules/admin/config.json +++ b/modules/admin/config.json @@ -1,6 +1,5 @@ { "ignorable": false, - "dbKeys": [ "bans" ], "dependencies": [ "command" ], "help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md" } diff --git a/modules/command/api.js b/modules/command/api.js index 51202e9..dd19b9e 100644 --- a/modules/command/api.js +++ b/modules/command/api.js @@ -4,8 +4,10 @@ var api = function(dbot) { return { 'isBanned': function(user, command) { var banned = false; - if(_.has(dbot.db.bans, command)) { - if(_.include(dbot.db.bans[command], user) || _.include(dbot.db.bans['*'], user)) { + if(_.has(dbot.db.bans, user)) { + if(_.include(dbot.db.bans[user], command) || + _.include(dbot.db.bans[user], dbot.commands[command].module) || + _.include(dbot.db.bans[user], '*')) { banned = true; } } @@ -39,7 +41,8 @@ var api = function(dbot) { 'isIgnoring': function(item, command) { var module = dbot.commands[command].module; return (_.has(dbot.db.ignores, item) && - _.include(dbot.db.ignores[item], module)); + (_.include(dbot.db.ignores[item], module) || + _.include(dbot.db.ignores[item], '*'))); }, /** diff --git a/modules/command/commands.js b/modules/command/commands.js index 96ac77a..68d7a28 100644 --- a/modules/command/commands.js +++ b/modules/command/commands.js @@ -18,8 +18,27 @@ var commands = function(dbot) { '~help': function(event) { var moduleName = event.params[1]; + if(!moduleName) { + helpfulModules = _.filter(dbot.modules, function(element, index, array) { + return _.has(dbot.config[element], 'help'); + }); + + event.reply(dbot.t('usage', { + 'command': '~help', + 'usage': '~help [module]' + })); + event.reply(dbot.t('loaded_modules_with_help', { + 'modules': helpfulModules.join(', ') + })); + return; + } + if(!_.has(dbot.modules, moduleName)) { - var moduleName = dbot.commands[moduleName].module; + if(_.has(dbot.commands, moduleName)) { + var moduleName = dbot.commands[moduleName].module; + } else { + var moduleName = undefined; + } } if(moduleName && _.has(dbot.config[moduleName], 'help')) { diff --git a/modules/command/config.json b/modules/command/config.json index f7de9b5..bace93b 100644 --- a/modules/command/config.json +++ b/modules/command/config.json @@ -1,5 +1,5 @@ { "ignorable": false, "help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md", - "dbKeys": [ "ignores" ] + "dbKeys": [ "ignores", "bans" ] } diff --git a/modules/command/strings.json b/modules/command/strings.json index 676532e..341aae2 100644 --- a/modules/command/strings.json +++ b/modules/command/strings.json @@ -26,5 +26,8 @@ "no_help": { "en": "No help found for {module}.", "na'vi": "Fì{module}ìri oel ke tsun run srungit" + }, + "loaded_modules_with_help": { + "en": "Loaded modules with help information: {modules}." } } diff --git a/modules/command/usage.json b/modules/command/usage.json new file mode 100644 index 0000000..8aaf80e --- /dev/null +++ b/modules/command/usage.json @@ -0,0 +1,4 @@ +{ + "~usage": "~usage [command]", + "~help": "~help [module]" +} diff --git a/modules/dns/README.md b/modules/dns/README.md new file mode 100644 index 0000000..f730352 --- /dev/null +++ b/modules/dns/README.md @@ -0,0 +1,17 @@ +## DNS + +Performs and reports upon basic DNS functions. + +### Description + +This module utilises the domain name system to discover basic information about +domain names and IP addresses. + +### Commands + +#### ~lookup [domain name] +Looks up the specified domain name in the domain name system. If a match is found, +the first corresponding A or AAAA record is displayed. +#### ~rdns [IP address] +Looks up the specified IP address in the domain name system. If a match is found, +the first corresponding rDNS domain name is displayed. diff --git a/modules/dns/dns.js b/modules/dns/dns.js new file mode 100644 index 0000000..e061d83 --- /dev/null +++ b/modules/dns/dns.js @@ -0,0 +1,37 @@ +/** + * Module Name: DNS + * Description: Performs and reports on basic DNS functions. + */ +var dnsmod = require('dns'); + +var dns = function(dbot) { + var commands = { + '~lookup': function(event) { + domain = event.params[1]; + dnsmod.lookup(domain, function (error, addr) { + if (error) { + event.reply(dbot.t("lookup-error",{"domain": domain, "code": error.code})); + } else { + event.reply(dbot.t("lookup",{"domain": domain, "address": addr})); + } + }); + }, + '~rdns': function(event) { + ip = event.params[1]; + dnsmod.reverse(ip, function (error, domain) { + if (error) { + event.reply(dbot.t("rdns-error",{"domain": domain, "ip": ip, "error": error.code})); + } else { + event.reply(dbot.t("rdns",{"domain": domain, "ip": ip})); + } + }); + } + }; + this.commands = commands; + + this.on = 'PRIVMSG'; +}; + +exports.fetch = function(dbot) { + return new dns(dbot); +}; diff --git a/modules/dns/strings.json b/modules/dns/strings.json new file mode 100644 index 0000000..f8c69bc --- /dev/null +++ b/modules/dns/strings.json @@ -0,0 +1,14 @@ +{ + "lookup-error": { + "en": "{domain} is \u000303AVAILABLE! \u000314({code})" + }, + "lookup": { + "en": "{domain} is \u000305TAKEN! \u000314({address})" + }, + "rdns": { + "en": "{ip} \u2192 {domain}" + }, + "rdns-error": { + "en": "Unable to lookup {ip}. \u000314({error})" + } +} diff --git a/modules/finger/README.md b/modules/finger/README.md deleted file mode 100644 index 549e850..0000000 --- a/modules/finger/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## Finger - -Retrieves user information from a remote server. - -### Description -Uses the ``finger`` command to retrieve limited information on users. - - -### Commands -###~finger [username] -Returns the real name of the user specified. -### Dependencies -* ``npm install request`` diff --git a/modules/finger/finger.js b/modules/finger/finger.js deleted file mode 100644 index f0a2e34..0000000 --- a/modules/finger/finger.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Module Name: Finger - * Description: Returns the name of users via the Finger protocol - */ -var request = require('request'), - _ = require('underscore')._, - exec = require('child_process').exec; - -var finger = function(dbot) { - var commands = { - '~finger': function(event) { - var username = event.params[1]; - exec("finger -s " + username + "@central.aber.ac.uk",function(error,stdout,stderr){ - stdout = stdout.replace(/(\r\n|\n|\r)/gm,""); - name = stdout.search("Name:"); - stdout = stdout.substring(name); - ret = stdout.search("Dir"); - stdout = stdout.substring(6,ret); - if (stdout == "Welcom") { - event.reply(dbot.t("nonexistent",{user: username})); - } else { - event.reply(dbot.t("name",{user: username, name: stdout})); - } - }); - } - }; - this.commands = commands; - - this.on = 'PRIVMSG'; -}; - -exports.fetch = function(dbot) { - return new finger(dbot); -}; diff --git a/modules/finger/strings.json b/modules/finger/strings.json deleted file mode 100644 index 710e0f5..0000000 --- a/modules/finger/strings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": { - "en": "{user} is {name}." - }, - "nonexistent": { - "en": "{user} not found." - } -} diff --git a/modules/ignore/config.json b/modules/ignore/config.json index fa1961a..14e12c2 100644 --- a/modules/ignore/config.json +++ b/modules/ignore/config.json @@ -1,6 +1,6 @@ { "ignorable": false, "dependencies": [ "command" ], - "dbKeys": [ "ignores" ], + "dbKeys": [ "ignores", "bans" ], "help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md" } diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index 9fa9eac..3e3d974 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -24,7 +24,7 @@ var ignore = function(dbot) { 'modules': ignorableModules.join(', ') })); } else { - if(_.include(ignorableModules, module)) { + if(module == '*' || _.include(ignorableModules, module)) { if(_.has(dbot.db.ignores, event.user) && _.include(dbot.db.ignores[event.user], module)) { event.reply(dbot.t('already_ignoring', { 'user': event.user })); } else { @@ -72,12 +72,72 @@ var ignore = function(dbot) { } }, + '~ban': function(event) { + var user = event.params[1]; + var module = event.params[2]; + + if(_.isUndefined(user) || _.isUndefined(module)) { + event.reply(dbot.t('ban_usage', {'user': event.user})); + return; + } + + if(module == '*' || _.include(dbot.config.moduleNames, module) || _.include(dbot.commands, module)) { + if(_.has(dbot.db.bans, user) && _.include(dbot.db.bans[user], module)) { + event.reply(dbot.t('already_banned', { + 'user': event.user, + 'banned': user + })); + return; + } + + if(_.has(dbot.db.bans, event.params[1])) { + dbot.db.bans[event.params[1]].push(module); + } else { + dbot.db.bans[event.params[1]] = [module]; + } + + event.reply(dbot.t('banned_success', { + 'user': event.user, + 'banned': user, + 'module': module + })); + } else { + event.reply(dbot.t('invalid_ban', {'user': event.user})); + } + }, + + '~unban': function(event) { + var bannedModules = []; + + var user = event.params[1]; + var module = event.params[2]; + + if(_.isUndefined(user) || _.isUndefined(module)) { + event.reply(dbot.t('unban_usage', {'user': event.user})); + } else { + if(_.has(dbot.db.bans, user) && _.include(dbot.db.bans[user], module)) { + dbot.db.bans[user].splice(dbot.db.bans[user].indexOf(module), 1); + + event.reply(dbot.t('unbanned_success', { + 'user': event.user, + 'banned': user, + 'module': module + })); + } else { + event.reply(dbot.t('invalid_unban', { + 'user': event.user, + 'banned': user + })); + } + } + }, + '~ignorechannel': function(event) { var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]); var module = event.params[2]; // Ignoring the value of 'ignorable' at the moment - if(_.include(dbot.config.moduleNames, module)) { + if(module == '*' || _.include(dbot.config.moduleNames, module)) { if(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = []; if(!_.include(dbot.db.ignores[channel], module)) { dbot.db.ignores[channel].push(module); @@ -118,6 +178,8 @@ var ignore = function(dbot) { } }; + commands['~ban'].access = 'moderator'; + commands['~unban'].access = 'moderator'; commands['~ignorechannel'].access = 'moderator'; commands['~unignorechannel'].access = 'moderator'; diff --git a/modules/ignore/strings.json b/modules/ignore/strings.json index 8202cb0..0badd2a 100644 --- a/modules/ignore/strings.json +++ b/modules/ignore/strings.json @@ -41,6 +41,27 @@ "na'vi": "{user}: Nga terìng mikyun {module}ne set", "cy": "{user}: Ddim yn anwybyddu {module} bellach" }, + "ban_usage": { + "en": "{user}: Usage: ~ban [user] [module/command]. Use * for all modules and commands." + }, + "already_banned": { + "en": "{user}: {banned} is already banned from that module." + }, + "banned_success": { + "en": "{user}: {banned} is now banned from {module}." + }, + "invalid_ban": { + "en": "{user}: That isn't a valid module name." + }, + "unban_usage": { + "en": "{user}: Usage: ~unban [user] [module]." + }, + "invalid_unban": { + "en": "{user}: {banned} is not banned from that module or it doesn't exist." + }, + "unbanned_success": { + "en": "{user}: {banned} is no longer banned from {module}." + }, "ignoring_channel": { "en": "Now ignoring {module} in {channel}", "na'vi": "Oe ke stayawm {module}ur mì {channel}" diff --git a/modules/link/link.js b/modules/link/link.js index 2d9c994..e07c178 100644 --- a/modules/link/link.js +++ b/modules/link/link.js @@ -16,7 +16,7 @@ var link = function(dbot) { body = body.replace(/(\r\n|\n\r|\n)/gm, " "); var title = body.valMatch(/