mirror of
https://github.com/reality/dbot.git
synced 2024-11-27 14:29:29 +01:00
Merge pull request #535 from reality/database
Merge Database Branch to Master
This commit is contained in:
commit
aa40c78127
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,6 +4,3 @@
|
||||
[submodule "modules/github"]
|
||||
path = modules/github
|
||||
url = git://github.com/zuzak/dbot-github.git
|
||||
[submodule "modules/stats"]
|
||||
path = modules/stats
|
||||
url = git@github.com:SamStudio8/dbot-stats.git
|
||||
|
19
README.md
19
README.md
@ -11,18 +11,11 @@ given I started it rather a long time after I began development of the project.
|
||||
Please don't judge me too harshly for this as I am, in fact, mildly allergic to
|
||||
writing documentation.
|
||||
|
||||
Requirements:
|
||||
## Getting Started
|
||||
|
||||
- Node JS
|
||||
- [JSBot](http://github.com/reality/JSBot "JSBot"), a Javascript library which
|
||||
handles the IRC protocol
|
||||
- Underscore JS library
|
||||
- Various modules have their own requirements also.
|
||||
You can install DBot's dependencies, configure and run the bot for the first
|
||||
time with the following command:
|
||||
|
||||
### External Modules
|
||||
|
||||
JSBot and externally developed modules can be imported by running the following
|
||||
commands in the cloned repository:
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
sh install.sh
|
||||
```
|
||||
|
33
database.js
Normal file
33
database.js
Normal file
@ -0,0 +1,33 @@
|
||||
var databank = require('databank'),
|
||||
Databank = databank.Databank,
|
||||
DatabankObject = databank.DatabankObject,
|
||||
_ = require('underscore')._;
|
||||
|
||||
/**
|
||||
* Multiplex databank objects
|
||||
*/
|
||||
var DatabaseDriver = function(config) {
|
||||
this.config = config;
|
||||
this.databanks = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to or create a new DataBank
|
||||
*/
|
||||
DatabaseDriver.prototype.createDB = function(name, driver, schema, callback) {
|
||||
var params = { 'schema': schema };
|
||||
|
||||
if(driver == 'redis' && _.has(this.config, 'redisPort')) params.port = this.config.redisPort;
|
||||
if(driver == 'disk') params.dir = 'db';
|
||||
|
||||
this.databanks[name] = Databank.get(driver, params);
|
||||
this.databanks[name].connect({}, function(err) {
|
||||
if(err) {
|
||||
console.log('Didn\'t manage to connect to the data source - ' + err);
|
||||
} else {
|
||||
callback(this.databanks[name]);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
exports.DatabaseDriver = DatabaseDriver;
|
@ -14,7 +14,7 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
npm install wordnik ent underscore request sandbox express moment jade@0.25
|
||||
npm install wordnik node-uuid underscore request sandbox express moment jade databank databank-redis ent
|
||||
|
||||
cd public/
|
||||
wget http://twitter.github.com/bootstrap/assets/bootstrap.zip
|
||||
|
2
jsbot
2
jsbot
@ -1 +1 @@
|
||||
Subproject commit 11cbb75b504fbb703450a2f8c938d5a81680109c
|
||||
Subproject commit bb1e72b173a136816287bc8d90509cc38a0986e3
|
@ -26,6 +26,15 @@ channel, it will attempt to give the caller ops in the current channel.
|
||||
Perform a git pull, and then execute the 'reload' command. Saves a lot of time
|
||||
updating!
|
||||
|
||||
#### version [module]
|
||||
Shows the git version of the currently loaded revision of DBot. If module is
|
||||
provided, it will attempt to get the revision of the module (this is only useful
|
||||
for submodules).
|
||||
|
||||
#### status [module]
|
||||
Show the recorded status for a given module, this is helpful for debugging
|
||||
issues when loading or for checking if a module is loaded.
|
||||
|
||||
#### reload
|
||||
Reload all of the modules currently in use by DBot. By using this, all module
|
||||
functionality should be reloadable and replaceable without having to restart the
|
||||
@ -46,12 +55,18 @@ loaded by the standard DBot process.
|
||||
Unload a currently loaded module. This removes the module, and then triggers a
|
||||
reload of all modules.
|
||||
|
||||
#### ban [user] [command]
|
||||
Ban a user from using a command. Command may be replaced with '\*,' which will
|
||||
ban a user from use of all commands. Users banned from all commands will still
|
||||
be subject to module listeners.
|
||||
#### setconfig [path] [value]
|
||||
Set a config value at path to be a certain value persistently. For example, if
|
||||
you want to change the web module to listen on port 9001, you can run _setconfig
|
||||
web.webPort 9001_.
|
||||
|
||||
#### unban [user] [command]
|
||||
Unban a user from using a given command. If a user was previously banned using
|
||||
the '\*' wildcard, they may also be unbanned from such by replacing command with
|
||||
an asterisk here as well.
|
||||
#### pushconfig [path] [value]
|
||||
Push a new value to an existing config array. For example, if you want to add
|
||||
the user 'batman62' to the DBot moderators, you can run _pushconfig moderators
|
||||
batman62_.
|
||||
|
||||
#### showconfig [path]
|
||||
Use this to explore and view the DBot configuration. If called without a path,
|
||||
it will display the config keys in the root; if the path is a subkey, it will
|
||||
show all config keys under that key. If you give it an actual key, it'll show you
|
||||
the currently effective config value.
|
||||
|
@ -1,12 +1,56 @@
|
||||
/**
|
||||
* Module Name: Admin
|
||||
* Description: Set of commands which only one who is a DepressionBot
|
||||
* administrator can run - as such, it has its own command execution listener.
|
||||
* administrator can run.
|
||||
*/
|
||||
var fs = require('fs'),
|
||||
_ = require('underscore')._;
|
||||
|
||||
var admin = function(dbot) {
|
||||
this.internalAPI = {
|
||||
'getCurrentConfig': function(configKey, callback) {
|
||||
var configPath = dbot.config;
|
||||
configKey = configKey.split('.');
|
||||
|
||||
for(var i=0;i<configKey.length;i++) {
|
||||
if(_.has(configPath, configKey[i])) {
|
||||
configPath = configPath[configKey[i]];
|
||||
} else {
|
||||
configPath = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
callback(configPath);
|
||||
},
|
||||
|
||||
'setConfig': function(configKey, newOption, callback) {
|
||||
var configPath = dbot.customConfig,
|
||||
oldOption = null;
|
||||
configKey = configKey.split('.');
|
||||
|
||||
for(var i=0;i<configKey.length-1;i++) {
|
||||
if(!_.has(configPath, configKey[i])) {
|
||||
configPath[configKey[i]] = {};
|
||||
}
|
||||
configPath = configPath[configKey[i]];
|
||||
}
|
||||
|
||||
if(_.has(configPath, configKey[i])) {
|
||||
oldOption = configPath[configKey[i]];
|
||||
}
|
||||
configPath[configKey[i]] = newOption;
|
||||
|
||||
this.internalAPI.saveConfig();
|
||||
dbot.reloadModules();
|
||||
callback(null, oldOption);
|
||||
}.bind(this),
|
||||
|
||||
'saveConfig': function() {
|
||||
var config = dbot.customConfig;
|
||||
fs.writeFileSync('config.json', JSON.stringify(config, null, ' '));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
|
@ -5,45 +5,7 @@ var fs = require('fs'),
|
||||
|
||||
var commands = function(dbot) {
|
||||
var noChangeConfig = [ 'servers', 'name', 'moduleNames' ];
|
||||
|
||||
var getCurrentConfig = function(configKey) {
|
||||
var defaultConfigPath = dbot.config;
|
||||
var userConfigPath = dbot.db.config;
|
||||
|
||||
if(configKey) {
|
||||
var configKey = configKey.split('.');
|
||||
for(var i=0;i<configKey.length-1;i++) {
|
||||
if(_.has(defaultConfigPath, configKey[i])) {
|
||||
if(!_.has(userConfigPath, configKey[i])) {
|
||||
userConfigPath[configKey[i]] = {};
|
||||
}
|
||||
userConfigPath = userConfigPath[configKey[i]];
|
||||
defaultConfigPath = defaultConfigPath[configKey[i]];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var currentOption;
|
||||
if(configKey && configKey.length != 1) {
|
||||
configKey = _.last(configKey);
|
||||
if(_.has(userConfigPath, configKey) && !_.isUndefined(userConfigPath[configKey])) {
|
||||
currentOption = userConfigPath[configKey];
|
||||
} else if(_.has(defaultConfigPath, configKey)) {
|
||||
currentOption = defaultConfigPath[configKey];
|
||||
}
|
||||
} else {
|
||||
currentOption = defaultConfigPath[configKey];
|
||||
}
|
||||
|
||||
return {
|
||||
'user': userConfigPath,
|
||||
'default': defaultConfigPath,
|
||||
'value': currentOption
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
var commands = {
|
||||
// Join a channel
|
||||
'~join': function(event) {
|
||||
@ -120,9 +82,15 @@ var commands = function(dbot) {
|
||||
if(_.has(dbot.status, moduleName)) {
|
||||
var status = dbot.status[moduleName];
|
||||
if(status === true) {
|
||||
event.reply(dbot.t("status_good",{"module":moduleName, "reason": status}));
|
||||
event.reply(dbot.t('status_good', {
|
||||
'module': moduleName,
|
||||
'reason': status
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t("status_bad",{"module":moduleName, "reason": status}));
|
||||
event.reply(dbot.t('status_bad', {
|
||||
'module': moduleName,
|
||||
'reason': status
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("status_unloaded"));
|
||||
@ -133,7 +101,9 @@ var commands = function(dbot) {
|
||||
'~reload': function(event) {
|
||||
dbot.db = JSON.parse(fs.readFileSync('db.json', 'utf-8'));
|
||||
dbot.reloadModules();
|
||||
event.reply(dbot.t('reload'));
|
||||
process.nextTick(function() {
|
||||
event.reply(dbot.t('reload'));
|
||||
});
|
||||
},
|
||||
|
||||
// Say something in a channel
|
||||
@ -150,18 +120,21 @@ var commands = function(dbot) {
|
||||
'~load': function(event) {
|
||||
var moduleName = event.params[1];
|
||||
if(!_.include(dbot.config.moduleNames, moduleName)) {
|
||||
dbot.config.moduleNames.push(moduleName);
|
||||
dbot.customConfig.moduleNames.push(moduleName);
|
||||
this.internalAPI.saveConfig();
|
||||
dbot.reloadModules();
|
||||
if(dbot.status[moduleName] === true) {
|
||||
event.reply(dbot.t('load_module', {'moduleName': moduleName}));
|
||||
} else {
|
||||
event.reply(dbot.t("load_failed",{"module": moduleName}));
|
||||
}
|
||||
process.nextTick(function() {
|
||||
if(dbot.status[moduleName] === true) {
|
||||
event.reply(dbot.t('load_module', { 'moduleName': moduleName }));
|
||||
} else {
|
||||
event.reply(dbot.t('load_failed', { 'module': moduleName }));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if(moduleName == 'web') {
|
||||
event.reply(dbot.t('already_loaded_web'));
|
||||
} else {
|
||||
event.reply(dbot.t('already_loaded', {'moduleName': moduleName}));
|
||||
event.reply(dbot.t('already_loaded', { 'moduleName': moduleName }));
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -176,98 +149,136 @@ var commands = function(dbot) {
|
||||
var cacheKey = require.resolve(moduleDir + moduleName);
|
||||
delete require.cache[cacheKey];
|
||||
} catch(err) { }
|
||||
dbot.config.moduleNames = _.without(dbot.config.moduleNames, moduleName);
|
||||
|
||||
dbot.customConfig.moduleNames = _.without(dbot.config.moduleNames, moduleName);
|
||||
this.internalAPI.saveConfig();
|
||||
dbot.reloadModules();
|
||||
|
||||
event.reply(dbot.t('unload_module', {'moduleName': moduleName}));
|
||||
process.nextTick(function() {
|
||||
event.reply(dbot.t('unload_module', { 'moduleName': moduleName }));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('unload_error', {'moduleName': moduleName}));
|
||||
event.reply(dbot.t('unload_error', { 'moduleName': moduleName }));
|
||||
}
|
||||
},
|
||||
|
||||
/*** Config options ***/
|
||||
|
||||
'~setconfig': function(event) {
|
||||
var configPathString = event.params[1],
|
||||
configKey = _.last(configPathString.split('.')),
|
||||
newOption = event.params[2];
|
||||
var configPath = event.input[1],
|
||||
newOption = event.input[2];
|
||||
|
||||
if(!_.include(noChangeConfig, configKey)) {
|
||||
var configPath = getCurrentConfig(configPathString);
|
||||
if(!_.include(noChangeConfig, configPath)) {
|
||||
this.internalAPI.getCurrentConfig(configPath, function(config) {
|
||||
if(config !== null) {
|
||||
// Convert to boolean type if config item boolean
|
||||
if(_.isBoolean(config)) {
|
||||
newOption = (newOption == "true");
|
||||
}
|
||||
|
||||
if(configPath == false || _.isUndefined(configPath.value)) {
|
||||
event.reply(dbot.t("no_config_key"));
|
||||
return;
|
||||
}
|
||||
var currentOption = configPath.value;
|
||||
// Convert to integer type is config item integer
|
||||
if(_.isNumber(config)) {
|
||||
newOption = parseInt(newOption);
|
||||
}
|
||||
|
||||
// Convert to boolean type if config item boolean
|
||||
if(_.isBoolean(currentOption)) {
|
||||
newOption = (newOption == "true");
|
||||
}
|
||||
if(_.isArray(config)) {
|
||||
event.reply(dbot.t("config_array", { "alternate": "pushconfig" }));
|
||||
}
|
||||
} else {
|
||||
topConfigPath = configPath.split('.')[0];
|
||||
if(_.has(dbot.config.modules, topConfigPath)) {
|
||||
configPath.splice(0, 0, 'modules');
|
||||
event.params[1] = configPath.join('.');
|
||||
this.commands['~showconfig'](event);
|
||||
return;
|
||||
} else {
|
||||
event.reply(dbot.t('new_config_key', { 'key': configPath }));
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to integer type is config item integer
|
||||
if(_.isNumber(currentOption)) {
|
||||
newOption = parseInt(newOption);
|
||||
}
|
||||
|
||||
if(_.isArray(currentOption)) {
|
||||
event.reply(dbot.t("config_array",{"alternate": "pushconfig"}));
|
||||
}
|
||||
|
||||
event.reply(configPathString + ": " + currentOption + " -> " + newOption);
|
||||
configPath['user'][configKey] = newOption;
|
||||
dbot.reloadModules();
|
||||
this.internalAPI.setConfig(configPath, newOption, function(err) {
|
||||
event.reply(configPath + ": " + config + " -> " + newOption);
|
||||
});
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t("config_lock"));
|
||||
}
|
||||
},
|
||||
|
||||
'~pushconfig': function(event) {
|
||||
var configPathString = event.params[1],
|
||||
configKey = _.last(configPathString.split('.')),
|
||||
newOption = event.params[2];
|
||||
var configPath = event.input[1],
|
||||
newOption = event.input[2];
|
||||
|
||||
if(!_.include(noChangeConfig, configKey)) {
|
||||
var configPath = getCurrentConfig(configPathString);
|
||||
if(configPath == false || _.isUndefined(configPath.value)) {
|
||||
event.reply(dbot.t("no_config_key"));
|
||||
return;
|
||||
}
|
||||
var currentArray = configPath.value;
|
||||
|
||||
if(!_.isArray(currentArray)) {
|
||||
event.reply(dbot.t("config_array",{"alternate": "setconfig"}));
|
||||
return;
|
||||
}
|
||||
|
||||
event.reply(configPathString + ": " + currentArray + " << " + newOption);
|
||||
currentArray.push(newOption);
|
||||
dbot.reloadModules();
|
||||
if(!_.include(noChangeConfig, configPath)) {
|
||||
this.internalAPI.getCurrentConfig(configPath, function(config) {
|
||||
if(config !== null) {
|
||||
if(_.isArray(config)) {
|
||||
event.reply(configPath + ": " + config + " << " + newOption);
|
||||
config.push(newOption);
|
||||
this.internalAPI.setConfig(configPath, config, function(err) {});
|
||||
} else {
|
||||
event.reply(dbot.t("config_array", { "alternate": "setconfig" }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("no_config_key", { 'path': configPath }));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t("config_lock"));
|
||||
}
|
||||
},
|
||||
|
||||
'~showconfig': function(event) {
|
||||
var configPathString = event.params[1];
|
||||
var configPath = getCurrentConfig(configPathString);
|
||||
|
||||
if(configPathString) {
|
||||
var configKey = _.last(configPathString.split('.'));
|
||||
if(!configKey) {
|
||||
event.reply(dbot.t("no_config_path"));
|
||||
return;
|
||||
}
|
||||
var configPath = event.params[1];
|
||||
if(configPath) {
|
||||
this.internalAPI.getCurrentConfig(configPath, function(config) {
|
||||
if(config !== null) {
|
||||
if(_.isArray(config)) {
|
||||
event.reply(dbot.t("config_keys_location", {
|
||||
"path": configPath,
|
||||
"value": config
|
||||
}));
|
||||
} else if(_.isObject(config)) {
|
||||
event.reply(dbot.t("config_keys_location", {
|
||||
"path": configPath,
|
||||
"value": _.keys(config)
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t("config_keys_location", {
|
||||
"path": configPath,
|
||||
"value": config
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("no_config_key", {'path': configPath}));
|
||||
|
||||
if(_.isArray(configPath.value)) {
|
||||
event.reply(configKey + ': ' + configPath.value);
|
||||
} else if(_.isObject(configPath.value)) {
|
||||
event.reply(dbot.t("config_keys_location",{"path":configPathString,"value":Object.keys(configPath.value)}));
|
||||
} else {
|
||||
event.reply(configKey + ': ' + configPath.value);
|
||||
}
|
||||
configPath = configPath.split('.');
|
||||
if(_.has(dbot.config.modules, configPath[0])) {
|
||||
configPath.splice(0, 0, 'modules');
|
||||
} else {
|
||||
configPath.pop();
|
||||
}
|
||||
|
||||
event.params[1] = configPath.join('.');
|
||||
this.commands['~showconfig'](event);
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t("config_keys_location",{"path":"root","value":Object.keys(configPath['default'])}));
|
||||
event.reply(dbot.t("config_keys_location", {
|
||||
"path": "root",
|
||||
"value": _.keys(dbot.config)
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
'~savemodules': function(event) {
|
||||
fs.readFile('config.json', 'utf-8', function(err, config) {
|
||||
config = JSON.parse(config);
|
||||
config.moduleNames = _.keys(dbot.modules);
|
||||
fs.writeFile('config.json', JSON.stringify(config, null, ' '), function() {
|
||||
event.reply(dbot.t('modules_saved', { 'modules': _.keys(dbot.modules) }));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -281,6 +292,9 @@ var commands = function(dbot) {
|
||||
commands['~opme'].access = 'moderator';
|
||||
commands['~say'].access = 'moderator';
|
||||
|
||||
commands['~pushconfig'].regex = [/~pushconfig ([^ ]+) ([^ ]+)/, 3];
|
||||
commands['~setconfig'].regex = [/~setconfig ([^ ]+) ([^ ]+)/, 3];
|
||||
|
||||
return commands;
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"ignorable": false,
|
||||
"dependencies": [ "command" ],
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md"
|
||||
"dbType": "redis",
|
||||
"dependencies": [ "command" ]
|
||||
}
|
||||
|
@ -5,7 +5,8 @@
|
||||
"na'vi": "fpxäkìm {channel}(nemfa)",
|
||||
"cy": "Wedi ymuno {channel}",
|
||||
"nl": "{channel} binnengekomen",
|
||||
"de": "{channel} beigetreten"
|
||||
"de": "{channel} beigetreten",
|
||||
"fr": "{channel} rejoint"
|
||||
},
|
||||
"part": {
|
||||
"en": "Left {channel}",
|
||||
@ -13,7 +14,8 @@
|
||||
"na'vi": "Hum {channel}",
|
||||
"cy": "Wedi gadael {channel}",
|
||||
"nl": "{channel} verlaten",
|
||||
"de": "{channel} verlassen"
|
||||
"de": "{channel} verlassen",
|
||||
"fr": "{channel} quitté"
|
||||
},
|
||||
"gpull": {
|
||||
"en": "Git pulled that shit.",
|
||||
@ -21,7 +23,8 @@
|
||||
"na'vi": "Gìtìl fì'uti stamarsìm.",
|
||||
"cy": "Wedi tynnu git yr cach na i gyd",
|
||||
"nl": "Git heeft die zooi binnengehaald.",
|
||||
"de": "Git hat es gezogen"
|
||||
"de": "Git hat es gezogen",
|
||||
"fr": "Git a pullé cette merde"
|
||||
},
|
||||
"reload": {
|
||||
"en": "Reloaded that shit.",
|
||||
@ -29,7 +32,8 @@
|
||||
"na'vi": "Oel fìuti stìyeftxaw.",
|
||||
"cy": "Ail-lwytho'r cach na",
|
||||
"nl": "Die zooi opnieuw geladen.",
|
||||
"de": "Neu geladen"
|
||||
"de": "Neu geladen",
|
||||
"fr": "Bordel rechargé"
|
||||
},
|
||||
"load_module": {
|
||||
"en": "Loaded new module: {moduleName}",
|
||||
@ -37,7 +41,8 @@
|
||||
"na'vi": "Oel {moduleName}it amip stìyeftxaw.",
|
||||
"cy": "Wedi llwytho modiwl newydd: {moduleName}",
|
||||
"nl": "Nieuwe module geladen: {moduleName}",
|
||||
"de": "Neues Modul geladen: {moduleName}"
|
||||
"de": "Neues Modul geladen: {moduleName}",
|
||||
"fr": "Nouveau module chargé : {moduleName}"
|
||||
},
|
||||
"unload_module": {
|
||||
"en": "Turned off module: {moduleName}",
|
||||
@ -45,7 +50,8 @@
|
||||
"na'vi": "Oel {moduleName} tswìya'.",
|
||||
"cy": "Wedi troi ffwrdd y modiwl: {moduleName}",
|
||||
"nl": "Module uitgeschakeld: {moduleName}",
|
||||
"de": "Modul ausgeschaltet: {moduleName}"
|
||||
"de": "Modul ausgeschaltet: {moduleName}",
|
||||
"fr": "Module déchargé : {moduleName}"
|
||||
},
|
||||
"unload_error": {
|
||||
"en": "{moduleName} isn't loaded. Idiot.",
|
||||
@ -53,7 +59,8 @@
|
||||
"na'vi": "Oel {moduleName}it omum. Nga skxawng lu.",
|
||||
"cy": "Di {moduleName} ddim wedi llwytho. Twpsyn",
|
||||
"nl": "{moduleName} is niet geladen. Idioot.",
|
||||
"de": "{moduleName} ist nicht geladen, du Idiot."
|
||||
"de": "{moduleName} ist nicht geladen, du Idiot.",
|
||||
"fr": "{moduleName} n'est pas chargé. Idiot."
|
||||
},
|
||||
"banned": {
|
||||
"en": "{user} banned from {command}",
|
||||
@ -61,7 +68,8 @@
|
||||
"na'vi": "{command}ìri {user} ke tung.",
|
||||
"cy": "{user} wedi ei gohurio o {command}",
|
||||
"nl": "{user} mag {command} niet meer gebruiken",
|
||||
"de": "{user} wurde von {command} gebannt"
|
||||
"de": "{user} wurde von {command} gebannt",
|
||||
"fr": "{user} a été interdit d'utiliser {command}"
|
||||
},
|
||||
"unbanned": {
|
||||
"en": "{user} unbanned from {command}",
|
||||
@ -69,7 +77,8 @@
|
||||
"na'vi": "{command}ìri {user} tung set.",
|
||||
"cy": "{user} wedi ei dad-wahardd o {command}",
|
||||
"nl": "{user} mag {command} weer gebruiken",
|
||||
"de": "{user} wurde von {command} entbannt"
|
||||
"de": "{user} wurde von {command} entbannt",
|
||||
"fr": "{user} peut de nouveau utiliser {command}"
|
||||
},
|
||||
"unban_error": {
|
||||
"en": "{user} wasn't banned from that command, fool.",
|
||||
@ -77,7 +86,8 @@
|
||||
"na'vi": "{user} fìtsu'oti tamung srekrr, nga skxawng lu.",
|
||||
"cy": "Nid oedd {user} wedi ei wahardd o'r gorchymyn yna, twpsyn",
|
||||
"nl": "{user} mag dat commando sowieso al gebruiken, mafketel.",
|
||||
"de": "{user} wurde nicht von {command} gebannt, du Trottel"
|
||||
"de": "{user} wurde nicht von {command} gebannt, du Trottel",
|
||||
"fr": "{user} n'a pas été interdit d'utiliser cette commande, imbécile."
|
||||
},
|
||||
"qlock": {
|
||||
"en": "Locked quote category: {category}",
|
||||
@ -85,84 +95,107 @@
|
||||
"na'vi": "{category}ìri oel 'upxareti fmoli",
|
||||
"cy": "Categori wedi cloi: {category}",
|
||||
"nl": "Quote categorie vergrendeld: {category}",
|
||||
"de": "Zitat-Kategorie geschlossen: {category}"
|
||||
"de": "Zitat-Kategorie geschlossen: {category}",
|
||||
"fr": "Catégorie de citations verrouillée : {category}"
|
||||
},
|
||||
"already_in_channel": {
|
||||
"en": "I'm already in {channel}",
|
||||
"na'vi": "Oel {channel}it tok li",
|
||||
"cy": "Rydw i eisoes yn {channel}",
|
||||
"nl": "Ik ben al in {channel}",
|
||||
"de": "Ich bin schon in {channel}"
|
||||
"de": "Ich bin schon in {channel}",
|
||||
"fr": "Je suis déjà dans {channel}"
|
||||
},
|
||||
"not_in_channel": {
|
||||
"en": "I'm not in {channel}",
|
||||
"na'vi": "Oel {channel}it ke tok",
|
||||
"cy": "Rydw i ddim yn {channel}",
|
||||
"nl": "Ik ben niet aanwezig in {channel}",
|
||||
"de": "Ich bin noch nicht in {channel}"
|
||||
"de": "Ich bin noch nicht in {channel}",
|
||||
"fr": "Je ne suis pas dans {channel}"
|
||||
},
|
||||
"already_loaded_web": {
|
||||
"en": "WHY CAN'T I LOAD ALL THIS WEB? (web already loaded)",
|
||||
"na'vi": "PELUN OEL KE TSUN OMUM FÌWETIT NÌWOTX (wetìri oe omum li)",
|
||||
"cy": "PAM ALLA I DDIM YN LWYTHO POB Y WE? (We eisoes yn lwytho)",
|
||||
"nl": "AL DIT WEB WORDT ME TOCH EEN BEETJE TE VEEL! (web is al geladen)",
|
||||
"de": "WARUM KANN DAS NICHT GELADEN WERDEN? (bereits geladen)"
|
||||
"de": "WARUM KANN DAS NICHT GELADEN WERDEN? (bereits geladen)",
|
||||
"fr": "POURQUOI EST-CE QUE JE PEUX PAS CHARGER TOUT CE WEB? (web déjà chargé)"
|
||||
},
|
||||
"already_loaded": {
|
||||
"en": "{moduleName} is already loaded.",
|
||||
"na'vi": "Oel omum teri {moduleName}it li.",
|
||||
"cy": "{moduleName} eisoes yn lwytho",
|
||||
"nl": "{moduleName} is al geladen.",
|
||||
"de": "{moduleName} ist bereits geladen."
|
||||
"de": "{moduleName} ist bereits geladen.",
|
||||
"fr": "{moduleName} est déjà chargé."
|
||||
},
|
||||
"no_version": {
|
||||
"en": "No version information or queried module not loaded.",
|
||||
"cy": "Dim gwybodaeth fersiwn neu modiwl holodd dim yn lwytho",
|
||||
"de": "Keine Informationen verfügbar oder gewünschtes Modul wurde noch nicht geladen."
|
||||
"de": "Keine Informationen verfügbar oder gewünschtes Modul wurde noch nicht geladen.",
|
||||
"fr": "Aucune information de version ou module demandé non chargé."
|
||||
},
|
||||
"status_good": {
|
||||
"en": "{module} status: Shit looks good",
|
||||
"cy": "{module} statws: Cachu yn edrych yn dda",
|
||||
"de": "Sieht gut aus"
|
||||
"de": "Sieht gut aus",
|
||||
"fr": "Statut de {module} : Cette merde tourne bien"
|
||||
},
|
||||
"status_bad": {
|
||||
"en": "{module} status: Failed to load: {reason}",
|
||||
"cy": "{module} statws: Methu i lwytho: {reason}",
|
||||
"de": "{module} Status: Konnte nicht geladen werden: {reason}"
|
||||
"de": "{module} Status: Konnte nicht geladen werden: {reason}",
|
||||
"fr": "Statut de {module} : échec de chargement : {reason}"
|
||||
},
|
||||
"status_unloaded": {
|
||||
"en": "Either that module wasn't on the roster or shit is totally fucked.",
|
||||
"cy": "Naill ai heb fod modiwl oedd ar y rhestr, neu cachu yn gwbl torrodd",
|
||||
"de": "Entweder ist das Modul nicht auf der Liste oder die Kacke ist am dampfen"
|
||||
"de": "Entweder ist das Modul nicht auf der Liste oder die Kacke ist am dampfen",
|
||||
"fr": "Soit ce module n'est pas sur la liste, soit tout est complètement niqué"
|
||||
},
|
||||
"load_failed": {
|
||||
"en": "Failed to load {module}. See 'status {module}'.",
|
||||
"cy": "Methu i lwytho {module}. Gwelwch 'status {module}'.",
|
||||
"de": "Konnte {module} nicht laden. Siehe 'status {module}'."
|
||||
"de": "Konnte {module} nicht laden. Siehe 'status {module}'.",
|
||||
"fr": "Echec du chargement de {module}. Voir 'status {module}'."
|
||||
},
|
||||
"no_config_key": {
|
||||
"en": "Config key doesn't exist bro",
|
||||
"cy": "Nid yw allwedd cyfluniad yn bodoli, fy mrawd",
|
||||
"de": "Einstellung existiert nicht, Bruder"
|
||||
"en": "{path} doesn't exist bro",
|
||||
"cy": "{path} cyfluniad yn bodoli, fy mrawd",
|
||||
"de": "{path} existiert nicht, Bruder",
|
||||
"fr": "{path} n'existe pas, fréro"
|
||||
},
|
||||
"config_array": {
|
||||
"en": "Config option is an array. Try '{alternate}'.",
|
||||
"cy": "Opsiwn cyfluniad ydy'r amrywiaeth. Rhowch gynnig ar '{alternate}'.",
|
||||
"de": "Einstellung ist ein Array, probiere '{alternate}' aus."
|
||||
"de": "Einstellung ist ein Array, probiere '{alternate}' aus.",
|
||||
"fr": "L'option de configuration est un array. Essaye '{alternate}'."
|
||||
},
|
||||
"config_lock": {
|
||||
"en": "This config option cannot be altered while the bot is running.",
|
||||
"cy": "Ni all yr opsiwn cyfluniad yn cael ei newid tra bod y bot yn rhedeg.",
|
||||
"de": "Diese Option kann während der Benutzung des Bots nicht verändert werden"
|
||||
"de": "Diese Option kann während der Benutzung des Bots nicht verändert werden",
|
||||
"fr": "Cette option de configuration ne peut pas être changée pendant que le bot est activé."
|
||||
},
|
||||
"no_config_path": {
|
||||
"en": "Config path doesn't exist bro",
|
||||
"cy": "Nid yw llwybr cyfluniad yn bodoli, fy mrawd",
|
||||
"de": "Konfigurationspfad nicht vorhanden, Bruder"
|
||||
"de": "Konfigurationspfad nicht vorhanden, Bruder",
|
||||
"fr": "Le chemin de configuration n'existe pas, fréro"
|
||||
},
|
||||
"new_config_key": {
|
||||
"en": "Warning: Creating new config key: {key}.",
|
||||
"fr": "Attention : création d'une nouvelle clé de configuration : {key}."
|
||||
},
|
||||
"config_keys_location": {
|
||||
"en": "Config keys in {path}: {value}",
|
||||
"cy": "Allweddi cyfluniad yn {path}: {value}",
|
||||
"de": "Die Konfiguration in {path}: {value}"
|
||||
"de": "Die Konfiguration in {path}: {value}",
|
||||
"fr": "Clés de configuration dans {path}: {value}"
|
||||
},
|
||||
"modules_saved": {
|
||||
"en": "Currently loaded modules now default: {modules}",
|
||||
"fr": "Les modules actuellement chargés sont maintenant chargés par défaut : {modules}"
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,17 @@ Command flow:
|
||||
This is the only module which is force loaded, even if it's not specified in
|
||||
the configuration file.
|
||||
|
||||
### Config
|
||||
|
||||
#### useNickserv: false
|
||||
Use the nickserv module to ensure a user is logged into their account before
|
||||
running any elevated commands. Note you will still have to load and configure
|
||||
the nickserv module yourself.
|
||||
|
||||
#### accessOutput: false
|
||||
Show a message to a user if they attempt to run a command they don't have the
|
||||
access level for.
|
||||
|
||||
### Commands
|
||||
|
||||
#### ~usage [command]
|
||||
|
@ -2,22 +2,10 @@ var _ = require('underscore')._;
|
||||
|
||||
var api = function(dbot) {
|
||||
return {
|
||||
'isBanned': function(user, command) {
|
||||
var banned = false;
|
||||
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;
|
||||
}
|
||||
}
|
||||
return banned;
|
||||
},
|
||||
|
||||
/**
|
||||
* Does the user have the correct access level to use the command?
|
||||
*/
|
||||
'hasAccess': function(server, user, command, callback) {
|
||||
'hasAccess': function(user, command, callback) {
|
||||
var accessNeeded = dbot.commands[command].access;
|
||||
|
||||
if(accessNeeded == 'admin' || accessNeeded == 'moderator' || accessNeeded == 'power_user') {
|
||||
@ -25,11 +13,11 @@ var api = function(dbot) {
|
||||
if(accessNeeded == 'moderator') allowedNicks = _.union(allowedNicks, dbot.config.moderators);
|
||||
if(accessNeeded == 'power_user') allowedNicks = _.union(allowedNicks, dbot.config.power_users);
|
||||
|
||||
if(!_.include(allowedNicks, user)) {
|
||||
if(!_.include(allowedNicks, user.primaryNick)) {
|
||||
callback(false);
|
||||
} else {
|
||||
if(_.has(dbot.modules, 'nickserv') && this.config.useNickserv == true) {
|
||||
dbot.api.nickserv.auth(server, user, function(result) {
|
||||
dbot.api.nickserv.auth(user.server, user.currentNick, function(result) {
|
||||
callback(result);
|
||||
});
|
||||
} else {
|
||||
@ -41,16 +29,6 @@ var api = function(dbot) {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Is item (user or channel) ignoring command?
|
||||
*/
|
||||
'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], '*')));
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply Regex to event message, store result. Return false if it doesn't
|
||||
* apply.
|
||||
@ -76,16 +54,6 @@ var api = function(dbot) {
|
||||
applies = true;
|
||||
}
|
||||
return applies;
|
||||
},
|
||||
|
||||
'addHook': function(command, callback) {
|
||||
console.log('adding hook');
|
||||
if(_.has(dbot.commands, command)) {
|
||||
if(!_.has(dbot.commands[command], 'hooks')) {
|
||||
dbot.commands[command].hooks = [];
|
||||
}
|
||||
dbot.commands[command].hooks.push(callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -5,9 +5,8 @@
|
||||
* ignoring that command.
|
||||
*/
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var command = function(dbot) {
|
||||
this.dbot = dbot;
|
||||
|
||||
/**
|
||||
* Run the appropriate command given the input.
|
||||
*/
|
||||
@ -20,24 +19,23 @@ var command = function(dbot) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.api.isBanned(event.user, commandName)) {
|
||||
event.reply(dbot.t('command_ban', {'user': event.user}));
|
||||
} else {
|
||||
this.api.hasAccess(event.server, event.user, commandName, function(result) {
|
||||
if(result) {
|
||||
if(!this.api.isIgnoring(event.user, commandName) &&
|
||||
!this.api.isIgnoring(event.channel, commandName) &&
|
||||
dbot.commands[commandName].disabled !== true) {
|
||||
|
||||
this.api.hasAccess(event.rUser, commandName, function(hasAccess) {
|
||||
dbot.api.ignore.isUserIgnoring(event.rUser, commandName, function(isIgnoring) {
|
||||
dbot.api.ignore.isUserBanned(event.rUser, commandName, function(isBanned) {
|
||||
if(isBanned) {
|
||||
if(this.config.banOutput && commandName != '~') {
|
||||
event.reply(dbot.t('command_ban', {'user': event.user}));
|
||||
}
|
||||
} else if(!hasAccess) {
|
||||
if(this.config.accessOutput) {
|
||||
event.reply(dbot.t('access_denied', { 'user': event.user }));
|
||||
}
|
||||
} else if(!isIgnoring && !dbot.commands[commandName].disabled) {
|
||||
if(this.api.applyRegex(commandName, event)) {
|
||||
try {
|
||||
var command = dbot.commands[commandName];
|
||||
var results = command.apply(dbot.modules[command.module], [event]);
|
||||
if(_.has(command, 'hooks') && results !== false) {
|
||||
_.each(command['hooks'], function(hook) {
|
||||
hook.apply(hook.module, _.values(results));
|
||||
}, this);
|
||||
}
|
||||
} catch(err) {
|
||||
if(dbot.config.debugMode == true) {
|
||||
var stack = err.stack.split('\n').slice(1, dbot.config.debugLevel + 1);
|
||||
@ -51,7 +49,7 @@ var command = function(dbot) {
|
||||
});
|
||||
}
|
||||
}
|
||||
dbot.api.event.emit('command', [ event ]);
|
||||
if(!_.include(['~reload', '~load', '~unload'], commandName)) dbot.api.event.emit('command', [ event ]);
|
||||
dbot.save();
|
||||
} else {
|
||||
if(commandName !== '~') {
|
||||
@ -63,9 +61,9 @@ var command = function(dbot) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
@ -48,8 +48,8 @@ var commands = function(dbot) {
|
||||
} else {
|
||||
var helpLink = dbot.config.repoRoot +
|
||||
'blob/master/modules/' + moduleName + '/README.md';
|
||||
if(dbot.config[moduleName].help) {
|
||||
helpLink = dbot.config[moduleName].help;
|
||||
if(dbot.config.modules[moduleName].help) {
|
||||
helpLink = dbot.config.modules[moduleName].help;
|
||||
}
|
||||
|
||||
// TODO: Check it exists
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"ignorable": false,
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md",
|
||||
"dependencies": [ "event", "ignore", "users" ],
|
||||
"useNickserv": false,
|
||||
"dbKeys": [ "ignores", "bans" ]
|
||||
"accessOutput": false,
|
||||
"banOutput": false
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
{
|
||||
"command_ban": {
|
||||
"en": "{user} is banned from using this command. Commence incineration.",
|
||||
"es": "{user} está prohibido de usar esta instrucción. Comenzar incineración.",
|
||||
"es": "{user} está prohibido de usar esta instrucción. urrently loaded modules now default: {modules}.",
|
||||
"na'vi": "Tsu'ori {user} ke tung. Nga skxawng lu.",
|
||||
"cy": "Mae {user} wedi ei gohurio gan ddefnyddio'r gorchymun yma. Cychwyn orfflosgiad",
|
||||
"nl": "{user} mag dit commando niet meer gebruiken. Bereid het verbrandingsritueel voor.",
|
||||
"de": "{user} wurde von diesem Befehl gebannt. Verbrennung einleiten"
|
||||
"de": "{user} wurde von diesem Befehl gebannt. Verbrennung einleiten",
|
||||
"fr": "{user} est interdit d'utiliser cette commande. Commencer l'incinération."
|
||||
},
|
||||
"syntax_error": {
|
||||
"en": "Invalid syntax. Initiate incineration.",
|
||||
@ -13,43 +14,54 @@
|
||||
"na'vi": "Ngeyä pamrel keyawr lu. Nga skxawng lu.",
|
||||
"cy": "Cystrawen annilys. Cychwyn orfflosgiad",
|
||||
"nl": "Ongeldige syntax. Bereid het verbrandingsritueel voor.",
|
||||
"de": "Syntax ungültig. Verbrennung einleiten"
|
||||
"de": "Syntax ungültig. Verbrennung einleiten",
|
||||
"fr": "Syntaxe invalide. Initier l'incinération."
|
||||
},
|
||||
"usage": {
|
||||
"en": "Usage for {command}: {usage}.",
|
||||
"na'vi": "Nga tsun sivar ìlä {command}: {usage}.",
|
||||
"cy": "Defnydd o {command}: {usage}.",
|
||||
"nl": "{command} wordt op de volgende manier gebruikt: {usage}.",
|
||||
"de": "Benutzung von {command}: [usage}."
|
||||
"de": "Benutzung von {command}: [usage}.",
|
||||
"fr": "Utilisation de {command}: {usage}."
|
||||
},
|
||||
"no_usage_info": {
|
||||
"en": "No usage information found for {command}.",
|
||||
"na'vi": "Oel ke tsun sivar {comamnd}it",
|
||||
"cy": "Ni chanfuwyd gwybodaeth am ddefnydd o {command}",
|
||||
"nl": "Geen gebruiksinformatie gevonden voor {command}.",
|
||||
"de": "Keine Gebrauchsanweisung gefunden für {command}."
|
||||
"de": "Keine Gebrauchsanweisung gefunden für {command}.",
|
||||
"fr": "Aucune information d'utilisation trouvée pour {command}"
|
||||
},
|
||||
"help_link": {
|
||||
"en": "Help for {module}: {link}",
|
||||
"na'vi": "{module}ä srungìl {link} it tok",
|
||||
"cy": "Cymorth am {module}: {link}",
|
||||
"nl": "Hulp voor {module}: {link}",
|
||||
"de": "Hilfe für {module}: {link}"
|
||||
"de": "Hilfe für {module}: {link}",
|
||||
"fr": "Aide pour {module}: {link}"
|
||||
},
|
||||
"no_help": {
|
||||
"en": "No help found for {module}.",
|
||||
"na'vi": "Fì{module}ìri oel ke tsun run srungit",
|
||||
"cy": "Ni chanfuwyd cymorth am {module}",
|
||||
"nl": "Geen hulp gevonden voor {module}.",
|
||||
"de": "Keine Hilfe gefunden für {module}."
|
||||
"de": "Keine Hilfe gefunden für {module}.",
|
||||
"fr": "Aucune aide trouvée pour {module}."
|
||||
},
|
||||
"loaded_modules": {
|
||||
"en": "Loaded modules: {modules}.",
|
||||
"cy": "Modiwlau sy'n lwythodd: {modules}.",
|
||||
"nl": "Geladen modules: {modules}.",
|
||||
"de": "Module geladen: {modules}."
|
||||
"de": "Module geladen: {modules}.",
|
||||
"fr": "Modules chargés: {modules}."
|
||||
},
|
||||
"access_denied": {
|
||||
"en": "{user}: You don't have the access level to run this command.",
|
||||
"fr": "{user}: Vous n'avez pas le niveau d'accès requis pour utiliser cette commande."
|
||||
},
|
||||
"module_commands": {
|
||||
"en": "Commands in {module}: {commands}."
|
||||
"en": "Commands in {module}: {commands}.",
|
||||
"fr": "Commandes de {module}: {commands}."
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
{
|
||||
"ignorable": true,
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/ctcp/README.md"
|
||||
"ignorable": true
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
{
|
||||
"username": "youruserhere",
|
||||
"password": "yourpasswordhere",
|
||||
"dependencies": [ "command" ],
|
||||
"dependencies": [ "link" ],
|
||||
"ignorable": true,
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/dent/README.md",
|
||||
"dentQuotes": false
|
||||
"dentQuotes": true
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ var request = require('request');
|
||||
_ = require('underscore')._;
|
||||
|
||||
var dent = function(dbot) {
|
||||
this.dbot = dbot;
|
||||
this.StatusRegex = {
|
||||
identica: /\bhttps?:\/\/identi\.ca\/notice\/(\d+)\b/ig,
|
||||
twitter: /\bhttps?:\/\/twitter\.com\/\w+\/status\/(\d+)\b/ig
|
||||
@ -15,8 +14,8 @@ var dent = function(dbot) {
|
||||
|
||||
this.api = {
|
||||
'post': function(content) {
|
||||
var username = dbot.config.dent.username,
|
||||
password = dbot.config.dent.password,
|
||||
var username = this.config.username,
|
||||
password = this.config.password,
|
||||
info,
|
||||
auth = "Basic " +
|
||||
new Buffer(username + ":" + password).toString("base64");
|
||||
@ -57,8 +56,8 @@ var dent = function(dbot) {
|
||||
this.commands['~dent'].regex = [/^~dent (.+)$/, 2];
|
||||
|
||||
this.onLoad = function() {
|
||||
if(dbot.config.dent.dentQuotes === true && _.has(dbot.modules, 'quotes')) {
|
||||
dbot.api.command.addHook('~qadd', function(key, text) {
|
||||
if(this.config.dentQuotes === true && _.has(dbot.modules, 'quotes')) {
|
||||
dbot.api.event.addHook('~qadd', function(key, text) {
|
||||
if(text.indexOf('~~') == -1) {
|
||||
this.api.post(key + ': ' + text);
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/dns/README.md"
|
||||
}
|
@ -16,6 +16,7 @@ var dns = function(dbot) {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'~rdns': function(event) {
|
||||
ip = event.params[1];
|
||||
dnsmod.reverse(ip, function (error, domain) {
|
||||
|
@ -3,21 +3,25 @@
|
||||
"en": "{domain} is \u000303AVAILABLE! \u000314({code})",
|
||||
"cy": "{domain} \u000303AR GAEL! \u000314({code})",
|
||||
"nl": "{domain} is \u000303BESCHIKBAAR! \u000314({code})",
|
||||
"de": "{domain} ist \u000303VERFÜGBAR! \u000314({code})"
|
||||
"de": "{domain} ist \u000303VERFÜGBAR! \u000314({code})",
|
||||
"fr": "{domain} est \u000303DISPONIBLE! \u000314({code})"
|
||||
},
|
||||
"lookup": {
|
||||
"en": "{domain} is \u000305TAKEN! \u000314({address})",
|
||||
"cy": "Dydy {domain} \u000305DDIM AR GAEL! \u000314({address})",
|
||||
"nl": "{domain} is \u000305BEZET! \u000314({address})",
|
||||
"de": "{domain} ist \u000305BELEGT! \u000314({address})"
|
||||
"de": "{domain} ist \u000305BELEGT! \u000314({address})",
|
||||
"fr": "{domain} est \u000305PRIS! \u000314({address})"
|
||||
},
|
||||
"rdns": {
|
||||
"en": "{ip} \u2192 {domain}"
|
||||
"en": "{ip} \u2192 {domain}",
|
||||
"fr": "{ip} \u2192 {domain}"
|
||||
},
|
||||
"rdns-error": {
|
||||
"en": "Unable to lookup {ip}. \u000314({error})",
|
||||
"cy": "Methu am-edrych {ip}. \u000314({error})",
|
||||
"nl": "{ip} kan niet worden opgezocht. \u000314({error})",
|
||||
"de": "Kann {ip} nicht auflösen. \u000314({error})"
|
||||
"de": "Kann {ip} nicht auflösen. \u000314({error})",
|
||||
"fr": "Impossible de rechercher {ip}. \u000314({error})"
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/event/README.md"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/flashy/README.md"
|
||||
}
|
@ -1 +0,0 @@
|
||||
Subproject commit 5f4e3dc8335000e97af528fee289b880a3c99e81
|
18
modules/github/LICENSE
Normal file
18
modules/github/LICENSE
Normal file
@ -0,0 +1,18 @@
|
||||
Copyright (c) 2013 Douglas Gardner <douglas@chippy.ch>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
28
modules/github/README.md
Normal file
28
modules/github/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
## Github
|
||||
|
||||
Grabs interesting data from the GitHub API.
|
||||
|
||||
### Description
|
||||
|
||||
This module for [depressionbot](https://github.com/reality/depressionbot) takes some interesting information about Github and parses it in a pleasing manner.
|
||||
|
||||
### Configuration
|
||||
#### defaultrepo
|
||||
When repository information is lacking from the command, this repository will be used.
|
||||
#### sortorder
|
||||
Defines the behaviour of ~issue when no arguments are given. Options are ``created``, ``updated``, or ``comments``.
|
||||
### Commands
|
||||
#### ~commits
|
||||
Returns the number of commits in the repository of the current depressionbot instance.
|
||||
#### ~gstatus
|
||||
Returns the [current status of Github](https://status.github.com), and a message explaining the current state of affairs.
|
||||
#### ~issue (user/repo) [id]
|
||||
Gives information about the isse pecified, from the default repository if one is not explicitly stated.
|
||||
#### ~milestone [milestone name]
|
||||
Returns milestone progress for any given milestone, with a link to the milestone in question.
|
||||
#### ~repo (repo name)
|
||||
Returns information about the repo given as a parameter. The repo should be specified as ``user/name``; for example, ``twitter/snowflake``.
|
||||
#### ~repocount [user]
|
||||
Returns the number of public Github repositories for the specified user.
|
||||
### Dependencies
|
||||
* [request](https://github.com/mikeal/request/):``$ npm install request``
|
8
modules/github/config.json
Normal file
8
modules/github/config.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"dependencies": [ "command" ],
|
||||
"ignorable": true,
|
||||
"help": "http://github.com/zuzak/dbot-github/blob/master/README.md",
|
||||
"defaultrepo": "reality/dbot",
|
||||
"sortorder": "updated",
|
||||
"useragent": "reality/depressionbot github module"
|
||||
}
|
200
modules/github/github.js
Normal file
200
modules/github/github.js
Normal file
@ -0,0 +1,200 @@
|
||||
/**
|
||||
* Module Name: Github
|
||||
* Description: Retrieves interesting Github information
|
||||
*/
|
||||
var request = require('request'),
|
||||
exec = require('child_process').exec;
|
||||
|
||||
var github = function(dbot) {
|
||||
this.api = {
|
||||
"githubStatus": function(callback){
|
||||
var reqUrl = "https://status.github.com/api/last-message.json";
|
||||
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
callback(JSON.parse(body));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var commands = {
|
||||
'~repocount': function(event) {
|
||||
var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos";
|
||||
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
if(response.statusCode == "200") {
|
||||
var result = JSON.parse(body);
|
||||
event.reply(dbot.t("repocount",{"user": event.params[1], "count": result.length}));
|
||||
} else {
|
||||
event.reply(dbot.t("usernotfound"));
|
||||
}
|
||||
});
|
||||
},
|
||||
'~repo': function(event) {
|
||||
var repo = event.params[1];
|
||||
if (typeof repo == 'undefined') {
|
||||
repo = this.config.defaultrepo;
|
||||
}
|
||||
|
||||
var reqUrl = "https://api.github.com/";
|
||||
reqUrl += "repos/" + repo;
|
||||
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
|
||||
var data = JSON.parse(body);
|
||||
if (data["fork"]) {
|
||||
event.reply(dbot.t("forkedrepo",data));
|
||||
} else {
|
||||
event.reply(dbot.t("unforkedrepo",data));
|
||||
}
|
||||
// TODO: move this shizz into an api call
|
||||
var longurl = "http://github.com/" + repo;
|
||||
request({method: 'POST', uri: 'http://git.io', form:{url: longurl}}, function(error, response, body){
|
||||
event.reply(dbot.t('location')+" "+response.headers["location"]);
|
||||
});
|
||||
});
|
||||
},
|
||||
'~gstatus': function(event) {
|
||||
data = this.api.githubStatus(function(data){
|
||||
console.log(data);
|
||||
event.reply(dbot.t("status"+data["status"]));
|
||||
event.reply(data["body"]);
|
||||
}.bind(this));
|
||||
},
|
||||
'~milestone': function(event) {
|
||||
var repo = this.config.defaultrepo;
|
||||
var name = event.params[1];
|
||||
if (event.params[2]){
|
||||
repo = name;
|
||||
name = event.params[2];
|
||||
}
|
||||
var reqUrl = "https://api.github.com/repos/";
|
||||
reqUrl += repo + "/milestones";
|
||||
|
||||
request({"url": reqUrl, "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
var data = JSON.parse(body);
|
||||
for (var section in data) {
|
||||
var milestone = data[section];
|
||||
if (milestone["title"] == name){
|
||||
var str = "Milestone " + milestone["title"];
|
||||
var progress = milestone["closed_issues"] / (milestone["open_issues"] + milestone["closed_issues"]);
|
||||
progress = Math.round(progress*100);
|
||||
var bar = "[";
|
||||
for (var i = 10; i < 100; i += 10) {
|
||||
if ((progress/i) > 1) {
|
||||
bar += "█";
|
||||
} else {
|
||||
bar += " ";
|
||||
}
|
||||
}
|
||||
bar += "]";
|
||||
str += " is " + bar + progress + "% complete";
|
||||
|
||||
var longurl = "http://github.com/" + repo + "/issues?milestone=" + milestone["number"];
|
||||
request({method: 'POST', uri: 'http://git.io', form:{url: longurl}}, function(error, response, body){
|
||||
event.reply(response.headers["location"]);
|
||||
});
|
||||
event.reply(str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
'~repocount': function(event) {
|
||||
// TODO: add handling for non existent user
|
||||
var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos";
|
||||
request({"url": reqUrl,"headers": { "User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
var result = JSON.parse(body);
|
||||
event.reply(event.params[1] + " has " + result.length + " public repositories.");
|
||||
});
|
||||
},
|
||||
'~grate': function(event) {
|
||||
request.get({"url":"https://api.github.com/rate_limit", "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
var data = JSON.parse(body);
|
||||
if (data.message){
|
||||
event.reply(data.message);
|
||||
} else {
|
||||
event.reply(data.rate.remaining + " requests of " + data.rate.limit + " remaining.");
|
||||
}
|
||||
});
|
||||
},
|
||||
'~issue': function(event) {
|
||||
var repo, issue, randflag;
|
||||
if (isNaN(event.params[1]) && event.params[1]){ // if ~issue foo/bar
|
||||
repo = event.params[1];
|
||||
issue = event.params[2];
|
||||
} else {
|
||||
repo = this.config.defaultrepo;
|
||||
issue = event.params[1];
|
||||
}
|
||||
|
||||
if (issue == "*" || issue == "random" || issue == "0") {
|
||||
issue = "";
|
||||
randflag = true;
|
||||
} else if (!issue) { // issue is undefined
|
||||
issue = "";
|
||||
} else {
|
||||
issue = "/" + issue; // got to be a better way
|
||||
}
|
||||
|
||||
var reqUrl = "https://api.github.com/repos/" + repo + "/issues" +
|
||||
issue + "?sort=" + this.config.sortorder;
|
||||
request.get({"url": reqUrl, headers: { "User-Agent": this.config.useragent}}, function(error,response, body) {
|
||||
if (response.statusCode == "200") {
|
||||
var data = JSON.parse(body);
|
||||
if (!issue){
|
||||
if (randflag) {
|
||||
data = data[Math.floor(Math.random() * data.length)];
|
||||
} else {
|
||||
data = data[0];
|
||||
}
|
||||
}
|
||||
if (data["pull_request"]["html_url"]){
|
||||
console.log(data["pull_request"]["html_url"]);
|
||||
data["pull_request"] = " with code";
|
||||
} else {
|
||||
data["pull_request"] = "";
|
||||
}
|
||||
if (data["state"]=="open") {
|
||||
data["state"] = "\u000303" + data["state"];
|
||||
} else {
|
||||
data["state"] = "\u000304" + data["state"];
|
||||
}
|
||||
var labels = "";
|
||||
for (var i=0; i < data["labels"].length; i++) { // for-in doesn't like me
|
||||
var color = "\u0003" + (parseInt(data["labels"][i]["color"],16) % 15);
|
||||
labels += " " + color + data["labels"][i]["name"];
|
||||
}
|
||||
data["label"] = labels;
|
||||
event.reply(dbot.t("issue",data));
|
||||
event.reply(data["html_url"]);
|
||||
} else {
|
||||
event.reply(dbot.t("issuenotfound"));
|
||||
}
|
||||
});
|
||||
},
|
||||
'~commits': function(event) {
|
||||
exec("git rev-list --all | wc -l", function(error, stdout, stderr) {
|
||||
stdout = stdout.trim();
|
||||
request({"url":"http://numbersapi.com/" + stdout + "?fragment&default=XXX"}, function(error, response, body){
|
||||
if (body != "XXX"){
|
||||
event.reply(dbot.t("commitcountfun",{"fact": body, "count": stdout}));
|
||||
} else {
|
||||
// nothing fun about the number, let's try the year
|
||||
request({"url":"http://numbersapi.com/" + stdout + "/year?fragment&default=XXX"}, function(error, response, body){
|
||||
if (body != "XXX"){
|
||||
event.reply(dbot.t("commitcountyear",{"fact": body, "count": stdout}));
|
||||
} else {
|
||||
event.reply(dbot.t("commitcountboring",{"count": stdout}));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
this.commands = commands;
|
||||
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new github(dbot);
|
||||
};
|
81
modules/github/strings.json
Normal file
81
modules/github/strings.json
Normal file
@ -0,0 +1,81 @@
|
||||
{
|
||||
"repocount": {
|
||||
"en": "{user} has {count} public repos.",
|
||||
"cy": "Mae {count} archifdai cyhoeddus gan {user}.",
|
||||
"de": "{user} hat {count} öffnetliche Repos.",
|
||||
"fr": "{user} a {count} dépôt(s) public(s)."
|
||||
},
|
||||
"statusgood": {
|
||||
"en": "\u000309Shit's fine",
|
||||
"cy": "\u000309Cachu'n ddirwy",
|
||||
"de": "\u000309Alles in Ordnung",
|
||||
"fr": "\u000309Cette merde tourne bien"
|
||||
},
|
||||
"statusminor": {
|
||||
"en": "\u000308Shit's touchy",
|
||||
"cy": "\u000308Cachu'n fregus",
|
||||
"de": "\u000308Kleinere Probleme vorhanden",
|
||||
"fr": "\u000308Cette merde a un petit problème"
|
||||
},
|
||||
"statusmajor": {
|
||||
"en": "\u000304Shit's fucked:",
|
||||
"cy": "\u000304Cachu wedi cyrraedd y ffan:",
|
||||
"de": "\u000304Du bist am Arsch",
|
||||
"fr": "\u000304Cette merde est foutue : "
|
||||
},
|
||||
"location": {
|
||||
"en": "You can find that shit at:",
|
||||
"cy": "Gallwch ddod o hyd y cachu yn:",
|
||||
"de": "Kann nicht gefunden werden:",
|
||||
"fr": "Tu peux trouver cette merde ici : "
|
||||
},
|
||||
"forkedrepo": {
|
||||
"en": "{name} is a forked {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]",
|
||||
"cy": "{name} ydy archif {language} fforchog gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]",
|
||||
"de": "{name} ist eine geteilte {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]",
|
||||
"fr": "{name} est un dépôt fourché {language} avec {open_issues} problème(s) non résolu(s) [{forks}F {watchers}W]"
|
||||
},
|
||||
"unforkedrepo": {
|
||||
"en": "{name} is a {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]",
|
||||
"cy": "{name} ydy archif {language} gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]",
|
||||
"de": "{name} ist eine {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]",
|
||||
"fr": "{name} est un dépôt {language} avec {open_issues} problème(s) non résolu(s) [{forks}F {watchers}W]"
|
||||
},
|
||||
"usernotfound": {
|
||||
"en": "User not found.",
|
||||
"cy": "Defnyddiwr heb ei ganfod.",
|
||||
"de": "Benutzer nicht gefunden.",
|
||||
"fr": "Utilisateur non trouvé."
|
||||
},
|
||||
"issuenotfound": {
|
||||
"en": "Unable to find that issue.",
|
||||
"cy": "Wedi methu dod o hyd mater hwnnw",
|
||||
"de": "Kann dieses Problem nicht finden.",
|
||||
"fr": "Impossible de trouver ce problème."
|
||||
},
|
||||
"issue": {
|
||||
"en": "Issue \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}",
|
||||
"cy": "Mater \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} sylwadau]{label}",
|
||||
"de": "Problem \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}",
|
||||
"fr": "Problème \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} commentaires]{label}"
|
||||
},
|
||||
"commitcountboring": {
|
||||
"en": "My code has been committed {count} times.",
|
||||
"cy": "Mae fy cod wedi cael ei gyflawni ar {count} adegau.",
|
||||
"de": "Mein Code wurde {count} mal überstellt.",
|
||||
"fr": "Mon code a été modifié {count} fois."
|
||||
},
|
||||
"commitcountfun": {
|
||||
"en": "My repository has the same number of commits as {fact} ({count}).",
|
||||
"cy": "Yr un nifer o ymrwymo fel {fact} gan fy archif ({count}).",
|
||||
"de": "Meine Repository hat die gleiche Anzahl Commits wie {fact} ({count}).",
|
||||
"fr": "Mon dépôt a le même nombre de modifications que {fact} ({count})."
|
||||
},
|
||||
"commitcountyear": {
|
||||
"en": "My repository's commits number {count}, the year that {fact}.",
|
||||
"cy": "Nifer o ymrwymo gan fy archif: {count}, y flwyddyn y {fact}.",
|
||||
"de": "Anzahl der Commits in meinem Repository {count}, des Jahres {fact}",
|
||||
"fr": "Mon dépot compte {count} modifications, l'année où {fact}."
|
||||
}
|
||||
}
|
||||
|
49
modules/ignore/api.js
Normal file
49
modules/ignore/api.js
Normal file
@ -0,0 +1,49 @@
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var api = function(dbot) {
|
||||
return {
|
||||
// Is user ignoring command/module?
|
||||
'isUserIgnoring': function(user, item, callback) {
|
||||
this.internalAPI.isUserImpeded(user, item, 'ignores', callback);
|
||||
},
|
||||
|
||||
// Is user banned from command/module?
|
||||
'isUserBanned': function(user, item, callback) {
|
||||
this.internalAPI.isUserImpeded(user, item, 'bans', callback);
|
||||
},
|
||||
|
||||
// Is channel ignoring module?
|
||||
// TODO: Command support
|
||||
'isChannelIgnoring': function(channelName, item, callback) {
|
||||
var isIgnoring = false,
|
||||
channel = false;
|
||||
|
||||
this.db.search('channel_ignores', {
|
||||
'server': server,
|
||||
'name': channel
|
||||
}, function(result) {
|
||||
channel = result;
|
||||
}, function(err) {
|
||||
if(!err && channel && _.include(channel.ignores, item)) {
|
||||
isIgnoring = true;
|
||||
}
|
||||
callback(isIgnoring);
|
||||
});
|
||||
},
|
||||
|
||||
// Resolve a nick and return their user and ignores object
|
||||
'getUserIgnores': function(user, callback) {
|
||||
this.db.read('ignores', user.id, function(err, ignores) {
|
||||
if(!err && ignores) {
|
||||
callback(false, ignores);
|
||||
} else {
|
||||
callback(true, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return api(dbot);
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ignorable": false,
|
||||
"dependencies": [ "command" ],
|
||||
"dependencies": [ "users" ],
|
||||
"dbKeys": [ "ignores", "bans" ],
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md"
|
||||
"dbType": "redis"
|
||||
}
|
||||
|
@ -5,15 +5,35 @@
|
||||
* this information, since that actually performs the ignorance. Also provides
|
||||
* commands for moderators to choose the bot to ignore certain channels.
|
||||
*/
|
||||
var _ = require('underscore')._;
|
||||
var _ = require('underscore')._,
|
||||
databank = require('databank'),
|
||||
uuid = require('node-uuid'),
|
||||
NoSuchThingError = databank.NoSuchThingError;
|
||||
|
||||
var ignore = function(dbot) {
|
||||
this.internalAPI = {
|
||||
'isUserImpeded': function(user, item, by, callback) {
|
||||
this.api.getUserIgnores(user, function(err, ignores) {
|
||||
var isImpeded = false;
|
||||
if(!err && ignores) {
|
||||
if(_.has(dbot.commands, item)) {
|
||||
item = dbot.commands[item].module;
|
||||
}
|
||||
if(_.include(ignores[by], item)) {
|
||||
isImpeded = true;
|
||||
}
|
||||
}
|
||||
callback(isImpeded);
|
||||
});
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
var commands = {
|
||||
'~ignore': function(event) {
|
||||
var module = event.params[1];
|
||||
var ignorableModules = _.chain(dbot.modules)
|
||||
.filter(function(module, name) {
|
||||
return dbot.config[module].ignorable === true;
|
||||
return dbot.config.modules[module].ignorable === true;
|
||||
})
|
||||
.pluck('name')
|
||||
.value();
|
||||
@ -25,21 +45,30 @@ var ignore = function(dbot) {
|
||||
}));
|
||||
} else {
|
||||
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 {
|
||||
if(_.has(dbot.db.ignores, module)) {
|
||||
dbot.db.ignores[event.user].push(module);
|
||||
} else {
|
||||
dbot.db.ignores[event.user] = [module];
|
||||
this.api.getUserIgnores(event.rUser, function(err, ignores) {
|
||||
if(!ignores) {
|
||||
ignores = {
|
||||
'id': event.rUser.id,
|
||||
'ignores': [],
|
||||
'bans': []
|
||||
};
|
||||
}
|
||||
|
||||
dbot.instance.ignoreTag(event.user, module);
|
||||
event.reply(dbot.t('ignored', {
|
||||
'user': event.user,
|
||||
'module': module
|
||||
}));
|
||||
}
|
||||
if(!_.include(ignores.ignores, module)) {
|
||||
ignores.ignores.push(module);
|
||||
this.db.save('ignores', event.rUser.id, ignores, function(err) {
|
||||
if(!err) {
|
||||
dbot.instance.ignoreTag(event.user, module);
|
||||
event.reply(dbot.t('ignored', {
|
||||
'user': event.user,
|
||||
'module': module
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('already_ignoring', { 'user': event.user }));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_ignore', { 'user': event.user }));
|
||||
}
|
||||
@ -47,137 +76,192 @@ var ignore = function(dbot) {
|
||||
},
|
||||
|
||||
'~unignore': function(event) {
|
||||
var ignoredModules = [];
|
||||
if(_.has(dbot.db.ignores, event.user)) {
|
||||
ignoredModules = dbot.db.ignores[event.user];
|
||||
}
|
||||
var module = event.params[1];
|
||||
|
||||
if(_.isUndefined(module)) {
|
||||
event.reply(dbot.t('unignore_usage', {
|
||||
'user': event.user,
|
||||
'modules': ignoredModules.join(', ')
|
||||
}));
|
||||
} else {
|
||||
if(_.include(ignoredModules, module)) {
|
||||
dbot.db.ignores[event.user].splice(dbot.db.ignores[event.user].indexOf(module), 1);
|
||||
dbot.instance.removeIgnore(event.user, module)
|
||||
event.reply(dbot.t('unignored', {
|
||||
'user': event.user,
|
||||
'module': module
|
||||
}));
|
||||
this.api.getUserIgnores(event.rUser, function(err, ignores) {
|
||||
if(err || !ignores || _.isUndefined(module)) {
|
||||
if(ignores) {
|
||||
event.reply(dbot.t('unignore_usage', {
|
||||
'user': event.user,
|
||||
'modules': ignores.ignores.join(', ')
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('empty_unignore_usage', {
|
||||
'user': event.user
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_unignore', { 'user': event.user }));
|
||||
if(_.include(ignores.ignores, module)) {
|
||||
ignores.ignores = _.without(ignores.ignores, module);
|
||||
this.db.save('ignores', event.rUser.id, ignores, function(err) {
|
||||
if(!err) {
|
||||
dbot.instance.removeIgnore(event.user, module)
|
||||
event.reply(dbot.t('unignored', {
|
||||
'user': event.user,
|
||||
'module': module
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_unignore', { 'user': event.user }));
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~ban': function(event) {
|
||||
var user = event.params[1];
|
||||
var module = event.params[2];
|
||||
var nick = event.input[1],
|
||||
item = event.input[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(module == '*' || _.include(dbot.config.moduleNames, item) || _.include(dbot.commands, item)) {
|
||||
dbot.api.users.resolveUser(event.server, nick, function(user) {
|
||||
this.api.getUserIgnores(user, function(err, ignores) {
|
||||
if(!err) {
|
||||
if(!ignores) {
|
||||
ignores = {
|
||||
'id': user.id,
|
||||
'ignores': [],
|
||||
'bans': []
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
}));
|
||||
if(!_.include(ignores.bans, item)) {
|
||||
ignores.bans.push(item);
|
||||
this.db.save('ignores', user.id, ignores, function(err) {
|
||||
if(!err) {
|
||||
event.reply(dbot.t('banned_success', {
|
||||
'user': event.user,
|
||||
'banned': nick,
|
||||
'module': item
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('already_banned', {
|
||||
'user': event.user,
|
||||
'banned': nick
|
||||
}));
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_ban', {'user': event.user}));
|
||||
event.reply(dbot.t('invalid_ban', { 'user': event.user }));
|
||||
}
|
||||
},
|
||||
|
||||
'~unban': function(event) {
|
||||
var bannedModules = [];
|
||||
var nick = event.input[1],
|
||||
item = event.input[2];
|
||||
|
||||
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
|
||||
}));
|
||||
}
|
||||
}
|
||||
dbot.api.users.resolveUser(event.server, nick, function(user) {
|
||||
this.api.getUserIgnores(user, function(err, ignores) {
|
||||
if(err || !ignores) {
|
||||
event.reply(dbot.t('invalid_unban', {
|
||||
'user': event.user,
|
||||
'banned': nick
|
||||
}));
|
||||
} else {
|
||||
if(_.include(ignores.bans, item)) {
|
||||
ignores.bans = _.without(ignores.bans, item);
|
||||
this.db.save('ignores', user.id, ignores, function(err) {
|
||||
event.reply(dbot.t('unbanned_success', {
|
||||
'user': event.user,
|
||||
'banned': nick,
|
||||
'module': item
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_unban', {
|
||||
'user': event.user,
|
||||
'banned': nick
|
||||
}));
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~ignorechannel': function(event) {
|
||||
var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]);
|
||||
var module = event.params[2];
|
||||
var channelName = event.input[1],
|
||||
module = event.input[2];
|
||||
|
||||
// Ignoring the value of 'ignorable' at the moment
|
||||
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);
|
||||
dbot.instance.ignoreTag(channel, module);
|
||||
event.reply(dbot.t('ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channel
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('already_ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channel
|
||||
}));
|
||||
}
|
||||
var channel = false;
|
||||
|
||||
this.db.search('channel_ignores', {
|
||||
'server': event.server,
|
||||
'name': channelName
|
||||
}, function(result) {
|
||||
channel = result;
|
||||
}, function(err) {
|
||||
if(!channel) {
|
||||
var id = uuid.v4();
|
||||
channel = {
|
||||
'id': id,
|
||||
'server': event.server,
|
||||
'name': channelName,
|
||||
'ignores': []
|
||||
};
|
||||
}
|
||||
|
||||
if(!_.include(channel.ignores, module)) {
|
||||
channel.ignores.push(module);
|
||||
this.db.save('channel_ignores', channel.id, channel, function(err) {
|
||||
dbot.instance.ignoreTag(channel, module);
|
||||
event.reply(dbot.t('ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channelName
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('already_ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channelName
|
||||
}));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('module_not_exist', { 'module': module }));
|
||||
}
|
||||
},
|
||||
|
||||
'~unignorechannel': function(event) {
|
||||
var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]);
|
||||
var module = event.params[2];
|
||||
var channelName = event.input[1],
|
||||
module = event.input[2],
|
||||
channel = false;
|
||||
|
||||
if(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = [];
|
||||
if(_.include(dbot.db.ignores[channel], module)) {
|
||||
dbot.db.ignores[channel] = _.without(dbot.db.ignores[channel], module);
|
||||
dbot.instance.removeIgnore(channel, module);
|
||||
event.reply(dbot.t('unignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channel
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('not_ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channel
|
||||
}));
|
||||
}
|
||||
this.db.search('channel_ignores', {
|
||||
'server': event.server,
|
||||
'name': channelName
|
||||
}, function(result) {
|
||||
channel = result;
|
||||
}, function(err) {
|
||||
if(channel && _.include(channel.ignores, module)) {
|
||||
channel.ignores = _.without(channel.ignores, module);
|
||||
this.db.save('channel_ignores', channel.id, channel, function(err) {
|
||||
dbot.instance.removeIgnore(channel, module);
|
||||
event.reply(dbot.t('unignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channelName
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('not_ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channelName
|
||||
}));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
commands['~ban'].regex = [/^~ban ([^ ]+) ([^ ]+)$/, 3];
|
||||
commands['~unban'].regex = [/^~unban ([^ ]+) ([^ ]+)$/, 3];
|
||||
commands['~ignorechannel'].regex = [/^~ignorechannel ([^ ]+) ([^ ]+)$/, 3];
|
||||
commands['~unignorechannel'].regex = [/^~unignorechannel ([^ ]+) ([^ ]+)$/, 3];
|
||||
|
||||
commands['~ban'].access = 'moderator';
|
||||
commands['~unban'].access = 'moderator';
|
||||
commands['~ignorechannel'].access = 'moderator';
|
||||
@ -187,11 +271,22 @@ var ignore = function(dbot) {
|
||||
|
||||
this.onLoad = function() {
|
||||
dbot.instance.clearIgnores();
|
||||
_.each(dbot.db.ignores, function(ignores, item) {
|
||||
_.each(ignores, function(ignore) {
|
||||
dbot.instance.ignoreTag(item, ignore);
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
this.db.scan('ignores', function(ignores) {
|
||||
dbot.api.users.getUser(ignores.id, function(user) {
|
||||
if(user) {
|
||||
_.each(ignores.ignores, function(module) {
|
||||
dbot.instance.ignoreTag(user.primaryNick, module);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, function(err) { });
|
||||
|
||||
this.db.scan('channel_ignores', function(channel) {
|
||||
_.each(channel.ignores, function(module) {
|
||||
dbot.instance.ignoreTag(channel, module);
|
||||
});
|
||||
}, function(err) { });
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,8 @@
|
||||
"na'vi": "{user}: Sar: ~ignore ['u]. U, nga ke tìng mikyun: {modules}.",
|
||||
"cy": "{user}: Defnydd: ~ignore [modiwl]. Modiwlau a allech anwybyddu yw: {modules}.",
|
||||
"nl": "{user}: Gebruik: ~ignore [module]. Modules die negeert kunnen worden zijn: {modules}.",
|
||||
"de": "{user}: Benutzung: ~ignore [module]. Module, die ignoriert werden können: {modules}."
|
||||
"de": "{user}: Benutzung: ~ignore [module]. Module, die ignoriert werden können: {modules}.",
|
||||
"fr": "{user}: Utilisation: ~ignore [module]. Les modules que vous pouvez ignorer sont: {modules}."
|
||||
},
|
||||
"already_ignoring": {
|
||||
"en": "{user}: You're already ignoring that module.",
|
||||
@ -13,7 +14,8 @@
|
||||
"na'vi": "{user}: 'uri nga ke tìng mikyun srekrr.",
|
||||
"cy": "{user}: Mi rwyt ti'n anwybyddu'r modiwl yna'n barod.",
|
||||
"nl": "{user}: Je negeert deze module al.",
|
||||
"de": "{user}: Dieses Modul wird bereits ignoriert."
|
||||
"de": "{user}: Dieses Modul wird bereits ignoriert.",
|
||||
"fr": "{user}: Vous ignorez déjà ce module."
|
||||
},
|
||||
"ignored": {
|
||||
"en": "{user}: Now ignoring {module}.",
|
||||
@ -21,7 +23,8 @@
|
||||
"na'vi": "{user}: Nga ke terìng mikyun {module}ne set.",
|
||||
"cy": "{user}: Nawr yn anwybyddu {module}",
|
||||
"nl": "{user}: {module} wordt nu genegeerd.",
|
||||
"de": "{user}: {module} wird nun ignoriert."
|
||||
"de": "{user}: {module} wird nun ignoriert.",
|
||||
"fr": "{user}: {module} désormais ignoré."
|
||||
},
|
||||
"invalid_ignore": {
|
||||
"en": "{user}: That isn't a valid module name.",
|
||||
@ -29,7 +32,8 @@
|
||||
"na'vi": "{user}: Tsatstxo eyawr ke lu.",
|
||||
"cy": "{user}: Nid oedd hwna'n modiwl dilys",
|
||||
"nl": "{user}: Dat is geen geldige modulenaam.",
|
||||
"de": "{user}: Dies ist nicht der Name eines Moduls."
|
||||
"de": "{user}: Dies ist nicht der Name eines Moduls.",
|
||||
"fr": "{user}: Ceci ne correspond pas à un nom de module valide."
|
||||
},
|
||||
"unignore_usage": {
|
||||
"en": "{user}: Usage: ~unignore [module]. Modules you are currently ignoring: {modules}.",
|
||||
@ -37,7 +41,17 @@
|
||||
"na'vi": "{user}: Sar: ~unignore ['u]. Uri, nga ke terìng mikyun: {modules}.",
|
||||
"cy": "{user}: Defnydd: ~unignore [modiwl]. Modiwlau rydech yn anwybyddu ar hyn o bryd: {modules}",
|
||||
"nl": "{user}: Gebruik: ~unignore [module]. Modules die momenteel worden genegeerd: {modules}.",
|
||||
"de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ignoriert werden: {modules}."
|
||||
"de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ignoriert werden: {modules}.",
|
||||
"fr": "{user}: Utilisation: ~unignore [module]. Modules que vous ignorez actuellement: {modules}."
|
||||
},
|
||||
"empty_unignore_usage": {
|
||||
"en": "{user}: Usage: ~unignore [module].",
|
||||
"es": "{user}: Modo de empleo: ~unignore [módulo].",
|
||||
"na'vi": "{user}: Sar: ~unignore ['u].",
|
||||
"cy": "{user}: Defnydd: ~unignore [modiwl].",
|
||||
"nl": "{user}: Gebruik: ~unignore [module].",
|
||||
"de": "{user}: Benutzung: ~unignore [module].",
|
||||
"fr": "{user}: Utilisation: ~unignore [module]."
|
||||
},
|
||||
"invalid_unignore": {
|
||||
"en": "{user}: You're not ignoring that module or it doesn't exist.",
|
||||
@ -45,7 +59,8 @@
|
||||
"na'vi":"{user}: Nga terìng mikyun fu fì'ul fìtsengit ke tok.",
|
||||
"cy": "{user}: Nid wyt ti'n anwybyddu'r modiwl yna neu nid yw e'n bodoli",
|
||||
"nl": "{user}: Deze module bestaat niet of wordt niet genegeerd.",
|
||||
"de": "{user}: Dieses Modul wird entweder nicht ignoriert oder existiert nicht."
|
||||
"de": "{user}: Dieses Modul wird entweder nicht ignoriert oder existiert nicht.",
|
||||
"fr": "{user}: Vous n'ignorez pas ce module ou il n'existe pas."
|
||||
},
|
||||
"unignored": {
|
||||
"en": "{user}: No longer ignoring {module}.",
|
||||
@ -53,83 +68,96 @@
|
||||
"na'vi": "{user}: Nga terìng mikyun {module}ne set",
|
||||
"cy": "{user}: Ddim yn anwybyddu {module} bellach",
|
||||
"nl": "{user}: {module} wordt niet langer genegeerd.",
|
||||
"de": "{user}: {module} wird nicht länger ignoriert."
|
||||
"de": "{user}: {module} wird nicht länger ignoriert.",
|
||||
"fr": "{user}: {module} n'est plus ignoré à présent."
|
||||
},
|
||||
"ban_usage": {
|
||||
"en": "{user}: Usage: ~ban [user] [module/command]. Use * for all modules and commands.",
|
||||
"cy": "{user}: Defnydd: ~ban [defnyddiwr] [modiwl/gorchymyn]. Defnyddio * am pob modiwlau a gorchmynion.",
|
||||
"nl": "{user}: Gebruik: ~ban [gebruiker] [module/commando]. Gebruik * voor alle modules en alle commandos.",
|
||||
"de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle."
|
||||
"de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle.",
|
||||
"fr": "{user}: Utilisation: ~ban [user] [module/command]. Utilisez * pour tous les modules et commandes."
|
||||
},
|
||||
"already_banned": {
|
||||
"en": "{user}: {banned} is already banned from that module.",
|
||||
"cy": "{user}: {banned} eisoes wedi ei wahardd o'r modiwl.",
|
||||
"nl": "{user}: {banned} is al geband van deze module.",
|
||||
"de": "{user}: {banned} ist bereits von diesem Modul gebannt."
|
||||
"de": "{user}: {banned} ist bereits von diesem Modul gebannt.",
|
||||
"fr": "{user}: {banned} est déjà interdit d'utiliser ce module."
|
||||
},
|
||||
"banned_success": {
|
||||
"en": "{user}: {banned} is now banned from {module}.",
|
||||
"cy": "{user}: {banned} ei wahardd yn awr am {module}.",
|
||||
"nl": "{user}: {banned} mag {module} nu niet meer gebruiken.",
|
||||
"de": "{user}: {banned} ist nun von {module} gebannt."
|
||||
"de": "{user}: {banned} ist nun von {module} gebannt.",
|
||||
"fr": "{user}: {banned} est maintenant interdit d'utiliser {module}."
|
||||
},
|
||||
"invalid_ban": {
|
||||
"en": "{user}: That isn't a valid module name.",
|
||||
"cy": "{user}: Nid oedd hwna'n modiwl dilys",
|
||||
"nl": "{user}: Dat is geen geldige modulenaam.",
|
||||
"de": "{user}: Dies ist nicht der Name eines Moduls."
|
||||
"de": "{user}: Dies ist nicht der Name eines Moduls.",
|
||||
"fr": "{user}: Ceci n'est pas un nom de module valide."
|
||||
},
|
||||
"unban_usage": {
|
||||
"en": "{user}: Usage: ~unban [user] [module].",
|
||||
"cy": "{user}: Defnydd: ~unban [defnyddiwr] [modiwl].",
|
||||
"nl": "{user}: Gebruik: ~unban [gebruiker] [module].",
|
||||
"de": "{user}: Benutzung: ~unban [Benutzer] [module]."
|
||||
"de": "{user}: Benutzung: ~unban [Benutzer] [module].",
|
||||
"fr": "{user}: Utilisation: ~unban [user] [module]."
|
||||
},
|
||||
"invalid_unban": {
|
||||
"en": "{user}: {banned} is not banned from that module or it doesn't exist.",
|
||||
"cy": "{user}: Nid oedd {banned} wedi ei wahardd o'r modiwl, neu nid yw'n bodoli.",
|
||||
"nl": "{user}: {banned} is niet geband van die module of de module bestaat niet.",
|
||||
"de": "{user}: {banned} ist von diesem Modul nicht gebannt, oder es existiert nicht."
|
||||
"de": "{user}: {banned} ist von diesem Modul nicht gebannt, oder es existiert nicht.",
|
||||
"fr": "{user}: {banned} n'est pas interdit d'utiliser ce module, ou il n'existe pas."
|
||||
},
|
||||
"unbanned_success": {
|
||||
"en": "{user}: {banned} is no longer banned from {module}.",
|
||||
"cy": "{user}: Nid yw {banned} yn cael ei wahardd mwyach.",
|
||||
"nl": "{user}: {banned} mag {module} weer gebruiken.",
|
||||
"de": "{user}: {banned} wurde von {module} entbannt."
|
||||
"de": "{user}: {banned} wurde von {module} entbannt.",
|
||||
"fr": "{user}: {banned} n'est plus interdit d'utiliser {module}."
|
||||
},
|
||||
"ignoring_channel": {
|
||||
"en": "Now ignoring {module} in {channel}.",
|
||||
"na'vi": "Oe ke stayawm {module}ur mì {channel}",
|
||||
"cy": "Bellach yn anwybyddu {module} yn {channel}.",
|
||||
"nl": "{module} wordt nu genegeerd in {channel}.",
|
||||
"de": "{module} in [channel} wird nun ignoriert."
|
||||
"de": "{module} in {channel} wird nun ignoriert.",
|
||||
"fr": "{module} dans {channel} maintenant ignoré."
|
||||
},
|
||||
"already_ignoring_channel": {
|
||||
"en": "Already ignoring {module} in {channel}.",
|
||||
"na'vi": "Oe ke stayawm {module}ur mì {channel} li",
|
||||
"cy": "Eisoes anwybyddu {module} yn {channel}",
|
||||
"nl": "{module} wordt al genegeerd in {channel}.",
|
||||
"de": "{module} in {channel} wird bereits ignoriert."
|
||||
"de": "{module} in {channel} wird bereits ignoriert.",
|
||||
"fr": "{module} dans {channel} déjà ignoré."
|
||||
},
|
||||
"module_not_exist": {
|
||||
"en": "{module} isn't loaded or doesn't exist.",
|
||||
"na'vi": "Oel ke omum teri {module}it fu {module} ke fkeytok",
|
||||
"cy": "Dydy {module} ddim yn lwythodd, neu ddim yn bodoli.",
|
||||
"nl": "{module} is niet geladen of bestaat niet.",
|
||||
"de": "{module} ist nicht geladen oder existiert nicht."
|
||||
"de": "{module} ist nicht geladen oder existiert nicht.",
|
||||
"fr": "{module} n'est pas chargé ou n'existe pas."
|
||||
},
|
||||
"unignoring_channel": {
|
||||
"en": "No longer ignoring {module} in {channel}.",
|
||||
"na'vi": "Oel stayawm {module}ur mì {channel} set.",
|
||||
"cy": "Nid anwybyddu {module} yn {channel} mwyach.",
|
||||
"nl": "{module} wordt niet meer genegeerd in {channel}.",
|
||||
"de": "{module} in {channel} wird nicht länger ignoriert."
|
||||
"de": "{module} in {channel} wird nicht länger ignoriert.",
|
||||
"fr": "{module} dans {channel} n'est plus ignoré à présent."
|
||||
},
|
||||
"not_ignoring_channel": {
|
||||
"en": "{module} wasn't being ignored in {channel}.",
|
||||
"na'vi": "Oel stayawm {module}ur mì {channel} li.",
|
||||
"cy": "Nid yw {module} yn cael ei anwybyddu yn {channel}.",
|
||||
"nl": "{module} werd niet genegeerd in {channel}.",
|
||||
"de": "{module} wurde in {channel} nicht ignoriert."
|
||||
"de": "{module} wurde in {channel} nicht ignoriert.",
|
||||
"fr": "{module} n'était pas ignoré dans {channel}."
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"dbKeys": [ "imgur" ],
|
||||
"dependencies": [ "web", "api" ],
|
||||
"dependencies": [ "web", "api", "link" ],
|
||||
"imagelength": 5,
|
||||
"nsfwwarn": true,
|
||||
"apikey": "86fd3a8da348b65",
|
||||
|
@ -8,7 +8,6 @@ var _ = require('underscore')._,
|
||||
crypto = require('crypto');
|
||||
|
||||
var imgur = function(dbot) {
|
||||
this.db = dbot.db.imgur;
|
||||
this.internalAPI = {
|
||||
'infoString': function(imgData) {
|
||||
info = '';
|
||||
@ -77,21 +76,21 @@ var imgur = function(dbot) {
|
||||
var testUrl = 'http://i.imgur.com/' +
|
||||
testSlug +
|
||||
'.' + ext[_.random(0, ext.length - 1)];
|
||||
this.db.totalHttpRequests += 1;
|
||||
dbot.db.imgur.totalHttpRequests += 1;
|
||||
var image = request(testUrl, function(error, response, body) {
|
||||
// 492 is body.length of a removed image
|
||||
if(!error && response.statusCode == 200 && body.length != 492) {
|
||||
this.db.totalImages += 1;
|
||||
dbot.db.imgur.totalImages += 1;
|
||||
var hash = crypto.createHash('md5').update(body).digest("hex");
|
||||
if(_.has(dbot.modules, 'quotes')){
|
||||
// autoadd: {"abcdef": "facebookman"}
|
||||
if(_.has(dbot.config.imgur.autoadd,hash)){
|
||||
if(_.has(dbot.config.modules.imgur.autoadd,hash)){
|
||||
var category = dbot.config.imgur.autoadd[hash];
|
||||
if (_.contains(category, testUrl)){
|
||||
// there's probably less than 62^5 chance of this happening
|
||||
} else {
|
||||
if(!_.has(dbot.db.quoteArrs, category)) dbot.db.quoteArrs[category] = [];
|
||||
dbot.db.quoteArrs[category].push(testUrl);
|
||||
dbot.api.quotes.addQuote(category, testUrl,
|
||||
dbot.config.name, function() { });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,10 +112,10 @@ var imgur = function(dbot) {
|
||||
'url': 'https://api.imgur.com/3/image/' + slug + '.json',
|
||||
'json': true,
|
||||
'headers': {
|
||||
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
|
||||
'Authorization': 'Client-ID ' + this.config.apikey
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
this.db.totalApiRequests += 1;
|
||||
dbot.db.imgur.totalApiRequests += 1;
|
||||
callback(body);
|
||||
}.bind(this));
|
||||
},
|
||||
@ -126,7 +125,7 @@ var imgur = function(dbot) {
|
||||
'url': 'https://api.imgur.com/3/album/' + slug + '.json',
|
||||
'json': true,
|
||||
'headers': {
|
||||
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
|
||||
'Authorization': 'Client-ID ' + this.config.apikey
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
this.db.totalApiRequests += 1;
|
||||
@ -139,7 +138,7 @@ var imgur = function(dbot) {
|
||||
'url': 'https://api.imgur.com/3/gallery/' + slug + '.json',
|
||||
'json': true,
|
||||
'headers': {
|
||||
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
|
||||
'Authorization': 'Client-ID ' + this.config.apikey
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
this.db.totalApiRequests += 1;
|
||||
@ -197,6 +196,7 @@ var imgur = function(dbot) {
|
||||
if(!_.has(dbot.db.imgur, 'totalHttpRequests')) dbot.db.imgur.totalHttpRequests = 0;
|
||||
if(!_.has(dbot.db.imgur, 'totalApiRequests')) dbot.db.imgur.totalApiRequests = 0;
|
||||
if(!_.has(dbot.db.imgur, 'totalImages')) dbot.db.imgur.totalImages = 0;
|
||||
this.db = dbot.db.imgur;
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
|
@ -4,9 +4,11 @@
|
||||
"na'vi": "kxawm ke wivìntxu evengur",
|
||||
"cy": "Gallai fod yn anniogel ar gwaith",
|
||||
"nl": "bevat mogelijk gevoelige beelden",
|
||||
"de": "Könnte 18+ Material enthalten"
|
||||
"de": "Könnte 18+ Material enthalten",
|
||||
"fr": "peut être risqué pour le travail (NSFW)"
|
||||
},
|
||||
"imgurinfo": {
|
||||
"en": "[{info}]"
|
||||
"en": "[{info}]",
|
||||
"fr": "[{info}]"
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,5 @@
|
||||
}
|
||||
},
|
||||
"dependencies": [ "command" ],
|
||||
"ignorable": true,
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/js/README.md"
|
||||
"ignorable": true
|
||||
}
|
||||
|
@ -21,6 +21,16 @@ var js = function(dbot) {
|
||||
|
||||
// Run JS code un-sandboxed, with access to DBot memory (admin-only).
|
||||
'~ajs': function(event) {
|
||||
var callback = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
for(var i=0;i<args.length;i++) {
|
||||
var arg = args[i];
|
||||
if(_.isObject(arg) && !_.isArray(arg)) {
|
||||
arg = '[object Object]: ' + _.keys(arg).join(', ');
|
||||
}
|
||||
event.reply('Callback[' + i + ']: ' + arg);
|
||||
}
|
||||
};
|
||||
var ret = eval(event.input[1]);
|
||||
if(ret !== undefined) {
|
||||
event.reply(ret);
|
||||
|
@ -91,16 +91,13 @@ var commands = function(dbot) {
|
||||
timeout = event.input[1],
|
||||
banee = event.input[2],
|
||||
reason = event.input[3],
|
||||
adminChannel = this.config.admin_channel[event.server];
|
||||
adminChannel = dbot.config.servers[server].admin_channel,
|
||||
channels = dbot.config.servers[server].channels,
|
||||
network = event.server;
|
||||
|
||||
if(this.config.network_name[event.server]) {
|
||||
network = this.config.network_name[event.server];
|
||||
}
|
||||
console.log(timeout);
|
||||
console.log(banee);
|
||||
console.log(reason);
|
||||
|
||||
dbot.api.nickserv.getUserHost(event.server, banee, function(host) {
|
||||
// Add host record entry
|
||||
@ -148,34 +145,37 @@ var commands = function(dbot) {
|
||||
|
||||
// Add qutoe category documenting ban
|
||||
if(this.config.document_bans && _.has(dbot.modules, 'quotes')) {
|
||||
dbot.db.quoteArrs['ban_' + banee.toLowerCase()] = [ quoteString ];
|
||||
dbot.api.quotes.addQuote('ban_' + banee.toLowerCase(),
|
||||
quoteString, banee, function() {});
|
||||
notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee });
|
||||
}
|
||||
|
||||
// Notify moderators, banee
|
||||
if(this.config.admin_channel[event.server]) {
|
||||
if(!_.isUndefined(adminChannel)) {
|
||||
channels = _.without(channels, adminChannel);
|
||||
} else {
|
||||
adminChannel = event.channel.name;
|
||||
}
|
||||
|
||||
dbot.api.report.notify(server, adminChannel, notifyString);
|
||||
dbot.say(event.server, adminChannel, notifyString);
|
||||
dbot.api.report.notify(server, adminChannel, notifyString);
|
||||
dbot.say(event.server, adminChannel, notifyString);
|
||||
|
||||
if(!_.isUndefined(timeout)) {
|
||||
dbot.say(event.server, banee, dbot.t('tbanned_notify', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'reason': reason,
|
||||
'hours': timeout,
|
||||
'admin_channel': adminChannel
|
||||
}));
|
||||
} else {
|
||||
dbot.say(event.server, banee, dbot.t('nbanned_notify', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'reason': reason,
|
||||
'hours': timeout,
|
||||
'admin_channel': adminChannel
|
||||
}));
|
||||
}
|
||||
if(!_.isUndefined(timeout)) {
|
||||
dbot.say(event.server, banee, dbot.t('tbanned_notify', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'reason': reason,
|
||||
'hours': timeout,
|
||||
'admin_channel': adminChannel
|
||||
}));
|
||||
} else {
|
||||
dbot.say(event.server, banee, dbot.t('nbanned_notify', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'reason': reason,
|
||||
'hours': timeout,
|
||||
'admin_channel': adminChannel
|
||||
}));
|
||||
}
|
||||
|
||||
// Ban the user from all channels
|
||||
|
@ -1,12 +1,8 @@
|
||||
{
|
||||
"dbKeys": [ "kicks", "kickers", "hosts", "tempBans" ],
|
||||
"dependencies": [ "command", "report", "users" ],
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/kick/README.md",
|
||||
"ignorable": true,
|
||||
"countSilently": true,
|
||||
"admin_channel": {
|
||||
"aberwiki": "#fishbox"
|
||||
},
|
||||
"network_name": {
|
||||
"aberwiki": "OAOSIDL"
|
||||
},
|
||||
|
@ -28,22 +28,24 @@ var kick = function(dbot) {
|
||||
'networkUnban': function(server, unbanee, unbanner, callback) {
|
||||
var channels = dbot.config.servers[server].channels,
|
||||
network = this.config.network_name[server] || server,
|
||||
adminChannel = this.config.admin_channel[server];
|
||||
adminChannel = dbot.config.servers[server].admin_channel;
|
||||
|
||||
if(_.has(this.hosts, server) && _.has(this.hosts[server], unbanee)) {
|
||||
var host = this.hosts[server][unbanee];
|
||||
|
||||
// Notify Staff
|
||||
if(!_.isUndefined(adminChannel)) {
|
||||
var notifyString = dbot.t('nunbanned', {
|
||||
'network': network,
|
||||
'unbanee': unbanee,
|
||||
'unbanner': unbanner
|
||||
});
|
||||
dbot.api.report.notify(server, adminChannel, notifyString);
|
||||
dbot.say(server, adminChannel, notifyString);
|
||||
if(_.isUndefined(adminChannel)) {
|
||||
adminChannel = event.channel.name;
|
||||
}
|
||||
|
||||
var notifyString = dbot.t('nunbanned', {
|
||||
'network': network,
|
||||
'unbanee': unbanee,
|
||||
'unbanner': unbanner
|
||||
});
|
||||
dbot.api.report.notify(server, adminChannel, notifyString);
|
||||
dbot.say(server, adminChannel, notifyString);
|
||||
|
||||
// Notify Unbanee
|
||||
dbot.say(server, unbanee, dbot.t('nunban_notify', {
|
||||
'network': network,
|
||||
@ -74,7 +76,7 @@ var kick = function(dbot) {
|
||||
} else {
|
||||
callback(true); // No host could be found
|
||||
}
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -5,16 +5,20 @@
|
||||
"na'vi": "Tuteol {user}it tsrame'i {kicks} hìmtxan ulte sute tsrame'i {kicked} hìmtxan.",
|
||||
"cy": "Cafwyd {user} ei gicio {kicks} gwaith ac wedi cicio pobl {kicked} gwaith.",
|
||||
"nl": "{user} is {kicks} keer gekickt en heeft anderen {kicked} keer gekickt.",
|
||||
"de": "{user} wurde {kicks} mal gekickt und hat {kicked} mal andere Benutzer gekickt."
|
||||
"de": "{user} wurde {kicks} mal gekickt und hat {kicked} mal andere Benutzer gekickt.",
|
||||
"fr": "{user} a été kické {kicks} fois et a kické des personnes {kicked} fois."
|
||||
},
|
||||
"quieted": {
|
||||
"en": "Quieted {quietee}. Remember: don't be a coconut."
|
||||
"en": "Quieted {quietee}. Remember: don't be a coconut.",
|
||||
"fr": "{quietee} a été rendu silencieux. Rappelle-toi : ne sois pas têtu."
|
||||
},
|
||||
"tquieted": {
|
||||
"en": "Quieted {quietee} for {minutes} minutes. Remember: don't be a coconut."
|
||||
"en": "Quieted {quietee} for {minutes} minutes. Remember: don't be a coconut.",
|
||||
"fr": "{quietee} a été rendu silencieux pour {minutes} minutes. Rappelle-toi : ne sois pas têtu."
|
||||
},
|
||||
"unquieted": {
|
||||
"en": "Unquieted {quietee}. Remember: don't be a coconut."
|
||||
"en": "Unquieted {quietee}. Remember: don't be a coconut.",
|
||||
"fr": "{quietee} peut maintenant parler. Rappelle-toi : ne sois pas têtu."
|
||||
},
|
||||
"kicked_dbot": {
|
||||
"en": "Thou shalt not kick {botname}",
|
||||
@ -22,52 +26,65 @@
|
||||
"na'vi": "Ngal {botname}it ke tsun tsrive'i",
|
||||
"cy": "Ni ddylech cicio {botname}",
|
||||
"nl": "Gij zult {botname} niet kicken",
|
||||
"de": "Du sollst {botname} nicht kicken"
|
||||
"de": "Du sollst {botname} nicht kicken",
|
||||
"fr": "Tu ne kickeras pas {botname}"
|
||||
},
|
||||
"ckicked": {
|
||||
"en": "Attention: {kicker} has kicked {kickee} from {channel}. The reason given was: \"{reason}.\"",
|
||||
"cy": "Sylw: {kicker} wedi cicio'r {kickee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}.\"",
|
||||
"de": "Achtung: {kicker} hat {kickee} von {channel} verwiesen. Grund: \"{reason}.\""
|
||||
"de": "Achtung: {kicker} hat {kickee} von {channel} verwiesen. Grund: \"{reason}.\"",
|
||||
"fr": "Attention : {kicker} a kické {kickee} de {channel}. Raison donnée : \"{reason}.\""
|
||||
},
|
||||
"cbanned": {
|
||||
"en": "Attention: {banner} has banned {banee} from {channel}. The reason given was \"{reason}.\"",
|
||||
"cy": "Sylw: {banner} wedi gwahardd {banee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}.\"",
|
||||
"de": "Achtung: {banner} hat {banee} von {channel} gebannt. Grund: \"{reason}.\""
|
||||
"de": "Achtung: {banner} hat {banee} von {channel} gebannt. Grund: \"{reason}.\"",
|
||||
"fr": "Attention : {banner} a banni {banee} de {channel}. Raison donnée : \"{reason}.\""
|
||||
},
|
||||
"tbanned": {
|
||||
"en": "Attention: {banner} has banned {banee} from the {network} network for {hours} hours. The reason given was \"{reason}.\""
|
||||
"en": "Attention: {banner} has banned {banee} from the {network} network for {hours} hours. The reason given was \"{reason}.\"",
|
||||
"fr": "Attention : {banner} a banni {banee} du réseau {network} pour {hours} heures. Raison donnée : \"{reason}.\""
|
||||
},
|
||||
"tbanned_notify": {
|
||||
"en": "You have been banned from the {network} network for {hours} hours by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban."
|
||||
"en": "You have been banned from the {network} network for {hours} hours by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban.",
|
||||
"fr": "Vous avez été banni du réseau {network} pour {hours} heures par {banner}. La raison donnée était \"{reason}.\" Vous pouvez rejoindre {admin_channel} pour plus d'information or pour discuter du ban."
|
||||
},
|
||||
"nbanned": {
|
||||
"en": "Attention: {banner} has banned {banee} from the {network} network. The reason given was \"{reason}.\"",
|
||||
"cy": "Sylw: {banner} wedi gwahardd {banee} ledled y rhwydwaith. Y rheswm a roddwyd oedd: \"{reason}.\"",
|
||||
"de": "Achtung: {banner} hat {banee} auf dem gesamten Netzwerk gebannt. Grund: \"{reason}.\""
|
||||
"de": "Achtung: {banner} hat {banee} auf dem gesamten Netzwerk gebannt. Grund: \"{reason}.\"",
|
||||
"fr": "Attention : {banner} a banni {banee} du réseau {network}. Raison donnée : \"{reason}.\""
|
||||
},
|
||||
"nbanned_notify": {
|
||||
"en": "You have been banned from the {network} network by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban."
|
||||
"en": "You have been banned from the {network} network by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban.",
|
||||
"fr": "Vous avez été banni du réseau {network} par {banner}. La raison donnée était \"{reason}.\" Vous pouvez rejoindre {admin_channel} pour plus d'information or pour discuter du ban."
|
||||
},
|
||||
"nban_quote": {
|
||||
"en": "{banee} was banned from the network by {banner} on {time}. The reason given was \"{reason}.\"",
|
||||
"cy": "Cafodd {banee} ei wahardd o'r rhwydwaith gan {banner} ar {time}. Y rheswm a roddwyd oedd: \"{reason}.\"",
|
||||
"de": "{banee} wurde von {banner} auf dem gesamten Netzwerk um {time} gebannt. Grund: \"{reason}.\""
|
||||
"de": "{banee} wurde von {banner} auf dem gesamten Netzwerk um {time} gebannt. Grund: \"{reason}.\"",
|
||||
"fr": "{banee} a été banni du réseau par {banner} à {time}. Raison donnée : \"{reason}.\""
|
||||
},
|
||||
"no_user": {
|
||||
"en": "{user} doesn't seem to be online on this server."
|
||||
"en": "{user} doesn't seem to be online on this server.",
|
||||
"fr": "{user} ne semble pas être connecté à ce serveur."
|
||||
},
|
||||
"nunbanned": {
|
||||
"en": "Attention: {unbanee} has been unbanned from the {network} network by {unbanner}."
|
||||
"en": "Attention: {unbanee} has been unbanned from the {network} network by {unbanner}.",
|
||||
"fr": "Attention : {unbanee} a été débanni du réseau {network} par {unbanner}."
|
||||
},
|
||||
"nunban_notify": {
|
||||
"en": "You have been unbanned from the {network} network by {unbanner}."
|
||||
"en": "You have been unbanned from the {network} network by {unbanner}.",
|
||||
"fr": "Vous avez été débanni du réseau {network} par {unbanner}."
|
||||
},
|
||||
"nunban_error": {
|
||||
"en": "It appears {unbanee} was not banned using the ~nban command."
|
||||
"en": "It appears {unbanee} was not banned using the ~nban command.",
|
||||
"fr": "Il semble que {unbanee} n'a pas été banni en utilisant la commande ~nban."
|
||||
},
|
||||
"quote_recorded": {
|
||||
"en": "This has been recorded in ~ban_{user}.",
|
||||
"cy": "Mae hyn wedi cael ei gofnodi yn ~ban_{user}.",
|
||||
"de": "Dies wurde in ~ban_{user} aufgenommen."
|
||||
"de": "Dies wurde in ~ban_{user} aufgenommen.",
|
||||
"fr": "Cela a été enregistré dans ~ban_{user}."
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
{
|
||||
"autoTitle": false,
|
||||
"dependencies": [ "command" ],
|
||||
"autoTitle": true,
|
||||
"ignorable": true,
|
||||
"outputPrefix": "\u00032link\u000f",
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/link/README.md"
|
||||
|
@ -126,7 +126,7 @@ var link = function(dbot) {
|
||||
var urlMatches = event.message.match(this.urlRegex);
|
||||
if(urlMatches !== null) {
|
||||
this.links[event.channel.name] = urlMatches[0];
|
||||
if(dbot.config.link.autoTitle == true) {
|
||||
if(this.config.autoTitle == true) {
|
||||
var handlerFound = false;
|
||||
for(var i=0;i<this.handlers.length;i++) {
|
||||
var matches = this.handlers[i].regex.exec(urlMatches[0]);
|
||||
|
@ -4,19 +4,23 @@
|
||||
"na'vi": "Oel ke tsun run 'upxare atxin.",
|
||||
"cy": "Ni chanfuwyd teitl y dudalen",
|
||||
"nl": "Er is geen paginatitel gevonden.",
|
||||
"de": "Kein Seitenname gefunden."
|
||||
"de": "Kein Seitenname gefunden.",
|
||||
"fr": "Aucun titre de page trouvé."
|
||||
},
|
||||
"xkcd": {
|
||||
"en": "xkcd {num}: {title} https://xkcd.com/{num}"
|
||||
"en": "xkcd {num}: {title} https://xkcd.com/{num}",
|
||||
"fr": "xkcd {num}: {title} https://xkcd.com/{num}"
|
||||
},
|
||||
"no-hits": {
|
||||
"en": "No hits.",
|
||||
"na'vi": "Oel ke tsun rivum ayuoti.",
|
||||
"cy": "Dim canlyniadau.",
|
||||
"nl": "Geen resultaten.",
|
||||
"de": "Keine Treffer."
|
||||
"de": "Keine Treffer.",
|
||||
"fr": "Aucun résultat."
|
||||
},
|
||||
"link": {
|
||||
"en": "{link}"
|
||||
"en": "{link}",
|
||||
"fr": "{link}"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"log_message": {
|
||||
"en": "[{time}] {user}: {command}"
|
||||
"en": "[{time}] {user}: {command}",
|
||||
"fr": "[{time}] {user}: {command}"
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
{
|
||||
"servers": {
|
||||
"nc": {
|
||||
"aberwiki": {
|
||||
"matcher": "STATUS ([^ ]+) (\\d)$",
|
||||
"acceptableState": 3,
|
||||
"infoCommand": "status"
|
||||
}
|
||||
},
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/nickserv/README.md"
|
||||
}
|
||||
}
|
||||
|
@ -72,8 +72,9 @@ var nickserv = function(dbot) {
|
||||
|
||||
if(match[1]) match[1] = match[1].replace('\*', '');
|
||||
if(match && _.has(this.userStack, event.server) && _.has(this.userStack[event.server], match[1])) {
|
||||
this.userStack[event.server][match[1]](match[3].trim());
|
||||
var callback = this.userStack[event.server][match[1]];
|
||||
delete this.userStack[event.server][match[1]];
|
||||
callback(match[3].trim());
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
|
@ -1,14 +1,18 @@
|
||||
{
|
||||
"authed": {
|
||||
"en": "{nick} is authed with nickserv."
|
||||
"en": "{nick} is authed with nickserv.",
|
||||
"fr": "{nick} est authentifié avec nickserv."
|
||||
},
|
||||
"not_authed": {
|
||||
"en": "{nick} is not authed with nickserv."
|
||||
"en": "{nick} is not authed with nickserv.",
|
||||
"fr": "{nick} n'est pas authentifié avec nickserv."
|
||||
},
|
||||
"hostmask": {
|
||||
"en": "Hostmask for {nick}: {host}"
|
||||
"en": "Hostmask for {nick}: {host}",
|
||||
"fr": "Hostmask pour {nick}: {host}"
|
||||
},
|
||||
"no_hostmask": {
|
||||
"en": "No hostmask could be found for {nick}"
|
||||
"en": "No hostmask could be found for {nick}",
|
||||
"fr": "Aucun hostmask trouvé pour {nick}"
|
||||
}
|
||||
}
|
||||
|
@ -1,183 +1,196 @@
|
||||
var _ = require('underscore')._;
|
||||
var _ = require('underscore')._,
|
||||
databank = require('databank'),
|
||||
AlreadyExistsError = databank.AlreadyExistsError,
|
||||
NoSuchThingError = databank.NoSuchThingError;
|
||||
|
||||
var commands = function(dbot) {
|
||||
var polls = dbot.db.polls;
|
||||
var commands = {
|
||||
'~newpoll': function(event) {
|
||||
var name = event.input[1].toLowerCase(),
|
||||
options = event.input[2].toLowerCase().split(','),
|
||||
description = event.input[3];
|
||||
|
||||
if(_.has(polls, name)) {
|
||||
event.reply(dbot.t('poll_exists', { 'name': name }));
|
||||
} else {
|
||||
polls[name] = {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'owner': dbot.api.users.resolveUser(event.server, event.user),
|
||||
'votes': {},
|
||||
'votees': {}
|
||||
};
|
||||
for(var i=0;i<options.length;i++) {
|
||||
polls[name]['votes'][options[i]] = 0;
|
||||
}
|
||||
|
||||
|
||||
event.reply(dbot.t('poll_created', {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'url': dbot.api.web.getUrl('/poll/' + name)
|
||||
}));
|
||||
}
|
||||
_.each(options, function(item, index, list) { list[index] = [ item, 0 ]; })
|
||||
votes = _.object(options);
|
||||
|
||||
this.db.create('poll', name, {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'owner': event.rUser.id,
|
||||
'votes': votes,
|
||||
'votees': {}
|
||||
}, function(err, value) {
|
||||
if(!err) {
|
||||
event.reply(dbot.t('poll_created', {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'url': dbot.api.web.getUrl('poll/' + name)
|
||||
}));
|
||||
} else if(err instanceof AlreadyExistsError) {
|
||||
event.reply(dbot.t('poll_exists', { 'name': name }));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'~addoption': function(event) {
|
||||
var name = event.input[1].toLowerCase(),
|
||||
option = event.input[2].toLowerCase(),
|
||||
user = dbot.api.users.resolveUser(event.server, event.user);
|
||||
option = event.input[2].toLowerCase();
|
||||
|
||||
if(_.has(polls, name)) {
|
||||
if(polls[name].owner === user) {
|
||||
if(!_.has(polls[name].votes, option)) {
|
||||
polls[name]['votes'][option] = 0;
|
||||
event.reply(dbot.t('option_added', {
|
||||
'user': event.user,
|
||||
'name': name,
|
||||
'option': option
|
||||
}));
|
||||
this.db.read('poll', name, function(err, poll) {
|
||||
if(!err) {
|
||||
if(poll.owner === event.rUser.id) {
|
||||
if(!_.has(poll.votes, option)) {
|
||||
poll.votes[option] = 0;
|
||||
this.db.save('poll', name, poll, function(err) {
|
||||
event.reply(dbot.t('option_added', {
|
||||
'user': event.user,
|
||||
'name': name,
|
||||
'option': option
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('option_exists', {
|
||||
'option': option,
|
||||
'name': name,
|
||||
'user': event.user
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('option_exists', {
|
||||
'option': option,
|
||||
'name': name,
|
||||
'user': event.user
|
||||
event.reply(dbot.t('not_poll_owner', {
|
||||
'user': event.user,
|
||||
'name': name
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('not_poll_owner', {
|
||||
'user': event.user,
|
||||
'name': name
|
||||
}));
|
||||
if(err instanceof NoSuchThingError) {
|
||||
event.reply(dbot.t('poll_unexistent', { 'name': name }));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('poll_unexistent', {'name': name}));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~rmoption': function(event) {
|
||||
var name = event.input[1].toLowerCase(),
|
||||
option = event.input[2].toLowerCase(),
|
||||
user = dbot.api.users.resolveUser(event.server, event.user);
|
||||
|
||||
if(_.has(polls, name)) {
|
||||
if(polls[name].owner === user) {
|
||||
if(_.has(polls[name].votes, option)) {
|
||||
delete polls[name]['votes'][option];
|
||||
event.reply(dbot.t('option_removed', {
|
||||
'user': event.user,
|
||||
'name': name,
|
||||
'option': option
|
||||
}));
|
||||
option = event.input[2].toLowerCase();
|
||||
|
||||
this.db.read('poll', name, function(err, poll) {
|
||||
if(!err) {
|
||||
if(poll.owner === event.rUser.id) {
|
||||
if(_.has(poll.votes, option)) {
|
||||
delete poll.votes[option];
|
||||
|
||||
this.db.save('poll', name, poll, function(err) {
|
||||
event.reply(dbot.t('option_removed', {
|
||||
'user': event.user,
|
||||
'name': name,
|
||||
'option': option
|
||||
}));
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_vote', { 'vote': option }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_vote', { 'vote': option }));
|
||||
event.reply(dbot.t('not_poll_owner', { 'name': name }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('not_poll_owner', { 'name': name }));
|
||||
if(err instanceof NoSuchThingError) {
|
||||
event.reply(dbot.t('poll_unexistent', { 'name': name }));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('poll_unexistent', { 'name': name }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~vote': function(event) {
|
||||
var name = event.input[1].toLowerCase(),
|
||||
vote = event.input[2].toLowerCase(),
|
||||
user = dbot.api.users.resolveUser(event.server, event.user);
|
||||
vote = event.input[2].toLowerCase();
|
||||
|
||||
this.db.read('poll', name, function(err, poll) {
|
||||
if(!err) {
|
||||
if(_.has(poll.votes, vote)) {
|
||||
if(_.has(poll.votees, event.rUser.id)) {
|
||||
var oldVote = poll.votees[event.rUser.id];
|
||||
poll.votes[oldVote]--;
|
||||
poll.votes[vote]++;
|
||||
poll.votees[event.rUser.id] = vote;
|
||||
} else {
|
||||
poll.votes[vote]++;
|
||||
poll.votees[event.rUser.id] = vote;
|
||||
}
|
||||
|
||||
if(_.has(polls, name)) {
|
||||
if(_.has(polls[name].votes, vote)) {
|
||||
if(_.has(polls[name].votees, user)) {
|
||||
var oldVote = polls[name].votees[user];
|
||||
polls[name].votes[oldVote]--;
|
||||
polls[name].votes[vote]++;
|
||||
polls[name].votees[user] = vote;
|
||||
|
||||
event.reply(dbot.t('changed_vote', {
|
||||
'vote': vote,
|
||||
'poll': name,
|
||||
'count': polls[name].votes[vote],
|
||||
'user': event.user
|
||||
}));
|
||||
this.db.save('poll', name, poll, function(err) {
|
||||
event.reply(dbot.t('voted', {
|
||||
'vote': vote,
|
||||
'poll': name,
|
||||
'count': poll.votes[vote],
|
||||
'user': event.user
|
||||
}));
|
||||
}.bind(this));
|
||||
} else {
|
||||
polls[name].votes[vote]++;
|
||||
polls[name].votees[user] = vote;
|
||||
event.reply(dbot.t('voted', {
|
||||
'vote': vote,
|
||||
'poll': name,
|
||||
'count': polls[name].votes[vote],
|
||||
'user': event.user
|
||||
}));
|
||||
event.reply(dbot.t('invalid_vote', { 'vote': vote }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_vote', { 'vote': vote }));
|
||||
if(err instanceof NoSuchThingError) {
|
||||
event.reply(dbot.t('poll_unexistent', { 'name': name }));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('poll_unexistent', { 'name': name }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~pdesc': function(event) {
|
||||
var name = event.input[1].toLowerCase();
|
||||
this.db.read('poll', name, function(err, poll) {
|
||||
if(!err) {
|
||||
var options = _.keys(poll.votes);
|
||||
var optionString = " Choices: ";
|
||||
for(var i=0;i<options.length;i++) {
|
||||
optionString += options[i] + ', ';
|
||||
}
|
||||
optionString = optionString.slice(0, -2) + '.';
|
||||
|
||||
if(_.has(polls, name)) {
|
||||
var options = _.keys(polls[name].votes);
|
||||
var optionString = " Choices: ";
|
||||
for(var i=0;i<options.length;i++) {
|
||||
optionString += options[i] + ', ';
|
||||
event.reply(dbot.t('poll_describe', {
|
||||
'name': name,
|
||||
'description': poll.description,
|
||||
'url': dbot.api.web.getUrl('poll/' + name)
|
||||
}) + optionString);
|
||||
} else {
|
||||
if(err instanceof NoSuchThingError) {
|
||||
event.reply(dbot.t('poll_unexistent', { 'name': name }));
|
||||
}
|
||||
}
|
||||
optionString = optionString.slice(0, -2) + '.';
|
||||
|
||||
event.reply(dbot.t('poll_describe', {
|
||||
'name': name,
|
||||
'description': polls[name].description,
|
||||
'url': dbot.t('url', {
|
||||
'host': dbot.config.web.webHost,
|
||||
'port': dbot.config.web.webPort,
|
||||
'path': 'polls/' + name
|
||||
})
|
||||
}) + optionString);
|
||||
} else {
|
||||
event.reply(dbot.t('poll_unexistent', { 'name': name }));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'~count': function(event) {
|
||||
var name = event.input[1].toLowerCase();
|
||||
|
||||
if(_.has(polls, name)) {
|
||||
var order;
|
||||
var votesArr = [];
|
||||
this.db.read('poll', name, function(err, poll) {
|
||||
if(!err) {
|
||||
var order;
|
||||
var votesArr = [];
|
||||
|
||||
var order = _.chain(polls[name].votes)
|
||||
.pairs()
|
||||
.sortBy(function(option) { return option[1] })
|
||||
.reverse()
|
||||
.value();
|
||||
var order = _.chain(poll.votes)
|
||||
.pairs()
|
||||
.sortBy(function(option) { return option[1]; })
|
||||
.reverse()
|
||||
.value();
|
||||
|
||||
var orderString = "";
|
||||
for(var i=0;i<order.length;i++) {
|
||||
orderString += order[i][0] +
|
||||
" (" + order[i][1] + "), ";
|
||||
var orderString = "";
|
||||
for(var i=0;i<order.length;i++) {
|
||||
orderString += order[i][0] +
|
||||
" (" + order[i][1] + "), ";
|
||||
}
|
||||
orderString = orderString.slice(0, -2);
|
||||
|
||||
event.reply(dbot.t('count', {
|
||||
'poll': name,
|
||||
'description': poll.description,
|
||||
'places': orderString
|
||||
}));
|
||||
} else {
|
||||
if(err instanceof NoSuchThingError) {
|
||||
event.reply(dbot.t('poll_unexistent', {'name': name}));
|
||||
}
|
||||
}
|
||||
orderString = orderString.slice(0, -2);
|
||||
|
||||
event.reply(dbot.t('count', {
|
||||
'poll': name,
|
||||
'description': polls[name].description,
|
||||
'places': orderString
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('poll_unexistent', {'name': name}));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
commands['~newpoll'].regex = [/~newpoll ([^ ]+) options=([^ ]+) (.+)/, 4];
|
||||
|
@ -1,6 +1,12 @@
|
||||
{
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/poll/README.md",
|
||||
"dbType": "redis",
|
||||
"dbKeys": [ "polls" ],
|
||||
"ignorable": true,
|
||||
"dependencies": [ "users", "command" ]
|
||||
"dependencies": [ "users", "web", "event" ],
|
||||
"schema": {
|
||||
"poll": {
|
||||
"pkey": "name",
|
||||
"fields": [ "description", "owner", "votes", "votees" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +1,57 @@
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var pages = function(dbot) {
|
||||
var polls = dbot.db.polls;
|
||||
var pages = {
|
||||
// Shows the results of a poll
|
||||
'/polls/:key': function(req, res) {
|
||||
'/poll/:key': function(req, res) {
|
||||
var key = req.params.key.toLowerCase();
|
||||
if(_.has(dbot.db.polls, key)) {
|
||||
var totalVotes = _.reduce(dbot.db.polls[key].votes,
|
||||
function(memo, option) {
|
||||
this.db.read('poll', key, function(err, poll) {
|
||||
if(!err) {
|
||||
var totalVotes = _.reduce(poll.votes, function(memo, option) {
|
||||
return memo += option;
|
||||
}, 0);
|
||||
res.render('polls', {
|
||||
'name': dbot.config.name,
|
||||
'description': dbot.db.polls[key].description,
|
||||
'votees': Object.keys(dbot.db.polls[key].votees),
|
||||
'options': dbot.db.polls[key].votes,
|
||||
locals: {
|
||||
'totalVotes': totalVotes,
|
||||
'url_regex': RegExp.prototype.url_regex()
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.render('error', {
|
||||
'name': dbot.config.name,
|
||||
'message': 'No polls under that key.'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
var voterNicks = [];
|
||||
/* TODO: Fix stupid fucking async issue bullshit
|
||||
var voterNicks = _.map(poll.votees, function(vote, id) {
|
||||
dbot.api.users.getUser(id, function(user) {
|
||||
return user.primaryNick;
|
||||
});
|
||||
});*/
|
||||
|
||||
process.nextTick(function() {
|
||||
console.log(voterNicks);
|
||||
res.render('polls', {
|
||||
'name': dbot.config.name,
|
||||
'description': poll.description,
|
||||
'votees': voterNicks,
|
||||
'options': poll.votes,
|
||||
locals: {
|
||||
'totalVotes': totalVotes,
|
||||
'url_regex': RegExp.prototype.url_regex()
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.render('error', {
|
||||
'name': dbot.config.name,
|
||||
'message': 'No polls under that key.'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Lists all of the polls
|
||||
'/poll': function(req, res) {
|
||||
res.render('polllist', {
|
||||
'name': dbot.config.name,
|
||||
'polllist': Object.keys(dbot.db.polls)
|
||||
var pollKeys = [];
|
||||
this.db.scan('poll', function(result) {
|
||||
if(result) pollKeys.push(result.name);
|
||||
}, function(err) {
|
||||
console.log(pollKeys);
|
||||
res.render('polllist', {
|
||||
'name': dbot.config.name,
|
||||
'polllist': pollKeys
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,22 +1,26 @@
|
||||
var poll = function(dbot) {
|
||||
this.internalAPI = {
|
||||
'updatePollNicks': function(server, oldNick) {
|
||||
var newNick = dbot.api.users.resolveUser(server, oldNick);
|
||||
_.each(dbot.db.polls, function(poll) {
|
||||
if(poll.owner === oldNick) {
|
||||
poll.owner = newNick;
|
||||
'updatePollNicks': function(server, oldUser, newUser) {
|
||||
this.db.scan('poll', function(poll) {
|
||||
var needsUpdating = false;
|
||||
if(poll.owner == oldUser.id) {
|
||||
poll.owner = newUser.id;
|
||||
needsUpdating = true;
|
||||
}
|
||||
if(_.has(poll.votees, oldNick)) {
|
||||
poll.votees[newNick] = poll.votees[oldNick];
|
||||
delete poll.votees[oldNick];
|
||||
if(_.has(poll.votees, oldUser.id)) {
|
||||
poll.votes[poll.votees[oldUser.id]]--;
|
||||
delete poll.votees[oldUser.id];
|
||||
needsUpdating = true;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
if(needsUpdating) {
|
||||
this.db.save('poll', poll.name, poll, function(err) {});
|
||||
}
|
||||
}.bind(this), function(err) {});
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
this.onLoad = function() {
|
||||
dbot.api.command.addHook('~setaliasparent', this.internalAPI.updatePollNicks);
|
||||
dbot.api.command.addHook('~mergeusers', this.internalAPI.updatePollNicks);
|
||||
dbot.api.event.addHook('~mergeusers', this.internalAPI.updatePollNicks);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,8 @@
|
||||
"na'vi": "Usage: ~newpoll tstxo [sìftxey=tìfxey1,tìfxey2,fìfxey3] tìsla'tsu",
|
||||
"cy": "Defnydd: ~newpoll enw [optiynau=opt1,opt2,op3] disgrifiad",
|
||||
"nl": "Gebruik: ~newpoll name [options=opt1,opt2,opt3] description",
|
||||
"de": "Benutzung: ~newpoll name [options=opt1,opt2,opt3] Beschreibung"
|
||||
"de": "Benutzung: ~newpoll name [options=opt1,opt2,opt3] Beschreibung",
|
||||
"fr": "Utilisation: ~newpoll nom [options=opt1,opt2,opt3] description"
|
||||
},
|
||||
"poll_exists": {
|
||||
"en": "Poll '{name}' already exists.",
|
||||
@ -13,17 +14,20 @@
|
||||
"na'vi": "sìpawm sna'o '{name}' fkeytok srekrr.",
|
||||
"cy": "Mae'r pôl {name} bodoli'n barod",
|
||||
"nl": "Poll '{name}' bestaat al.",
|
||||
"de": "Umfrage '{name}' existiert bereits."
|
||||
"de": "Umfrage '{name}' existiert bereits.",
|
||||
"fr": "Le sondage '{name}' existe déjà."
|
||||
},
|
||||
"poll_created": {
|
||||
"en": "Poll '{name}' created ({description}). Cast thy votations! - {url}",
|
||||
"es" : "Votación '{name}' creado ({description}). ¡Emited sus votas! - {url}",
|
||||
"na'vi": "sìpawm sna'o '{name}' ngìyop ({description}). Nga tìpe'unit Pe'eiun - {url}",
|
||||
"nl": "Poll '{name}' aangemaakt ({description}). Laat uw stem horen! - {url}",
|
||||
"de": "Umfrage '{name}' gestartet ({description}). Lasst Antworten ertönen! - {url}"
|
||||
"de": "Umfrage '{name}' gestartet ({description}). Lasst Antworten ertönen! - {url}",
|
||||
"fr": "Sondage '{name}' créé ({description}). Tous aux ballots de vote ! - {url}"
|
||||
},
|
||||
"poll_describe": {
|
||||
"en": "{name}: {description} - {url}."
|
||||
"en": "{name}: {description} - {url}.",
|
||||
"fr": "{name}: {description} - {url}."
|
||||
},
|
||||
"changed_vote": {
|
||||
"en": "{user} changed their vote in {poll} to '{vote}' ({count}).",
|
||||
@ -31,7 +35,8 @@
|
||||
"na'vi": "{user} lìyatem ngeyä tìpe'un {poll}mì, ngeyä tìpe'un amip '{vote}'({count}) lu.",
|
||||
"cy": "Newidiodd {user} eu pleidlais yn {poll} i '{vote}' ({count}).",
|
||||
"nl": "{user} heeft zijn stem voor {poll} veranderd in '{vote}' ({count}).",
|
||||
"de": "{user} hat seine Antwort in {poll} zu '{vote}' geändert ({count})."
|
||||
"de": "{user} hat seine Antwort in {poll} zu '{vote}' geändert ({count}).",
|
||||
"fr": "{user} a changé son vote dans {sondage} pour '{vote}' ({count})."
|
||||
},
|
||||
"voted": {
|
||||
"en": "{user} voted for '{vote}' in {poll} ({count}).",
|
||||
@ -39,7 +44,8 @@
|
||||
"na'vi": "'{vote}'ìri {user} pìye'un {poll}mì ({count}).",
|
||||
"cy": "Pledleisiodd {user} am '{vote}' yn {poll} ({count}).",
|
||||
"nl": "{user} heeft gestemd voor '{vote}' in {poll} ({count}).",
|
||||
"de": "{user} hat für '{vote}' in {poll} gestimmt ({count})."
|
||||
"de": "{user} hat für '{vote}' in {poll} gestimmt ({count}).",
|
||||
"fr":"{user} a voté pour '{vote}' dans {poll} ({count})."
|
||||
},
|
||||
"invalid_vote": {
|
||||
"en": "Invalid vote: {vote}",
|
||||
@ -47,7 +53,8 @@
|
||||
"na'vi": "Ngeyä tìpe'un keyawr lu ({vote}).",
|
||||
"cy": "Pleidlais annilys: {vote}",
|
||||
"nl": "Ongeldige stem: {vote}",
|
||||
"de": "Ungültige Antwort: {vote}"
|
||||
"de": "Ungültige Antwort: {vote}",
|
||||
"fr": "Vote invalide: {vote}"
|
||||
},
|
||||
"poll_unexistent": {
|
||||
"en": "Poll '{name}' doesn't exist.",
|
||||
@ -55,7 +62,8 @@
|
||||
"na'vi": "sìpawm sna'o '{name}' ke fkeytok.",
|
||||
"cy": "Nid yw pôl '{name}' yn bodoli",
|
||||
"nl": "Poll '{name}' bestaat niet.",
|
||||
"de": "Umfrage '{name}' existiert nicht."
|
||||
"de": "Umfrage '{name}' existiert nicht.",
|
||||
"fr": "Le sondage '{name}' n'existe pas."
|
||||
},
|
||||
"option_added": {
|
||||
"en": "{user}: '{option}' added to '{name}'.",
|
||||
@ -63,7 +71,8 @@
|
||||
"na'vi": "'{name}'ur {user}ìl '{option}'it sung.",
|
||||
"cy": "{user}: Ychwanegwyd '{option}' i '{name}'",
|
||||
"nl": "{user}: '{option}' toegevoegd aan '{name}'.",
|
||||
"de": "{user}: '{option}'in '{name}' hinzugefügt."
|
||||
"de": "{user}: '{option}'in '{name}' hinzugefügt.",
|
||||
"fr": "{user}: '{option}' ajouté à '{name}'."
|
||||
},
|
||||
"option_exists": {
|
||||
"en": "{user}: '{option}' already exists in '{name}'.",
|
||||
@ -71,7 +80,8 @@
|
||||
"na'vi": "{user}: '{option}' fkeytok srekrr '{name}'mì.",
|
||||
"cy": "{user}: Mae '{option}' yn bodoli'n barod yn '{name}'.",
|
||||
"nl": "{user}: '{option}' bestaat al in '{name}'.",
|
||||
"de": "{user}: '{option}' existiert bereits in '{name}'."
|
||||
"de": "{user}: '{option}' existiert bereits in '{name}'.",
|
||||
"fr": "{user}: '{option} existe déjà dans '{name}'."
|
||||
},
|
||||
"not_poll_owner": {
|
||||
"en": "{user}: You don't own the '{name}' poll.",
|
||||
@ -79,7 +89,8 @@
|
||||
"na'vi": "{user}: ngaru '{name}' sìpawm sna'o ke lu.",
|
||||
"cy": "{user}: Nid ydech chi'n berchen y pôl '{name}'.",
|
||||
"nl": "{user}: Je bent niet de eigenaar van de poll '{name}'.",
|
||||
"de": "{user}: Du darfst die Umfrage '{name}' nicht verändern."
|
||||
"de": "{user}: Du darfst die Umfrage '{name}' nicht verändern.",
|
||||
"fr": "{user}: Le sondage '{name}' ne t'appartient pas."
|
||||
},
|
||||
"option_removed": {
|
||||
"en": "{user}: '{option}' removed from '{name}'",
|
||||
@ -87,7 +98,8 @@
|
||||
"na'vi": "{user}: '{option}'it 'aku '{name}'ta",
|
||||
"cy": "{user}: '{option}' wedi ei ddileu o '{name}'",
|
||||
"nl": "{user}: '{option}' verwijderd van '{name}'",
|
||||
"de": "{user}: '{option}' entfernt aus '{name}'"
|
||||
"de": "{user}: '{option}' entfernt aus '{name}'",
|
||||
"fr": "{user}: '{option}' enlevé de '{name}'"
|
||||
},
|
||||
"av_voted": {
|
||||
"en": "{user} voted '{vote}' in {poll}.",
|
||||
@ -95,7 +107,8 @@
|
||||
"na'vi": "{user}ìl '{vote}'it pìye'un '{poll}'mì.",
|
||||
"cy": "Pledleisiodd {user} am '{vote}' yn {poll}",
|
||||
"nl": "{user} heeft '{vote}' gestemd in {poll}.",
|
||||
"de": "{user} hat in {poll} für '{vote}' gestimmt."
|
||||
"de": "{user} hat in {poll} für '{vote}' gestimmt.",
|
||||
"fr": "{user} a voté '{vote}' dans {poll}."
|
||||
},
|
||||
"av_changed_vote": {
|
||||
"en": "{user} changed their vote in {poll} to '{vote}'.",
|
||||
@ -103,13 +116,15 @@
|
||||
"na'vi": "{user}ìl lìyatem ngeyä tìpa'unit '{poll}'mì, ngeyä tìpe'un '{vote} lu set.",
|
||||
"cy": "Newidiodd {user} eu pleidlais yn {poll} i '{vote}'",
|
||||
"nl": "{user} heeft zijn stem veranderd naar '{vote}' in {poll}.",
|
||||
"de": "{user} hat seine Stimme in {poll} auf '{vote}' geändert."
|
||||
"de": "{user} hat seine Stimme in {poll} auf '{vote}' geändert.",
|
||||
"fr": "{user} a changé son vote dans {sondage} pour '{vote}'."
|
||||
},
|
||||
"count": {
|
||||
"en": "The running-order of poll '{poll}' ({description}) is: {places}.",
|
||||
"na'vi": "Sute tsnì pole'un '{poll}'mì ({description}) lu: {places}.",
|
||||
"cy": "Trefn yr pôl '{poll}' ({description}) yw: {places}",
|
||||
"nl": "De volgorde van poll '{poll}' ({description}) is: {places}.",
|
||||
"de": "Das Ergebnis der Umfrage '{poll}' ({description}) lautet: {places}."
|
||||
"de": "Das Ergebnis der Umfrage '{poll}' ({description}) lautet: {places}.",
|
||||
"fr": "L'ordre de passage du sondage '{poll}' ({description}) est : {places}."
|
||||
}
|
||||
}
|
||||
|
@ -4,64 +4,98 @@ var api = function(dbot) {
|
||||
return {
|
||||
|
||||
/**
|
||||
* Create a profile for a new primary user on a given server.
|
||||
* If the server does not already exist, create it.
|
||||
* Create a new profile for a given "databanked" user.
|
||||
* Typically only called as a hook to the new_user emit event.
|
||||
* TODO(@samstudio8) Migrate to internalAPI
|
||||
*/
|
||||
"createProfile": function(server, primary){
|
||||
var primaryLower = primary.toLowerCase();
|
||||
|
||||
if(!_.has(this.profiles, server)){
|
||||
this.profiles[server] = {};
|
||||
"createProfile": function(user, callback){
|
||||
if(user){
|
||||
this.db.create('profiles', user.id, {
|
||||
'id': user.id,
|
||||
'profile': this.config.schema.profile,
|
||||
'preferences': this.config.schema.preferences
|
||||
}, function(err, result){
|
||||
if(err){
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
if(!_.has(this.profiles[server], primaryLower)){
|
||||
this.profiles[server][primaryLower] = {
|
||||
"profile": {},
|
||||
"preferences": {}
|
||||
};
|
||||
this.profiles[server][primaryLower].profile.primary = primary;
|
||||
}
|
||||
|
||||
// Ensure all profiles have the keys specified by config.json
|
||||
//TODO(samstudio8) Currently only handles "top-level"
|
||||
_.defaults(this.profiles[server][primaryLower].profile, this.config.schema.profile);
|
||||
_.defaults(this.profiles[server][primaryLower].preferences, this.config.schema.preferences);
|
||||
},
|
||||
|
||||
//TODO(samstudio8) Merge Profiles
|
||||
'mergeProfile': function(server, nick, callback){
|
||||
console.log("mergeProfile not implemented");
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a server and "new" alias, resolve this alias to the user's
|
||||
* new primary name and move profile data pertaining to the alias to
|
||||
* the new primary name.
|
||||
*/
|
||||
'renameProfile': function(server, alias){
|
||||
if(!_.has(this.profiles, server)) return;
|
||||
var profiles = dbot.db.profiles[server];
|
||||
'getProfile': function(server, nick, callback){
|
||||
dbot.api.users.resolveUser(server, nick, function(user){
|
||||
if(user){
|
||||
this.db.read('profiles', user.id, function(err, profile){
|
||||
if(!err){
|
||||
callback(false, user, profile);
|
||||
}
|
||||
else{
|
||||
callback(true, user, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
callback(true, null, null);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
if(_.has(profiles, alias)){
|
||||
var primary = dbot.api.users.resolveUser(server, alias, true);
|
||||
var primaryLower = primary.toLowerCase();
|
||||
alias = alias.trim().toLowerCase();
|
||||
|
||||
profiles[primaryLower] = profiles[alias];
|
||||
profiles[primaryLower].profile.primary = primary;
|
||||
delete profiles[alias];
|
||||
'getProfileByUUID': function(uuid, callback){
|
||||
if(uuid){
|
||||
this.db.read('profiles', uuid, function(err, profile){
|
||||
if(!err){
|
||||
callback(false, uuid, profile);
|
||||
}
|
||||
else{
|
||||
callback(true, uuid, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
callback(true, null, null);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a server and a primary username which has been converted to a
|
||||
* secondary alias find and remove the profile for the alias.
|
||||
*/
|
||||
'mergeProfile': function(server, mergeFromPrimary){
|
||||
if(!_.has(this.profiles, server)) return;
|
||||
var profiles = dbot.db.profiles[server];
|
||||
'getAllProfiles': function(callback){
|
||||
var profiles = [];
|
||||
this.db.scan('profiles', function(profile){
|
||||
profiles.push(profile);
|
||||
}, function(err){
|
||||
if(!err){
|
||||
callback(profiles);
|
||||
}
|
||||
else{
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
mergeFromPrimary = mergeFromPrimary.toLowerCase();
|
||||
var mergeToPrimary = dbot.api.users.resolveUser(server, mergeFromPrimary, true).toLowerCase();
|
||||
if(!_.has(profiles, mergeToPrimary)
|
||||
|| !_.has(profiles, mergeFromPrimary)) return;
|
||||
'setProperty': function(server, nick, field, value, callback){
|
||||
this.api.getProfile(server, nick, function(err, user, profile){
|
||||
if(!err){
|
||||
profile.profile[field] = value;
|
||||
this.db.save('profiles', user.id, profile, function(err){
|
||||
if(!err){
|
||||
callback("Ok!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// Remove the profile of the alias
|
||||
delete profiles[mergeFromPrimary];
|
||||
'getProperty': function(server, nick, field, callback){
|
||||
this.api.getProfile(server, nick, function(err, user, profile){
|
||||
if(!err){
|
||||
if(profile.profile[field]){
|
||||
callback(profile.profile[field]);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
}
|
||||
};
|
||||
|
@ -2,49 +2,33 @@ var _ = require('underscore')._;
|
||||
|
||||
var commands = function(dbot){
|
||||
var commands = {
|
||||
|
||||
"~getprop": function(event){
|
||||
'~getprop': function(event){
|
||||
if(event.params[1]){
|
||||
var primary = dbot.api.users.resolveUser(event.server, event.user);
|
||||
var res = dbot.db.profiles[event.server][primary.toLowerCase()].profile[event.params[1]];
|
||||
if(res){
|
||||
event.reply(res);
|
||||
}
|
||||
else{
|
||||
event.reply("Nope.");
|
||||
if(_.has(this.config.schema.profile, event.params[1])){
|
||||
this.api.getProperty(event.server, event.user, event.params[1], function(reply){
|
||||
event.reply(reply);
|
||||
});
|
||||
} else {
|
||||
event.reply('Invalid property. Go home.');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"~setprop": function(event){
|
||||
'~setprop': function(event){
|
||||
if(event.input[1] && event.input[2]){
|
||||
if(_.has(this.config.schema.profile, event.input[1])){
|
||||
var primary = dbot.api.users.resolveUser(event.server, event.user);
|
||||
dbot.db.profiles[event.server][primary.toLowerCase()].profile[event.input[1]] = event.input[2];
|
||||
event.reply("Property set, maybe?");
|
||||
}
|
||||
else{
|
||||
event.reply("Invalid property. Go home.");
|
||||
this.api.setProperty(event.server, event.user, event.input[1], event.input[2], function(reply){
|
||||
event.reply(reply);
|
||||
});
|
||||
} else {
|
||||
event.reply('Invalid property. Go home.');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"~profile": function(event){
|
||||
if(event.params[1]){
|
||||
var primary = dbot.api.users.resolveUser(event.server, event.params[1]);
|
||||
if(_.has(dbot.db.profiles[event.server], primary.toLowerCase())){
|
||||
event.reply(dbot.api.web.getUrl("profile/"+event.server+"/"+primary.toLowerCase()));
|
||||
}
|
||||
else{
|
||||
event.reply("No profile found for "+event.params[1]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
event.message = '~profile ' + event.user;
|
||||
event.action = 'PRIVMSG';
|
||||
event.params = event.message.split(' ');
|
||||
dbot.instance.emit(event);
|
||||
}
|
||||
'~profile': function(event) {
|
||||
var user = event.params[1] || event.user;
|
||||
event.reply(dbot.api.web.getUrl('profile/' + event.server + '/' + user));
|
||||
}
|
||||
};
|
||||
commands['~setprop'].regex = [/~setprop ([^ ]+) (.+)/, 3];
|
||||
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"ignorable": false,
|
||||
"dbKeys": [ "profiles" ],
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/profile/README.md",
|
||||
"dbType": "redis",
|
||||
"schema": {
|
||||
"profile": {
|
||||
"primary": null,
|
||||
@ -17,5 +16,5 @@
|
||||
"timezone": null
|
||||
}
|
||||
},
|
||||
"dependencies": [ "quotes", "users", "command" ]
|
||||
"dependencies": [ "web", "quotes", "users" ]
|
||||
}
|
||||
|
@ -5,58 +5,80 @@ var pages = function(dbot) {
|
||||
return {
|
||||
'/profile/:connection/:user': function(req, res) {
|
||||
var connection = req.params.connection;
|
||||
var user = dbot.cleanNick(req.params.user);
|
||||
var nick = req.params.user;
|
||||
|
||||
var primary = dbot.api.users.resolveUser(connection, user, true);
|
||||
//var profile = dbot.api.profile.getProfile(primary);
|
||||
var profile = dbot.db.profiles[connection][primary.toLowerCase()].profile;
|
||||
var stats = dbot.api.stats.getUserChansStats(connection, primary.toLowerCase(), [
|
||||
"lines", "words", "lincent", "wpl", "in_mentions"]
|
||||
);
|
||||
dbot.api.users.resolveUser(connection, nick, function(user){
|
||||
if(user){
|
||||
dbot.api.profile.getProfile(connection, user.primaryNick, function(err, user, profile){
|
||||
if(!err){
|
||||
var stats = [];
|
||||
|
||||
res.render('profile', {
|
||||
'name': dbot.config.name,
|
||||
'connection': connection,
|
||||
'primary': primary,
|
||||
'profile': profile,
|
||||
'stats': stats.channels,
|
||||
/*TODO(@samstudio8)
|
||||
* stats functionality currently disabled as it has not been databanked
|
||||
*/
|
||||
//var stats = dbot.api.stats.getUserChansStats(connection, user.primaryNick, [
|
||||
// "lines", "words", "lincent", "wpl", "in_mentions"]
|
||||
//);
|
||||
|
||||
res.render('profile', {
|
||||
'name': dbot.config.name,
|
||||
'connection': connection,
|
||||
'primary': user.primaryNick,
|
||||
'profile': profile.profile,
|
||||
'stats': stats.channels,
|
||||
});
|
||||
}
|
||||
else{
|
||||
res.render('error', {
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
res.render('not_found', {
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'/profile/:connection': function(req, res) {
|
||||
var connection = req.params.connection;
|
||||
var profiles = dbot.db.profiles[connection];
|
||||
dbot.api.profile.getAllProfiles(function(profiles){
|
||||
var thumbnails = [];
|
||||
_.each(profiles, function(profile){
|
||||
var nick = dbot.api.users.getUser(profile.id, function(user){
|
||||
if(user){
|
||||
|
||||
// TODO: Clean up
|
||||
_.each(profiles, function(profile) {
|
||||
if(_.has(dbot.db.quoteArrs, profile.profile.primary) && !profile.profile.avatar) {
|
||||
var category = dbot.db.quoteArrs[profile.profile.primary];
|
||||
var avatar = _.find(category, function(quote) {
|
||||
return quote.match(/(\.jpg|\.png|\.jpeg)$/i);
|
||||
/*TODO(@tmenari / @samstudio8)
|
||||
* if username has a quote array and no avatar:
|
||||
* search their quote array for a jpg, png, jpeg or gif
|
||||
* set this as their new avatar
|
||||
*/
|
||||
|
||||
if(profile.profile.avatar){
|
||||
thumbnails.push({
|
||||
"avatar": profile.profile.avatar,
|
||||
"nick": user.primaryNick
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if(avatar) profile.profile.avatar = avatar;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var nicks = [];
|
||||
for (var p in profiles) {
|
||||
if (profiles.hasOwnProperty(p) && profiles[p].profile.avatar) {
|
||||
nicks.push(p);
|
||||
}
|
||||
}
|
||||
nicks.sort(function(a, b) {
|
||||
var x = profiles[a].profile.primary.toLowerCase();
|
||||
var y = profiles[b].profile.primary.toLowerCase();
|
||||
if(x > y) return 1;
|
||||
if(x < y) return -1;
|
||||
return 0;
|
||||
});
|
||||
process.nextTick(function(){
|
||||
thumbnails.sort(function(a, b) {
|
||||
var x = a.nick.toLowerCase();
|
||||
var y = b.nick.toLowerCase();
|
||||
if(x > y) return 1;
|
||||
if(x < y) return -1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
res.render('profile_grid', {
|
||||
'name': dbot.config.name,
|
||||
'connection': connection,
|
||||
'nicks': nicks,
|
||||
'profiles': profiles,
|
||||
res.render('profile_grid', {
|
||||
'name': dbot.config.name,
|
||||
'connection': req.params.connection,
|
||||
'thumbnails': thumbnails,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2,28 +2,28 @@ var _ = require('underscore')._;
|
||||
|
||||
var profile = function(dbot) {
|
||||
|
||||
this.profiles = dbot.db.profiles;
|
||||
|
||||
/**
|
||||
* Iterate over known user profiles and ensure they contain all the
|
||||
* required properties as defined in the configuation.
|
||||
*/
|
||||
this.onLoad = function(){
|
||||
var api = this.api;
|
||||
var schema = this.config.schema;
|
||||
|
||||
// Ensure all known users have a profile
|
||||
_.each(dbot.api.users.getAllUsers(), function(server, serverName){
|
||||
_.each(server, function(primary, primaryi){
|
||||
api.createProfile(serverName, primary);
|
||||
});
|
||||
});
|
||||
dbot.save();
|
||||
|
||||
// Ensure all users have a profile
|
||||
dbot.api.users.getAllUsers(function(users){
|
||||
if(users){
|
||||
_.each(users, function(user){
|
||||
this.api.getProfileByUUID(user.id, function(err, uuid, profile){
|
||||
// If function returns an error and uuid, create a new profile
|
||||
if(err && uuid){
|
||||
this.api.createProfile(user);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
// Add API Hooks
|
||||
dbot.api.command.addHook('~setaliasparent', this.api.renameProfile);
|
||||
dbot.api.command.addHook('~mergeusers', this.api.mergeProfile);
|
||||
dbot.api.event.addHook('new_user', this.api.createProfile);
|
||||
|
||||
//TODO(@samstudio8) Profile Merging
|
||||
//dbot.api.command.addHook('~mergeusers', this.api.mergeProfile);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -3,8 +3,7 @@ var exec = require('child_process').exec,
|
||||
_ = require('underscore');
|
||||
|
||||
var pages = function(dbot) {
|
||||
var quoteCat = dbot.db.quoteArrs[dbot.config.name],
|
||||
rev, diff, branch, credit, authors = [];
|
||||
var rev, diff, branch, credit, authors = [];
|
||||
exec("git log --format='%cN¬' | sort -u | tr -d '\n'", function (error, stdout, sderr) {
|
||||
var credit = stdout.split("¬"); // nobody uses ¬, do they?
|
||||
for (var i = 0; i < credit.length; i++) {
|
||||
@ -30,72 +29,71 @@ var pages = function(dbot) {
|
||||
|
||||
/* TODO: merge back into github module */
|
||||
var milestones;
|
||||
request({"url":"https://api.github.com/repos/" + dbot.config.github.defaultrepo + "/milestones?state=open","headers":{"User-Agent":"reality/depressionbot (project module)"}}, function(error, response, body){
|
||||
request({"url":"https://api.github.com/repos/" + dbot.config.modules.github.defaultrepo + "/milestones?state=open","headers":{"User-Agent":"reality/depressionbot (project module)"}}, function(error, response, body){
|
||||
milestones = JSON.parse(body);
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
'/project': function(req, res) {
|
||||
var quote = dbot.config.name;
|
||||
if(quoteCat) {
|
||||
quote = quoteCat[Math.floor(Math.random()*quoteCat.length)];
|
||||
}
|
||||
dbot.api.quotes.getQuote(dbot.config.name, function(quote) {
|
||||
if(!quote) quote = dbot.config.name;
|
||||
|
||||
res.render('project', {
|
||||
"translation": dbot.modules.project.api.translationProgress(),
|
||||
"configList": dbot.modules.project.api.configList(),
|
||||
"authors": authors,
|
||||
"credits": dbot.t("credits"),
|
||||
"thanks": dbot.t("thanks"),
|
||||
"name": dbot.config.name,
|
||||
"intro": dbot.t("dbotintro", {
|
||||
"botname": dbot.config.name
|
||||
}),
|
||||
"curr839": dbot.config.language,
|
||||
"repo": dbot.config.github.defaultrepo,
|
||||
"branch": dbot.t("branch",{
|
||||
"branch": branch
|
||||
}),
|
||||
"currver": dbot.config.version,
|
||||
"currlang": dbot.t("dbotspeaks",{
|
||||
"lang839": dbot.config.language,
|
||||
"langen": dbot.strings[dbot.config.language]["en"],
|
||||
"lang": dbot.t(dbot.config.language),
|
||||
"name": dbot.config.name
|
||||
}),
|
||||
"projectstatus": dbot.t("projectstatus"),
|
||||
"revnum": dbot.t("revnum",{
|
||||
res.render('project', {
|
||||
"translation": dbot.modules.project.api.translationProgress(),
|
||||
"configList": dbot.modules.project.api.configList(),
|
||||
"authors": authors,
|
||||
"credits": dbot.t("credits"),
|
||||
"thanks": dbot.t("thanks"),
|
||||
"name": dbot.config.name,
|
||||
"rev": rev
|
||||
}),
|
||||
"modules": dbot.config.moduleNames,
|
||||
"loadmod": dbot.t("loadedmodules"),
|
||||
"debugmode": dbot.t("debugmode-" + dbot.config.debugMode),
|
||||
"milestones": milestones,
|
||||
"milestoneprog": dbot.t("milestoneprog"),
|
||||
"config": dbot.t("configoptions"),
|
||||
"milestonename": dbot.t("milestonename"),
|
||||
"openmilestone": dbot.t("openmilestone"),
|
||||
"closedmilestone": dbot.t("closedmilestone"),
|
||||
"development": dbot.t("development"),
|
||||
"dquote": quote,
|
||||
"diff": diff,
|
||||
"pagetitle": dbot.t("pagetitle", {
|
||||
"botname": dbot.config.name
|
||||
}),
|
||||
"git": dbot.t("git"),
|
||||
"milestonehead": dbot.t("milestones"),
|
||||
"propaganda": dbot.t("propaganda"),
|
||||
"languagecurr": dbot.t(dbot.config.language),
|
||||
"languagenati": dbot.t("langhead-native"),
|
||||
"languageeng": dbot.t("en"),
|
||||
"languageprog": dbot.t("langhead-progress"),
|
||||
"languagetrans": dbot.t("langhead-translations"),
|
||||
"languagetranshead": dbot.t("translations"),
|
||||
"pullreqs": dbot.t("outstanding-pullreq")
|
||||
});
|
||||
},
|
||||
"intro": dbot.t("dbotintro", {
|
||||
"botname": dbot.config.name
|
||||
}),
|
||||
"curr839": dbot.config.language,
|
||||
"repo": dbot.config.modules.github.defaultrepo,
|
||||
"branch": dbot.t("branch",{
|
||||
"branch": branch
|
||||
}),
|
||||
"currver": dbot.config.version,
|
||||
"currlang": dbot.t("dbotspeaks",{
|
||||
"lang839": dbot.config.language,
|
||||
"langen": dbot.strings[dbot.config.language]["en"],
|
||||
"lang": dbot.t(dbot.config.language),
|
||||
"name": dbot.config.name
|
||||
}),
|
||||
"projectstatus": dbot.t("projectstatus"),
|
||||
"revnum": dbot.t("revnum",{
|
||||
"name": dbot.config.name,
|
||||
"rev": rev
|
||||
}),
|
||||
"modules": dbot.config.moduleNames,
|
||||
"loadmod": dbot.t("loadedmodules"),
|
||||
"debugmode": dbot.t("debugmode-" + dbot.config.debugMode),
|
||||
"milestones": milestones,
|
||||
"milestoneprog": dbot.t("milestoneprog"),
|
||||
"config": dbot.t("configoptions"),
|
||||
"milestonename": dbot.t("milestonename"),
|
||||
"openmilestone": dbot.t("openmilestone"),
|
||||
"closedmilestone": dbot.t("closedmilestone"),
|
||||
"development": dbot.t("development"),
|
||||
"dquote": quote,
|
||||
"diff": diff,
|
||||
"pagetitle": dbot.t("pagetitle", {
|
||||
"botname": dbot.config.name
|
||||
}),
|
||||
"git": dbot.t("git"),
|
||||
"milestonehead": dbot.t("milestones"),
|
||||
"propaganda": dbot.t("propaganda"),
|
||||
"languagecurr": dbot.t(dbot.config.language),
|
||||
"languagenati": dbot.t("langhead-native"),
|
||||
"languageeng": dbot.t("en"),
|
||||
"languageprog": dbot.t("langhead-progress"),
|
||||
"languagetrans": dbot.t("langhead-translations"),
|
||||
"languagetranshead": dbot.t("translations"),
|
||||
"pullreqs": dbot.t("outstanding-pullreq")
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -14,30 +14,30 @@ var project = function(dbot) {
|
||||
var list = [];
|
||||
if(_.has(dbot.modules,'dent')){
|
||||
list.push(dbot.t("dent-account", {
|
||||
"username": dbot.config.dent.username
|
||||
"username": dbot.config.modules.dent.username
|
||||
}));
|
||||
if(_.has(dbot.config.dent.dentQuotes)) {
|
||||
if(_.has(dbot.config.modules.dent.dentQuotes)) {
|
||||
list.push(dbot.t("dent-push"));
|
||||
}
|
||||
}
|
||||
if(_.has(dbot.modules,'link')){
|
||||
if(dbot.config.link.autoTitle){
|
||||
if(dbot.config.modules.link.autoTitle){
|
||||
list.push(dbot.t("link-autotitle"));
|
||||
}
|
||||
}
|
||||
if(_.has(dbot.modules,'quotes')){
|
||||
list.push(dbot.t("quote-rmlimit", {
|
||||
"limit": dbot.config.quotes.rmLimit
|
||||
"limit": dbot.config.modules.quotes.rmLimit
|
||||
}));
|
||||
}
|
||||
if(_.has(dbot.modules,'report')){
|
||||
if(dbot.config.report.notifyVoice){
|
||||
if(dbot.config.modules.report.notifyVoice){
|
||||
list.push(dbot.t("report-notifyvoice"));
|
||||
}
|
||||
}
|
||||
if(_.has(dbot.modules,'web')){
|
||||
list.push(dbot.t("web-port", {
|
||||
"port": dbot.config.web.webPort
|
||||
"port": dbot.config.modules.web.webPort
|
||||
}));
|
||||
}
|
||||
return list;
|
||||
|
@ -28,7 +28,7 @@
|
||||
},
|
||||
"en": {
|
||||
"en": "English",
|
||||
"fr": "anglais",
|
||||
"fr": "Anglais",
|
||||
"de": "Englisch",
|
||||
"it": "inglese",
|
||||
"cy": "saesneg",
|
||||
@ -36,7 +36,7 @@
|
||||
},
|
||||
"fr": {
|
||||
"en": "French",
|
||||
"fr": "français",
|
||||
"fr": "Français",
|
||||
"de": "Französisch",
|
||||
"it": "francese",
|
||||
"cy": "Ffrangeg",
|
||||
@ -44,7 +44,7 @@
|
||||
},
|
||||
"de": {
|
||||
"en": "German",
|
||||
"fr": "allemande",
|
||||
"fr": "Allemand",
|
||||
"de": "Deutsch",
|
||||
"it": "tedesco",
|
||||
"cy": "Almaeneg",
|
||||
@ -52,7 +52,7 @@
|
||||
},
|
||||
"it": {
|
||||
"en": "Italian",
|
||||
"fr": "italien",
|
||||
"fr": "Italien",
|
||||
"de": "Italiener",
|
||||
"it": "italiano",
|
||||
"cy": "Eidaleg",
|
||||
@ -60,7 +60,7 @@
|
||||
},
|
||||
"cy": {
|
||||
"en": "Welsh",
|
||||
"fr": "gallois",
|
||||
"fr": "Gallois",
|
||||
"de": "Walisisch",
|
||||
"it": "gallese",
|
||||
"cy": "cymraeg",
|
||||
@ -77,7 +77,7 @@
|
||||
},
|
||||
"es": {
|
||||
"en": "Spanish",
|
||||
"fr": "espagnole",
|
||||
"fr": "Espagnol",
|
||||
"de": "Spanisch",
|
||||
"it": "spagnolo",
|
||||
"cy": "Sbaeneg",
|
||||
@ -87,11 +87,12 @@
|
||||
"nl": {
|
||||
"en": "Dutch",
|
||||
"cy": "Iseldireg",
|
||||
"nl": "Nederlands"
|
||||
"nl": "Nederlands",
|
||||
"fr": "Néerlandais"
|
||||
},
|
||||
"revnum": {
|
||||
"en": "{name} is at revision {rev}",
|
||||
"fr": "{name} est à révision {rev}",
|
||||
"fr": "{name} est à la révision {rev}",
|
||||
"de": "{name} ist in der Revision {rev}",
|
||||
"it": "{name} il numero di revisione {rev}",
|
||||
"cy": "{name} ar diwygiad {rev}",
|
||||
@ -115,7 +116,7 @@
|
||||
},
|
||||
"debugmode-true": {
|
||||
"en": "Debug mode active",
|
||||
"fr": "debug actif",
|
||||
"fr": "Mode de débogage activé",
|
||||
"de": "Debug-Modus aktiviert",
|
||||
"it": "debug attivo",
|
||||
"cy": "Modd dadfygio gweithredol",
|
||||
@ -123,7 +124,7 @@
|
||||
},
|
||||
"debugmode-false": {
|
||||
"en": "Debug off",
|
||||
"fr": "debug éteint",
|
||||
"fr": "Mode de débogage arrêté",
|
||||
"de": "Debug-Modus ausgeschaltet",
|
||||
"it": "debug spento",
|
||||
"cy": "Modd dadfygio wedi'i ddiffodd",
|
||||
@ -131,7 +132,7 @@
|
||||
},
|
||||
"milestones": {
|
||||
"en": "Milestones",
|
||||
"fr": "étapes",
|
||||
"fr": "Etapes",
|
||||
"cy": "Cerrig milltir",
|
||||
"de": "Zwischenziel"
|
||||
},
|
||||
@ -177,36 +178,43 @@
|
||||
},
|
||||
"dent-account": {
|
||||
"en": "Submitting dents to @{username}",
|
||||
"cy": "Cyflwyno 'dents' i'w @{username}"
|
||||
"cy": "Cyflwyno 'dents' i'w @{username}",
|
||||
"fr": "Envoi de 'dents' à @{username}"
|
||||
},
|
||||
"dent-push": {
|
||||
"en": "Pushing quotes to identi.ca",
|
||||
"cy": "Gwthio dyfyniadau i identi.ca"
|
||||
"cy": "Gwthio dyfyniadau i identi.ca",
|
||||
"fr": "Envoi des citations vers identi.ca"
|
||||
},
|
||||
"quote-rmlimit": {
|
||||
"en": "Quote removal throttle set to {limit}",
|
||||
"cy": "Trothwy ar dileu dyfyniadau gosod i {limit}"
|
||||
"cy": "Trothwy ar dileu dyfyniadau gosod i {limit}",
|
||||
"fr": "Commande d'enlèvement de citations réglée à {limit}"
|
||||
},
|
||||
"report-notifyvoice": {
|
||||
"en": "Voiced users are being notified of reports",
|
||||
"cy": "Defnyddwyr leisiwyd yn cael eu hysbysu o adroddiadau"
|
||||
"cy": "Defnyddwyr leisiwyd yn cael eu hysbysu o adroddiadau",
|
||||
"fr": "Les utilisateurs ayant la parole sont notifiés des rapports"
|
||||
},
|
||||
"web-port": {
|
||||
"en": "Web is listening on {port}",
|
||||
"cy": "We yn gwrando ar {port}"
|
||||
"cy": "We yn gwrando ar {port}",
|
||||
"fr": "Le web écoute sur {port}"
|
||||
},
|
||||
"propaganda": {
|
||||
"en": "Contribute to the code on Github!",
|
||||
"cy": "Cyfrannu at ay cod ar Github!"
|
||||
"cy": "Cyfrannu at ay cod ar Github!",
|
||||
"fr": "Contribuez au code sur GitHub!"
|
||||
},
|
||||
"branch": {
|
||||
"en": "{branch}"
|
||||
"en": "{branch}",
|
||||
"fr": "{branch}"
|
||||
},
|
||||
"git": {
|
||||
"en": "version control",
|
||||
"de": "Versionsverwaltung",
|
||||
"es": "Control de versiones",
|
||||
"fr": "Festion de versions",
|
||||
"fr": "Gestion de versions",
|
||||
"it": "Controllo versione",
|
||||
"cy": "Rheoli fersiwn",
|
||||
"nl": "Versiebeheersysteem"
|
||||
@ -230,7 +238,7 @@
|
||||
},
|
||||
"langhead-progress": {
|
||||
"en": "Translation Progress",
|
||||
"fr": "Avancement de la Traduction",
|
||||
"fr": "Avancement de la traduction",
|
||||
"cy": "Cynnydd Cyfieithu",
|
||||
"de": "Übersetzungsfortschritt"
|
||||
},
|
||||
@ -241,13 +249,16 @@
|
||||
},
|
||||
"outstanding-pullreq": {
|
||||
"en": "There are outstanding pull requests",
|
||||
"cy": "Mae disgwyl ceisiadau tynnu"
|
||||
"cy": "Mae disgwyl ceisiadau tynnu",
|
||||
"fr": "Il a des requêtes pull en attente"
|
||||
},
|
||||
"oaosidl": {
|
||||
"en": "The Official Aberystwyth Open Source International Development League"
|
||||
"en": "The Official Aberystwyth Open Source International Development League",
|
||||
"fr": "La Ligue Officielle de Développement International Open Source d'Aberystwyth"
|
||||
},
|
||||
"link-autotitle": {
|
||||
"en": "Automatically titling links in channels",
|
||||
"cy": "Teitlo awtomatig cysylltiadau mewn sianelau"
|
||||
"cy": "Teitlo awtomatig cysylltiadau mewn sianelau",
|
||||
"fr": "Titre automatiquement les liens dans les channels"
|
||||
}
|
||||
}
|
||||
|
@ -11,42 +11,31 @@ This is the original reason that DBot was created, stores and displays quotes.
|
||||
#### rmLimit: 10
|
||||
Amount of quotes which can be removed before admin approval is required.
|
||||
|
||||
### Commands
|
||||
#### quotesOnJoin: false
|
||||
Show quotes for users when they enter channels.
|
||||
|
||||
### Commands: Quote Addition
|
||||
|
||||
#### ~qadd [category] = [quote]
|
||||
Add a new quote to the database under the given category.
|
||||
|
||||
### Commands: Quote Retrieval
|
||||
|
||||
#### ~[category]
|
||||
Alias for ~q.
|
||||
|
||||
#### ~q [category]
|
||||
Display a random quote from a given category.
|
||||
|
||||
#### ~qadd [category] = [quote]
|
||||
Add a new quote to the database.
|
||||
#### ~rq
|
||||
Show a random quote from the database.
|
||||
|
||||
#### ~qstats
|
||||
Show a list of the biggest quote categories.
|
||||
|
||||
#### ~qsearch [category] = [needle]
|
||||
Search a category for quotes including the given text.
|
||||
|
||||
#### ~rmlast [category]
|
||||
Remove the last quote added to a given category.
|
||||
### Commands: Quote Removal
|
||||
|
||||
#### ~rmstatus
|
||||
Show how many quotes are currently in the removal cache, and whether they will
|
||||
be randomly removed.
|
||||
|
||||
#### ~rm [category] = [quote]
|
||||
Remove a given quote from the given category.
|
||||
|
||||
#### ~qcount [category]
|
||||
Show the number of quotes stored in the given category, or if called without a
|
||||
category it will show the total number of quotes in the database.
|
||||
|
||||
#### ~rq
|
||||
Show a random quote from the database.
|
||||
|
||||
#### ~link [category]
|
||||
Show a link to the page on the web interface which shows this category's quotes.
|
||||
|
||||
### Admin-only Commands
|
||||
|
||||
#### ~rmconfirm
|
||||
Confirm that the quotes currently in the removal cache are okay to be removed,
|
||||
and permanently delete them.
|
||||
@ -55,10 +44,48 @@ and permanently delete them.
|
||||
Re-instate the quotes that are currently in the removal cache back into the main
|
||||
quote database.
|
||||
|
||||
#### ~rmlast [category]
|
||||
Remove the last quote added to a given category.
|
||||
|
||||
#### ~rm [category] = [quote]
|
||||
Remove a given quote from the given category.
|
||||
|
||||
### Commands: Stats & Searching
|
||||
|
||||
#### ~qstats
|
||||
Show a list of the biggest quote categories.
|
||||
|
||||
#### ~qsearch [category] = [needle]
|
||||
Search a category for quotes including the given text. If category is given as
|
||||
_*_, then all categories will be searched for the given text.
|
||||
|
||||
#### ~qcount [category]
|
||||
Show the number of quotes stored in the given category, or if called without a
|
||||
category it will show the total number of quotes in the database.
|
||||
|
||||
#### ~qrename [oldName] [newName]
|
||||
Rename a quote category.
|
||||
|
||||
#### ~qmerge [primary] [secondary]
|
||||
Merge two quote categories into one.
|
||||
|
||||
#### ~link [category]
|
||||
Show a link to the page on the web interface which shows this category's quotes.
|
||||
|
||||
### API
|
||||
|
||||
#### getQuote(event, category)
|
||||
Returns a random quote from the given category.
|
||||
#### addQuote(key, quote, user, callback)
|
||||
Add the given quote to the category stored under the given key. If it's a new
|
||||
quote category, then the owner of the category will be recorded as the given
|
||||
user. The callback is called with one argument, the new quote count of the given
|
||||
category.
|
||||
|
||||
#### getQuote (key, callback)
|
||||
Get a random quote from the given category. Callback is called with one
|
||||
argument, either a random quote under the given key, or false if the category
|
||||
doesn't exist. This getQuote function does not require a server argument, and as
|
||||
such does not run the quote through the interpolation function (does not parse
|
||||
~~category~~ etc).
|
||||
|
||||
### Removal Spam Protection
|
||||
|
||||
|
@ -1,13 +1,76 @@
|
||||
var _ = require('underscore')._;
|
||||
var _ = require('underscore')._,
|
||||
databank = require('databank'),
|
||||
uuid = require('node-uuid');
|
||||
|
||||
var commands = function(dbot) {
|
||||
var quotes = dbot.db.quoteArrs;
|
||||
var commands = {
|
||||
// Alternative syntax to ~q
|
||||
/*** Quote Addition ***/
|
||||
|
||||
// Add a quote to a category
|
||||
'~qadd': function(event) {
|
||||
var key = event.input[1].toLowerCase().trim(),
|
||||
quote = event.input[2];
|
||||
|
||||
this.api.addQuote(key, quote, event.user, function(newCount) {
|
||||
if(newCount) {
|
||||
dbot.api.event.emit('~qadd', [ key, quote ]);
|
||||
event.reply(dbot.t('quote_saved', {
|
||||
'category': key,
|
||||
'count': newCount
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('quote_exists'));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*** Quote Retrieval ***/
|
||||
|
||||
// Alternative ~q syntax
|
||||
'~': function(event) {
|
||||
commands['~q'].bind(this)(event);
|
||||
},
|
||||
|
||||
// Retrieve quote from a category in the database.
|
||||
'~q': function(event) {
|
||||
var key = event.input[1];
|
||||
this.api.getInterpolatedQuote(event.server, event.channel, key, function(quote) {
|
||||
if(quote) {
|
||||
event.reply(key + ': ' + quote);
|
||||
} else {
|
||||
if(this.config.udFallback === true && _.has(dbot.modules, 'link')) {
|
||||
dbot.api.link.udLookup(key, function(word, definition) {
|
||||
if(word) {
|
||||
event.reply(key + '[UD]: ' + definition);
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': key }));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': key }));
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// Choose a random quote category and a random quote from that
|
||||
// TODO: This is quite inefficient, but databank must evolve to do otherwise.
|
||||
'~rq': function(event) {
|
||||
var categories = [];
|
||||
this.db.scan('quote_category', function(result) {
|
||||
if(result) {
|
||||
categories.push(result);
|
||||
}
|
||||
}, function(err) {
|
||||
var cIndex = _.random(0, _.size(categories) -1);
|
||||
var qIndex = _.random(0, categories[cIndex].quotes.length - 1);
|
||||
event.reply(categories[cIndex].name + ': ' + categories[cIndex].quotes[qIndex]);
|
||||
});
|
||||
},
|
||||
|
||||
/*** Quote Removal ***/
|
||||
|
||||
// Show number of quotes in removal cache
|
||||
'~rmstatus': function(event) {
|
||||
var rmCacheCount = this.rmCache.length;
|
||||
if(rmCacheCount < dbot.config.quotes.rmLimit) {
|
||||
@ -19,6 +82,7 @@ var commands = function(dbot) {
|
||||
}
|
||||
},
|
||||
|
||||
// Confirm removal of quote cache
|
||||
'~rmconfirm': function(event) {
|
||||
var rmCacheCount = this.rmCache.length;
|
||||
this.rmCache.length = 0;
|
||||
@ -26,213 +90,306 @@ var commands = function(dbot) {
|
||||
{ 'count': rmCacheCount }));
|
||||
},
|
||||
|
||||
// Reinstate all quotes in removal cache
|
||||
'~rmdeny': function(event) {
|
||||
var rmCache = this.rmCache;
|
||||
var rmCacheCount = rmCache.length;
|
||||
for(var i=0;i<rmCacheCount;i++) {
|
||||
if(!_.has(quotes, rmCache[i].key)) {
|
||||
quotes[rmCache[i].key] = [];
|
||||
}
|
||||
quotes[rmCache[i].key].push(rmCache[i].quote);
|
||||
}
|
||||
rmCache.length = 0;
|
||||
|
||||
_.each(rmCache, function(quote, index) {
|
||||
this.api.addQuote(quote.key, quote.quote, event.user, function(newCount) { });
|
||||
}.bind(this));
|
||||
|
||||
rmCache.length = 0;
|
||||
event.reply(dbot.t('quote_cache_reinstated',
|
||||
{ 'count': rmCacheCount }));
|
||||
},
|
||||
|
||||
'~rmlast': function(event) {
|
||||
if(this.rmAllowed === true || _.include(dbot.config.admins, event.user)) {
|
||||
var key = event.input[1].trim().toLowerCase(),
|
||||
category = false,
|
||||
removedQuote;
|
||||
var quoteRemoved = function(err) {
|
||||
this.internalAPI.resetRemoveTimer(event, key, removedQuote);
|
||||
event.reply(dbot.t('removed_from', {
|
||||
'quote': removedQuote,
|
||||
'category': key
|
||||
}));
|
||||
}.bind(this);
|
||||
|
||||
// Retrieve quote from a category in the database.
|
||||
'~q': function(event) {
|
||||
var key = event.input[1].trim().toLowerCase();
|
||||
var quote = this.api.getQuote(event, event.input[1]);
|
||||
if(quote) {
|
||||
event.reply(key + ': ' + quote);
|
||||
} else {
|
||||
if(this.config.udFallback === true && _.has(dbot.modules, 'link')) {
|
||||
dbot.api.link.udLookup(key, function(word, definition) {
|
||||
if(word) {
|
||||
event.reply(key + '[UD]: ' + definition);
|
||||
this.db.search('quote_category', { 'name': key }, function(result) {
|
||||
category = result;
|
||||
}, function(err) {
|
||||
if(category) {
|
||||
removedQuote = category.quotes.pop();
|
||||
if(category.quotes.length == 0) {
|
||||
this.db.del('quote_category', category.id, quoteRemoved);
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', {'category': key}));
|
||||
this.db.save('quote_category', category.id, category, quoteRemoved);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', {'category': key}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': key }));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('rmlast_spam'));
|
||||
}
|
||||
},
|
||||
|
||||
// Remove specific quote from category
|
||||
'~rm': function(event) {
|
||||
if(this.rmAllowed == true || _.include(dbot.config.admins, event.user)) {
|
||||
var key = event.input[1].trim().toLowerCase();
|
||||
quote = event.input[2],
|
||||
category = false;
|
||||
var quoteRemoved = function(err) {
|
||||
this.internalAPI.resetRemoveTimer(event, key, quote);
|
||||
event.reply(dbot.t('removed_from', {
|
||||
'category': key,
|
||||
'quote': quote
|
||||
}));
|
||||
}.bind(this);
|
||||
|
||||
this.db.search('quote_category', { 'name': key }, function(result) {
|
||||
category = result;
|
||||
}, function(err) {
|
||||
if(category) {
|
||||
if(category.quotes.indexOf(quote) != -1) {
|
||||
category.quotes = _.without(category.quotes, quote);
|
||||
if(category.quotes.length == 0) {
|
||||
this.db.del('quote_category', category.id, quoteRemoved);
|
||||
} else {
|
||||
this.db.save('quote_category', category.id, category, quoteRemoved);
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('q_not_exist_under', {
|
||||
'category': key,
|
||||
'quote': quote
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': key }));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('rmlast_spam'));
|
||||
}
|
||||
},
|
||||
|
||||
/*** Quote Statistics and Searching ***/
|
||||
|
||||
// Shows a list of the biggest categories
|
||||
'~qstats': function(event) {
|
||||
var qSizes = _.chain(quotes)
|
||||
.pairs()
|
||||
.sortBy(function(category) { return category[1].length })
|
||||
.reverse()
|
||||
.first(10)
|
||||
.value();
|
||||
var quoteSizes = {};
|
||||
this.db.scan('quote_category', function(category) {
|
||||
if(category) {
|
||||
quoteSizes[category.name] = category.quotes.length;
|
||||
}
|
||||
}.bind(this), function(err) {
|
||||
var qSizes = _.chain(quoteSizes)
|
||||
.pairs()
|
||||
.sortBy(function(category) { return category[1] })
|
||||
.reverse()
|
||||
.first(10)
|
||||
.value();
|
||||
|
||||
var qString = dbot.t('large_categories');
|
||||
for(var i=0;i<qSizes.length;i++) {
|
||||
qString += qSizes[i][0] + " (" + qSizes[i][1].length + "), ";
|
||||
}
|
||||
var qString = dbot.t('large_categories');
|
||||
for(var i=0;i<qSizes.length;i++) {
|
||||
qString += qSizes[i][0] + " (" + qSizes[i][1] + "), ";
|
||||
}
|
||||
|
||||
event.reply(qString.slice(0, -2));
|
||||
event.reply(qString.slice(0, -2));
|
||||
});
|
||||
},
|
||||
|
||||
// Search a given category for some text.
|
||||
'~qsearch': function(event) {
|
||||
var haystack = event.input[1].trim().toLowerCase();
|
||||
var needle = event.input[2];
|
||||
if(_.has(quotes, haystack)) {
|
||||
var matches = _.filter(quotes[haystack], function(quote) {
|
||||
return quote.indexOf(needle) != -1;
|
||||
}, this);
|
||||
|
||||
if(matches.length == 0) {
|
||||
event.reply(dbot.t('no_results'));
|
||||
} else {
|
||||
event.reply(dbot.t('search_results', {
|
||||
'category': haystack,
|
||||
'needle': needle,
|
||||
'quote': matches[0],
|
||||
'matches': matches.length
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('empty_category'));
|
||||
}
|
||||
},
|
||||
|
||||
'~rmlast': function(event) {
|
||||
if(this.rmAllowed === true || _.include(dbot.config.admins, event.user)) {
|
||||
var key = event.input[1].trim().toLowerCase();
|
||||
if(_.has(quotes, key)) {
|
||||
var quote = quotes[key].pop();
|
||||
if(quotes[key].length == 0) {
|
||||
delete quotes[key];
|
||||
var haystack = event.input[1].trim().toLowerCase(),
|
||||
needle = event.input[2],
|
||||
category = false;
|
||||
|
||||
if(haystack == '*') {
|
||||
var matches = [];
|
||||
this.db.scan('quote_category', function(category) {
|
||||
if(category) {
|
||||
var theseMatches =_.each(category.quotes, function(quote) {
|
||||
if(quote.indexOf(needle) != -1) {
|
||||
matches.push({
|
||||
'category': category.name,
|
||||
'quote': quote
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
this.internalAPI.resetRemoveTimer(event, key, quote);
|
||||
|
||||
event.reply(dbot.t('removed_from', {
|
||||
'quote': quote,
|
||||
'category': key
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('no_quotes', {'category': key}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('rmlast_spam'));
|
||||
}
|
||||
},
|
||||
|
||||
'~rm': function(event) {
|
||||
if(this.rmAllowed == true || _.include(dbot.config.admins, event.user)) {
|
||||
var key = event.input[1].trim().toLowerCase();
|
||||
var quote = event.input[2];
|
||||
|
||||
if(_.has(quotes, key)) {
|
||||
var category = quotes[key];
|
||||
var index = category.indexOf(quote);
|
||||
if(index !== -1) {
|
||||
category.splice(index, 1);
|
||||
if(category.length === 0) {
|
||||
delete quotes[key];
|
||||
}
|
||||
this.internalAPI.resetRemoveTimer(event, key, quote);
|
||||
|
||||
event.reply(dbot.t('removed_from', {'category': key, 'quote': quote}));
|
||||
}, function(err) {
|
||||
if(matches.length > 0) {
|
||||
event.reply(dbot.t('search_results', {
|
||||
'category': matches[0].category,
|
||||
'needle': needle,
|
||||
'quote': matches[0].quote,
|
||||
'matches': matches.length
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('q_not_exist_under', {'category': key, 'quote': quote}));
|
||||
event.reply(dbot.t('no_results'));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', {'category': key}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('rmlast_spam'));
|
||||
this.db.search('quote_category', { 'name': haystack }, function(result) {
|
||||
category = result;
|
||||
}, function(err) {
|
||||
if(category) {
|
||||
var matches = _.filter(category.quotes, function(quote) {
|
||||
return quote.indexOf(needle) != -1;
|
||||
});
|
||||
|
||||
if(matches.length == 0) {
|
||||
event.reply(dbot.t('no_results'));
|
||||
} else {
|
||||
event.reply(dbot.t('search_results', {
|
||||
'category': haystack,
|
||||
'needle': needle,
|
||||
'quote': matches[0],
|
||||
'matches': matches.length
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('empty_category'));
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Count quotes in a given category or total quotes overall
|
||||
'~qcount': function(event) {
|
||||
var input = event.message.valMatch(/^~qcount ([\d\w\s-]*)/, 2);
|
||||
if(input) { // Give quote count for named category
|
||||
var key = input[1].trim().toLowerCase();
|
||||
if(_.has(quotes, key)) {
|
||||
event.reply(dbot.t('quote_count', {
|
||||
'category': key,
|
||||
'count': quotes[key].length
|
||||
}));
|
||||
var key = input[1].trim().toLowerCase(),
|
||||
category = false;
|
||||
|
||||
this.db.search('quote_category', { 'name': key }, function(result) {
|
||||
category = result;
|
||||
}, function(err) {
|
||||
if(category) {
|
||||
event.reply(dbot.t('quote_count', {
|
||||
'category': key,
|
||||
'count': category.quotes.length
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': key }));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var quoteCount = 0;
|
||||
this.db.scan('quote_category', function(category) {
|
||||
if(category) {
|
||||
quoteCount += category.quotes.length;
|
||||
}
|
||||
}, function(err) {
|
||||
event.reply(dbot.t('total_quotes', { 'count': quoteCount }));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Rename a quote category
|
||||
'~qrename': function(event) {
|
||||
var oldName = event.input[1],
|
||||
newName = event.input[2],
|
||||
oldCategory = false,
|
||||
newCategory = false;
|
||||
|
||||
this.db.search('quote_category', { 'name': newName }, function(result) {
|
||||
newCategory = result;
|
||||
}, function(err) {
|
||||
if(!newCategory) {
|
||||
this.db.search('quote_category', { 'name': oldName }, function(result) {
|
||||
oldCategory = result;
|
||||
}, function(err) {
|
||||
oldCategory.name = newName;
|
||||
this.db.save('quote_category', oldCategory.id, oldCategory, function(err) {
|
||||
event.reply(dbot.t('category_renamed', {
|
||||
'oldName': oldName,
|
||||
'newName': newName
|
||||
}));
|
||||
});
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('no_quotes', { 'category': key }));
|
||||
event.reply(dbot.t('newcat_exists', { 'newcat': newName }));
|
||||
}
|
||||
} else { // Give total quote count
|
||||
var totalQuoteCount = _.reduce(quotes, function(memo, category) {
|
||||
return memo + category.length;
|
||||
}, 0);
|
||||
event.reply(dbot.t('total_quotes', { 'count': totalQuoteCount }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~qadd': function(event) {
|
||||
var key = event.input[1].toLowerCase().trim();
|
||||
var text = event.input[2].trim();
|
||||
if(!_.isArray(quotes[key])) {
|
||||
quotes[key] = [];
|
||||
}
|
||||
// Merge a quote category insto another
|
||||
'~qmerge': function(event) {
|
||||
var primaryName = event.input[1],
|
||||
secondName = event.input[2],
|
||||
primary = false,
|
||||
secondary = false;
|
||||
|
||||
if(_.include(quotes[key], text)) {
|
||||
event.reply(dbot.t('quote_exists'));
|
||||
} else {
|
||||
quotes[key].push(text);
|
||||
this.rmAllowed = true;
|
||||
event.reply(dbot.t('quote_saved', {
|
||||
'category': key,
|
||||
'count': quotes[key].length
|
||||
}));
|
||||
|
||||
return { 'key': key, 'text': text };
|
||||
}
|
||||
return false;
|
||||
this.db.search('quote_category', { 'name': primaryName }, function(result) {
|
||||
primary = result;
|
||||
}, function(err) {
|
||||
if(primary) {
|
||||
this.db.search('quote_category', { 'name': secondName }, function(result) {
|
||||
secondary = result;
|
||||
}, function(err) {
|
||||
if(secondary) {
|
||||
primary.quotes = _.union(primary.quotes, secondary.quotes);
|
||||
this.db.save('quote_category', primary.id, primary, function(err) {
|
||||
this.db.del('quote_category', secondary.id, function(err) {
|
||||
event.reply(dbot.t('categories_merged', {
|
||||
'from': secondName,
|
||||
'into': primaryName
|
||||
}));
|
||||
});
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': secondName }));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': primaryName }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~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, event.user, category));
|
||||
} else {
|
||||
event.reply(dbot.t('no_results'));
|
||||
}
|
||||
},
|
||||
|
||||
// Link to quote web page
|
||||
'~link': function(event) {
|
||||
var key = event.input[1].toLowerCase();
|
||||
if(_.has(quotes, key)) {
|
||||
if(_.has(dbot.config, 'web') && _.has(dbot.config.web, 'webHost') &&
|
||||
_.has(dbot.config.web, 'webPort')) {
|
||||
event.reply(dbot.t('quote_link', {
|
||||
'category': key,
|
||||
'url': dbot.api.web.getUrl('quotes/' + encodeURIComponent(key))
|
||||
}));
|
||||
var key = event.input[1].toLowerCase(),
|
||||
category = false;
|
||||
|
||||
this.db.search('quote_category', { 'name': key }, function(result) {
|
||||
category = result;
|
||||
}, function(err) {
|
||||
if(category) {
|
||||
if(_.has(dbot.modules, 'web')) {
|
||||
event.reply(dbot.t('quote_link', {
|
||||
'category': key,
|
||||
'url': dbot.api.web.getUrl('quotes/' + encodeURIComponent(key))
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('web_not_configured'));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('web_not_configured'));
|
||||
event.reply(dbot.t('category_not_found', { 'category': key }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': key }));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
commands['~'].regex = [/^~([\d\w\s-]*)/, 2];
|
||||
commands['~q'].regex = [/^~q ([\d\w\s-]*)/, 2];
|
||||
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['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2];
|
||||
commands['~qadd'].regex = [/^~qadd ([\d\w-]+[\d\w\s-]*)[ ]?=[ ]?(.+)$/, 3];
|
||||
commands['~qrename'].regex = [/^~qrename ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3];
|
||||
commands['~qmerge'].regex = [/^~qmerge ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3];
|
||||
commands['~link'].regex = [/^~link ([\d\w\s-]*)/, 2];
|
||||
|
||||
commands['~rmconfirm'].access = 'moderator';
|
||||
commands['~rmdeny'].access = 'moderator';
|
||||
commands['~qrename'].access = 'moderator';
|
||||
commands['~qmerge'].access = 'moderator';
|
||||
|
||||
return commands;
|
||||
};
|
||||
|
@ -1,9 +1,8 @@
|
||||
{
|
||||
"dbKeys": [ "quoteArrs" ],
|
||||
"dependencies": [ "command", "users", "event" ],
|
||||
"dbType": "redis",
|
||||
"dependencies": [ "users", "event" ],
|
||||
"rmLimit": 10,
|
||||
"ignorable": true,
|
||||
"quotesOnJoin": false,
|
||||
"udFallback": false,
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/quotes/README.md"
|
||||
"udFallback": false
|
||||
}
|
||||
|
@ -3,23 +3,39 @@ var pages = function(dbot) {
|
||||
return {
|
||||
// Lists quotes in a category
|
||||
'/quotes/:key': function(req, res) {
|
||||
var key = req.params.key.toLowerCase();
|
||||
if(_.has(dbot.db.quoteArrs, key)) {
|
||||
res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[key], locals: { 'url_regex': RegExp.prototype.url_regex() } });
|
||||
} else {
|
||||
res.render('error', { 'name': dbot.config.name, 'message': 'No quotes under that key.' });
|
||||
}
|
||||
this.api.getQuoteCategory(req.params.key, function(category) {
|
||||
if(category) {
|
||||
res.render('quotes', {
|
||||
'name': dbot.config.name,
|
||||
'quotes': category.quotes,
|
||||
'locals': {
|
||||
'url_regex': RegExp.prototype.url_regex()
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.render('error', {
|
||||
'name': dbot.config.name,
|
||||
'message': 'No quotes under that key.'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Show quote list.
|
||||
'/quotes': function(req, res) {
|
||||
res.render('quotelist', { 'name': dbot.config.name, 'quotelist': Object.keys(dbot.db.quoteArrs) });
|
||||
this.api.getCategoryKeys(function(keys) {
|
||||
res.render('quotelist', {
|
||||
'name': dbot.config.name,
|
||||
'quotelist': keys
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// Load random quote category page
|
||||
'/rq': function(req, res) {
|
||||
var rCategory = Object.keys(dbot.db.quoteArrs).random();
|
||||
res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[rCategory], locals: { 'url_regex': RegExp.prototype.url_regex() } });
|
||||
'/quoteremovals': function(req, res) {
|
||||
res.render('quotes', {
|
||||
'name': dbot.config.name,
|
||||
'quotes': _.pluck(this.rmCache, 'quote')
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,50 +1,46 @@
|
||||
var _ = require('underscore')._;
|
||||
var _ = require('underscore')._,
|
||||
uuid = require('node-uuid');
|
||||
|
||||
var quotes = function(dbot) {
|
||||
dbot.sessionData.rmCache = [];
|
||||
this.quotes = dbot.db.quoteArrs,
|
||||
this.addStack = [],
|
||||
this.rmAllowed = true,
|
||||
this.rmCache = dbot.sessionData.rmCache,
|
||||
this.rmCache = dbot.sessionData.rmCache;
|
||||
this.quotes = dbot.db.quoteArrs;
|
||||
this.rmAllowed = true;
|
||||
this.rmTimer;
|
||||
|
||||
this.internalAPI = {
|
||||
// Retrieve a random quote from a given category, interpolating any quote
|
||||
// references (~~QUOTE CATEGORY~~) within it
|
||||
'interpolatedQuote': function(server, channel, user, key, quoteTree) {
|
||||
if(!_.isUndefined(quoteTree) && quoteTree.indexOf(key) != -1) {
|
||||
return '';
|
||||
} else if(_.isUndefined(quoteTree)) {
|
||||
quoteTree = [];
|
||||
}
|
||||
|
||||
var index = _.random(0, this.quotes[key].length - 1);
|
||||
var quoteString = this.quotes[key][index];
|
||||
|
||||
// Parse quote interpolations
|
||||
var quoteRefs = quoteString.match(/~~([\d\w\s-]*)~~/g);
|
||||
var thisRef;
|
||||
|
||||
while(quoteRefs && (thisRef = quoteRefs.shift()) !== undefined) {
|
||||
var cleanRef = dbot.cleanNick(thisRef.replace(/^~~/,'').replace(/~~$/,'').trim());
|
||||
if(cleanRef === '-nicks-') {
|
||||
var randomNick = dbot.api.users.getRandomChannelUser(server, channel);
|
||||
quoteString = quoteString.replace("~~" + cleanRef + "~~", randomNick);
|
||||
quoteTree.pop();
|
||||
} else if(cleanRef === '-user-') {
|
||||
quoteString = quoteString.replace("~~" + cleanRef + "~~", user);
|
||||
quoteTree.pop();
|
||||
} else if(_.has(this.quotes, cleanRef)) {
|
||||
quoteTree.push(key);
|
||||
quoteString = quoteString.replace("~~" + cleanRef + "~~",
|
||||
this.internalAPI.interpolatedQuote(server, channel, user, cleanRef, quoteTree.slice()));
|
||||
quoteTree.pop();
|
||||
// Parse quote interpolations
|
||||
'interpolatedQuote': function(server, channel, key, quote, callback) {
|
||||
var quoteRefs = quote.match(/~~([\d\w\s-]*)~~/g);
|
||||
if(quoteRefs) {
|
||||
var ref = this.internalAPI.cleanRef(quoteRefs[0].replace(/^~~/,'').replace(/~~$/,'').trim());
|
||||
if(ref === '-nicks-') {
|
||||
dbot.api.users.getRandomChannelUser(server, channel, function(user) {
|
||||
quote = quote.replace('~~' + ref + '~~', randomNick);
|
||||
this.internalAPI.interpolatedQuote(server, channel, key, quote, callback);
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.api.getQuote(ref, function(interQuote) {
|
||||
if(!interQuote || ref == key) {
|
||||
interQuote = '';
|
||||
}
|
||||
quote = quote.replace('~~' + ref + '~~', interQuote);
|
||||
this.internalAPI.interpolatedQuote(server, channel, key, quote, callback);
|
||||
}.bind(this));
|
||||
}
|
||||
} else {
|
||||
callback(quote);
|
||||
}
|
||||
|
||||
return quoteString;
|
||||
}.bind(this),
|
||||
|
||||
'cleanRef': function(key) {
|
||||
key = key.toLowerCase();
|
||||
while(key.slice(-1) == '_') {
|
||||
key = key.substring(0, key.length-1);
|
||||
}
|
||||
return key;
|
||||
},
|
||||
|
||||
'resetRemoveTimer': function(event, key, quote) {
|
||||
this.rmAllowed = false;
|
||||
setTimeout(function() {
|
||||
@ -57,7 +53,7 @@ var quotes = function(dbot) {
|
||||
});
|
||||
|
||||
clearTimeout(this.rmTimer);
|
||||
if(this.rmCache.length < dbot.config.quotes.rmLimit) {
|
||||
if(this.rmCache.length < this.config.rmLimit) {
|
||||
this.rmTimer = setTimeout(function() {
|
||||
this.rmCache.length = 0; // lol what
|
||||
}.bind(this), 600000);
|
||||
@ -70,37 +66,81 @@ var quotes = function(dbot) {
|
||||
};
|
||||
|
||||
this.api = {
|
||||
'getQuote': function(event, category) {
|
||||
var key = category.trim().toLowerCase();
|
||||
var altKey;
|
||||
if(key.split(' ').length > 0) {
|
||||
altKey = key.replace(/ /g, '_');
|
||||
}
|
||||
'addQuote': function(key, quote, user, callback) {
|
||||
var key = key.toLowerCase().trim(),
|
||||
newCount,
|
||||
category = false;
|
||||
|
||||
if(key.charAt(0) !== '_') { // lol
|
||||
if(_.has(this.quotes, key)) {
|
||||
return this.internalAPI.interpolatedQuote(event.server, event.channel.name, event.user, key);
|
||||
} else if(_.has(this.quotes, altKey)) {
|
||||
return this.internalAPI.interpolatedQuote(event.server, event.channel.name, event.user, altKey);
|
||||
this.db.search('quote_category', { 'name': key }, function(result) {
|
||||
category = result;
|
||||
}, function(err) {
|
||||
if(!category) {
|
||||
var id = uuid.v4();
|
||||
category = {
|
||||
'id': id,
|
||||
'name': key,
|
||||
'quotes': [],
|
||||
'owner': user
|
||||
};
|
||||
}
|
||||
|
||||
if(_.include(category.quotes, quote)) {
|
||||
callback(false);
|
||||
} else {
|
||||
return false;
|
||||
newCount = category.quotes.push(quote);
|
||||
this.db.save('quote_category', category.id, category, function(err) {
|
||||
this.rmAllowed = true;
|
||||
callback(newCount);
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
},
|
||||
|
||||
'getQuote': function(key, callback) {
|
||||
this.api.getQuoteCategory(key, function(category) {
|
||||
if(category) {
|
||||
var quotes = category.quotes;
|
||||
var index = _.random(0, quotes.length - 1);
|
||||
callback(quotes[index]);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getQuoteCategory': function(name) {
|
||||
console.log(name);
|
||||
var key = name.trim().toLowerCase();
|
||||
if(_.has(this.quotes, key)) {
|
||||
return this.quotes[key];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
'getInterpolatedQuote': function(server, channel, key, callback) {
|
||||
key = key.trim().toLowerCase(),
|
||||
|
||||
this.api.getQuote(key, function(quote) {
|
||||
if(quote) {
|
||||
this.internalAPI.interpolatedQuote(server, channel, key, quote, callback);
|
||||
} else {
|
||||
callback(quote);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'getQuoteCategory': function(key, callback) {
|
||||
var category = false,
|
||||
key = key.trim().toLowerCase();
|
||||
|
||||
this.db.search('quote_category', { 'name': key }, function(result) {
|
||||
category = result;
|
||||
}, function(err) {
|
||||
callback(category);
|
||||
});
|
||||
},
|
||||
|
||||
'getCategoryKeys': function(callback) {
|
||||
var keys = [];
|
||||
this.db.scan('quote_category', function(result) {
|
||||
if(result) keys.push(result.name);
|
||||
}, function(err) {
|
||||
callback(keys);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.api['getQuoteCategory'].external = true;
|
||||
this.api['getQuoteCategory'].extMap = [ 'name' ];
|
||||
|
||||
this.listener = function(event) {
|
||||
if(event.action == 'PRIVMSG') {
|
||||
@ -111,17 +151,17 @@ var quotes = function(dbot) {
|
||||
}
|
||||
|
||||
if(once) {
|
||||
event.message = '~qadd realityonce=reality ' + once[1];
|
||||
event.action = 'PRIVMSG';
|
||||
event.params = event.message.split(' ');
|
||||
dbot.instance.emit(event);
|
||||
}
|
||||
this.api.addQuote('realityonce', 'reality' + once[1], event.user, function(newCount) {
|
||||
event.reply('\'reality ' + once[1] + '\' saved (' + newCount + ').');
|
||||
});
|
||||
}
|
||||
} else if(event.action == 'JOIN') {
|
||||
if(this.config.quotesOnJoin == true) {
|
||||
var userQuote = this.api.getQuote(event, event.user)
|
||||
if(userQuote) {
|
||||
event.reply(event.user + ': ' + this.api.getQuote(event, event.user));
|
||||
}
|
||||
this.api.getQuote(event.user, function(quote) {
|
||||
if(quote) {
|
||||
event.reply(event.user + ': ' + quote);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
|
@ -5,7 +5,8 @@
|
||||
"na'vi": "{category} yawne ke lu kawturu.",
|
||||
"cy": "Does neb yn caru {category}",
|
||||
"nl": "Niemand houdt van {category}",
|
||||
"de": "Niemand hat {category} gerne"
|
||||
"de": "Niemand hat {category} gerne",
|
||||
"fr": "Personne n'aime {category}"
|
||||
},
|
||||
"large_categories": {
|
||||
"en": "Largest categories: ",
|
||||
@ -13,7 +14,8 @@
|
||||
"na'vi": "U atsawl: ",
|
||||
"cy": "Categoriau mwyaf: ",
|
||||
"nl": "Grootste categoriën: ",
|
||||
"de": "Größte Kategorien: "
|
||||
"de": "Größte Kategorien: ",
|
||||
"fr": "Les plus grandes catégories :"
|
||||
},
|
||||
"empty_category": {
|
||||
"en": "That category has no quotes in. Commence incineration.",
|
||||
@ -21,7 +23,8 @@
|
||||
"na'vi": "Tsauru upxare lu. Nga skxawng lu.",
|
||||
"cy": "Nid yw'r categori yna efo dyfyniadau. Cychwyn orfflosgiad",
|
||||
"nl": "Die categorie heeft geen quotes. Bereid het verbrandingsritueel voor.",
|
||||
"de": "In dieser Kategorie befinden sich keine Zitate. Verbennung einleiten."
|
||||
"de": "In dieser Kategorie befinden sich keine Zitate. Verbennung einleiten.",
|
||||
"fr": "Cette catégorie ne contient aucune citation. Commencer l'incinération."
|
||||
},
|
||||
"no_results": {
|
||||
"en": "No results found.",
|
||||
@ -29,7 +32,8 @@
|
||||
"na'vi": "Oel kea humit rìmun",
|
||||
"cy": "Dim canlyniadau ar gael",
|
||||
"nl": "Geen resultaten gevonden.",
|
||||
"de": "Keine Ergebnisse gefunden."
|
||||
"de": "Keine Ergebnisse gefunden.",
|
||||
"fr": "Aucun résultat trouvé."
|
||||
},
|
||||
"locked_category": {
|
||||
"en": "{category} is locked. Commence incineration.",
|
||||
@ -37,7 +41,8 @@
|
||||
"na'vi": "{category} ke fkeytok set. Nga skxawng lu nafì'u",
|
||||
"cy": "Mae {category} wedi cloi. Cychwyn orfflosgiad",
|
||||
"nl": "{category} is op slot. Bereid het verbrandingsritueel voor.",
|
||||
"de": "{category} ist geschlossen. Verbrennung einleiten."
|
||||
"de": "{category} ist geschlossen. Verbrennung einleiten.",
|
||||
"fr": "{category} est verrouillé(e). Commencer l'incinération."
|
||||
},
|
||||
"no_quotes": {
|
||||
"en": "No quotes exist under {category}",
|
||||
@ -45,7 +50,8 @@
|
||||
"na'vi": "Kea upxare fkeytok {category}mì",
|
||||
"cy": "Does dim dyfyniadau gan {category}",
|
||||
"nl": "Er zijn geen quotes in {category}",
|
||||
"de": "Es existieren keine Ziatate in {category}"
|
||||
"de": "Es existieren keine Ziatate in {category}",
|
||||
"fr": "Il n'existe aucune citation dans {category}"
|
||||
},
|
||||
"last_removed": {
|
||||
"en": "Last quote removed from {category}.",
|
||||
@ -53,7 +59,8 @@
|
||||
"na'vi": "Oel 'upxareti aham 'aku {category}ta",
|
||||
"cy": "Dyfyniad olaf wedi ei ddileu o {category}",
|
||||
"nl": "De laatste quote is verwijderd uit {category}.",
|
||||
"de": "Das letzte Zitat wurde aus {category} entfernt."
|
||||
"de": "Das letzte Zitat wurde aus {category} entfernt.",
|
||||
"fr": "Dernière citation enlevée de {category}."
|
||||
},
|
||||
"no_recent_adds": {
|
||||
"en": "No quotes were added recently.",
|
||||
@ -61,7 +68,8 @@
|
||||
"na'vi": "Kea upxareti samung nìfkrr",
|
||||
"cy": "Nid oes unrhyw dyfyniadau wedi ei ychwwanegu'n ddiweddar",
|
||||
"nl": "Er zijn recentelijk geen quotes toegevoegd.",
|
||||
"de": "Es wurden neulich keine Zitate hinzugefügt."
|
||||
"de": "Es wurden neulich keine Zitate hinzugefügt.",
|
||||
"fr": "Aucune citation n'a été ajoutée récemment."
|
||||
},
|
||||
"rmlast_spam": {
|
||||
"en": "No spamming that shit. Try again in a few minutes...",
|
||||
@ -69,7 +77,8 @@
|
||||
"na'vi": "Nga Tsasngelit ke zene fpivere'. Sweylu nga fmivi ye'rìn...",
|
||||
"cy": "Peidiwch a sbamio hwna. Triwch eto mewn ychydyg funudau...",
|
||||
"nl": "Dat spammen kun je ook lekker laten. Probeer het zometeen nog eens...",
|
||||
"de": "Hör auf zu spammen. Versuche es in einigen Minuten erneut..."
|
||||
"de": "Hör auf zu spammen. Versuche es in einigen Minuten erneut...",
|
||||
"fr": "Pas de spam de cette merde. Réessaye dans quelques minutes..."
|
||||
},
|
||||
"removed_from": {
|
||||
"en": "'{quote}' removed from {category}",
|
||||
@ -77,7 +86,8 @@
|
||||
"na'vi": "'{quote}'(it/ti) 'ìyaku {category}",
|
||||
"cy": "'{quote}' wedi ei ddileu o {category}",
|
||||
"nl": "{quote} verwijderd uit {category}",
|
||||
"de": "'{quote} aus {category} gelöscht"
|
||||
"de": "'{quote} aus {category} gelöscht",
|
||||
"fr": "'{quote}' enlevé(e) {category}"
|
||||
},
|
||||
"q_not_exist_under": {
|
||||
"en": "'{quote}' doesn't exist under '{category}'.",
|
||||
@ -85,7 +95,8 @@
|
||||
"na'vi": "'{quote}' ke fkeytok '{category}'ta.",
|
||||
"cy": "Nid yw '{quote}' yn bodoli yn '{category}'",
|
||||
"nl": "{quote} bestaat niet in '{category}'.",
|
||||
"de": "'{quote} existiert nicht in '{category}'."
|
||||
"de": "'{quote} existiert nicht in '{category}'.",
|
||||
"fr": "'{quote}' ne semble pas exister dans '{category}'."
|
||||
},
|
||||
"total_quotes": {
|
||||
"en": "Total quote count: {count}.",
|
||||
@ -93,7 +104,8 @@
|
||||
"na'vi": "'upxareri holpxay: {count}.",
|
||||
"cy": "Cyfanswm dyfyniadau: {count}.",
|
||||
"nl": "Totaal aantal quotes: {count}.",
|
||||
"de": "Anzahl Zitate insgesamt: {count}."
|
||||
"de": "Anzahl Zitate insgesamt: {count}.",
|
||||
"fr": "Nombre total de citations: {count}."
|
||||
},
|
||||
"quote_exists": {
|
||||
"en": "Quote already in DB. Initiate incineration.",
|
||||
@ -101,7 +113,8 @@
|
||||
"na'vi": "'Upxarel säomumit fìtsengit tok srekrr. Nga skxawng lu.",
|
||||
"cy": "Dyfyniad yn y gronfa ddata yn barod. Cychwyn orfflosgiad",
|
||||
"nl": "De quote bestaat al. Bereid het verbrandingsritueel voor.",
|
||||
"de": "Zitat ist bereits in der Datenbank. Verbennung einleiten."
|
||||
"de": "Zitat ist bereits in der Datenbank. Verbennung einleiten.",
|
||||
"fr": "La citation existe déjà dans la base de données. Initier l'incinération."
|
||||
},
|
||||
"quote_saved": {
|
||||
"en": "Quote saved in '{category}' ({count}).",
|
||||
@ -109,7 +122,8 @@
|
||||
"na'vi": "Oe zayerok '{category}'mì ({count}).",
|
||||
"cy": "Dyfyniad wedi ei gadw yn '{category}' ({count}).",
|
||||
"nl": "Quote opgeslagen in '{category}' ({count}).",
|
||||
"de": "Zitat in '{category}' gespeichert ({count})."
|
||||
"de": "Zitat in '{category}' gespeichert ({count}).",
|
||||
"fr": "Citation sauvegardée dans '{category}' ({count})."
|
||||
},
|
||||
"quote_replace": {
|
||||
"en": "No replacing arrays, you whore.",
|
||||
@ -117,7 +131,8 @@
|
||||
"na'vi": "Ngal fìsäomumit ke tsun rivawn. Nga muntxa sayi suteo hrh.",
|
||||
"cy": "Peidiwch a newid rhestrau, y cachgi",
|
||||
"nl": "Geen arrays vervangen, slet.",
|
||||
"de": "Ersetze keine Arrays, du Schlampe."
|
||||
"de": "Ersetze keine Arrays, du Schlampe.",
|
||||
"fr": "On ne remplace pas les arrays, espèce de salope."
|
||||
},
|
||||
"quote_count": {
|
||||
"en": "{category} has {count} quotes.",
|
||||
@ -125,7 +140,8 @@
|
||||
"na'vi": "{count}a upxare {category}ur lu.",
|
||||
"cy": "{count} dyfyniad yn {category}",
|
||||
"nl": "{category} heeft {count} quotes.",
|
||||
"de": "{count} Zitate befinden sich in {category}."
|
||||
"de": "{count} Zitate befinden sich in {category}.",
|
||||
"fr": "{category} contient {count} citations."
|
||||
},
|
||||
"quote_link": {
|
||||
"en": "Link to {category} - {url}",
|
||||
@ -133,7 +149,8 @@
|
||||
"na'vi": "Fya'o {category}ne - {url}",
|
||||
"cy": "Dolen i {category} - {url}",
|
||||
"nl": "Link naar {category} - {url}",
|
||||
"de": "Link zu {category} - {url}"
|
||||
"de": "Link zu {category} - {url}",
|
||||
"fr": "Lien vers {category} - {url}"
|
||||
},
|
||||
"search_results": {
|
||||
"en": "{category} ({needle}): '{quote}' [{matches} results]",
|
||||
@ -141,47 +158,66 @@
|
||||
"na'vi": "{category} ({needle}): '{quote}' [kum a{matches}]",
|
||||
"cy": "{category} ({needle}): '{quote}' [{matches} canlyniad]",
|
||||
"nl": "{category} ({needle}): '{quote}' [{matches} resultaten]",
|
||||
"de": "{category} ({needle}): '{quote}' [{matches} Ergebnisse]"
|
||||
"de": "{category} ({needle}): '{quote}' [{matches} Ergebnisse]",
|
||||
"fr": "{category} ({needle}): '{quote}' [{matches} résultats]"
|
||||
},
|
||||
"quote_cache_auto_remove": {
|
||||
"en": "There are {count} quotes in the removal cache, which will be automatically cleared.",
|
||||
"na'vi": "{count}a 'upxarel sngelit tok, Oel 'ayku sngelit lukenga.",
|
||||
"cy": "Mae {count} dyfyniadau yn y celc dileu a fydd yn cael ei clirio yn awtomatig.",
|
||||
"nl": "Er staan {count} quotes klaar om verwijderd te worden, wat automatisch zal gebeuren.",
|
||||
"de": "Es befinden sich {count} im Cache, die automatisch entfernt werden."
|
||||
"de": "Es befinden sich {count} im Cache, die automatisch entfernt werden.",
|
||||
"fr": "Il y a {count} citations dans le cache de suppression, qui va être automatiquement vidé."
|
||||
},
|
||||
"quote_cache_manual_remove": {
|
||||
"en": "There are {count} quotes in the removal cache, which must be manually cleared.",
|
||||
"na'vi": "{count}a 'upxarel sngelit tok slä oel ke 'ayku sngelit tafral nga zene 'aivku",
|
||||
"cy": "Mae {count} dyfyniadau yn y celc dileu a fydd yn cael ei clirio â llaw.",
|
||||
"nl": "Er staan {count} quotes klaar om verwijderd te worden, wat handmatig zal moeten gebeuren.",
|
||||
"de": "Es befinden sich {count} im Cache, die manuell entfernt werden müssen."
|
||||
"de": "Es befinden sich {count} im Cache, die manuell entfernt werden müssen.",
|
||||
"fr": "Il y a {count} citations dans le cache de suppression, qui doit être manuellement vidé."
|
||||
},
|
||||
"quote_cache_cleared": {
|
||||
"en": "{count} quotes cleared from the removal cache.",
|
||||
"na'vi": "Oel 'aìmku {count}a 'upxareti ta sngel.",
|
||||
"cy": "{count} dyfyniadau wedi ei clirio o'r celc dileu",
|
||||
"nl": "{count} quotes verwijderd uit de verwijderlijst.",
|
||||
"de": "{count} Zitate wurden aus dem Cache entfernt."
|
||||
"de": "{count} Zitate wurden aus dem Cache entfernt.",
|
||||
"fr": "{count} citation(s) supprimée(s) du cache de suppression."
|
||||
},
|
||||
"quote_cache_reinstated": {
|
||||
"en": "{count} quotes reinstated from the removal cache.",
|
||||
"na'vi": "{count}a 'upxare tolätxaw ta sngel.",
|
||||
"cy": "{count} dyfyniadau wedi ei adfer o'r celc dileu",
|
||||
"nl": "{count} quotes hersteld van de verwijderlijst.",
|
||||
"de": "{count} Zitate wurden aus dem Cache gerettet."
|
||||
"de": "{count} Zitate wurden aus dem Cache gerettet.",
|
||||
"fr": "{count} citation(s) restaurée(s) du cache de suppression."
|
||||
},
|
||||
"rm_cache_limit": {
|
||||
"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.",
|
||||
"cy": "Sylw: Gormod o dyfyniadau wedi ei clirio, rhaid i'r celc dileu yn cael ei glirio neu adfer â llaw gyda ~rmconfirm neu ~rmdeny.",
|
||||
"nl": "Waarschuwing: Er zijn te veel quotes verwijderd. rmCache moet opgeschoond of herinstalleerd worden met ~rmconfirm of ~rmdeny",
|
||||
"de": "Achtung: Zu viele Zitate gelöscht, rmCache muss geleert werden oder manuell via ~rmconfirm oder ~rmdeny wiedereingesetzt werden."
|
||||
"de": "Achtung: Zu viele Zitate gelöscht, rmCache muss geleert werden oder manuell via ~rmconfirm oder ~rmdeny wiedereingesetzt werden.",
|
||||
"fr": "Attention : Trop de citations enlevées, rmCache doit être vidé ou restauré manuellement avec ~rmconfirm ou ~rmdeny."
|
||||
},
|
||||
"web_not_configured": {
|
||||
"en": "Cannot link to category. Web module is either not loaded or misconfigured.",
|
||||
"cy": "Ni all gysylltu â gategori. Modiwl we yn naill ai nid lwytho neu wedi ei camffurfweddu.",
|
||||
"nl": "De categorie kan niet gelinkt worden. De web module is niet geladen of onjuist geconfigureerd.",
|
||||
"de": "Diese Kategorie kann nicht gelinkt werden. Das Web-Modul ist entweder nicht geladen oder falsch konfiguriert."
|
||||
"de": "Diese Kategorie kann nicht gelinkt werden. Das Web-Modul ist entweder nicht geladen oder falsch konfiguriert.",
|
||||
"fr": "Impossible de donner le lien vers la catégorie. Le module web n'est pas chargé ou est mal configuré."
|
||||
},
|
||||
"category_renamed": {
|
||||
"en": "Category ~{oldName} renamed to ~{newName}.",
|
||||
"fr": "Catégorie ~{oldName} renommée ~{newName}."
|
||||
},
|
||||
"newcat_exists": {
|
||||
"en": "Category ~{newcat} already exists. Delete that first or use ~qmerge.",
|
||||
"fr": "La catégorie ~{newcat} existe déjà. Supprimez-la en premier ou utilisez ~qmerge."
|
||||
},
|
||||
"categories_merged": {
|
||||
"en": "Category ~{from} and its quotes merged into ~{into}.",
|
||||
"fr": "La catégorie ~{from} et ses citations ont été fusionnée dans ~{into}."
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
{
|
||||
"dependencies": [ "command" ],
|
||||
"ignorable": true,
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/rain/README.md",
|
||||
"apikey": "7707e78c7125741e"
|
||||
}
|
||||
|
@ -4,96 +4,110 @@
|
||||
"na'vi": "tompa ke zup {place}ur.",
|
||||
"cy": "Dyw hi ddim yn bwrw glaw yn {place}.",
|
||||
"nl": "Het regent niet in {place}.",
|
||||
"de": "Es ist trocken in {place}."
|
||||
"de": "Es ist trocken in {place}.",
|
||||
"fr": "Il ne pleut pas à {place}."
|
||||
},
|
||||
"rain-1": {
|
||||
"en" : "It's raining in {place}.",
|
||||
"na'vi":"tompa zup {place}ur.",
|
||||
"cy": "Mae'n bwrw glaw yn {place}.",
|
||||
"nl": "Het regent in {place}.",
|
||||
"de": "Es regnet in {place}."
|
||||
"de": "Es regnet in {place}.",
|
||||
"fr": "Il pleut à {place}."
|
||||
},
|
||||
"rain-2": {
|
||||
"en" : "It's raining rather a lot in {place}.",
|
||||
"na'vi":"tompa zup {place}ur nìhawng.",
|
||||
"cy": "Mae'n bwrw glaw cryn dipyn yn {place}.",
|
||||
"nl": "Het regent tamelijk hard in {place}.",
|
||||
"de": "Es regnet relativ viel in {place}."
|
||||
"de": "Es regnet relativ viel in {place}.",
|
||||
"fr": "Il pleut assez fortement à {place}."
|
||||
},
|
||||
"rain-3": {
|
||||
"en" : "It's raining shitloads.",
|
||||
"na'vi":"tompa zup {place}ur nìhawng.",
|
||||
"cy": "Mae'n bwrw glaw yn uffern o lawer yn {place}.",
|
||||
"nl": "Het regent nu toch wel erg hard.",
|
||||
"de": "Es regnet stark."
|
||||
"de": "Es regnet stark.",
|
||||
"fr": "Il pleut à mort."
|
||||
},
|
||||
"rain-4": {
|
||||
"en" : "It's raining fucktons.",
|
||||
"na'vi": "tompa zup {place}ur nìhawng.",
|
||||
"cy": "Mae'n bwrw glaw yn drwm iawn yn {place}.",
|
||||
"nl": "De regen komt verdorie met bakken uit de lucht.",
|
||||
"de": "Es regnet extrem stark."
|
||||
"de": "Es regnet extrem stark.",
|
||||
"fr": "Il pleut vraiment des putains de tonnes."
|
||||
},
|
||||
"rain-5": {
|
||||
"en" : "It's raining whales (in {place})!",
|
||||
"na'vi": "payoang zup {place}ur",
|
||||
"cy": "Mae'n bwrw glaw cathod a chŵn yn {place}.",
|
||||
"nl": "Een punker krijgt z'n hanekam niet meer omhoog gehouden.",
|
||||
"de": "Es regnet unglaublich stark (in {place})!"
|
||||
"de": "Es regnet unglaublich stark (in {place})!",
|
||||
"fr": "Il pleut des baleines (à {place}) !"
|
||||
},
|
||||
"rain-6": {
|
||||
"en" : "IT'S SO FUCKING WET OUT HERE MAN",
|
||||
"na'vi" : "pey lu oeru nìhawng taluna tok fìtengeti",
|
||||
"cy": "MAE'N WIR GWLYB TU ALLAN.",
|
||||
"nl": "Dit is dus een inloopdouche.",
|
||||
"de": "ES IST SO VERDAMMT NASS HIER MANN."
|
||||
"de": "ES IST SO VERDAMMT NASS HIER MANN.",
|
||||
"fr": "C'EST TELLEMENT MOUILLE DEHORS MEC"
|
||||
},
|
||||
"rain-7": {
|
||||
"en" : "I AM SO MOIST RIGHT NOW",
|
||||
"na'vi":"pey lu oeru nìhawng taluna tok fìtengeti",
|
||||
"cy": "RYDW I'N LLAITH IAWN AR HYN O BRYD",
|
||||
"nl": "IK VOEL ME NU TOCH ANDERS WEL BEHOORLIJK ONDER GEZEKEN.",
|
||||
"de": "ICH BIN SO EINGENÄSST."
|
||||
"de": "ICH BIN SO EINGENÄSST.",
|
||||
"fr": "JE SUIS TELLEMENT MOITE LA"
|
||||
},
|
||||
"rain-8": {
|
||||
"en" : "You used a #3 pencil instead of #2, didn't you?",
|
||||
"na'vi": "Nga pamrel sami hu pencìl a#3 ulte ke pamrel sami pencìl a#2 kefyak?",
|
||||
"cy": "Rydych yn defnyddio #2 pensil yn hytrach na #3 pensil, ie?",
|
||||
"nl": "PROOST.",
|
||||
"de": "Jemand muss dich hassen"
|
||||
"de": "Jemand muss dich hassen",
|
||||
"fr": "T'as utilisé un crayon #3 au lieu d'un #2, n'est-ce pas ?"
|
||||
},
|
||||
"rain-9": {
|
||||
"en" : "WELCOME TO ATLANTIS",
|
||||
"na'vi": "ziva'u nìprrte atlantisftu.",
|
||||
"cy": "CROESO I ATLANTIS!",
|
||||
"nl": "HAD IK GEVRAAGD OM EEN OMMETJE ATLANTIS?!",
|
||||
"de": "WILLKOMMEN IN ATLANTIS"
|
||||
"de": "WILLKOMMEN IN ATLANTIS",
|
||||
"fr": "BIENVENUE A ATLANTIS"
|
||||
},
|
||||
"rain-10": {
|
||||
"en" : "GET INSIDE",
|
||||
"na'vi": "Sweylu txo nga livatam futa ngal fìtsengeti tok",
|
||||
"nl": "SCHUIL, BITCH! SCHUIL!",
|
||||
"de": "REIN MIT DIR"
|
||||
"de": "REIN MIT DIR",
|
||||
"fr": "RENTRE CHEZ TOI"
|
||||
},
|
||||
"rain-11": {
|
||||
"en" : "LOL U PROBABLY DIED",
|
||||
"na'vi": "hrh kxawm nga tolerkup.",
|
||||
"cy": "EWCH I MEWN",
|
||||
"nl": "HA, NU BEN JE TOCH ZEKER VERZOPEN?!",
|
||||
"de": "LOL DU MIST VERMUTLICH TOT"
|
||||
"de": "LOL DU MIST VERMUTLICH TOT",
|
||||
"fr": "LOL T'ES PROBABLEMENT MORT"
|
||||
},
|
||||
"rain-e": {
|
||||
"en" : "Unable to fetch weather data.",
|
||||
"na'vi":"Oel ke tsun rivum sänumeti teriyafkeyk.",
|
||||
"cy": "Nid gallu nôl data tywydd.",
|
||||
"nl": "Geen weerinformatie beschikbaar.",
|
||||
"de": "Keine Wetterdaten vorhanden."
|
||||
"de": "Keine Wetterdaten vorhanden.",
|
||||
"fr": "Impossible de récupérer les données météo."
|
||||
},
|
||||
"rain-u": {
|
||||
"en": "Location too ambiguous to process.",
|
||||
"na'vi":"tsengeri, yayayr lu oeru.",
|
||||
"cy": "Lleoliad yn rhy amwys i brosesu.",
|
||||
"nl": "Deze locatie is te onduidelijk.",
|
||||
"de": "Wähle den nächst größeren Ort."
|
||||
"de": "Wähle den nächst größeren Ort.",
|
||||
"fr": "Location trop ambiguë à traiter."
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
{
|
||||
"outputPrefix": "\u000312reddit\u000f"
|
||||
"outputPrefix": "\u000312reddit\u000f",
|
||||
"dependencies": [ "link" ]
|
||||
}
|
||||
|
@ -2,20 +2,24 @@
|
||||
"about_subreddit": {
|
||||
"en": "[{display_name} has {subscribers} subscribers ({active} active)]",
|
||||
"cy": "[Mae {display_name} wedi {subscribers} subscribers ({active} active)]",
|
||||
"de": "[{display_name} hat {subscribers} Abonnenten ({active} active)]"
|
||||
"de": "[{display_name} hat {subscribers} Abonnenten ({active} active)]",
|
||||
"fr": "[{display_name} a {subscribers} abonnés ({active} actifs)]"
|
||||
},
|
||||
"about_post": {
|
||||
"en": "[Post by {poster} in {subreddit} — Comments: {comments}, Score: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)] — {url}",
|
||||
"cy": "[Postio gan {poster} yn {subreddit} - Sylwadau: {comments}, Sgôr: {score} (\u00039]▲{up}\u000f|\u000312{down}▼\u000f)] — {url}",
|
||||
"de": "[Beitrag von {poster} in {subreddit} — Kommentare: {comments}, Bewertung: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)] — {url}"
|
||||
"de": "[Beitrag von {poster} in {subreddit} — Kommentare: {comments}, Bewertung: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)] — {url}",
|
||||
"fr": "[Message de {poster} dans {subreddit} — Commentaires: {comments}, Score: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)] — {url}"
|
||||
},
|
||||
"about_comment": {
|
||||
"en": "[Comment by {poster} in {subreddit} — Score: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]",
|
||||
"cy": "[Sylw gan {poster} yn {subreddit} - Sgôr: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]",
|
||||
"de": "[Kommentar von {poster} in {subreddit} — Bewertung: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]"
|
||||
"de": "[Kommentar von {poster} in {subreddit} — Bewertung: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]",
|
||||
"fr": "[Commentaire de {poster} dans {subreddit} — Score: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]"
|
||||
},
|
||||
"nsfw": {
|
||||
"en": "[NSFW]",
|
||||
"cy": "[Anniogel Ar Gwaith (AAG)]"
|
||||
"cy": "[Anniogel Ar Gwaith (AAG)]",
|
||||
"fr": "[Risqué Pour le Travail (NSFW)]"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
{
|
||||
"ignorable": true,
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/regex/README.md"
|
||||
"ignorable": true
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ignorable": true,
|
||||
"notifyVoice": false,
|
||||
"dependencies": [ "command", "users" ],
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/report/README.md"
|
||||
"dependencies": [ "users" ],
|
||||
"dbType": "redis"
|
||||
}
|
||||
|
44
modules/report/pages.js
Normal file
44
modules/report/pages.js
Normal file
@ -0,0 +1,44 @@
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var pages = function(dbot) {
|
||||
return {
|
||||
'/notify': function(req, res) {
|
||||
res.render('servers', {
|
||||
'name': dbot.config.name,
|
||||
'servers': _.keys(dbot.config.servers)
|
||||
});
|
||||
},
|
||||
|
||||
'/notify/:server': function(req, res) {
|
||||
var server = req.params.server;
|
||||
res.render('channels', {
|
||||
'name': dbot.config.name,
|
||||
'server': server,
|
||||
'channels': _.keys(dbot.instance.connections[server].channels)
|
||||
});
|
||||
},
|
||||
|
||||
'/notify/:server/:channel': function(req, res) {
|
||||
var server = req.params.server,
|
||||
channel = req.params.channel,
|
||||
notifies = [];
|
||||
|
||||
this.db.search('notifies', {
|
||||
'server': server,
|
||||
'channel': channel
|
||||
}, function(notify) {
|
||||
notifies.push(notify);
|
||||
}, function(err) {
|
||||
res.render('notifies', {
|
||||
'name': dbot.config.name,
|
||||
'server': server,
|
||||
'notifies': notifies
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return pages(dbot);
|
||||
};
|
@ -1,6 +1,11 @@
|
||||
var _ = require('underscore')._;
|
||||
var _ = require('underscore')._,
|
||||
uuid = require('node-uuid'),
|
||||
async = require('async');
|
||||
|
||||
var report = function(dbot) {
|
||||
if(!dbot.db.pending) dbot.db.pending = {};
|
||||
this.pending = dbot.db.pending;
|
||||
|
||||
this.api = {
|
||||
'notify': function(server, channel, message) {
|
||||
var channel = dbot.instance.connections[server].channels[channel];
|
||||
@ -12,42 +17,78 @@ var report = function(dbot) {
|
||||
}
|
||||
}, this);
|
||||
|
||||
_.each(ops, function(user) {
|
||||
dbot.say(server, user.name, message);
|
||||
}, this);
|
||||
dbot.api.users.getChannel(server, channel, function(channel) {
|
||||
if(channel) {
|
||||
var perOps = channel.op;
|
||||
if(this.config.notifyVoice) pOps = _.union(perOps, channel.voice);
|
||||
|
||||
async.eachSeries(ops, function(nick, next) {
|
||||
dbot.api.users.resolveUser(server, nick, function(user) {
|
||||
perOps = _.without(perOps, user.id); next();
|
||||
});
|
||||
}, function() {
|
||||
offlineUsers = perOps;
|
||||
_.each(offlineUsers, function(id) {
|
||||
if(!this.pending[id]) this.pending[id] = [];
|
||||
this.pending[id].push(message);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
var i = 0;
|
||||
var notifyChannel = function(ops) {
|
||||
if(i >= ops.length) return;
|
||||
dbot.say(server, ops[i].name, message);
|
||||
setTimeout(function() {
|
||||
i++; notifyChannel(ops);
|
||||
}, 1000);
|
||||
};
|
||||
notifyChannel(ops);
|
||||
}
|
||||
};
|
||||
|
||||
this.listener = function(event) {
|
||||
if(_.has(this.pending, event.rUser.id)) {
|
||||
_.each(this.pending[event.rUser.id], function(message) {
|
||||
dbot.say(event.server, event.rUser.currentNick, message);
|
||||
});
|
||||
delete this.pending[event.rUser.id];
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = 'JOIN';
|
||||
|
||||
var commands = {
|
||||
'~report': function(event) {
|
||||
var channelName = event.input[1];
|
||||
var nick = event.input[2];
|
||||
var reason = event.input[3];
|
||||
var channelName = event.input[1],
|
||||
nick = event.input[2],
|
||||
reason = event.input[3];
|
||||
|
||||
if(_.has(event.allChannels, channelName)) {
|
||||
if(dbot.api.users.isChannelUser(event.server, nick, channelName, true)) {
|
||||
nick = dbot.api.users.resolveUser(event.server, nick, true);
|
||||
this.api.notify(event.server, channelName, dbot.t('report', {
|
||||
'reporter': event.user,
|
||||
'reported': nick,
|
||||
'channel': channelName,
|
||||
'reason': reason
|
||||
}));
|
||||
event.reply(dbot.t('reported', { 'reported': nick }));
|
||||
dbot.api.users.resolveUser(event.server, nick, function(reportee) {
|
||||
if(_.has(event.allChannels, channelName)) {
|
||||
if(reportee) {
|
||||
this.api.notify(event.server, channelName, dbot.t('report', {
|
||||
'reporter': event.user,
|
||||
'reported': nick,
|
||||
'channel': channelName,
|
||||
'reason': reason
|
||||
}));
|
||||
event.reply(dbot.t('reported', { 'reported': nick }));
|
||||
} else {
|
||||
event.reply(dbot.t('user_not_found', {
|
||||
'reported': nick,
|
||||
'channel': channelName
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('user_not_found', {
|
||||
'reported': nick,
|
||||
'channel': channelName
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('not_in_channel', { 'channel': channelName }));
|
||||
}
|
||||
event.reply(dbot.t('not_in_channel', { 'channel': channelName }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~notify': function(event) {
|
||||
var channelName = event.input[1];
|
||||
var message = event.input[2];
|
||||
var channelName = event.input[1],
|
||||
message = event.input[2];
|
||||
|
||||
if(_.has(event.allChannels, channelName)) {
|
||||
this.api.notify(event.server, channelName, dbot.t('notify', {
|
||||
@ -55,6 +96,17 @@ var report = function(dbot) {
|
||||
'notifier': event.user,
|
||||
'message': message
|
||||
}));
|
||||
|
||||
var id = uuid.v4();
|
||||
this.db.save('notifies', id, {
|
||||
'id': id,
|
||||
'server': event.server,
|
||||
'channel': channelName,
|
||||
'user': event.user,
|
||||
'time': new Date().getTime(),
|
||||
'message': message
|
||||
}, function() {});
|
||||
|
||||
event.reply(dbot.t('notified', {
|
||||
'user': event.user,
|
||||
'channel': channelName
|
||||
|
@ -4,33 +4,39 @@
|
||||
"na'vi": "{reporter}ìl fpìl futa {reported} fe' lu taluna {reason}.",
|
||||
"cy": "Sylw! {reporter} wedi adrodd {reported} yn {channel}. Y rheswm a rhoddwyd oedd: \"{reason}.\"",
|
||||
"nl": "Waarschuwing: {reporter} heeft {reported} aangegeven in {channel}. De reden die gegeven werd was: \"{reason}.\"",
|
||||
"de": "Achtung: {reporter} hat {reported} in {channel} gemeldet. Grund: \"{reason}.\""
|
||||
"de": "Achtung: {reporter} hat {reported} in {channel} gemeldet. Grund: \"{reason}.\"",
|
||||
"fr": "Attention : {reporter} a reporté {reported} dans {channel}. Raison donnée : \"{reason}.\""
|
||||
},
|
||||
"reported": {
|
||||
"en": "Thank you, {reported} has been reported to the channel administrators.",
|
||||
"na'vi": "Irayo si ngari, fìtsengìri ayeyktan omum teri {reported}it set.",
|
||||
"cy": "Diolch, {reported} wedi cael ei adrodd i'r gweinyddwyr sianel.",
|
||||
"nl": "Bedankt, {reported} is aangegeven bij de administrators.",
|
||||
"de": "Danke, {reported} wurde bei den Administratoren dieses Kanals gemeldet."
|
||||
"de": "Danke, {reported} wurde bei den Administratoren dieses Kanals gemeldet.",
|
||||
"fr": "Merci, {reported} a été reporté aux administrateurs du canal."
|
||||
},
|
||||
"user_not_found": {
|
||||
"en": "{reported} isn't a known user in {channel}.",
|
||||
"na'vi": "Oel ke omum {reported}it mì {channel}.",
|
||||
"cy": "Nid yw {reported} yn ddefnyddiwr hysbys yn {channel}.",
|
||||
"nl": "{reported} is geen bestaande gebruiker in {channel}.",
|
||||
"de": "{reported} ist kein bekannter Benutzer in {channel}."
|
||||
"de": "{reported} ist kein bekannter Benutzer in {channel}.",
|
||||
"fr": "{reported} n'est pas un utilisateur connu dans {channel}."
|
||||
},
|
||||
"not_in_channel": {
|
||||
"en": "I am not present in {channel}.",
|
||||
"na'vi": "Oel {channel}it ke tok.",
|
||||
"cy": "Dydw i ddim yn bresennol yn {channel}.",
|
||||
"nl": "Ik ben niet aanwezig in {channel}.",
|
||||
"de": "Ich bin nicht in {channel} aktiv."
|
||||
"de": "Ich bin nicht in {channel} aktiv.",
|
||||
"fr": "Je ne suis pas présent dans {channel}."
|
||||
},
|
||||
"notify": {
|
||||
"en": "Attention {channel}: {notifier}: {message}"
|
||||
"en": "Attention {channel}: {notifier}: {message}",
|
||||
"fr": "Attention {channel}: {notifier}: {message}"
|
||||
},
|
||||
"notified": {
|
||||
"en": "{user}: {channel} staff notified."
|
||||
"en": "{user}: {channel} staff notified.",
|
||||
"fr": "{user}: l'équipe de {channel} a été notifiée."
|
||||
}
|
||||
}
|
||||
|
5
modules/soundcloud/config.json
Normal file
5
modules/soundcloud/config.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"client_id": "391bcf67b5ad70fd64c6a4f79374f2f4",
|
||||
"outputPrefix": "\u000307soundcloud\u000f",
|
||||
"dependencies": [ "link" ]
|
||||
}
|
70
modules/soundcloud/soundcloud.js
Normal file
70
modules/soundcloud/soundcloud.js
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Module Name: soundcloud
|
||||
* Description: Various SoundCloud functionality
|
||||
*/
|
||||
var _ = require('underscore')._,
|
||||
request = require('request');
|
||||
|
||||
var soundcloud = function(dbot) {
|
||||
this.ApiRoot = 'http://api.soundcloud.com';
|
||||
|
||||
this.commands = {
|
||||
'~soundcloud': function(event) {
|
||||
var query = event.input[1];
|
||||
request.get(this.ApiRoot + '/tracks.json', {
|
||||
'qs': {
|
||||
'client_id': this.config.client_id,
|
||||
'q': query
|
||||
},
|
||||
'json': true
|
||||
}, function(error, response, body) {
|
||||
if(body.length != 0) {
|
||||
body = body[0];
|
||||
if(!body.genre) body.genre = '';
|
||||
event.reply(dbot.t('sc_track', {
|
||||
'title': body.title,
|
||||
'artist': body.user.username,
|
||||
'genre': body.genre.trim(),
|
||||
'plays': body.playback_count,
|
||||
'favs': body.favoritings_count
|
||||
}) + ' — ' + body.permalink_url);
|
||||
} else {
|
||||
event.reply(dbot.t('sc_notrack'));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
this.commands['~soundcloud'].regex = [/^~soundcloud (.+)$/, 2];
|
||||
|
||||
this.onLoad = function() {
|
||||
dbot.api.link.addHandler(this.name,
|
||||
/https?:\/\/(www\.)?soundcloud\.com\//,
|
||||
function(event, match, name) {
|
||||
var url = match.input;
|
||||
request.get(this.ApiRoot + '/resolve.json', {
|
||||
'qs': {
|
||||
'client_id': this.config.client_id,
|
||||
'url': url
|
||||
},
|
||||
'json': true
|
||||
}, function(error, response, body) {
|
||||
if(response.statusCode == 200) {
|
||||
if(body.kind == 'track') {
|
||||
if(!body.genre) body.genre = '';
|
||||
event.reply(dbot.t('sc_track', {
|
||||
'title': body.title,
|
||||
'artist': body.user.username,
|
||||
'genre': body.genre.trim(),
|
||||
'plays': body.playback_count,
|
||||
'favs': body.favoritings_count
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new soundcloud(dbot);
|
||||
};
|
10
modules/soundcloud/strings.json
Normal file
10
modules/soundcloud/strings.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"sc_track": {
|
||||
"en": "[{title} by {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]",
|
||||
"fr": "[{title} par {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]"
|
||||
},
|
||||
"sc_notrack": {
|
||||
"en": "No results found.",
|
||||
"fr": "Aucun résultat trouvé."
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
{
|
||||
"ignorable": true,
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/spelling/README.md"
|
||||
"ignorable": true
|
||||
}
|
||||
|
@ -5,7 +5,8 @@
|
||||
"na'vi": "Sweylu {correcter} pamrel sivi: {fix}",
|
||||
"cy": "Oedd {correcter} yn feddwl: {fix}",
|
||||
"nl": "{correcter} bedoelde: {fix}",
|
||||
"de": "{correcter} meinte: {fix}"
|
||||
"de": "{correcter} meinte: {fix}",
|
||||
"fr": "{correcter} voulait dire : {fix}"
|
||||
},
|
||||
"spelling_other": {
|
||||
"en": "{correcter} thinks {candidate} meant: {fix}",
|
||||
@ -13,6 +14,7 @@
|
||||
"na'vi": "{correcter} fpìl futa sweylu {candiate} pamrel sivi: {fix}",
|
||||
"cy": "Mae {correcter} yn meddwl bod {candidate} yn feddwl: {fix}",
|
||||
"nl": "{correcter} denkt dat {candidate} bedoelde: {fix}",
|
||||
"de": "{corrector} denkt, dass {canditate} meinte: {fix}"
|
||||
"de": "{corrector} denkt, dass {canditate} meinte: {fix}",
|
||||
"fr": "{correcter} pense que {candidate} voulait dire : {fix}"
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,28 @@
|
||||
#spotify
|
||||
dbot spotify module
|
||||
## spotify
|
||||
|
||||
Various Spotify functionality.
|
||||
|
||||
### Description
|
||||
This module posts information on Spotify links, as well as providing Spotify
|
||||
search functionality.
|
||||
|
||||
## Commands
|
||||
|
||||
### ~spotify [query]
|
||||
Search spotify for a song.
|
||||
|
||||
### ~syt [youtube link]
|
||||
Attempt to get a Spotify link from a YouTube link. If no link is provided with
|
||||
the commands, it will attempt to use the last link posted in the channel.
|
||||
|
||||
## API
|
||||
|
||||
#### spotifySearch(query, callback)
|
||||
Run a search query on Spotify. If no results are found, the callback will pass
|
||||
false. If a result is found, the callback takes two arguments: data about the
|
||||
found track, and a link to the track.
|
||||
|
||||
### Hooks
|
||||
|
||||
#### link
|
||||
Posts information about a Spotify link when one is posted in a channel.
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"dependencies": [ "command" ],
|
||||
"dependencies": [ "link" ],
|
||||
"ignorable": true,
|
||||
"outputPrefix": "\u00039spotify\u000f"
|
||||
}
|
||||
|
@ -2,28 +2,33 @@
|
||||
"artist": {
|
||||
"en": "[artist] {artist}",
|
||||
"cy": "[cyfansoddwr] {artist}",
|
||||
"de": "[Interpret] {artist}"
|
||||
"de": "[Interpret] {artist}",
|
||||
"fr": "[artiste] {artist}"
|
||||
},
|
||||
"album": {
|
||||
"en": "[album] {artist} – {album}",
|
||||
"cy": "[albwm] {artist} - {album}",
|
||||
"de": "[Album] {artist} – {album}"
|
||||
"cy": "[albwm] {artist} – {album}",
|
||||
"de": "[Album] {artist} – {album}",
|
||||
"fr": "[album] {artist} – {album}"
|
||||
},
|
||||
"track": {
|
||||
"en": "[track] {artist} – {track} (from {album})",
|
||||
"cy": "[trac] {artist} - {track} (o'r albwm: {album})",
|
||||
"de": "[Track] {artist} – {track} (aus dem Album {album})"
|
||||
"cy": "[trac] {artist} – {track} (o'r albwm: {album})",
|
||||
"de": "[Track] {artist} – {track} (aus dem Album {album})",
|
||||
"fr": "[piste] {artist} – {track} (tiré de {album})"
|
||||
},
|
||||
"found": {
|
||||
"en": "[{url}] {artist} – {track} (from {album})",
|
||||
"cy": "[{url}] {artist} - {track} (o'r albwm: {album})",
|
||||
"de": "[{url}] {artist} – {track} (aus dem Album {album})"
|
||||
"cy": "[{url}] {artist} – {track} (o'r albwm: {album})",
|
||||
"de": "[{url}] {artist} – {track} (aus dem Album {album})",
|
||||
"fr": "[{url}] {artist} – {track} (tiré de {album})"
|
||||
},
|
||||
"not-found": {
|
||||
"en": "No results.",
|
||||
"na'vi": "{s}, Oel ke tsun rivum ayuoti.",
|
||||
"na'vi": "Oel ke tsun rivum ayuoti.",
|
||||
"cy": "Dim canlyniadau.",
|
||||
"nl": "Geen resultaten.",
|
||||
"de": "Kein Ergebnis."
|
||||
"de": "Kein Ergebnis.",
|
||||
"fr": "Aucun résultat."
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit f7599c7564396a22a8ca9f05bd386d6531f41d1a
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/timers/README.md"
|
||||
}
|
@ -5,8 +5,7 @@ Track users.
|
||||
### Description
|
||||
|
||||
This module tracks users and their aliases through nick changes and all that
|
||||
kind of thing. It's mainly a utility module for other modules to use. It's
|
||||
also totally !insaned.
|
||||
kind of thing. It's mainly a utility module for other modules to use.
|
||||
|
||||
### Commands
|
||||
|
||||
@ -27,30 +26,67 @@ Requires moderator level access by default.
|
||||
|
||||
### API
|
||||
|
||||
#### resolveUser(server, nick, [useLowerCase])
|
||||
This resolves a given nick to its primary user and returns it.
|
||||
#### resolveUser(server, nick, callback)
|
||||
This resolves a given nick to its primary user, returning false if no user
|
||||
record is found in the store associated with the given nickname (either as a
|
||||
primary nick or an alias). The callback is called with one argument, a _user_
|
||||
object or false if no user was found.
|
||||
|
||||
Note that if the useLowerCase argument is set to true, it will do a lower-case
|
||||
search, however it will return the username in its properly capitalised form, so
|
||||
remember to lower case the return value if you are using lower case values as
|
||||
keys.
|
||||
#### getUser(uuid, callback)
|
||||
Get a user by its uuid. Callback is called with one argument, a _user_ object or
|
||||
false if no user was found by that uuid.
|
||||
|
||||
#### resolveUser(server, user)
|
||||
Return whether a user is known either as an alias or a primary user.
|
||||
#### getChannel(server, channelName, callback)
|
||||
This resolves a given server and channel name to a particular channel. The
|
||||
callback is called with one argument, a _channel_ object or false if no channel
|
||||
was found with the given name on the given server.
|
||||
|
||||
#### isPrimaryUser(server, nick)
|
||||
Return whether a nick is known as a primary user.
|
||||
#### getRandomChannelUser(server, channel, callback)
|
||||
Given a server name and a channel name, this gets a random user from that
|
||||
channel. Callback is called with one argument, a _user_ object or false if no
|
||||
channel was found from the given parameters.
|
||||
|
||||
#### getAliases(server, user)
|
||||
Return a list of aliases for a given primary user.
|
||||
#### getAllusers(callback)
|
||||
Get a list of all users the bot currently knows about. Callback is called with
|
||||
one argument, a list of user records.
|
||||
|
||||
#### isOnline(server, user, channel, useLowerCase)
|
||||
Return whether a user is online in a given channel on the given server.
|
||||
#### isOnline
|
||||
Is the given nick on the given server currently in the given channel. Callback
|
||||
is called with one argument, a boolean as to whether the nick is currently in
|
||||
the specified place.
|
||||
|
||||
### Data
|
||||
|
||||
#### User Object
|
||||
|
||||
{
|
||||
id: user uuid,
|
||||
primaryNick,
|
||||
currentNick: Current or last used nickname,
|
||||
server,
|
||||
channels: A list of names for channels this user has been in,
|
||||
aliases: A list of known aliases for this user
|
||||
}
|
||||
|
||||
#### Channel Object
|
||||
|
||||
{
|
||||
id: channel uuid,
|
||||
server,
|
||||
name,
|
||||
users: A list of the uuids of users who are in this channel
|
||||
}
|
||||
|
||||
### Events
|
||||
|
||||
#### nick_changed(server, newNick)
|
||||
This is executed when a new alias is added for a user.
|
||||
#### new_user(user)
|
||||
This is executed when a new user is added to the known users DB.
|
||||
|
||||
#### new_user(server, nick)
|
||||
This is executed when a new primary user is added to the known users DB.
|
||||
#### new_user_alias(user, newNick)
|
||||
When a new user alias is added.
|
||||
|
||||
#### new_channel(channel)
|
||||
Executed when DBot creates a new channel object.
|
||||
|
||||
#### new_channel_user(user, channel)
|
||||
Executed when DBot creates a new channel object.
|
||||
|
@ -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 escapeRegexen = function(str) {
|
||||
@ -6,100 +11,124 @@ var api = function(dbot) {
|
||||
};
|
||||
|
||||
var api = {
|
||||
'resolveUser': function(server, nick, useLowerCase) {
|
||||
var knownUsers = this.getServerUsers(server);
|
||||
var user = nick;
|
||||
|
||||
if(!useLowerCase) {
|
||||
if(!_.include(knownUsers.users, nick) && _.has(knownUsers.aliases, nick)) {
|
||||
user = knownUsers.aliases[nick];
|
||||
// Return a user record given a primary nick or an alias
|
||||
'resolveUser': function(server, nick, callback) {
|
||||
var user = false;
|
||||
this.db.search('users', { 'server': server }, function(result) {
|
||||
if(result.primaryNick == nick || _.include(result.aliases, nick)) {
|
||||
user = result;
|
||||
}
|
||||
} else {
|
||||
// this is retarded
|
||||
user = user.toLowerCase();
|
||||
var toMatch = new RegExp("^" + escapeRegexen(user) + "$", "i");
|
||||
}, function(err) {
|
||||
if(!err) {
|
||||
callback(user);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
var resolvedUser = _.find(knownUsers.users, function(nick) {
|
||||
return nick.match(toMatch) !== null;
|
||||
}, this);
|
||||
// Return a user record given a UUID
|
||||
'getUser': function(uuid, callback) {
|
||||
this.db.read('users', uuid, function(err, user) {
|
||||
if(err) user = false;
|
||||
callback(user);
|
||||
});
|
||||
},
|
||||
|
||||
if(!resolvedUser) {
|
||||
resolvedUser = _.find(knownUsers.aliases, function(nick, alias) {
|
||||
if(alias.match(toMatch) !== null) return nick;
|
||||
'getChannel': function(server, channelName, callback) {
|
||||
var channel = false;
|
||||
this.db.search('channel_users', {
|
||||
'server': server,
|
||||
'name': channelName
|
||||
}, function(result) {
|
||||
channel = result;
|
||||
}, function(err) {
|
||||
if(!err) {
|
||||
callback(channel);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'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)) {
|
||||
var randomUser = channel.users[_.random(0, channel.users.length - 1)];
|
||||
this.api.resolveUser(server, randomUser, function(user) {
|
||||
callback(user);
|
||||
});
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getAllUsers': function(callback) {
|
||||
var users = [];
|
||||
this.db.scan('users', function(user) {
|
||||
users.push(user);
|
||||
}, function(err) {
|
||||
if(!err) {
|
||||
callback(users);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getAllChannels': function(callback) {
|
||||
var channels = [];
|
||||
this.db.scan('channel_users', function(channel) {
|
||||
channels.push(channel);
|
||||
}, function(err) {
|
||||
if(!err) {
|
||||
callback(channels);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'isOnline': function(server, nick, channel, callback) {
|
||||
this.api.resolveUser(server, nick, function(user) {
|
||||
var possiNicks = [user].concat(user.aliases);
|
||||
|
||||
if(_.has(dbot.instance.connections[server].channels, channel)) {
|
||||
var onlineNicks = dbot.instance.connections[server].channels[channel].nicks;
|
||||
var isOnline = _.any(onlineNicks, function(nick) {
|
||||
nick = nick.name;
|
||||
return _.include(possiNicks, nick);
|
||||
}, this);
|
||||
if(!_.isUndefined(resolvedUser)) user = resolvedUser;
|
||||
|
||||
callback(isOnline);
|
||||
}
|
||||
else{
|
||||
user = resolvedUser;
|
||||
});
|
||||
},
|
||||
|
||||
'isKnownUser': function(server, nick, callback) {
|
||||
this.api.resolveUser(server, nick, function(isKnown) {
|
||||
if(isKnown == false) {
|
||||
callback(false);
|
||||
} else {
|
||||
callback(true);
|
||||
}
|
||||
}
|
||||
return user;
|
||||
},
|
||||
|
||||
'getRandomChannelUser': function(server, channel) {
|
||||
var channelUsers = this.getServerUsers(server).channelUsers[channel];
|
||||
if(!_.isUndefined(channelUsers)) {
|
||||
return channelUsers[_.random(0, channelUsers.length - 1)];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
'getServerUsers': function(server) {
|
||||
return dbot.db.knownUsers[server].users;
|
||||
},
|
||||
|
||||
'getAllUsers': function() {
|
||||
return _.reduce(dbot.db.knownUsers, function(memo, server, name) {
|
||||
memo[name] = server.users;
|
||||
return memo;
|
||||
}, {}, this);
|
||||
},
|
||||
|
||||
'isKnownUser': function(server, nick) {
|
||||
var knownUsers = this.getServerUsers(server);
|
||||
return (_.include(knownUsers.users, nick) || _.has(knownUsers.aliases, nick));
|
||||
},
|
||||
|
||||
'isPrimaryUser': function(server, nick) {
|
||||
var knownUsers = this.getServerUsers(server);
|
||||
return _.include(knownUsers.users, nick);
|
||||
},
|
||||
|
||||
'getAliases': function(server, nick) {
|
||||
var knownUsers = this.getServerUsers(server);
|
||||
return _.chain(knownUsers.aliases)
|
||||
.keys()
|
||||
.filter(function(user) {
|
||||
return knownUsers.aliases[user] == nick;
|
||||
}, this)
|
||||
.value();
|
||||
},
|
||||
|
||||
'isOnline': function(server, user, channel, useLowerCase) {
|
||||
var user = this.api.resolveUser(server, user, useLowerCase);
|
||||
var possiNicks = [user].concat(this.api.getAliases(server, user));
|
||||
|
||||
if(!_.has(dbot.instance.connections[server].channels, channel)) return false;
|
||||
var onlineNicks = dbot.instance.connections[server].channels[channel].nicks;
|
||||
|
||||
return _.any(onlineNicks, function(nick) {
|
||||
nick = nick.name;
|
||||
return _.include(possiNicks, nick);
|
||||
}, this);
|
||||
},
|
||||
|
||||
'isChannelUser': function(server, user, channel, useLowerCase) {
|
||||
var knownUsers = this.getServerUsers(server);
|
||||
var user = this.api.resolveUser(server, user, useLowerCase);
|
||||
|
||||
if(!_.has(knownUsers.channelUsers, channel)) {
|
||||
return false;
|
||||
}
|
||||
return _.include(knownUsers.channelUsers[channel], user);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
api['resolveUser'].external = true;
|
||||
api['resolveUser'].extMap = [ 'server', 'nick', 'callback' ];
|
||||
|
||||
api['getChannel'].external = true;
|
||||
api['getChannel'].extMap = [ 'server', 'channel', 'callback' ];
|
||||
|
||||
api['getAllUsers'].external = true;
|
||||
api['getAllUsers'].extMap = [ 'callback' ];
|
||||
|
||||
api['getAllChannels'].external = true;
|
||||
api['getAllChannels'].extMap = [ 'callback' ];
|
||||
|
||||
return api;
|
||||
};
|
||||
|
||||
|
@ -3,106 +3,139 @@ var _ = require('underscore')._;
|
||||
var commands = function(dbot) {
|
||||
var commands = {
|
||||
'~alias': function(event) {
|
||||
var knownUsers = this.getServerUsers(event.server),
|
||||
alias = event.params[1].trim();
|
||||
var nick = event.params[1].trim() || event.user;
|
||||
this.api.resolveUser(event.server, nick, function(user) {
|
||||
if(user) {
|
||||
if(nick == user.primaryNick) {
|
||||
var aliases = _.first(user.aliases, 10);
|
||||
var including = 'including: ' + aliases.join(', ') + '.';
|
||||
|
||||
if(_.include(knownUsers.users, alias)) {
|
||||
var aliases = this.api.getAliases(event.server, alias);
|
||||
var aliasCount = aliases.length;
|
||||
|
||||
if(aliasCount != 0) {
|
||||
var aliases = _.first(aliases, 10);
|
||||
var including = 'including: ' + aliases.join(', ') + '.';
|
||||
|
||||
event.reply(dbot.t('primary', {
|
||||
'user': alias,
|
||||
'count': aliasCount
|
||||
}) + including);
|
||||
if(user.aliases.length != 0) {
|
||||
event.reply(dbot.t('primary', {
|
||||
'user': nick,
|
||||
'currentNick': user.currentNick,
|
||||
'count': user.aliases.length,
|
||||
}) + including);
|
||||
} else {
|
||||
event.reply(dbot.t('primary', {
|
||||
'user': nick,
|
||||
'currentNick': user.currentNick,
|
||||
'count': user.aliases.length
|
||||
}).slice(0, -2) + ".");
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('alias', {
|
||||
'alias': nick,
|
||||
'user': user.primaryNick
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('primary', {
|
||||
'user': alias,
|
||||
'count': aliasCount
|
||||
}).slice(0, -2) + ".");
|
||||
event.reply(dbot.t('unknown_alias', { 'alias': nick }));
|
||||
}
|
||||
} else if(_.has(knownUsers.aliases, alias)) {
|
||||
event.reply(dbot.t('alias', {
|
||||
'alias': alias,
|
||||
'user': knownUsers.aliases[alias]
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('unknown_alias', { 'alias': alias }));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'~addalias': function(event) {
|
||||
var nick = event.input[1],
|
||||
alias = event.input[2];
|
||||
|
||||
this.api.resolveUser(event.server, nick, function(user) {
|
||||
if(user) {
|
||||
if(!_.include(user.aliases, alias)) {
|
||||
user.aliases.push(alias);
|
||||
this.db.save('users', user.id, user, function(err) {
|
||||
if(!err) {
|
||||
event.reply(dbot.t('alias_added', {
|
||||
'user': user.primaryNick,
|
||||
'alias': alias
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('alias_exists', { 'alias': alias }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('unknown_alias', { 'alias': nick }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~setaliasparent': function(event) {
|
||||
var knownUsers = this.getServerUsers(event.server);
|
||||
var newParent = event.params[1];
|
||||
var newPrimary = event.params[1].trim();
|
||||
this.api.resolveUser(event.server, newPrimary, function(user) {
|
||||
if(user && user.primaryNick != newPrimary) {
|
||||
var newAlias = user.primaryNick;
|
||||
user.primaryNick = newPrimary;
|
||||
user.aliases = _.without(user.aliases, newPrimary);
|
||||
user.aliases.push(newAlias);
|
||||
this.internalAPI.updateChannelPrimaryUser(event.server, newAlias, newPrimary);
|
||||
|
||||
if(_.has(knownUsers.aliases, newParent)) {
|
||||
var newAlias = knownUsers.aliases[newParent];
|
||||
|
||||
// Replace user entry
|
||||
knownUsers.users = _.without(knownUsers.users, newAlias);
|
||||
knownUsers.users.push(newParent);
|
||||
|
||||
// Replace channels entries with new primary user
|
||||
this.updateChannels(event, newAlias, newParent);
|
||||
|
||||
// Remove alias for new parent & add alias for new alias
|
||||
delete knownUsers.aliases[newParent];
|
||||
knownUsers.aliases[newAlias] = newParent;
|
||||
|
||||
// Update aliases to point to new primary user
|
||||
this.updateAliases(event, newAlias, newParent);
|
||||
|
||||
event.reply(dbot.t('aliasparentset', {
|
||||
'newParent': newParent,
|
||||
'newAlias': newAlias
|
||||
}));
|
||||
|
||||
return {
|
||||
'server': event.server,
|
||||
'alias': newAlias
|
||||
};
|
||||
} else {
|
||||
event.reply(dbot.t('unknown_alias', { 'alias': newParent }));
|
||||
}
|
||||
return false;
|
||||
this.db.save('users', user.id, user, function(err) {
|
||||
if(!err) {
|
||||
event.reply(dbot.t('aliasparentset', {
|
||||
'newParent': newPrimary,
|
||||
'newAlias': newAlias
|
||||
}));
|
||||
dbot.api.event.emit('~setaliasparent', {
|
||||
'server': event.server,
|
||||
'alias': newAlias
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('unknown_alias', { 'alias': newPrimarj }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~mergeusers': function(event) {
|
||||
var knownUsers = this.getServerUsers(event.server);
|
||||
var primaryUser = event.params[1];
|
||||
var secondaryUser = event.params[2];
|
||||
|
||||
if(_.include(knownUsers.users, primaryUser) && _.include(knownUsers.users, secondaryUser)) {
|
||||
knownUsers.users = _.without(knownUsers.users, secondaryUser);
|
||||
knownUsers.aliases[secondaryUser] = primaryUser;
|
||||
this.updateAliases(event, secondaryUser, primaryUser);
|
||||
this.updateChannels(event, secondaryUser, primaryUser);
|
||||
|
||||
event.reply(dbot.t('merged_users', {
|
||||
'old_user': secondaryUser,
|
||||
'new_user': primaryUser
|
||||
}));
|
||||
|
||||
return {
|
||||
'server': event.server,
|
||||
'secondary': secondaryUser
|
||||
};
|
||||
} else {
|
||||
event.reply(dbot.t('unprimary_error'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
this.api.resolveUser(event.server, primaryUser, function(user) {
|
||||
if(user) {
|
||||
this.api.resolveUser(event.server, secondaryUser, function(oldUser) {
|
||||
if(oldUser) {
|
||||
user.aliases.push(oldUser.primaryNick);
|
||||
user.aliases = _.union(user.aliases, oldUser.aliases);
|
||||
this.internalAPI.mergeChannelUsers(event.server, oldUser, user);
|
||||
this.db.del('users', oldUser.id, function(err) {
|
||||
if(!err) {
|
||||
this.db.save('users', user.id, user, function(err) {
|
||||
if(!err) {
|
||||
this.internalAPI.mergeChannelUsers(event.server, secondaryUser, primaryUser);
|
||||
event.reply(dbot.t('merged_users', {
|
||||
'old_user': secondaryUser,
|
||||
'new_user': primaryUser
|
||||
}));
|
||||
dbot.api.event.emit('~mergeusers', [
|
||||
event.server,
|
||||
oldUser,
|
||||
user
|
||||
]);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('unprimary_error', { 'nick': secondaryUser }));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('unprimary_error', { 'nick': primaryUser }));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
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['~addalias'].regex = [/^~addalias ([\d\w[\]{}^|\\`_-]+?) ([\d\w[\]{}^|\\`_-]+?)$/, 3];
|
||||
|
||||
commands['~setaliasparent'].access = 'moderator';
|
||||
commands['~mergeusers'].access = 'moderator';
|
||||
commands['~addalias'].access = 'moderator';
|
||||
|
||||
return commands;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ignorable": false,
|
||||
"dependencies": [ "command", "event" ],
|
||||
"dependencies": [ "event" ],
|
||||
"dbKeys": [ "knownUsers" ],
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md"
|
||||
"dbType": "redis"
|
||||
}
|
||||
|
@ -4,41 +4,55 @@
|
||||
"na'vi": "ayfko syaw {user} {alias} nìteng",
|
||||
"cy": "{alias} ydy enw arall o {user}",
|
||||
"nl": "{alias} is een alias van {user}",
|
||||
"de": "{alias} ist ein Nickname von {user}"
|
||||
"de": "{alias} ist ein Nickname von {user}",
|
||||
"fr": "{alias} est un alias de {user}"
|
||||
},
|
||||
"primary": {
|
||||
"en": "{user} is a primary user with {count} aliases, ",
|
||||
"na'vi": "{user} lu txin ulte {count}a stxo lu poru, ",
|
||||
"cy": "Mae {user} yn ddefnyddiwr gynradd gyda {count} enwau eraill, ",
|
||||
"nl": "{user} is een primaire gebruiker met {count} aliassen, ",
|
||||
"de": "{user} ist ein Benutzer mit {count} Nicknamen, "
|
||||
"en": "{user} (currently {currentNick}) is a primary user with {count} aliases, ",
|
||||
"na'vi": "{user} ({currentNick}) lu txin ulte {count}a stxo lu poru, ",
|
||||
"nl": "{user} ({currentNick}) is een primaire gebruiker met {count} aliassen, ",
|
||||
"cy": "Mae {user} ({currentNick}) yn ddefnyddiwr gynradd gyda {count} enwau eraill, ",
|
||||
"de": "{user} ({currentNick}) ist ein Benutzer mit {count} Nicknamen, ",
|
||||
"fr": "{user} (actuellement {currentNick}) est un utilisateur primaire avec {count} alias, "
|
||||
},
|
||||
"unknown_alias": {
|
||||
"en": "{alias} does not currently exist as an alias or known user.",
|
||||
"na'vi": "{alias} ke fkeytok nìfkrr",
|
||||
"cy": "Nid yw {alias} yn bodoli fel enw arall neu defnyddiwr yn hysbys.",
|
||||
"nl": "{alias} staat momenteel niet bekend als een bestaande gebruiker of alias.",
|
||||
"de": "{alias} existiert nicht oder ist kein Nickname eines Benutzers."
|
||||
"de": "{alias} existiert nicht oder ist kein Nickname eines Benutzers.",
|
||||
"fr": "{alias} n'existe pas actuellement en tant qu'alias ou utilisateur connu."
|
||||
},
|
||||
"aliasparentset": {
|
||||
"en": "{newParent} is now the parent user, and {newAlias} is an alias.",
|
||||
"na'vi": "{newParent} lu sa'sem set ulte {newAlias} lu stxo set nìteng.",
|
||||
"cy": "Mae {newParent} ydy defnyddiwr rhiant nawr, a {alias} ydy enw arall.",
|
||||
"nl": "{newParent} is nu de bovenliggende gebruiker, en {newAlias} is een alias.",
|
||||
"de": "{newParent} ist nun der Hauptname und {newAlias} ist ein Nickname."
|
||||
"de": "{newParent} ist nun der Hauptname und {newAlias} ist ein Nickname.",
|
||||
"fr": "{newParent} est maintenant le même utilisateur parent, et {newAlias} est un alias."
|
||||
},
|
||||
"unprimary_error": {
|
||||
"en": "One of those users isn't currently recorded as a primary user.",
|
||||
"en": "{nick} isn't recorded as a primary user.",
|
||||
"na'vi": "fo sute txin ke lu.",
|
||||
"cy": "Nid yw un o'r defnyddwyr hynny yn cael ei gofnodi ar hyn o bryd fel defnyddiwr gynradd.",
|
||||
"nl": "Een van deze gebruikers is nog niet bekend als een primaire gebruiker.",
|
||||
"de": "Einer dieser Benutzer ist nicht als Hauptbenutzer gespeichert."
|
||||
"de": "Einer dieser Benutzer ist nicht als Hauptbenutzer gespeichert.",
|
||||
"fr": "{nick} n'est pas enregistré en tant qu'utilisateur primaire."
|
||||
},
|
||||
"merged_users": {
|
||||
"en": "{old_user} and their aliases have been merged into {new_user}.",
|
||||
"na'vi": "{old_user} ulte stxo alahe {new_user} lu set.",
|
||||
"cy": "{old_user} a'u enwau eraill wedi cael eu cyfuno i mewn i {new_user}.",
|
||||
"nl": "{old_user} en zijn aliassen zijn samengevoegd met {new_user}.",
|
||||
"de": "{old_user} und seine Nicknamen wurden zusammengelegt in {new_user}."
|
||||
"de": "{old_user} und seine Nicknamen wurden zusammengelegt in {new_user}.",
|
||||
"fr": "{old_user} et ses alias ont été fusionnés dans {new_user}."
|
||||
},
|
||||
"alias_exists": {
|
||||
"en": "Alias {alias} already exists.",
|
||||
"fr": "L'alias {alias} existe déjà."
|
||||
},
|
||||
"alias_added": {
|
||||
"en": "Alias {alias} added to {user}.",
|
||||
"fr": "Alias {alias} ajouté à {user}."
|
||||
}
|
||||
}
|
||||
|
@ -2,93 +2,228 @@
|
||||
* Name: Users
|
||||
* Description: Track known users
|
||||
*/
|
||||
var _ = require('underscore')._;
|
||||
var _ = require('underscore')._,
|
||||
uuid = require('node-uuid'),
|
||||
async = require('async');
|
||||
|
||||
var users = function(dbot) {
|
||||
this.knownUsers = dbot.db.knownUsers;
|
||||
this.getServerUsers = function(server) {
|
||||
var knownUsers = this.knownUsers;
|
||||
if(!_.has(knownUsers, server)) {
|
||||
knownUsers[server] = { 'users': [], 'aliases': {}, 'channelUsers': {} };
|
||||
}
|
||||
if(!_.has(knownUsers[server], 'channelUsers')) {
|
||||
knownUsers[server].channelUsers = {};
|
||||
}
|
||||
return knownUsers[server];
|
||||
};
|
||||
|
||||
this.updateAliases = function(event, oldUser, newUser) {
|
||||
var knownUsers = this.getServerUsers(event.server);
|
||||
_.each(knownUsers.aliases, function(user, alias) {
|
||||
if(user == oldUser) {
|
||||
knownUsers.aliases[alias] = newUser;
|
||||
/*** Internal API ***/
|
||||
this.internalAPI = {
|
||||
'createUser': function(server, nick, callback) {
|
||||
var id = uuid.v4();
|
||||
this.db.create('users', id, {
|
||||
'id': id,
|
||||
'primaryNick': nick,
|
||||
'currentNick': nick,
|
||||
'server': server,
|
||||
'channels': [],
|
||||
'aliases': []
|
||||
}, function(err, result) {
|
||||
if(!err) {
|
||||
dbot.api.event.emit('new_user', [ result ]);
|
||||
callback(result);
|
||||
}
|
||||
});
|
||||
}.bind(this),
|
||||
|
||||
'createChannel': function(server, name, callback) {
|
||||
var id = uuid.v4();
|
||||
this.db.create('channel_users', id, {
|
||||
'id': id,
|
||||
'server': server,
|
||||
'name': name,
|
||||
'users': [],
|
||||
'op': [],
|
||||
'voice': []
|
||||
}, function(err, result) {
|
||||
if(!err) {
|
||||
dbot.api.event.emit('new_channel', [ result ]);
|
||||
callback(result);
|
||||
}
|
||||
});
|
||||
}.bind(this),
|
||||
|
||||
'addChannelUser': function(channel, user, staff, callback) {
|
||||
if(!_.include(channel.users, user.id)) {
|
||||
channel.users.push(user.id);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
this.updateChannels = function(event, oldUser, newUser) {
|
||||
var channelUsers = this.getServerUsers(event.server).channelUsers;
|
||||
channelUsers = _.each(channelUsers, function(channel, channelName) {
|
||||
channelUsers[channelName] = _.without(channel, oldUser);
|
||||
channelUsers[channelName].push(newUser);
|
||||
}, this);
|
||||
};
|
||||
|
||||
this.listener = function(event) {
|
||||
var knownUsers = this.getServerUsers(event.server);
|
||||
var nick = event.user;
|
||||
|
||||
if(event.action == 'JOIN' && nick != dbot.config.name) {
|
||||
if(!_.has(knownUsers.channelUsers, event.channel.name)) {
|
||||
knownUsers.channelUsers[event.channel.name] = [];
|
||||
if(!_.include(user.channels, channel.id)) {
|
||||
user.channels.push(channel.id);
|
||||
}
|
||||
var channelUsers = knownUsers.channelUsers[event.channel.name];
|
||||
|
||||
if(this.api.isKnownUser(event.server, nick)) {
|
||||
nick = this.api.resolveUser(event.server, nick);
|
||||
if(!channel.op) channel.op = [];
|
||||
if(!channel.voice) channel.voice = [];
|
||||
|
||||
if(staff.op) {
|
||||
channel.op.push(user.id);
|
||||
} else if(staff.voice) {
|
||||
channel.voice.push(user.id);
|
||||
}
|
||||
|
||||
this.db.save('users', user.id, user, function(err) {
|
||||
this.db.save('channel_users', channel.id, channel, function(err) {
|
||||
dbot.api.event.emit('new_channel_user', [ user, channel ]);
|
||||
callback(err);
|
||||
});
|
||||
}.bind(this));
|
||||
}.bind(this),
|
||||
|
||||
'modChannelStaff': function(channel, user, staff, callback) {
|
||||
var needsUpdating = false;
|
||||
|
||||
if(!channel.op) {
|
||||
channel.op = [];
|
||||
needsUpdating = true;
|
||||
}
|
||||
if(!channel.voice) {
|
||||
channel.voice = [];
|
||||
needsUpdating = true;
|
||||
}
|
||||
|
||||
if(!_.include(channel.op, user.id) && staff.op) {
|
||||
channel.op.push(user.id);
|
||||
needsUpdating = true;
|
||||
} else if(!_.include(channel.voice, user.id) && staff.voice) {
|
||||
channel.voice.push(user.id);
|
||||
needsUpdating = true;
|
||||
} else if(_.include(channel.op, user.id) && !staff.op) {
|
||||
channel.op = _.without(channel.op, user.id);
|
||||
needsUpdating = true;
|
||||
} else if(_.include(channel.voice, user.id) && !staff.voice) {
|
||||
channel.voice = _.without(channel.voice, user.id);
|
||||
needsUpdating = true;
|
||||
}
|
||||
|
||||
if(needsUpdating) {
|
||||
this.db.save('channel_users', channel.id, channel, function(err) {
|
||||
callback(err);
|
||||
});
|
||||
} else {
|
||||
knownUsers.users.push(nick);
|
||||
dbot.api.event.emit('new_user', [ event.server, nick ]);
|
||||
callback();
|
||||
}
|
||||
}.bind(this),
|
||||
|
||||
'updateChannelPrimaryUser': function(server, oldUser, newUser) {
|
||||
this.db.search('channel_users', { 'server': server }, function(channel) {
|
||||
channel.users = _.without(channel.users, oldUser);
|
||||
if(!_.include(channel.users, newUser)) channel.users.push(newUser);
|
||||
this.db.save('channel_users', channel.id, channel, function(err) {
|
||||
if(err) {
|
||||
// QQ
|
||||
}
|
||||
});
|
||||
}.bind(this), function(err) {
|
||||
if(err) {
|
||||
// QQ
|
||||
}
|
||||
});
|
||||
}.bind(this),
|
||||
|
||||
'mergeChannelUsers': function(server, oldUser, newUser) {
|
||||
newUser.channels = _.union(oldUser.channels, newUser.channels);
|
||||
_.each(newUser.channels, function(name) {
|
||||
this.api.getChannel(server, name, function(channel) {
|
||||
if(_.include(channel.users, oldUser.id)) {
|
||||
channel.users = _.without(channel.users, oldUser.id);
|
||||
}
|
||||
if(!_.include(channel.users, newUser.id)) {
|
||||
channel.users.push(newUser.id);
|
||||
}
|
||||
this.db.save('channel_users', channel.id, channel, function(err) {
|
||||
if(err) {
|
||||
// QQ
|
||||
}
|
||||
});
|
||||
}.bind(this));
|
||||
}, this);
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
this.listener = function(event) {
|
||||
if(event.action == 'JOIN' && event.user != dbot.config.name) {
|
||||
if(!event.rUser) {
|
||||
this.internalAPI.createUser(event.server, event.user, function(user) {
|
||||
this.internalAPI.addChannelUser(event.rChannel, user, {}, function() {});
|
||||
}.bind(this));
|
||||
} else if(!_.include(event.rUser.channels, event.rChannel.id)) {
|
||||
this.internalAPI.addChannelUser(event.rChannel, event.rUser, {}, function() {});
|
||||
}
|
||||
|
||||
if(!_.include(channelUsers, nick)) {
|
||||
channelUsers.push(nick);
|
||||
if(event.rUser.currentNick != event.user) {
|
||||
event.rUser.currentNick = event.user;
|
||||
this.db.save('users', event.rUser.id, event.rUser, function() {});
|
||||
}
|
||||
} else if(event.action == 'NICK') {
|
||||
var newNick = event.newNick;
|
||||
if(!this.api.isKnownUser(newNick)) {
|
||||
knownUsers.aliases[newNick] = this.api.resolveUser(event.server, event.user);
|
||||
dbot.api.event.emit('nick_change', [ event.server, newNick ]);
|
||||
}
|
||||
this.api.isKnownUser(event.server, event.newNick, function(isKnown) {
|
||||
event.rUser.currentNick = event.newNick;
|
||||
|
||||
if(!isKnown) {
|
||||
event.rUser.aliases.push(event.newNick);
|
||||
}
|
||||
|
||||
this.db.save('users', event.rUser.id, event.rUser, function(err) {
|
||||
dbot.api.event.emit('new_user_alias', [ event.rUser, event.newNick ]);
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = ['JOIN', 'NICK'];
|
||||
|
||||
this.onLoad = function() {
|
||||
// Trigger updateNickLists to stat current users in channel
|
||||
dbot.instance.addListener('366', 'users', function(event) {
|
||||
var knownUsers = this.getServerUsers(event.server);
|
||||
if(!_.has(knownUsers.channelUsers, event.channel.name)) {
|
||||
knownUsers.channelUsers[event.channel.name] = [];
|
||||
}
|
||||
var channelUsers = knownUsers.channelUsers[event.channel.name];
|
||||
this.on = ['JOIN', 'NICK'];
|
||||
|
||||
_.each(event.channel.nicks, function(nick) {
|
||||
nick = nick.name;
|
||||
if(this.api.isKnownUser(event.server, nick)) {
|
||||
nick = this.api.resolveUser(event.server, nick);
|
||||
} else {
|
||||
knownUsers.users.push(nick);
|
||||
dbot.api.event.emit('new_user', [ event.server, nick ]);
|
||||
}
|
||||
if(!_.include(channelUsers, nick)) {
|
||||
channelUsers.push(nick);
|
||||
}
|
||||
}, this);
|
||||
this.onLoad = function() {
|
||||
dbot.instance.addPreEmitHook(function(event, callback) {
|
||||
if(event.user) {
|
||||
this.api.resolveUser(event.server, event.user, function(user) {
|
||||
event.rUser = user;
|
||||
callback(false);
|
||||
});
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
dbot.instance.addPreEmitHook(function(event, callback) {
|
||||
if(event.channel) {
|
||||
this.api.getChannel(event.server, event.channel.name, function(channel) {
|
||||
event.rChannel = channel;
|
||||
callback(false);
|
||||
});
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
var connections = dbot.instance.connections;
|
||||
_.each(connections, function(connection) {
|
||||
dbot.instance.addListener('366', 'users', function(event) {
|
||||
var checkChannel = function(channel) {
|
||||
async.eachSeries(_.keys(event.channel.nicks), function(nick, next) {
|
||||
var staff = event.channel.nicks[nick];
|
||||
|
||||
this.api.resolveUser(event.server, nick, function(user) {
|
||||
var checkChannelUser = function(user) {
|
||||
if(!_.include(channel.users, user.id)) {
|
||||
this.internalAPI.addChannelUser(channel, user, staff, next);
|
||||
} else {
|
||||
this.internalAPI.modChannelStaff(channel, user, staff, next);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
if(user) {
|
||||
checkChannelUser(user);
|
||||
} else {
|
||||
this.internalAPI.createUser(event.server, nick, checkChannelUser);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this), function(err) {});
|
||||
}.bind(this);
|
||||
|
||||
if(!event.rChannel) {
|
||||
this.internalAPI.createChannel(event.server, event.channel.name, checkChannel);
|
||||
} else {
|
||||
checkChannel(event.rChannel);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
_.each(dbot.instance.connections, function(connection) {
|
||||
connection.updateNickLists();
|
||||
});
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"dependencies": [ "report", "users", "web" ],
|
||||
"dbKeys": [ "warnings" ]
|
||||
"dbType": "redis"
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
var _ = require('underscore')._;
|
||||
var _ = require('underscore')._,
|
||||
async = require('async');
|
||||
|
||||
var pages = function(dbot) {
|
||||
this.warnings = dbot.db.warnings;
|
||||
@ -7,37 +8,59 @@ var pages = function(dbot) {
|
||||
'/warning': function(req, res) {
|
||||
res.render('servers', {
|
||||
'name': dbot.config.name,
|
||||
'servers': _.keys(this.warnings)
|
||||
'servers': _.keys(dbot.config.servers)
|
||||
});
|
||||
},
|
||||
|
||||
'/warning/:server': function(req, res) {
|
||||
var server = req.params.server;
|
||||
var server = req.params.server,
|
||||
userIds = [],
|
||||
userNicks = [];
|
||||
|
||||
if(_.has(this.warnings, server)) {
|
||||
res.render('users', {
|
||||
'name': dbot.config.name,
|
||||
'server': server,
|
||||
'users': _.keys(this.warnings[server])
|
||||
this.db.search('warnings', { 'server': server }, function(warning) {
|
||||
if(!_.include(userIds, warning.warnee)) userIds.push(warning.warnee);
|
||||
}, function(err) {
|
||||
async.eachSeries(userIds, function(id, callback) {
|
||||
dbot.api.users.getUser(id, function(user) {
|
||||
userNicks.push(user.primaryNick);
|
||||
callback(false);
|
||||
});
|
||||
}, function(err) {
|
||||
res.render('users', {
|
||||
'name': dbot.config.name,
|
||||
'server': server,
|
||||
'users': userNicks
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.render('error');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'/warning/:server/:user': function(req, res) {
|
||||
var server = req.params.server,
|
||||
user = req.params.user;
|
||||
|
||||
if(_.has(this.warnings, server) && _.has(this.warnings[server], user)) {
|
||||
res.render('warnings', {
|
||||
'name': dbot.config.name,
|
||||
dbot.api.users.resolveUser(server, user, function(user) {
|
||||
var warnings = [];
|
||||
this.db.search('warnings', {
|
||||
'server': server,
|
||||
'warnings': this.warnings[server][user]
|
||||
'warnee': user.id
|
||||
}, function(warning) {
|
||||
warnings.push(warning);
|
||||
}, function(err) {
|
||||
async.eachSeries(warnings, function(warning, callback) {
|
||||
dbot.api.users.getUser(warning.warner, function(user) {
|
||||
warning.warner = user.primaryNick;
|
||||
callback(false);
|
||||
});
|
||||
}, function(err) {
|
||||
res.render('warnings', {
|
||||
'name': dbot.config.name,
|
||||
'server': server,
|
||||
'warnings': warnings
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.render('error');
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -1,11 +1,14 @@
|
||||
{
|
||||
"no_warnings": {
|
||||
"en": "No warnings found for {user}."
|
||||
"en": "No warnings found for {user}.",
|
||||
"fr": "Aucun avertissement trouvé pour {user}."
|
||||
},
|
||||
"warning_info": {
|
||||
"en": "{user} has {num} warnings. More info can be found at {url}"
|
||||
"en": "{user} has {num} warnings. More info can be found at {url}",
|
||||
"fr": "{user} a {num} avertissements. Plus d'informations peuvent être trouvées ici : {url}"
|
||||
},
|
||||
"warn_notify": {
|
||||
"en": "Attention: {warner} has issued a warning to {warnee} for \"{reason}.\" More info can be found at {url}"
|
||||
"en": "Attention: {warner} has issued a warning to {warnee} for \"{reason}.\" More info can be found at {url}",
|
||||
"fr": "Attention : {warner} a donné un avertissement à {warnee} pour \"{reason}.\". Plus d'informations peuvent être trouvées ici : {url}"
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +1,69 @@
|
||||
var _ = require('underscore')._;
|
||||
uuid = require('node-uuid');
|
||||
|
||||
var warning = function(dbot) {
|
||||
this.warnings = dbot.db.warnings;
|
||||
|
||||
this.commands = {
|
||||
'~warn': function(event) {
|
||||
var warner = event.user,
|
||||
var warner = event.rUser,
|
||||
server = event.server,
|
||||
warnee = dbot.api.users.resolveUser(server, event.input[1]),
|
||||
reason = event.input[2],
|
||||
adminChannel = dbot.config.servers[server].admin_channel;
|
||||
|
||||
// Store the warn
|
||||
if(!_.has(this.warnings, server)) this.warnings[server] = {};
|
||||
if(!_.has(this.warnings[server], warnee)) this.warnings[server][warnee] = [];
|
||||
|
||||
this.warnings[server][warnee].push({
|
||||
'warner': warner,
|
||||
'reason': reason,
|
||||
'time': new Date().getTime()
|
||||
});
|
||||
|
||||
// Notify interested parties
|
||||
var notifyString = dbot.t('warn_notify', {
|
||||
'warner': warner,
|
||||
'warnee': warnee,
|
||||
'reason': reason,
|
||||
'url': dbot.api.web.getUrl('warning/' + server + '/' + warnee)
|
||||
});
|
||||
if(!_.isUndefined(adminChannel)) {
|
||||
adminChannel = event.channel.name;
|
||||
}
|
||||
dbot.api.report.notify(server, adminChannel, notifyString);
|
||||
dbot.say(server, adminChannel, notifyString);
|
||||
dbot.say(server, warnee, notifyString);
|
||||
dbot.api.users.resolveUser(server, event.input[1], function(warnee) {
|
||||
if(warnee) {
|
||||
var id = uuid.v4();
|
||||
this.db.save('warnings', id, {
|
||||
'id': id,
|
||||
'server': event.server,
|
||||
'warnee': warnee.id,
|
||||
'warner': warner.id,
|
||||
'reason': reason,
|
||||
'time': new Date().getTime()
|
||||
}, function(err) {
|
||||
var notifyString = dbot.t('warn_notify', {
|
||||
'warner': warner.primaryNick,
|
||||
'warnee': warnee.primaryNick,
|
||||
'reason': reason,
|
||||
'url': dbot.api.web.getUrl('warning/' + server + '/'
|
||||
+ warnee.primaryNick)
|
||||
});
|
||||
if(_.isUndefined(adminChannel)) {
|
||||
adminChannel = event.channel.name;
|
||||
}
|
||||
dbot.api.report.notify(server, adminChannel, notifyString);
|
||||
dbot.say(server, adminChannel, notifyString);
|
||||
dbot.say(server, warnee.currentNick, notifyString);
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('warnee_not_found', { 'user': event.input[1] }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~warnings': function(event) {
|
||||
var warnee = event.params[1],
|
||||
server = event.server;
|
||||
|
||||
if(_.has(this.warnings, server) && _.has(this.warnings[server], warnee)) {
|
||||
event.reply(dbot.t('warning_info', {
|
||||
'user': warnee,
|
||||
'num': this.warnings[server][warnee].length,
|
||||
'url': dbot.api.web.getUrl('warning/' + server + '/' + warnee)
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('no_warnings', { 'user': warnee }));
|
||||
}
|
||||
dbot.api.users.resolveUser(server, warnee, function(warnee) {
|
||||
var warnings = 0;
|
||||
this.db.search('warnings', {
|
||||
'server': server,
|
||||
'warnee': warnee.id
|
||||
}, function(warning) {
|
||||
warnings++;
|
||||
}, function(err) {
|
||||
if(warnings > 0) {
|
||||
event.reply(dbot.t('warning_info', {
|
||||
'user': warnee.primaryNick,
|
||||
'num': warnings,
|
||||
'url': dbot.api.web.getUrl('warning/' + server + '/'
|
||||
+ warnee.primaryNick)
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('no_warnings', { 'user': warnee }));
|
||||
}
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7,31 +7,21 @@ Web interface
|
||||
It's a web interface for DBot. What of it?
|
||||
|
||||
## Requirements
|
||||
###Express and Jade@0.25
|
||||
|
||||
### Express and Jade
|
||||
```
|
||||
npm install express
|
||||
npm install jade@0.25
|
||||
npm install express jade
|
||||
```
|
||||
###Express Patch
|
||||
Express currently needs to be patched, edit ~/node_modules/express/lib/express.js as thus;
|
||||
```
|
||||
52 for (var key in connect.middleware) {
|
||||
**53 if( !Object.prototype.hasOwnProperty(key) ) {
|
||||
54 Object.defineProperty(
|
||||
55 exports
|
||||
56 , key
|
||||
57 , Object.getOwnPropertyDescriptor(connect.middleware, key));
|
||||
**58 }
|
||||
59 }
|
||||
```
|
||||
###Twitter Bootstrap
|
||||
|
||||
### Twitter Bootstrap
|
||||
```
|
||||
cd depressionbot/public/
|
||||
wget http://twitter.github.com/bootstrap/assets/bootstrap.zip
|
||||
unzip bootstrap.zip
|
||||
rm bootstrap.zip
|
||||
```
|
||||
###d3.js
|
||||
|
||||
### d3.js
|
||||
```
|
||||
cd depressionbot/public/
|
||||
mkdir d3
|
||||
|
@ -1,6 +1,5 @@
|
||||
{
|
||||
"webHost": "nourishedcloud.com",
|
||||
"webPort": 8080,
|
||||
"externalPath": false,
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/web/README.md"
|
||||
"externalPath": false
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user