Merge git://github.com/reality/depressionbot into database. Also Users API now databankerised

Conflicts:
	modules/quotes/commands.js
This commit is contained in:
reality 2013-03-24 11:09:40 +00:00
commit cbc42e6fc3
28 changed files with 383 additions and 245 deletions

View File

@ -13,7 +13,7 @@
}, },
"admins": [ "batman" ], "admins": [ "batman" ],
"moderators": [ "whatever" ], "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", "language": "en",
"debugMode": true, "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)." "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)."

View File

@ -3,6 +3,17 @@ cat LICENCE
git submodule init git submodule init
git submodule update 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 npm install underscore request sandbox express moment jade@0.25
cd public/ cd public/

View File

@ -23,10 +23,10 @@ var commands = function(dbot) {
return false; return false;
} }
} }
} }
var currentOption; var currentOption;
if(configKey.length != 1) { if(configKey && configKey.length != 1) {
configKey = _.last(configKey); configKey = _.last(configKey);
if(_.has(userConfigPath, configKey) && !_.isUndefined(userConfigPath[configKey])) { if(_.has(userConfigPath, configKey) && !_.isUndefined(userConfigPath[configKey])) {
currentOption = userConfigPath[configKey]; currentOption = userConfigPath[configKey];
@ -173,8 +173,10 @@ var commands = function(dbot) {
var moduleName = event.params[1]; var moduleName = event.params[1];
if(_.include(moduleNames, moduleName)) { if(_.include(moduleNames, moduleName)) {
var moduleDir = '../' + moduleName + '/'; var moduleDir = '../' + moduleName + '/';
var cacheKey = require.resolve(moduleDir + moduleName); try {
delete require.cache[cacheKey]; var cacheKey = require.resolve(moduleDir + moduleName);
delete require.cache[cacheKey];
} catch(err) { }
dbot.config.moduleNames = _.without(dbot.config.moduleNames, moduleName); dbot.config.moduleNames = _.without(dbot.config.moduleNames, moduleName);
dbot.reloadModules(); 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 ***/ /*** Config options ***/
'setconfig': function(event) { 'setconfig': function(event) {
@ -291,19 +267,15 @@ var commands = function(dbot) {
} }
}; };
commands['greload'].access = 'admin'; _.each(commands, function(command) {
commands['reload'].access = 'admin'; command.access = 'admin';
commands['unload'].access = 'admin'; });
commands['load'].access = 'admin';
commands['version'].access = 'admin';
commands['setconfig'].access = 'admin';
commands['showconfig'].access = 'moderator'; commands['showconfig'].access = 'moderator';
commands['join'].access = 'moderator'; commands['join'].access = 'moderator';
commands['part'].access = 'moderator'; commands['part'].access = 'moderator';
commands['opme'].access = 'moderator'; commands['opme'].access = 'moderator';
commands['say'].access = 'moderator'; commands['say'].access = 'moderator';
commands['ban'].access = 'moderator';
commands['unban'].access = 'moderator';
return commands; return commands;
}; };

View File

@ -1,6 +1,5 @@
{ {
"ignorable": false, "ignorable": false,
"dbKeys": [ "bans" ],
"dependencies": [ "command" ], "dependencies": [ "command" ],
"help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md" "help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md"
} }

View File

@ -4,8 +4,10 @@ var api = function(dbot) {
return { return {
'isBanned': function(user, command) { 'isBanned': function(user, command) {
var banned = false; var banned = false;
if(_.has(dbot.db.bans, command)) { if(_.has(dbot.db.bans, user)) {
if(_.include(dbot.db.bans[command], user) || _.include(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; banned = true;
} }
} }
@ -39,7 +41,8 @@ var api = function(dbot) {
'isIgnoring': function(item, command) { 'isIgnoring': function(item, command) {
var module = dbot.commands[command].module; var module = dbot.commands[command].module;
return (_.has(dbot.db.ignores, item) && return (_.has(dbot.db.ignores, item) &&
_.include(dbot.db.ignores[item], module)); (_.include(dbot.db.ignores[item], module) ||
_.include(dbot.db.ignores[item], '*')));
}, },
/** /**

View File

@ -18,8 +18,27 @@ var commands = function(dbot) {
'~help': function(event) { '~help': function(event) {
var moduleName = event.params[1]; 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)) { 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')) { if(moduleName && _.has(dbot.config[moduleName], 'help')) {

View File

@ -1,5 +1,5 @@
{ {
"ignorable": false, "ignorable": false,
"help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md", "help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md",
"dbKeys": [ "ignores" ] "dbKeys": [ "ignores", "bans" ]
} }

View File

@ -26,5 +26,8 @@
"no_help": { "no_help": {
"en": "No help found for {module}.", "en": "No help found for {module}.",
"na'vi": "Fì{module}ìri oel ke tsun run srungit" "na'vi": "Fì{module}ìri oel ke tsun run srungit"
},
"loaded_modules_with_help": {
"en": "Loaded modules with help information: {modules}."
} }
} }

View File

@ -0,0 +1,4 @@
{
"~usage": "~usage [command]",
"~help": "~help [module]"
}

17
modules/dns/README.md Normal file
View File

@ -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.

37
modules/dns/dns.js Normal file
View File

@ -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);
};

14
modules/dns/strings.json Normal file
View File

@ -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})"
}
}

View File

@ -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``

View File

@ -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);
};

View File

@ -1,8 +0,0 @@
{
"name": {
"en": "{user} is {name}."
},
"nonexistent": {
"en": "{user} not found."
}
}

View File

@ -1,6 +1,6 @@
{ {
"ignorable": false, "ignorable": false,
"dependencies": [ "command" ], "dependencies": [ "command" ],
"dbKeys": [ "ignores" ], "dbKeys": [ "ignores", "bans" ],
"help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md" "help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md"
} }

View File

@ -24,7 +24,7 @@ var ignore = function(dbot) {
'modules': ignorableModules.join(', ') 'modules': ignorableModules.join(', ')
})); }));
} else { } else {
if(_.include(ignorableModules, module)) { if(module == '*' || _.include(ignorableModules, module)) {
if(_.has(dbot.db.ignores, event.user) && _.include(dbot.db.ignores[event.user], module)) { if(_.has(dbot.db.ignores, event.user) && _.include(dbot.db.ignores[event.user], module)) {
event.reply(dbot.t('already_ignoring', { 'user': event.user })); event.reply(dbot.t('already_ignoring', { 'user': event.user }));
} else { } 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) { '~ignorechannel': function(event) {
var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]); var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]);
var module = event.params[2]; var module = event.params[2];
// Ignoring the value of 'ignorable' at the moment // 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(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = [];
if(!_.include(dbot.db.ignores[channel], module)) { if(!_.include(dbot.db.ignores[channel], module)) {
dbot.db.ignores[channel].push(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['~ignorechannel'].access = 'moderator';
commands['~unignorechannel'].access = 'moderator'; commands['~unignorechannel'].access = 'moderator';

View File

@ -41,6 +41,27 @@
"na'vi": "{user}: Nga terìng mikyun {module}ne set", "na'vi": "{user}: Nga terìng mikyun {module}ne set",
"cy": "{user}: Ddim yn anwybyddu {module} bellach" "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": { "ignoring_channel": {
"en": "Now ignoring {module} in {channel}", "en": "Now ignoring {module} in {channel}",
"na'vi": "Oe ke stayawm {module}ur mì {channel}" "na'vi": "Oe ke stayawm {module}ur mì {channel}"

View File

@ -16,7 +16,7 @@ var link = function(dbot) {
body = body.replace(/(\r\n|\n\r|\n)/gm, " "); body = body.replace(/(\r\n|\n\r|\n)/gm, " ");
var title = body.valMatch(/<title>(.*)<\/title>/, 2); var title = body.valMatch(/<title>(.*)<\/title>/, 2);
if(title && title.length < 140) { if(title && title.length < 140) {
event.reply(ent.decode(title[1])); event.reply(ent.decode(title[1]).trim());
} }
} }
}); });

View File

@ -7,6 +7,32 @@ var commands = function(dbot) {
var quotes = dbot.db.quoteArrs; var quotes = dbot.db.quoteArrs;
var commands = { var commands = {
/*** Quote Addition ***/
// Add a quote to a category
'~qadd': function(event) {
var key = event.input[1].toLowerCase();
var quote = event.input[2];
this.db.indexOf('quote_category', key, quote, function(err, index) {
if(index == null || index == -1) {
this.db.append('quote_category', key, quote, function(err, newCount) {
this.rmAllowed = true;
dbot.api.event.emit('~qadd', {
'key': key,
'text': quote
});
event.reply(dbot.t('quote_saved', {
'category': key,
'count': newCount
}));
}.bind(this));
} else {
event.reply(dbot.t('quote_exists'));
}
}.bind(this));
},
/*** Quote Retrieval ***/ /*** Quote Retrieval ***/
// Alternative ~q syntax // Alternative ~q syntax
@ -27,6 +53,15 @@ var commands = function(dbot) {
}); });
}, },
'~rq': function(event) {
if(_.keys(quotes).length > 0) {
var category = _.keys(quotes)[_.random(0, _.size(quotes) -1)];
event.reply(category + ': ' + this.internalAPI.interpolatedQuote(event.server, event.channel.name, category));
} else {
event.reply(dbot.t('no_results'));
}
},
/*** Quote Removal ***/ /*** Quote Removal ***/
// Show number of quotes in removal cache // Show number of quotes in removal cache
@ -145,7 +180,6 @@ var commands = function(dbot) {
}, },
// Search a given category for some text. // Search a given category for some text.
// TODO fix
'~qsearch': function(event) { '~qsearch': function(event) {
var haystack = event.input[1].trim().toLowerCase(); var haystack = event.input[1].trim().toLowerCase();
var needle = event.input[2]; var needle = event.input[2];
@ -171,7 +205,8 @@ var commands = function(dbot) {
} }
}.bind(this)); }.bind(this));
}, },
// Count quotes in a given category or total quotes overall
'~qcount': function(event) { '~qcount': function(event) {
var input = event.message.valMatch(/^~qcount ([\d\w\s-]*)/, 2); var input = event.message.valMatch(/^~qcount ([\d\w\s-]*)/, 2);
if(input) { // Give quote count for named category if(input) { // Give quote count for named category
@ -198,51 +233,28 @@ var commands = function(dbot) {
} }
}, },
'~qadd': function(event) { // Link to quote web page
var key = event.input[1].toLowerCase();
var quote = event.input[2];
this.db.indexOf('quote_category', key, quote, function(err, index) {
if(index == null || index == -1) {
this.db.append('quote_category', key, quote, function(err, newCount) {
this.rmAllowed = true;
dbot.api.event.emit('~qadd', {
'key': key,
'text': quote
});
event.reply(dbot.t('quote_saved', {
'category': key,
'count': newCount
}));
}.bind(this));
} else {
event.reply(dbot.t('quote_exists'));
}
}.bind(this));
},
'~rq': function(event) {
var category = _.keys(quotes)[_.random(0, _.size(quotes) -1)];
event.reply(category + ': ' + this.internalAPI.interpolatedQuote(event.server, event.channel.name, category));
},
'~link': function(event) { '~link': function(event) {
var key = event.input[1].toLowerCase(); var key = event.input[1].toLowerCase();
this.db.read('quote_category', key, function(err, category) { this.db.read('quote_category', key, function(err, category) {
if(!err) { if(!err) {
event.reply(dbot.t('quote_link', { if(_.has(dbot.config, 'web') && _.has(dbot.config.web, 'webHost')
'category': key, event.reply(dbot.t('quote_link', {
'url': dbot.t('url', { 'category': key,
'host': dbot.config.web.webHost, 'url': dbot.t('url', {
'port': dbot.config.web.webPort, 'host': dbot.config.web.webHost,
'path': 'quotes/' + key 'port': dbot.config.web.webPort,
}) 'path': 'quotes/' + encodeURIComponent(key)
})); })
}));
} else {
event.reply(dbot.t('web_not_configured'));
}
} else if(err == NoSuchThingError) { } else if(err == NoSuchThingError) {
event.reply(dbot.t('category_not_found', { 'category': key })); event.reply(dbot.t('category_not_found', { 'category': key }));
} }
}); });
}, }
}; };
commands['~'].regex = [/^~([\d\w\s-]*)/, 2]; commands['~'].regex = [/^~([\d\w\s-]*)/, 2];
@ -250,7 +262,7 @@ var commands = function(dbot) {
commands['~qsearch'].regex = [/^~qsearch ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; commands['~qsearch'].regex = [/^~qsearch ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3];
commands['~rm'].regex = [/^~rm ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; commands['~rm'].regex = [/^~rm ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3];
commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2]; commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2];
commands['~qadd'].regex = [/^~qadd ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; commands['~qadd'].regex = [/^~qadd ([\d\w-]+[\d\w\s-]*)[ ]?=[ ]?(.+)$/, 3];
commands['~link'].regex = [/^~link ([\d\w\s-]*)/, 2]; commands['~link'].regex = [/^~link ([\d\w\s-]*)/, 2];
commands['~rmconfirm'].access = 'moderator'; commands['~rmconfirm'].access = 'moderator';

View File

@ -126,5 +126,8 @@
"rm_cache_limit": { "rm_cache_limit": {
"en": "Attention: Too many quotes removed, rmCache must be cleared or reinstated manually with ~rmconfirm or ~rmdeny.", "en": "Attention: Too many quotes removed, rmCache must be cleared or reinstated manually with ~rmconfirm or ~rmdeny.",
"na'vi": "Oel zerok 'upxareti apxay set, sweylu txo nga 'aivku upxareti ìlä ~rmconfirm fu ~rmdeny." "na'vi": "Oel zerok 'upxareti apxay set, sweylu txo nga 'aivku upxareti ìlä ~rmconfirm fu ~rmdeny."
},
"web_not_configured": {
"en": "Cannot link to category. Web module is either not loaded or misconfigured."
} }
} }

View File

@ -1,4 +1,9 @@
var _ = require('underscore')._; var _ = require('underscore')._,
uuid = require('node-uuid');
databank = require('databank'),
AlreadyExistsError = databank.AlreadyExistsError,
NoSuchThingError = databank.NoSuchThingError,
NotImplementedError = databank.NotImplementedError;
var api = function(dbot) { var api = function(dbot) {
var escapeRegexen = function(str) { var escapeRegexen = function(str) {
@ -6,113 +11,113 @@ var api = function(dbot) {
}; };
var api = { var api = {
'resolveUser': function(server, nick, useLowerCase) { 'resolveUser': function(server, nick, callback) {
var user = nick;
if(this.api.isPrimaryUser(nick)) { if(this.api.isPrimaryUser(nick)) {
return user; callback(nick);
} else { } else {
var user = false;
this.db.search('user', { 'server': server }, function(user) { this.db.search('user', { 'server': server }, function(user) {
if(_.include(user.aliases, nick)) user = user.primaryNick; if(_.include(user.aliases, nick)) user = user.primaryNick;
}.bind(this), function(err) { }, function(err) {
if(err instanceof NotImplementedError) { if(!err) {
// QQ callback(user);
} }
}); });
return user;
}
/** TODO: Re-add lowercase support
if(!useLowerCase) {
if(!_.include(knownUsers.users, nick) && _.has(knownUsers.aliases, nick)) {
user = knownUsers.aliases[nick];
}
} else {
// this is retarded
user = user.toLowerCase();
var toMatch = new RegExp("^" + escapeRegexen(user) + "$", "i");
var resolvedUser = _.find(knownUsers.users, function(nick) {
return nick.match(toMatch) !== null;
}, this);
if(!resolvedUser) {
resolvedUser = _.find(knownUsers.aliases, function(nick, alias) {
if(alias.match(toMatch) !== null) return nick;
}, this);
if(!_.isUndefined(resolvedUser)) user = resolvedUser;
}
else{
user = resolvedUser;
}
}
return user;
**/
},
'getRandomChannelUser': function(server, channel) {
this.db.get('channel_users', { '' })
var channelUsers = this.getServerUsers(server).channelUsers[channel];
if(!_.isUndefined(channelUsers)) {
return channelUsers[_.random(0, channelUsers.length - 1)];
} else {
return false;
} }
}, },
'getServerUsers': function(server) { 'getRandomChannelUser': function(server, channel, callback) {
var channel;
this.db.search('channel_users', {
'server': server,
'channel': channel
}, function(result) {
channel = result;
}, function(err) {
if(!err) {
if(!_.isUndefined(channel.users)) {
callback(channel.users[_.random(0, channel.users.length - 1)]);
} else {
callback(false);
}
}
});
},
'getServerUsers': function(server, callback) {
var users = []; var users = [];
this.db.search('user', { 'server': server }, function(user) { this.db.search('users', { 'server': server }, function(user) {
users.push(user.primaryNick); users.push(user);
}.bind(this), function(err) { }, function(err) {
if(err instanceof NotImplementedError) { if(!err) {
// QQ callback(users);
} }
}); });
return users;
}, },
'getAllUsers': function() { 'getAllUsers': function(callback) {
return _.reduce(dbot.db.knownUsers, function(memo, server, name) { var users = [];
memo[name] = server.users; this.db.scan('users', function(user) {
return memo; users.push(user);
}, {}, this); }, function(err) {
if(!err) {
callback(users);
}
});
}, },
'isKnownUser': function(server, nick) { 'isKnownUser': function(server, nick, callback) {
var knownUsers = this.getServerUsers(server); this.api.resolveUser(server, nick, function(isKnown) {
return (_.include(knownUsers.users, nick) || _.has(knownUsers.aliases, nick)); if(isKnown == false) {
callback(false);
} else {
callback(true);
}
});
}, },
'isPrimaryUser': function(server, nick) { 'isPrimaryUser': function(server, nick, callback) {
var knownUsers = this.getServerUsers(server); var isPrimaryUser = false;
return _.include(knownUsers.users, nick); this.db.search('users', {
'server': server,
'primaryNick': nick
}, function(user) {
isPrimaryUser = true;
}, function(err) {
if(!err) {
callback(isPrimaryUser);
}
});
}, },
'getAliases': function(server, nick) { 'getAliases': function(server, nick, callback) {
var knownUsers = this.getServerUsers(server); var aliases;
return _.chain(knownUsers.aliases) this.db.search('users', {
.keys() 'server': server,
.filter(function(user) { 'primaryNick': nick
return knownUsers.aliases[user] == nick; }, function(result) {
}, this) aliases = result.aliases;
.value(); }, function(err) {
callback(aliases);
});
}, },
'isOnline': function(server, user, channel, useLowerCase) { 'isOnline': function(server, user, channel, callback) {
var user = this.api.resolveUser(server, user, useLowerCase); var user = this.api.resolveUser(server, user, useLowerCase);
var possiNicks = [user].concat(this.api.getAliases(server, user)); var possiNicks = [user].concat(this.api.getAliases(server, user));
if(!_.has(dbot.instance.connections[server].channels, channel)) return false; if(!_.has(dbot.instance.connections[server].channels, channel)) return false;
var onlineNicks = dbot.instance.connections[server].channels[channel].nicks; var onlineNicks = dbot.instance.connections[server].channels[channel].nicks;
return _.any(onlineNicks, function(nick) { var isOnline = _.any(onlineNicks, function(nick) {
nick = nick.name; nick = nick.name;
return _.include(possiNicks, nick); return _.include(possiNicks, nick);
}, this); }, this);
callback(isOnline);
}, },
'isChannelUser': function(server, user, channel, useLowerCase) { 'isChannelUser': function(server, user, channel) {
var knownUsers = this.getServerUsers(server); var knownUsers = this.getServerUsers(server);
var user = this.api.resolveUser(server, user, useLowerCase); var user = this.api.resolveUser(server, user, useLowerCase);

View File

@ -12,12 +12,8 @@ var commands = function(dbot) {
if(aliasCount != 0) { if(aliasCount != 0) {
var aliases = _.first(aliases, 10); var aliases = _.first(aliases, 10);
var including = 'including: '; var including = 'including: ' + aliases.join(', ') + '.';
for(var i=0;i<aliases.length;i++) {
including += aliases[i] + ', ';
}
including = including.slice(0, -2) + '.';
event.reply(dbot.t('primary', { event.reply(dbot.t('primary', {
'user': alias, 'user': alias,
'count': aliasCount 'count': aliasCount
@ -26,7 +22,7 @@ var commands = function(dbot) {
event.reply(dbot.t('primary', { event.reply(dbot.t('primary', {
'user': alias, 'user': alias,
'count': aliasCount 'count': aliasCount
})); }).slice(0, -2) + ".");
} }
} else if(_.has(knownUsers.aliases, alias)) { } else if(_.has(knownUsers.aliases, alias)) {
event.reply(dbot.t('alias', { event.reply(dbot.t('alias', {
@ -100,7 +96,11 @@ var commands = function(dbot) {
return false; return false;
} }
}; };
commands['~alias'].regex = [/^~alias ([\d\w[\]{}^|\\`_-]+?)/, 2];
commands['~setaliasparent'].regex = [/^~setaliasparent ([\d\w[\]{}^|\\`_-]+?)/, 2];
commands['~mergeusers'].regex = [/^~mergeusers ([\d\w[\]{}^|\\`_-]+?)\s*?([\d\w[\]{}^|\\`_-]+?)/, 3];
commands['~setaliasparent'].access = 'moderator'; commands['~setaliasparent'].access = 'moderator';
commands['~mergeusers'].access = 'moderator'; commands['~mergeusers'].access = 'moderator';

View File

@ -2,5 +2,6 @@
"ignorable": false, "ignorable": false,
"dependencies": [ "command", "event" ], "dependencies": [ "command", "event" ],
"dbKeys": [ "knownUsers" ], "dbKeys": [ "knownUsers" ],
"help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md" "help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md",
"dbType": "memory"
} }

5
modules/users/usage.json Normal file
View File

@ -0,0 +1,5 @@
{
"~alias": "~alias [nick]",
"~setaliasparent": "~setaliasparent [nick]",
"~mergeusers": "~mergeusers [primary] [secondary]"
}

View File

@ -35,10 +35,10 @@ var users = function(dbot) {
}; };
this.listener = function(event) { this.listener = function(event) {
var knownUsers = this.getServerUsers(event.server); /*var knownUsers = this.getServerUsers(event.server);
var nick = event.user; var nick = event.user;
if(event.action == 'JOIN') { if(event.action == 'JOIN' && nick != dbot.config.name) {
if(!_.has(knownUsers.channelUsers, event.channel.name)) { if(!_.has(knownUsers.channelUsers, event.channel.name)) {
knownUsers.channelUsers[event.channel.name] = []; knownUsers.channelUsers[event.channel.name] = [];
} }
@ -55,17 +55,17 @@ var users = function(dbot) {
channelUsers.push(nick); channelUsers.push(nick);
} }
} else if(event.action == 'NICK') { } else if(event.action == 'NICK') {
var newNick = event.params.substr(1); var newNick = event.newNick;
if(!this.api.isKnownUser(newNick)) { if(!this.api.isKnownUser(newNick)) {
knownUsers.aliases[newNick] = this.api.resolveUser(event.server, event.user); knownUsers.aliases[newNick] = this.api.resolveUser(event.server, event.user);
dbot.api.event.emit('nick_change', [ event.server, newNick ]); dbot.api.event.emit('nick_change', [ event.server, newNick ]);
} }
} }*/
}.bind(this); }.bind(this);
this.on = ['JOIN', 'NICK']; this.on = ['JOIN', 'NICK'];
this.onLoad = function() { this.onLoad = function() {
// Trigger updateNickLists to stat current users in channel /* Trigger updateNickLists to stat current users in channel
dbot.instance.addListener('366', 'users', function(event) { dbot.instance.addListener('366', 'users', function(event) {
var knownUsers = this.getServerUsers(event.server); var knownUsers = this.getServerUsers(event.server);
if(!_.has(knownUsers.channelUsers, event.channel.name)) { if(!_.has(knownUsers.channelUsers, event.channel.name)) {
@ -90,7 +90,7 @@ var users = function(dbot) {
var connections = dbot.instance.connections; var connections = dbot.instance.connections;
_.each(connections, function(connection) { _.each(connections, function(connection) {
connection.updateNickLists(); connection.updateNickLists();
}); });*/
}; };
}; };

View File

@ -1,5 +1,4 @@
{ {
"ignorable": false,
"webHost": "localhost", "webHost": "localhost",
"webPort": 9001 "webPort": 8080
} }

24
run.js
View File

@ -90,16 +90,17 @@ DBot.prototype.say = function(server, channel, message) {
// Format given stored string in config language // Format given stored string in config language
DBot.prototype.t = function(string, formatData) { DBot.prototype.t = function(string, formatData) {
var formattedString; var formattedString = 'String not found. Something has gone screwy. Maybe.';
if(_.has(this.strings, string)) { if(_.has(this.strings, string)) {
var lang = this.config.language; var lang = this.config.language;
if(!_.has(this.strings[string], lang)) { if(!_.has(this.strings[string], lang)) {
lang = "en"; lang = "en";
} }
formattedString = this.strings[string][lang].format(formatData); if(_.has(this.strings[string], lang)) {
} else { formattedString = this.strings[string][lang].format(formatData);
formattedString = 'String not found. Something has gone screwy. Maybe.'; }
} }
return formattedString; return formattedString;
@ -157,10 +158,16 @@ DBot.prototype.reloadModules = function() {
this.instance.removeListeners(); this.instance.removeListeners();
moduleNames.each(function(name) { _.each(moduleNames, function(name) {
this.status[name] = true;
var moduleDir = './modules/' + name + '/'; var moduleDir = './modules/' + name + '/';
var cacheKey = require.resolve(moduleDir + name); try {
delete require.cache[cacheKey]; var cacheKey = require.resolve(moduleDir + name);
delete require.cache[cacheKey];
} catch(err) {
this.status[name] = 'Error loading module: ' + err + ' ' + err.stack.split('\n')[2].trim();
return;
}
try { try {
var webKey = require.resolve(moduleDir + 'web'); var webKey = require.resolve(moduleDir + 'web');
@ -170,8 +177,6 @@ DBot.prototype.reloadModules = function() {
delete require.cache[webKey]; delete require.cache[webKey];
} }
this.status[name] = true;
try { try {
// Load the module config data // Load the module config data
var config = {}; var config = {};
@ -304,6 +309,7 @@ DBot.prototype.reloadModules = function() {
module.onLoad(); module.onLoad();
} catch(err) { } catch(err) {
this.status[name] = 'Error in onLoad: ' + err + ' ' + err.stack.split('\n')[1].trim(); this.status[name] = 'Error in onLoad: ' + err + ' ' + err.stack.split('\n')[1].trim();
console.log('MODULE ONLOAD ERROR (' + name + '): ' + err );
} }
} }
}, this); }, this);