Merge pull request #70 from reality/module_overhaul

Module overhaul. Sweet Jesus.
This commit is contained in:
Luke Slater 2012-12-18 01:34:22 -08:00
commit e7e31a4135
36 changed files with 563 additions and 667 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
# Ignore the user config files
config.json
./config.json
# Ignore the user database
db.json

View File

@ -1,7 +1,5 @@
{
"name": "testressionbot",
"webHost": "lolcathost",
"webPort": 80,
"servers": {
"freenode": {
"server": "irc.freenode.net",
@ -13,5 +11,7 @@
]
}
},
"admin": [ "batman" ]
"admins": [ "batman" ],
"moduleNames": [ "ignore", "admin", "command", "dice", "js", "kick", "puns", "quotes", "spelling", "youare" ],
"language": "english"
}

View File

@ -53,7 +53,6 @@ var admin = function(dbot) {
// Reload DB, translations and modules.
'reload': function(event) {
dbot.db = JSON.parse(fs.readFileSync('db.json', 'utf-8'));
dbot.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8'));
dbot.reloadModules();
event.reply(dbot.t('reload'));
},
@ -71,20 +70,22 @@ var admin = function(dbot) {
// Load new module
'load': function(event) {
var moduleName = event.params[1];
dbot.moduleNames.push(moduleName);
dbot.config.moduleNames.push(moduleName);
dbot.reloadModules();
event.reply(dbot.t('load_module', {'moduleName': moduleName}));
},
// Unload a loaded module
'unload': function(event) {
var moduleNames = dbot.config.moduleNames;
var moduleName = event.params[1];
if(dbot.moduleNames.include(moduleName)) {
var cacheKey = require.resolve('../modules/' + moduleName);
if(moduleNames.include(moduleName)) {
var moduleDir = '../' + moduleName + '/';
var cacheKey = require.resolve(moduleDir + moduleName);
delete require.cache[cacheKey];
var moduleIndex = dbot.moduleNames.indexOf(moduleName);
dbot.moduleNames.splice(moduleIndex, 1);
var moduleIndex = moduleNames.indexOf(moduleName);
moduleNames.splice(moduleIndex, 1);
dbot.reloadModules();
event.reply(dbot.t('unload_module', {'moduleName': moduleName}));
@ -134,7 +135,7 @@ var admin = function(dbot) {
*/
'listener': function(event) {
var commandName = event.params[0];
if(commands.hasOwnProperty(commandName) && dbot.admin.include(event.user)) {
if(commands.hasOwnProperty(commandName) && dbot.config.admins.include(event.user)) {
commands[commandName](event);
dbot.save();
}

View File

@ -0,0 +1,3 @@
{
"dbKeys": [ "bans", "locks" ]
}

View File

@ -0,0 +1,68 @@
{
"join": {
"english": "Joined {channel}",
"spanish" : "Entrado en {channel}",
"na'vi": "fpxäkìm {channel}(nemfa)",
"welsh": "Wedi ymuno {channel}"
},
"part": {
"english": "Left {channel}",
"spanish" : "Abandonada {channel}",
"na'vi": "Hum {channel}",
"welsh": "Wedi gadael {channel}"
},
"gpull": {
"english": "Git pulled that shit.",
"spanish": "Hecho git pull en esta mierda.",
"na'vi": "Gìtìl fì'uti stamarsìm.",
"welsh": "Wedi tynnu git yr cach na i gyd"
},
"reload": {
"english": "Reloaded that shit.",
"spanish": "Recargado esta mierda.",
"na'vi": "Oel fìuti stìyeftxaw.",
"welsh": "Ail-lwytho'r cach na"
},
"load_module": {
"english": "Loaded new module: {moduleName}",
"spanish": "Cargado módulo nuevo: {moduleName}",
"na'vi": "Oel {moduleName}it amip stìyeftxaw.",
"welsh": "Wedi llwytho modiwl newydd: {moduleName}"
},
"unload_module": {
"english": "Turned off module: {moduleName}",
"spanish": "Descargado módulo: {moduleName}",
"na'vi": "Oel {moduleName} tswìya'.",
"welsh": "Wedi troi ffwrdd y modiwl: {moduleName}"
},
"unload_error": {
"english": "{moduleName} isn't loaded. Idiot.",
"spanish": "{moduleName} no está cargado. Idiota.",
"na'vi": "Oel {moduleName}it omum. Nga skxawng lu.",
"welsh": "Di {moduleName} ddim wedi llwytho. Twpsyn"
},
"banned": {
"english": "{user} banned from {command}",
"spanish": "{user} está prohibido de usar {command}",
"na'vi": "{command}ìri {user} ke tung.",
"welsh": "{user} wedi ei gohurio o {command}"
},
"unbanned": {
"english": "{user} unbanned from {command}",
"spanish": "{user} no está prohibido de user {command}",
"na'vi": "{command}ìri {user} tung set.",
"welsh": "{user} wedi ei dad-wahardd o {command}"
},
"unban_error": {
"english": "{user} wasn't banned from that command, fool.",
"spanish": "{user} no fue prohibido de esta instrucción, tont@.",
"na'vi": "{user} fìtsu'oti tamung srekrr, nga skxawng lu.",
"welsh": "Nid oedd {user} wedi ei wahardd o'r gyrchymun yna, fŵl"
},
"qlock": {
"english": "Locked quote category: {category}",
"spanish": "Cerrado la categoría: {category}",
"na'vi": "{category}ìri oel 'upxareti fmoli",
"welsh": "Categori wedi cloi: {category}"
}
}

View File

@ -1,41 +0,0 @@
/**
* Module Name: AutoShorten
* Description: Automatically shorten link over a certain length and post the
* short link to the channel.
*/
var http = require('http');
var autoshorten = function(dbot) {
return {
'name': 'autoshorten',
'ignorable': true,
'listener': function(event) {
var urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
var urlMatches = event.message.match(urlRegex);
if(urlMatches !== null && urlMatches[0].length > 80) {
var url = urlMatches[0]; // Only doing one, screw you.
// TODO: Make this use a decent URL shortener. Mine is shit.
var options = {
'host': dbot.webHost,
'port': dbot.webPort,
'path': '/mkurl?url=' + escape(url)
};
http.get(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (response) {
event.reply(dbot.t('shorten_link', {'user': event.user}) + JSON.parse(response).surl);
});
});
}
},
'on': 'PRIVMSG'
};
}
exports.fetch = function(dbot) {
return autoshorten(dbot);
};

View File

@ -56,10 +56,9 @@ var command = function(dbot) {
'commands': {
'~usage': function(event) {
var commandName = event.params[1];
console.log(commandName);
if(dbot.commands.hasOwnProperty(commandName)) {
if(dbot.usage.hasOwnProperty(commandName)) {
event.reply('Usage for ' + commandName + ': ' +
dbot.commands[commandName].usage);
dbot.usage[commandName]);
} else {
event.reply('No usage information for ' + commandName);
}
@ -84,8 +83,8 @@ var command = function(dbot) {
dbot.save();
} else {
if(commandName !== '~') {
if(dbot.commands[commandName].hasOwnProperty('usage')){
event.reply('Usage: ' + dbot.commands[commandName].usage);
if(dbot.usage.hasOwnProperty(commandName)){
event.reply('Usage: ' + dbot.usage[commandName]);
} else {
event.reply(dbot.t('syntax_error'));
}

View File

@ -0,0 +1,14 @@
{
"command_ban": {
"english": "{user} is banned from using this command. Commence incineration.",
"spanish": "{user} está prohibido de usar esta instrucción. Comenzar incineración.",
"na'vi": "Tsu'ori {user} ke tung. Nga skxawng lu.",
"welsh": "Mae {user} wedi ei gohurio gan ddefnyddio'r gorchymun yma. Cychwyn orfflosgiad"
},
"syntax_error": {
"english": "Invalid syntax. Initiate incineration.",
"spanish": "Sintaxis no válida. Iniciar incineración.",
"na'vi": "Ngeyä pamrel keyawr lu. Nga skxawng lu.",
"welsh": "Cystrawen annilys. Cychwyn orfflosgiad"
}
}

View File

@ -1,96 +0,0 @@
/**
* Module Name: Drama
* Description: Experimental, you probably don't want it.
*/
var brain = require('brain');
var drama = function(dbot) {
var dbot = dbot;
var last = {};
var options = {
'backend': {
'type': 'Redis',
'options': {
'hostname': 'localhost',
'port': 6379,
'name': 'dbotdrama'
}
},
'thresholds': {
'drama': 3,
'beinganasshole': 3,
'sd': 3, // self depracating
'normal': 1
},
'def': 'normal'
};
var bayes = new brain.BayesianClassifier(options);
var commands = {
'~train': function(event) {
if(dbot.admin.include(event.user)) {
bayes.train(last[event.params[1]][event.params[2]], event.params[3]);
event.reply('Last thing ' + event.params[2] + ' said in ' +
event.params[1] + ' (' + last[event.params[1]][event.params[2]] + ') classified as \'' + event.params[3] + '\'');
}
},
'~rtrain': function(event) {
if(dbot.admin.include(event.user)) {
var category = event.params[1];
event.params.splice(0, 2);
var msg = event.params.join(' ');
bayes.train(msg, category);
event.reply('\'' + msg + '\' classified as \'' + category + '\'');
}
},
'~classify': function(event) {
event.params.splice(0, 1);
var msg = event.params.join(' ');
bayes.classify(msg, function(category) {
event.reply('Classified as: ' + category + '!');
}.bind(this));
}
}
return {
'name': 'drama',
'ignorable': false,
'commands': commands,
'listener': function(data) {
var category = bayes.classify(data.message, function(category) {
if(category !== 'normal') {
if(category === 'beinganasshole') {
if(dbot.db.drama.beinganasshole.hasOwnProperty(event.user)) {
dbot.db.drama.beinganasshole[event.user]++;
} else {
dbot.db.drama.beinganasshole[event.user] = 1;
}
} else if(category === 'sd') {
if(dbot.db.drama.sd.hasOwnProperty(event.user)) {
dbot.db.drama.sd[event.user]++;
} else {
dbot.db.drama.sd[event.user] = 1;
}
}
}
}.bind(this));
if(last.hasOwnProperty(event.channel)) {
last[event.channel][event.user] = data.message;
} else {
last[event.channel] = { };
last[event.channel][event.user] = data.message;
}
},
'on': 'PRIVMSG'
};
}
exports.fetch = function(dbot) {
return drama(dbot);
};

View File

@ -0,0 +1,3 @@
{
"dbKeys": [ "ignores" ]
}

View File

@ -0,0 +1,44 @@
{
"ignore_usage": {
"english": "{user}: Usage: ~ignore [module]. Modules you can ignore are: {modules}.",
"spanish": "{user}: Modo de empleo: ~ignore [módulo]. Módulos que tú puedes ignorar son: {modules}.",
"na'vi": "{user}: Sar: ~ignore ['u]. U, nga ke tìng mikyun: {modules}.",
"welsh": "{user}: Defnydd: ~ignore [modiwl]. Modiwlau a allech anwybyddu yw: {modules}."
},
"already_ignoring": {
"english": "{user}: You're already ignoring that module.",
"spanish": "{user}: Ya ignoras este módulo.",
"na'vi": "{user}: 'uri nga ke tìng mikyun srekrr.",
"welsh": "{user}: Mi rwyt ti'n anwybyddu'r modiwl yna'n barod."
},
"ignored": {
"english": "{user}: Now ignoring {module}.",
"spanish": "{user}: Estás ignorando {module}.",
"na'vi": "{user}: Nga ke terìng mikyun {module}ne set.",
"welsh": "{user}: Nawr yn anwybyddu {module}"
},
"invalid_ignore": {
"english": "{user}: That isn't a valid module name.",
"spanish": "{user}: Ese no es un nombre de un módulo valido.",
"na'vi": "{user}: Tsatstxo eyawr ke lu.",
"welsh": "{user}: Nid oedd hwna'n modiwl dilys"
},
"unignore_usage": {
"english": "{user}: Usage: ~unignore [module]. Modules you are currently ignoring: {modules}.",
"spanish": "{user}: Modo de empleo: ~unignore [módulo]. Módulos que ignoras ahora mismo: {modules}.",
"na'vi": "{user}: Sar: ~unignore ['u]. Uri, nga ke terìng mikyun: {modules}.",
"welsh": "{user}: Defnydd ~unignore [modiwl]. Modiwlau rydech yn anwybyddu ar hyn o bryd: {modules}"
},
"invalid_unignore": {
"english": "{user}: You're not ignoring that module or it doesn't exist.",
"spanish": "{user}: No ignoras este módulo o no existe.",
"na'vi":"{user}: Nga terìng mikyun fu fì'ul fìtsengit ke tok.",
"welsh": "{user}: Nid wyt ti'n anwybyddu'r modiwl yna neu nid yw e'n bodoli"
},
"unignored": {
"english": "{user}: No longer ignoring {module}.",
"spanish": "{user}: Ya no ignoras {module}.",
"na'vi": "{user}: Nga terìng mikyun {module}ne set",
"welsh": "{user}: Ddim yn anwybyddu {module} bellach"
}
}

View File

@ -22,7 +22,7 @@ var js = function(dbot) {
// Run JS code un-sandboxed, with access to DBot memory (admin-only).
'~ajs': function(event) {
if(dbot.admin.include(event.user) ) {
if(dbot.config.admins.include(event.user) ) {
var ret = eval(event.input[1]);
if(ret !== undefined) {
event.reply(ret);
@ -32,8 +32,6 @@ var js = function(dbot) {
};
commands['~js'].regex = [/^~js (.*)/, 2];
commands['~ajs'].regex = [/^~ajs (.*)/, 2];
commands['~js'].usage = '~js [command]';
commands['~ajs'].usage = '~ajs [command]';
return {
'name': 'js',

4
modules/js/usage.json Normal file
View File

@ -0,0 +1,4 @@
{
"~js": "~js [command]",
"~ajs": "~ajs [command]"
}

3
modules/kick/config.json Normal file
View File

@ -0,0 +1,3 @@
{
"dbKeys": [ "kicks", "kickers" ]
}

View File

@ -46,10 +46,10 @@ var kick = function(dbot) {
'commands': commands,
'listener': function(event) {
if(event.kickee == dbot.name) {
if(event.kickee == dbot.config.name) {
dbot.instance.join(event, event.channel);
event.reply(dbot.t('kicked_dbot', {'botname': dbot.name}));
dbot.db.kicks[dbot.name] += 1;
event.reply(dbot.t('kicked_dbot', {'botname': dbot.config.name}));
dbot.db.kicks[dbot.config.name] += 1;
} else {
if(!dbot.db.kicks.hasOwnProperty(event.kickee)) {
dbot.db.kicks[event.kickee] = 1;

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

@ -0,0 +1,14 @@
{
"user_kicks": {
"english": "{user} has been kicked {kicks} times and has kicked people {kicked} times.",
"spanish": "Se ha expulsado {user} {kicks} veces y {user} ha expulsado personas {kicked} veces.",
"na'vi": "Tuteol {user}it tsrame'i {kicks} hìmtxan ulte sute tsrame'i {kicked} hìmtxan.",
"welsh": "Cafwyd {user} ei gicio {kicks} gwaith ac wedi cicio pobl {kicked} gwaith."
},
"kicked_dbot": {
"english": "Thou shalt not kick {botname}",
"spanish": "No expulsás {botname}",
"na'vi": "Ngal {botname}it ke tsun tsrive'i",
"welsh": "Ni ddylech cicio {botname}"
}
}

View File

@ -40,7 +40,8 @@ var poll = function(dbot) {
}
event.reply(dbot.t('poll_created', {'name': name, 'description': description,
'url': dbot.t('url', {'host': dbot.webHost, 'port': dbot.webPort, 'path': 'polls/' + name})}));
'url': dbot.t('url', {'host': dbot.config.web.webHost,
'port': dbot.config.web.webPort, 'path': 'polls/' + name})}));
}
}
},
@ -141,7 +142,8 @@ var poll = function(dbot) {
var name = event.input[1];
if(polls.hasOwnProperty(name)) {
event.reply(dbot.t('poll_describe', {'name': name, 'description': polls[name].description,
'url': dbot.t('url', {'host': dbot.webHost, 'port': dbot.webPort, 'path': 'polls/' + name})}));
'url': dbot.t('url', {'host': dbot.config.web.webHost, 'port':
dbot.config.web.webPort, 'path': 'polls/' + name})}));
} else {
event.reply(dbot.t('poll_unexistent', {'name': name}));
}
@ -215,12 +217,6 @@ var poll = function(dbot) {
commands['~pdesc'].regex = [/~pdesc ([^ ]+)/, 2];
commands['~count'].regex = [/~count ([^ ]+)/, 2];
commands['~newpoll'].usage = '~newpoll [pollname] options=[each,poll,option] [Poll Description]';
commands['~addoption'].usage = '~addoption [pollname] [newoption]';
commands['~rmoption'].usage= '~rmoption [pollname] [optiontoremove]';
commands['~vote'].usage= '~vote [pollname] [option]';
commands['~pdesc'].usage = '~pdesc [pollname]';
return {
'name': 'poll',
'ignorable': true,

87
modules/poll/strings.json Normal file
View File

@ -0,0 +1,87 @@
{
"newpoll_usage": {
"english": "Usage: ~newpoll name [options=opt1,opt2,opt3] description",
"spanish" : "Modo de empleo: ~newpoll nombre [options=opción1,opción2,opción3] descripción",
"na'vi": "Usage: ~newpoll tstxo [sìftxey=tìfxey1,tìfxey2,fìfxey3] tìsla'tsu",
"welsh": "Defnydd: ~newpoll enw [optiynau=opt1,opt2,op3] disgrifiad"
},
"poll_exists": {
"english": "Poll '{name}' already exists.",
"spanish" : "Votación '{name}' ya existe.",
"na'vi": "sìpawm sna'o '{name}' fkeytok srekrr.",
"welsh": "Mae'r pôl {name} bodoli'n barod"
},
"poll_created": {
"english": "Poll '{name}' created ({description}). Cast thy votations! - {url}",
"spanish" : "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}"
},
"poll_describe": {
"english": "{name}: {description} - {url}"
},
"changed_vote": {
"english": "{user} changed their vote in {poll} to '{vote}' ({count}).",
"spanish" : "{user} cambió su voto en {poll} a '{vote}' ({count}).",
"na'vi": "{user} lìyatem ngeyä tìpe'un {poll}mì, ngeyä tìpe'un amip '{vote}'({count}) lu.",
"welsh": "Newidiodd {user} eu pleidlais yn {poll} i '{vote}' ({count})."
},
"voted": {
"english": "{user} voted for '{vote}' in {poll} ({count}).",
"spanish" : "{user} votó para '{vote}' en {poll} ({count}).",
"na'vi": "'{vote}'ìri {user} pìye'un {poll}mì ({count}).",
"welsh": "Pledleisiodd {user} am '{vote}' yn {poll} ({count})."
},
"invalid_vote": {
"english": "Invalid vote: {vote}",
"spanish" : "Vota inválida: {vote}",
"na'vi": "Ngeyä tìpe'un keyawr lu ({vote}).",
"welsh": "Pleidlais annilys: {vote}"
},
"poll_unexistent": {
"english": "Poll '{name}' doesn't exist.",
"spanish" : "Votación '{name}' no existe.",
"na'vi": "sìpawm sna'o '{name}' ke fkeytok.",
"welsh": "Nid yw pôl '{name}' yn bodoli"
},
"option_added": {
"english": "{user}: '{option}' added to '{name}'.",
"spanish" : "{user}: '{option}' añadido a '{name}'.",
"na'vi": "'{name}'ur {user}ìl '{option}'it sung.",
"welsh": "{user}: Ychwanegwyd '{option}' i '{name}'"
},
"option_exists": {
"english": "{user}: '{option}' already exists in '{name}'.",
"spanish" : "{user}: '{option}' ya existe en '{name}'.",
"na'vi": "{user}: '{option}' fkeytok srekrr '{name}'mì.",
"welsh": "{user}: Mae '{option}' yn bodoli'n barod yn '{name}'."
},
"not_poll_owner": {
"english": "{user}: You don't own the '{name}' poll.",
"spanish" : "{user}: La votación '{name}' no es tuyo.",
"na'vi": "{user}: ngaru '{name}' sìpawm sna'o ke lu.",
"welsh": "{user}: Nid ydech chi'n berchen y pôl '{name}'."
},
"option_removed": {
"english": "{user}: '{option}' removed from '{name}'",
"spanish" : "{user}: '{option}' eliminado de '{name}'",
"na'vi": "{user}: '{option}'it 'aku '{name}'ta",
"welsh": "{user}: '{option}' wedi ei ddileu o '{name}'"
},
"av_voted": {
"english": "{user} voted '{vote}' in {poll}.",
"spanish": "{user} votó '{vote}' en {poll}.",
"na'vi": "{user}ìl '{vote}'it pìye'un '{poll}'mì.",
"welsh": "Pledleisiodd {user} am '{vote}' yn {poll}"
},
"av_changed_vote": {
"english": "{user} changed their vote in {poll} to '{vote}'.",
"spanish" : "{user} cambió su voto en {poll} a '{vote}'.",
"na'vi": "{user}ìl lìyatem ngeyä tìpa'unit '{poll}'mì, ngeyä tìpe'un '{vote} lu set.",
"welsh": "Newidiodd {user} eu pleidlais yn {poll} i '{vote}'"
},
"count": {
"english": "The running-order of poll '{poll}' ({description}) is: {places}.",
"na'vi": "Sute tsnì pole'un '{poll}'mì ({description}) lu: {places}.",
"welsh": "Trefn yr pôl '{poll}' ({description}) yw: {places}"
}
}

7
modules/poll/usage.json Normal file
View File

@ -0,0 +1,7 @@
{
"~newpoll": "~newpoll [pollname] options=[each,poll,option] [Poll Description]",
"~addoption": "~addoption [pollname] [newoption]",
"~rmoption": "~rmoption [pollname] [optiontoremove]",
"~vote": "~vote [pollname] [option]",
"~pdesc": "~pdesc [pollname]"
}

View File

@ -8,7 +8,7 @@ var puns = function(dbot) {
'listener': function(event) {
event.user = dbot.cleanNick(event.user);
if(dbot.moduleNames.include('quotes') &&
if(dbot.config.moduleNames.include('quotes') &&
dbot.db.quoteArrs.hasOwnProperty(event.user)) {
event.message = '~q ' + event.user;
event.action = 'PRIVMSG';

View File

@ -0,0 +1,3 @@
{
"dbKeys": [ "quoteArrs" ]
}

View File

@ -94,10 +94,10 @@ var quotes = function(dbot) {
},
'~rmlast': function(event) {
if(rmAllowed == true || dbot.admin.include(event.user)) {
if(rmAllowed == true || dbot.config.admins.include(event.user)) {
var key = event.input[1].trim().toLowerCase();
if(quotes.hasOwnProperty(key)) {
if(!dbot.db.locks.include(key) || dbot.admin.include(event.user)) {
if(!dbot.db.locks.include(key) || dbot.config.admins.include(event.user)) {
var quote = quotes[key].pop();
if(quotes[key].length === 0) {
delete quotes[key];
@ -116,7 +116,7 @@ var quotes = function(dbot) {
},
'~rm': function(event) {
if(rmAllowed == true || dbot.admin.include(event.user)) {
if(rmAllowed == true || dbot.config.admins.include(event.user)) {
var key = event.input[1].trim().toLowerCase();
var quote = event.input[2];
@ -156,7 +156,9 @@ var quotes = function(dbot) {
} else { // Give total quote count
var totalQuoteCount = 0;
for(var category in quotes) {
totalQuoteCount += category.length;
if(quotes.hasOwnProperty(category)) {
totalQuoteCount += quotes[category].length;
}
}
event.reply(dbot.t('total_quotes', {'count': totalQuoteCount}));
}
@ -187,29 +189,12 @@ var quotes = function(dbot) {
var key = event.params[1].trim().toLowerCase();
if(quotes.hasOwnProperty(key)) {
event.reply(dbot.t('quote_link', {'category': key,
'url': dbot.t('url', {'host': dbot.webHost,
'port': dbot.webPort, 'path': 'quotes/' + key})}));
'url': dbot.t('url', {'host': dbot.config.web.webHost,
'port': dbot.config.web.webPort, 'path': 'quotes/' + key})}));
} else {
event.reply(dbot.t('category_not_found'));
event.reply(dbot.t('category_not_found', {'category': key}));
}
},
'~qprune': function(event) {
var pruned = []
for(key in quotes) {
if(quotes.hasOwnProperty(key)) {
if(quotes[key].length == 0) {
delete quotes[key];
pruned.push(key);
}
}
}
if(pruned.length > 0) {
event.reply(dbot.t('prune', {'categories': pruned.join(", ")}));
} else {
event.reply(dbot.t('no_prune'));
}
}
};
commands['~'].regex = [/^~([\d\w\s-]*)/, 2];
@ -219,12 +204,6 @@ var quotes = function(dbot) {
commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2];
commands['~qadd'].regex = [/^~qadd ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3];
commands['~q'].usage = '~q [category]';
commands['~qsearch'].usage = '~qsearch [category]=[search]';
commands['~rm'].usage = '~rm [category]=[quote to delete]';
commands['~rmlast'].usage = '~rmlast [category]'
commands['~qadd'].usage = '~qadd [category]=[content]';
return {
'name': 'quotes',
'ignorable': true,
@ -237,6 +216,7 @@ var quotes = function(dbot) {
},
'listener': function(event) {
// Reality Once listener
if((dbot.db.ignores.hasOwnProperty(event) &&
dbot.db.ignores[event.user].include(name)) == false) {
if(event.user == 'reality') {

110
modules/quotes/strings.json Normal file
View File

@ -0,0 +1,110 @@
{
"category_not_found": {
"english": "Nobody loves {category}",
"spanish": "Nadie ama a {category}",
"na'vi": "{category} yawne ke lu kawturu.",
"welsh": "Does neb yn caru {category}"
},
"large_categories": {
"english": "Largest categories: ",
"spanish": "Los categorías más grandes: ",
"na'vi": "U atsawl: ",
"welsh": "Categoriau mwyaf: "
},
"empty_category": {
"english": "That category has no quotes in. Commence incineration.",
"spanish": "Categoría vacía. Iniciar incineración.",
"na'vi": "Tsauru upxare lu. Nga skxawng lu.",
"welsh": "Nid yw'r categori yna efo dyfyniadau. Cychwyn orfflosgiad"
},
"no_results": {
"english": "No results found.",
"spanish": "No hubo ningún resultado.",
"na'vi": "Oel kea humit rìmun",
"welsh": "Dim canlyniadau ar gael"
},
"locked_category": {
"english": "{category} is locked. Commence incineration.",
"spanish": "{category} está cerrada. Comenzar incineración.",
"na'vi": "{category} ke fkeytok set. Nga skxawng lu nafì'u",
"welsh": "Mae {category} wedi cloi. Cychwyn orfflosgiad"
},
"no_quotes": {
"english": "No quotes exist under {category}",
"spanish": "Ninguna cita existe en {category}",
"na'vi": "Kea upxare fkeytok {category}mì",
"welsh": "Does dim dyfyniadau gan {category}"
},
"last_removed": {
"english": "Last quote removed from {category}.",
"spanish": "Última cita quitado de {category}.",
"na'vi": "Oel 'upxareti aham 'aku {category}ta",
"welsh": "Dyfyniad olaf wedi ei ddileu o {category}"
},
"no_recent_adds": {
"english": "No quotes were added recently.",
"spanish": "Ninguna cita fue añadido recientamente.",
"na'vi": "Kea upxareti samung nìfkrr",
"welsh": "Nid oes unrhyw dyfyniadau wedi ei ychwwanegu'n ddiweddar"
},
"rmlast_spam": {
"english": "No spamming that shit. Try again in a few minutes...",
"spanish": "No me inundes de mierda. Intenta otra vez en unos minutos...",
"na'vi": "Nga Tsasngelit ke zene fpivere'. Sweylu nga fmivi ye'rìn...",
"welsh": "Peidiwch a sbamio hwna. Triwch eto mewn ychydyg funudau..."
},
"removed_from": {
"english": "'{quote}' removed from {category}",
"spanish": "'{quote}' quitado de {category}",
"na'vi": "'{quote}'(it/ti) 'ìyaku {category}",
"welsh": "'{quote}' wedi ei ddileu o {category}"
},
"q_not_exist_under": {
"english": "'{quote}' doesn't exist under '{category}'.",
"spanish": "'{quote}' no existe en '{category}'.",
"na'vi": "'{quote}' ke fkeytok '{category}'ta.",
"welsh": "Nid yw '{quote}' yn bodoli yn '{category}'"
},
"total_quotes": {
"english": "Total quote count: {count}.",
"spanish": "Total de citas: {count}.",
"na'vi": "'upxareri holpxay: {count}.",
"welsh": "Cyfanswm dyfyniadau: {count}."
},
"quote_exists": {
"english": "Quote already in DB. Initiate incineration.",
"spanish": "Cita ya existe. Iniciar incineración.",
"na'vi": "'Upxarel säomumit fìtsengit tok srekrr. Nga skxawng lu.",
"welsh": "Dyfyniad yn y gronfa ddata yn barod. Cychwyn orfflosgiad"
},
"quote_saved": {
"english": "Quote saved in '{category}' ({count}).",
"spanish": "Cita guardada en '{category}' ({count}).",
"na'vi": "Oe zayerok '{category}'mì ({count}).",
"welsh": "Dyfyniad wedi ei gadw yn '{category}' ({count})."
},
"quote_replace": {
"english": "No replacing arrays, you whore.",
"spanish": "No sustituites arrays, hijo de puta.",
"na'vi": "Ngal fìsäomumit ke tsun rivawn. Nga muntxa sayi suteo hrh.",
"welsh": "Peidiwch a newid rhestrau, y cachgi"
},
"quote_count": {
"english": "{category} has {count} quotes.",
"spanish": "{category} tiene {count} citas.",
"na'vi": "{count}a upxare {category}ur lu.",
"welsh": "{count} dyfyniad yn {category}"
},
"quote_link": {
"english": "Link to {category} - {url}",
"spanish": "Enlace a {category} - {url}",
"na'vi": "Fya'o {category}ne - {url}",
"welsh": "Dolen i {category} - {url}"
},
"search_results": {
"english": "{category} ({needle}): '{quote}' [{matches} results]",
"spanish" : "{category} ({needle}): '{quote}' [{matches} resultados]",
"na'vi": "{category} ({needle}): '{quote}' [kum a{matches}]",
"welsh": "{category} ({needle}): '{quote}' [{matches} canlyniad]"
}
}

View File

@ -0,0 +1,7 @@
{
"~q": "~q [category]",
"~qsearch": "~qsearch [category]=[search]",
"~rm": "~rm [category]=[quote to delete]",
"~rmlast": "~rmlast [category]",
"~qadd": "~qadd [category]=[content]"
}

View File

@ -38,7 +38,6 @@ var report = function(dbot) {
};
commands['~report'].regex = [/^~report ([^ ]+) ([^ ]+) (.+)$/, 4];
commands['~report'].usage = '~report [#channel] [username] [reason for reporting]';
return {
'name': 'report',

View File

@ -0,0 +1,3 @@
{
"~report": "~report [#channel] [username] [reason for reporting]"
}

View File

@ -0,0 +1,14 @@
{
"spelling_self": {
"english": "{correcter} meant: {fix}",
"spanish": "{correcter} quería decir: {fix}",
"na'vi": "Sweylu {correcter} pamrel sivi: {fix}",
"welsh": "Oedd {correcter} yn feddwl: {fix}"
},
"spelling_other": {
"english": "{correcter} thinks {candidate} meant: {fix}",
"spanish": "{correcter} piensa que {candidate} queria decir: {fix}",
"na'vi": "{correcter} fpìl futa sweylu {candiate} pamrel sivi: {fix}",
"welsh": "Mae {correcter} yn meddwl bod {candidate} yn feddwl: {fix}"
}
}

4
modules/web/config.json Normal file
View File

@ -0,0 +1,4 @@
{
"webHost": "localhost",
"webPort": 8080
}

View File

@ -9,21 +9,21 @@ var webInterface = function(dbot) {
app.set('view engine', 'jade');
app.get('/', function(req, res) {
res.render('index', { 'name': dbot.name });
res.render('index', { 'name': dbot.config.name });
});
app.get('/connections', function(req, res) {
var connections = Object.keys(dbot.instance.connections);
res.render('connections', { 'name': dbot.name, 'connections': connections });
res.render('connections', { 'name': dbot.config.name, 'connections': connections });
});
app.get('/channels/:connection', function(req, res) {
var connection = req.params.connection;
if(dbot.instance.connections.hasOwnProperty(connection)) {
var channels = Object.keys(dbot.instance.connections[connection].channels);
res.render('channels', { 'name': dbot.name, 'connection': connection, 'channels': channels});
res.render('channels', { 'name': dbot.config.name, 'connection': connection, 'channels': channels});
} else {
res.render('error', { 'name': dbot.name, 'message': 'No such connection.' });
res.render('error', { 'name': dbot.config.name, 'message': 'No such connection.' });
}
});
@ -35,10 +35,10 @@ var webInterface = function(dbot) {
if(connections.hasOwnProperty(connection) &&
connections[connection].channels.hasOwnProperty(channel)) {
var nicks = Object.keys(connections[connection].channels[channel].nicks);
res.render('users', { 'name': dbot.name, 'connection': connection,
res.render('users', { 'name': dbot.config.name, 'connection': connection,
'channel': channel, 'nicks': nicks });
} else {
res.render('error', { 'name': dbot.name, 'message': 'No such connection or channel.' });
res.render('error', { 'name': dbot.config.name, 'message': 'No such connection or channel.' });
}
});
@ -64,35 +64,35 @@ var webInterface = function(dbot) {
var kicked = dbot.db.kickers[req.params.user];
}
res.render('user', { 'name': dbot.name, 'user': req.params.user,
res.render('user', { 'name': dbot.config.name, 'user': req.params.user,
'channel': channel, 'connection': connection, 'cleanUser': user,
'quotecount': quoteCount, 'kicks': kicks, 'kicked': kicked });
});
// Lists the quote categories
app.get('/quotes', function(req, res) {
res.render('quotelist', { 'name': dbot.name, 'quotelist': Object.keys(dbot.db.quoteArrs) });
res.render('quotelist', { 'name': dbot.config.name, 'quotelist': Object.keys(dbot.db.quoteArrs) });
});
// Lists quotes in a category
app.get('/quotes/:key', function(req, res) {
var key = req.params.key.toLowerCase();
if(dbot.db.quoteArrs.hasOwnProperty(key)) {
res.render('quotes', { 'name': dbot.name, 'quotes': dbot.db.quoteArrs[key], locals: { 'url_regex': RegExp.prototype.url_regex() } });
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.name, 'message': 'No quotes under that key.' });
res.render('error', { 'name': dbot.config.name, 'message': 'No quotes under that key.' });
}
});
// Load random quote category page
app.get('/rq', function(req, res) {
var rCategory = Object.keys(dbot.db.quoteArrs).random();
res.render('quotes', { 'name': dbot.name, 'quotes': dbot.db.quoteArrs[rCategory], locals: { 'url_regex': RegExp.prototype.url_regex() } });
res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[rCategory], locals: { 'url_regex': RegExp.prototype.url_regex() } });
});
// Lists all of the polls
app.get('/polls', function(req, res) {
res.render('polllist', { 'name': dbot.name, 'polllist': Object.keys(dbot.db.polls) });
res.render('polllist', { 'name': dbot.config.name, 'polllist': Object.keys(dbot.db.polls) });
});
// Shows the results of a poll
@ -107,13 +107,13 @@ var webInterface = function(dbot) {
totalVotes += N;
}
}
res.render('polls', { 'name': dbot.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() } });
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.name, 'message': 'No polls under that key.' });
res.render('error', { 'name': dbot.config.name, 'message': 'No polls under that key.' });
}
});
app.listen(dbot.webPort);
app.listen(dbot.config.web.webPort);
return {
'name': 'web',

189
run.js
View File

@ -5,83 +5,64 @@ require('./snippets');
var DBot = function(timers) {
// Load external files
this.config = JSON.parse(fs.readFileSync('config.json', 'utf-8'));
this.db = null;
var requiredConfigKeys = [ 'name', 'servers', 'admins', 'moduleNames', 'language' ];
try {
this.config = JSON.parse(fs.readFileSync('config.json', 'utf-8'));
} catch(err) {
console.log('Config file is screwed up. Attempting to load defaults.');
try {
this.config = JSON.parse(fs.readFileSync('config.json.sample', 'utf-8'));
} catch(err) {
console.log('Error loading sample config. Bugger off. Stopping.');
process.exit();
}
}
requiredConfigKeys.each(function(key) {
if(!this.config.hasOwnProperty(key)) {
console.log('Error: Please set a value for ' + key + ' in ' +
'config.json. Stopping.');
process.exit();
}
}.bind(this));
var rawDB;
try {
var rawDB = fs.readFileSync('db.json', 'utf-8');
} catch (e) {
} catch(err) {
this.db = {}; // If no db file, make empty one
}
if(!this.db) { // If it wasn't empty
this.db = JSON.parse(rawDB);
}
// Repair any deficiencies in the DB; if this is a new DB, that's everything
if(!this.db.hasOwnProperty("bans")) {
this.db.bans = {};
}
if(!this.db.bans.hasOwnProperty("*")) {
this.db.bans["*"] = [];
}
if(!this.db.hasOwnProperty("quoteArrs")) {
this.db.quoteArrs = {};
}
if(!this.db.hasOwnProperty("kicks")) {
this.db.kicks = {};
}
if(!this.db.hasOwnProperty("kickers")) {
this.db.kickers = {};
}
if(!this.db.hasOwnProperty("modehate")) {
this.db.modehate = [];
}
if(!this.db.hasOwnProperty("locks")) {
this.db.locks = [];
}
if(!this.db.hasOwnProperty("ignores")) {
this.db.ignores = {};
}
if(!this.db.hasOwnProperty('polls')) {
this.db.polls = {};
try {
if(!this.db) { // If it wasn't empty
this.db = JSON.parse(rawDB);
}
} catch(err) {
console.log('Syntax error in db.json. Stopping: ' + err);
process.exit();
}
// Load Strings file
this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8'));
try {
this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8'));
} catch(err) {
console.log('Probably a syntax error in strings.json: ' + err);
this.strings = {};
}
// Initialise run-time resources
this.usage = {};
this.sessionData = {};
this.timers = timers.create();
// Populate bot properties with config data
this.name = this.config.name || 'dbox';
this.admin = this.config.admin || [ 'reality' ];
this.moduleNames = this.config.modules || [ 'ignore', 'admin', 'command', 'dice', 'js', 'kick', 'puns', 'quotes', 'spelling', 'youare' ];
this.language = this.config.language || 'english';
this.webHost = this.config.webHost || 'localhost';
this.webPort = this.config.webPort || 80;
// It's the user's responsibility to fill this data structure up properly in
// the config file. They can d-d-d-deal with it if they have problems.
this.servers = this.config.servers || {
'freenode': {
'server': 'irc.freenode.net',
'port': 6667,
'nickserv': 'nickserv',
'password': 'lolturtles',
'channels': [
'#realitest'
]
}
};
// Create JSBot and connect to each server
this.instance = jsbot.createJSBot(this.name);
for(var name in this.servers) {
if(this.servers.hasOwnProperty(name)) {
var server = this.servers[name];
this.instance.addConnection(name, server.server, server.port, this.admin, function(event) {
var server = this.servers[event.server];
this.instance = jsbot.createJSBot(this.config.name);
for(var name in this.config.servers) {
if(this.config.servers.hasOwnProperty(name)) {
var server = this.config.servers[name];
this.instance.addConnection(name, server.server, server.port,
this.config.admin, function(event) {
var server = this.config.servers[event.server];
for(var i=0;i<server.channels.length;i++) {
this.instance.join(event, server.channels[i]);
}
@ -101,12 +82,19 @@ DBot.prototype.say = function(server, channel, message) {
// Format given stored string in config language
DBot.prototype.t = function(string, formatData) {
var lang = this.language;
if(!this.strings[string].hasOwnProperty(lang)) {
lang = "english";
var formattedString;
if(this.strings.hasOwnProperty(string)) {
var lang = this.config.language;
if(!this.strings[string].hasOwnProperty(lang)) {
lang = "english";
}
formattedString = this.strings[string][lang].format(formatData);
} else {
formattedString = 'String not found. Something has gone screwy. Maybe.';
}
return this.strings[string][lang].format(formatData);
return formattedString;
};
/*DBot.prototype.act = function(channel, data) {
@ -132,13 +120,21 @@ DBot.prototype.reloadModules = function() {
this.modules = [];
this.commands = {};
this.commandMap = {}; // Map of which commands belong to which modules
this.usage = {};
this.timers.clearTimers();
this.save();
try {
this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8'));
} catch(err) {
this.strings = {};
}
var moduleNames = this.config.moduleNames;
// Enforce having command. it can still be reloaded, but dbot _will not_
// function without it, so not having it should be impossible
if(!this.moduleNames.include("command")) {
this.moduleNames.push("command");
if(!moduleNames.include("command")) {
moduleNames.push("command");
}
// Reload Javascript snippets
@ -148,12 +144,14 @@ DBot.prototype.reloadModules = function() {
this.instance.removeListeners();
this.moduleNames.each(function(name) {
var cacheKey = require.resolve('./modules/' + name);
moduleNames.each(function(name) {
var moduleDir = './modules/' + name + '/';
var cacheKey = require.resolve(moduleDir + name);
delete require.cache[cacheKey];
try {
var rawModule = require('./modules/' + name);
// Load the module itself
var rawModule = require(moduleDir + name);
var module = rawModule.fetch(this);
this.rawModules.push(rawModule);
@ -165,6 +163,7 @@ DBot.prototype.reloadModules = function() {
module.onLoad();
}
// Load module commands
if(module.commands) {
var newCommands = module.commands;
for(key in newCommands) {
@ -175,12 +174,58 @@ DBot.prototype.reloadModules = function() {
}
}
// Load the module usage data
try {
var usage = JSON.parse(fs.readFileSync(moduleDir + 'usage.json', 'utf-8'));
for(key in usage) {
if(usage.hasOwnProperty(key)) {
if(this.usage.hasOwnProperty(key)) {
console.log('Usage key clash for ' + key + ' in ' + name);
} else {
this.usage[key] = usage[key];
}
}
}
} catch(err) {
// Invalid or no usage info
}
// Load the module string data
try {
var strings = JSON.parse(fs.readFileSync(moduleDir + 'strings.json', 'utf-8'));
for(key in strings) {
if(strings.hasOwnProperty(key)) {
if(this.strings.hasOwnProperty(key)) {
console.log('Strings key clash for ' + key + ' in ' + name);
} else {
this.strings[key] = strings[key];
}
}
}
} catch(err) {
// Invalid or no string info
}
// Load the module config data
try {
var config = JSON.parse(fs.readFileSync(moduleDir + 'config.json', 'utf-8'))
this.config[name] = config;
for(var i=0;i<config.dbKeys.length;i++) {
if(!this.db.hasOwnProperty(config.dbKeys[i])) {
this.db[config.dbKeys[i]] = {};
}
}
} catch(err) {
// Invalid or no config data
}
this.modules.push(module);
} catch(err) {
console.log(this.t('module_load_error', {'moduleName': name}));
console.log(err);
console.log('MODULE ERROR: ' + name + ' ' + err);
}
}.bind(this));
this.save();
};
DBot.prototype.cleanNick = function(key) {

View File

@ -1,9 +1,9 @@
{
"syntax_error": {
"english": "Invalid syntax. Initiate incineration.",
"spanish": "Sintaxis no válida. Iniciar incineración.",
"na'vi": "Ngeyä pamrel keyawr lu. Nga skxawng lu.",
"welsh": "Cystrawen annilys. Cychwyn orfflosgiad"
"correction": {
"english": "Did you mean: ",
"spanish": "¿Querías decir: ",
"na'vi": "Srake sweylu nga pamrel sivi: ",
"welsh": "A oeddech chi'n feddwl: "
},
"module_load_error": {
"english": "Failed to load module: {moduleName}",
@ -11,379 +11,6 @@
"na'vi": "Oeru Oel {moduleName}it sung.",
"welsh": "Wedi methu a llwytho modiwl: {moduleName}"
},
"category_not_found": {
"english": "Nobody loves {category}",
"spanish": "Nadie ama a {category}",
"na'vi": "{category} yawne ke lu kawturu.",
"welsh": "Does neb yn caru {category}"
},
"large_categories": {
"english": "Largest categories: ",
"spanish": "Los categorías más grandes: ",
"na'vi": "U atsawl: ",
"welsh": "Categoriau mwyaf: "
},
"empty_category": {
"english": "That category has no quotes in. Commence incineration.",
"spanish": "Categoría vacía. Iniciar incineración.",
"na'vi": "Tsauru upxare lu. Nga skxawng lu.",
"welsh": "Nid yw'r categori yna efo dyfyniadau. Cychwyn orfflosgiad"
},
"no_results": {
"english": "No results found.",
"spanish": "No hubo ningún resultado.",
"na'vi": "Oel kea humit rìmun",
"welsh": "Dim canlyniadau ar gael"
},
"locked_category": {
"english": "{category} is locked. Commence incineration.",
"spanish": "{category} está cerrada. Comenzar incineración.",
"na'vi": "{category} ke fkeytok set. Nga skxawng lu nafì'u",
"welsh": "Mae {category} wedi cloi. Cychwyn orfflosgiad"
},
"no_quotes": {
"english": "No quotes exist under {category}",
"spanish": "Ninguna cita existe en {category}",
"na'vi": "Kea upxare fkeytok {category}mì",
"welsh": "Does dim dyfyniadau gan {category}"
},
"last_removed": {
"english": "Last quote removed from {category}.",
"spanish": "Última cita quitado de {category}.",
"na'vi": "Oel 'upxareti aham 'aku {category}ta",
"welsh": "Dyfyniad olaf wedi ei ddileu o {category}"
},
"no_recent_adds": {
"english": "No quotes were added recently.",
"spanish": "Ninguna cita fue añadido recientamente.",
"na'vi": "Kea upxareti samung nìfkrr",
"welsh": "Nid oes unrhyw dyfyniadau wedi ei ychwwanegu'n ddiweddar"
},
"rmlast_spam": {
"english": "No spamming that shit. Try again in a few minutes...",
"spanish": "No me inundes de mierda. Intenta otra vez en unos minutos...",
"na'vi": "Nga Tsasngelit ke zene fpivere'. Sweylu nga fmivi ye'rìn...",
"welsh": "Peidiwch a sbamio hwna. Triwch eto mewn ychydyg funudau..."
},
"removed_from": {
"english": "'{quote}' removed from {category}",
"spanish": "'{quote}' quitado de {category}",
"na'vi": "'{quote}'(it/ti) 'ìyaku {category}",
"welsh": "'{quote}' wedi ei ddileu o {category}"
},
"q_not_exist_under": {
"english": "'{quote}' doesn't exist under '{category}'.",
"spanish": "'{quote}' no existe en '{category}'.",
"na'vi": "'{quote}' ke fkeytok '{category}'ta.",
"welsh": "Nid yw '{quote}' yn bodoli yn '{category}'"
},
"total_quotes": {
"english": "Total quote count: {count}.",
"spanish": "Total de citas: {count}.",
"na'vi": "'upxareri holpxay: {count}.",
"welsh": "Cyfanswm dyfyniadau: {count}."
},
"quote_exists": {
"english": "Quote already in DB. Initiate incineration.",
"spanish": "Cita ya existe. Iniciar incineración.",
"na'vi": "'Upxarel säomumit fìtsengit tok srekrr. Nga skxawng lu.",
"welsh": "Dyfyniad yn y gronfa ddata yn barod. Cychwyn orfflosgiad"
},
"quote_saved": {
"english": "Quote saved in '{category}' ({count}).",
"spanish": "Cita guardada en '{category}' ({count}).",
"na'vi": "Oe zayerok '{category}'mì ({count}).",
"welsh": "Dyfyniad wedi ei gadw yn '{category}' ({count})."
},
"quote_replace": {
"english": "No replacing arrays, you whore.",
"spanish": "No sustituites arrays, hijo de puta.",
"na'vi": "Ngal fìsäomumit ke tsun rivawn. Nga muntxa sayi suteo hrh.",
"welsh": "Peidiwch a newid rhestrau, y cachgi"
},
"quote_count": {
"english": "{category} has {count} quotes.",
"spanish": "{category} tiene {count} citas.",
"na'vi": "{count}a upxare {category}ur lu.",
"welsh": "{count} dyfyniad yn {category}"
},
"prune": {
"english": "Pruning empty quote categories: {categories}",
"spanish": "Reduciendo categorías vacías: {categories}",
"na'vi": "Oel seng amek 'eraku, seng: {categories}",
"welsh": "Tocio categoriau dyfyniadau gwag: {categories}"
},
"no_prune": {
"english": "No empty quote categories. Commence incineration.",
"spanish": "Ninguna categoría vacía. Comenzar incineracíon.",
"na'vi": "Kea seng amek. Nga skxawng lu.",
"welsh": "Dim categoriau dyfyniadau gwag. Cychwyn orfflosgiad"
},
"command_ban": {
"english": "{user} is banned from using this command. Commence incineration.",
"spanish": "{user} está prohibido de usar esta instrucción. Comenzar incineración.",
"na'vi": "Tsu'ori {user} ke tung. Nga skxawng lu.",
"welsh": "Mae {user} wedi ei gohurio gan ddefnyddio'r gorchymun yma. Cychwyn orfflosgiad"
},
"correction": {
"english": "Did you mean: ",
"spanish": "¿Querías decir: ",
"na'vi": "Srake sweylu nga pamrel sivi: ",
"welsh": "A oeddech chi'n feddwl: "
},
"gpull": {
"english": "Git pulled that shit.",
"spanish": "Hecho git pull en esta mierda.",
"na'vi": "Gìtìl fì'uti stamarsìm.",
"welsh": "Wedi tynnu git yr cach na i gyd"
},
"reload": {
"english": "Reloaded that shit.",
"spanish": "Recargado esta mierda.",
"na'vi": "Oel fìuti stìyeftxaw.",
"welsh": "Ail-lwytho'r cach na"
},
"load_module": {
"english": "Loaded new module: {moduleName}",
"spanish": "Cargado módulo nuevo: {moduleName}",
"na'vi": "Oel {moduleName}it amip stìyeftxaw.",
"welsh": "Wedi llwytho modiwl newydd: {moduleName}"
},
"unload_module": {
"english": "Turned off module: {moduleName}",
"spanish": "Descargado módulo: {moduleName}",
"na'vi": "Oel {moduleName} tswìya'.",
"welsh": "Wedi troi ffwrdd y modiwl: {moduleName}"
},
"unload_error": {
"english": "{moduleName} isn't loaded. Idiot.",
"spanish": "{moduleName} no está cargado. Idiota.",
"na'vi": "Oel {moduleName}it omum. Nga skxawng lu.",
"welsh": "Di {moduleName} ddim wedi llwytho. Twpsyn"
},
"banned": {
"english": "{user} banned from {command}",
"spanish": "{user} está prohibido de usar {command}",
"na'vi": "{command}ìri {user} ke tung.",
"welsh": "{user} wedi ei gohurio o {command}"
},
"unbanned": {
"english": "{user} unbanned from {command}",
"spanish": "{user} no está prohibido de user {command}",
"na'vi": "{command}ìri {user} tung set.",
"welsh": "{user} wedi ei dad-wahardd o {command}"
},
"unban_error": {
"english": "{user} wasn't banned from that command, fool.",
"spanish": "{user} no fue prohibido de esta instrucción, tont@.",
"na'vi": "{user} fìtsu'oti tamung srekrr, nga skxawng lu.",
"welsh": "Nid oedd {user} wedi ei wahardd o'r gyrchymun yna, fŵl"
},
"modehate": {
"english": "Hating on {user}",
"spanish": "Odiando a {user}",
"na'vi": "Oel {user}it vere'kì.",
"welsh": "Casau ar {user}"
},
"unmodehate": {
"english": "No longer hating on {user}",
"spanish": "Ni siquera odiando a {user}",
"na'vi": "Oel {user}it ke vere'kì.",
"welsh": "Ddim yn casau ar {user} bellach"
},
"qlock": {
"english": "Locked quote category: {category}",
"spanish": "Cerrado la categoría: {category}",
"na'vi": "{category}ìri oel 'upxareti fmoli",
"welsh": "Categori wedi cloi: {category}"
},
"spelling_self": {
"english": "{correcter} meant: {fix}",
"spanish": "{correcter} quería decir: {fix}",
"na'vi": "Sweylu {correcter} pamrel sivi: {fix}",
"welsh": "Oedd {correcter} yn feddwl: {fix}"
},
"spelling_other": {
"english": "{correcter} thinks {candidate} meant: {fix}",
"spanish": "{correcter} piensa que {candidate} queria decir: {fix}",
"na'vi": "{correcter} fpìl futa sweylu {candiate} pamrel sivi: {fix}",
"welsh": "Mae {correcter} yn meddwl bod {candidate} yn feddwl: {fix}"
},
"quote_link": {
"english": "Link to {category} - {url}",
"spanish": "Enlace a {category} - {url}",
"na'vi": "Fya'o {category}ne - {url}",
"welsh": "Dolen i {category} - {url}"
},
"shorten_link": {
"english": "Shortened link from {user}: ",
"spanish": "Enlace corto de {user}: ",
"na'vi": "Fya'o apup {user}ta: ",
"welsh": "Dolen wedi ei fyrhau can {user}: "
},
"ignore_usage": {
"english": "{user}: Usage: ~ignore [module]. Modules you can ignore are: {modules}.",
"spanish": "{user}: Modo de empleo: ~ignore [módulo]. Módulos que tú puedes ignorar son: {modules}.",
"na'vi": "{user}: Sar: ~ignore ['u]. U, nga ke tìng mikyun: {modules}.",
"welsh": "{user}: Defnydd: ~ignore [modiwl]. Modiwlau a allech anwybyddu yw: {modules}."
},
"already_ignoring": {
"english": "{user}: You're already ignoring that module.",
"spanish": "{user}: Ya ignoras este módulo.",
"na'vi": "{user}: 'uri nga ke tìng mikyun srekrr.",
"welsh": "{user}: Mi rwyt ti'n anwybyddu'r modiwl yna'n barod."
},
"ignored": {
"english": "{user}: Now ignoring {module}.",
"spanish": "{user}: Estás ignorando {module}.",
"na'vi": "{user}: Nga ke terìng mikyun {module}ne set.",
"welsh": "{user}: Nawr yn anwybyddu {module}"
},
"invalid_ignore": {
"english": "{user}: That isn't a valid module name.",
"spanish": "{user}: Ese no es un nombre de un módulo valido.",
"na'vi": "{user}: Tsatstxo eyawr ke lu.",
"welsh": "{user}: Nid oedd hwna'n modiwl dilys"
},
"unignore_usage": {
"english": "{user}: Usage: ~unignore [module]. Modules you are currently ignoring: {modules}.",
"spanish": "{user}: Modo de empleo: ~unignore [módulo]. Módulos que ignoras ahora mismo: {modules}.",
"na'vi": "{user}: Sar: ~unignore ['u]. Uri, nga ke terìng mikyun: {modules}.",
"welsh": "{user}: Defnydd ~unignore [modiwl]. Modiwlau rydech yn anwybyddu ar hyn o bryd: {modules}"
},
"invalid_unignore": {
"english": "{user}: You're not ignoring that module or it doesn't exist.",
"spanish": "{user}: No ignoras este módulo o no existe.",
"na'vi":"{user}: Nga terìng mikyun fu fì'ul fìtsengit ke tok.",
"welsh": "{user}: Nid wyt ti'n anwybyddu'r modiwl yna neu nid yw e'n bodoli"
},
"unignored": {
"english": "{user}: No longer ignoring {module}.",
"spanish": "{user}: Ya no ignoras {module}.",
"na'vi": "{user}: Nga terìng mikyun {module}ne set",
"welsh": "{user}: Ddim yn anwybyddu {module} bellach"
},
"command_typo": {
"english": "Did you mean '{command}'? Learn to type.",
"spanish": "¿Querías decir '{command}'? Aprende escribir.",
"na'vi": "Sweylu nga pamrel sivi '{command}' srak? Sweylu ngeyä pamrel livu eyawr.",
"welsh": "A oeddech chi'n feddwl '{command}'? Dysgwch sut i teipio."
},
"user_kicks": {
"english": "{user} has been kicked {kicks} times and has kicked people {kicked} times.",
"spanish": "Se ha expulsado {user} {kicks} veces y {user} ha expulsado personas {kicked} veces.",
"na'vi": "Tuteol {user}it tsrame'i {kicks} hìmtxan ulte sute tsrame'i {kicked} hìmtxan.",
"welsh": "Cafwyd {user} ei gicio {kicks} gwaith ac wedi cicio pobl {kicked} gwaith."
},
"kicked_dbot": {
"english": "Thou shalt not kick {botname}",
"spanish": "No expulsás {botname}",
"na'vi": "Ngal {botname}it ke tsun tsrive'i",
"welsh": "Ni ddylech cicio {botname}"
},
"search_results": {
"english": "{category} ({needle}): '{quote}' [{matches} results]",
"spanish" : "{category} ({needle}): '{quote}' [{matches} resultados]",
"na'vi": "{category} ({needle}): '{quote}' [kum a{matches}]",
"welsh": "{category} ({needle}): '{quote}' [{matches} canlyniad]"
},
"join": {
"english": "Joined {channel}",
"spanish" : "Entrado en {channel}",
"na'vi": "fpxäkìm {channel}(nemfa)",
"welsh": "Wedi ymuno {channel}"
},
"part": {
"english": "Left {channel}",
"spanish" : "Abandonada {channel}",
"na'vi": "Hum {channel}",
"welsh": "Wedi gadael {channel}"
},
"newpoll_usage": {
"english": "Usage: ~newpoll name [options=opt1,opt2,opt3] description",
"spanish" : "Modo de empleo: ~newpoll nombre [options=opción1,opción2,opción3] descripción",
"na'vi": "Usage: ~newpoll tstxo [sìftxey=tìfxey1,tìfxey2,fìfxey3] tìsla'tsu",
"welsh": "Defnydd: ~newpoll enw [optiynau=opt1,opt2,op3] disgrifiad"
},
"poll_exists": {
"english": "Poll '{name}' already exists.",
"spanish" : "Votación '{name}' ya existe.",
"na'vi": "sìpawm sna'o '{name}' fkeytok srekrr.",
"welsh": "Mae'r pôl {name} bodoli'n barod"
},
"poll_created": {
"english": "Poll '{name}' created ({description}). Cast thy votations! - {url}",
"spanish" : "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}"
},
"poll_describe": {
"english": "{name}: {description} - {url}"
},
"changed_vote": {
"english": "{user} changed their vote in {poll} to '{vote}' ({count}).",
"spanish" : "{user} cambió su voto en {poll} a '{vote}' ({count}).",
"na'vi": "{user} lìyatem ngeyä tìpe'un {poll}mì, ngeyä tìpe'un amip '{vote}'({count}) lu.",
"welsh": "Newidiodd {user} eu pleidlais yn {poll} i '{vote}' ({count})."
},
"voted": {
"english": "{user} voted for '{vote}' in {poll} ({count}).",
"spanish" : "{user} votó para '{vote}' en {poll} ({count}).",
"na'vi": "'{vote}'ìri {user} pìye'un {poll}mì ({count}).",
"welsh": "Pledleisiodd {user} am '{vote}' yn {poll} ({count})."
},
"invalid_vote": {
"english": "Invalid vote: {vote}",
"spanish" : "Vota inválida: {vote}",
"na'vi": "Ngeyä tìpe'un keyawr lu ({vote}).",
"welsh": "Pleidlais annilys: {vote}"
},
"poll_unexistent": {
"english": "Poll '{name}' doesn't exist.",
"spanish" : "Votación '{name}' no existe.",
"na'vi": "sìpawm sna'o '{name}' ke fkeytok.",
"welsh": "Nid yw pôl '{name}' yn bodoli"
},
"option_added": {
"english": "{user}: '{option}' added to '{name}'.",
"spanish" : "{user}: '{option}' añadido a '{name}'.",
"na'vi": "'{name}'ur {user}ìl '{option}'it sung.",
"welsh": "{user}: Ychwanegwyd '{option}' i '{name}'"
},
"option_exists": {
"english": "{user}: '{option}' already exists in '{name}'.",
"spanish" : "{user}: '{option}' ya existe en '{name}'.",
"na'vi": "{user}: '{option}' fkeytok srekrr '{name}'mì.",
"welsh": "{user}: Mae '{option}' yn bodoli'n barod yn '{name}'."
},
"not_poll_owner": {
"english": "{user}: You don't own the '{name}' poll.",
"spanish" : "{user}: La votación '{name}' no es tuyo.",
"na'vi": "{user}: ngaru '{name}' sìpawm sna'o ke lu.",
"welsh": "{user}: Nid ydech chi'n berchen y pôl '{name}'."
},
"option_removed": {
"english": "{user}: '{option}' removed from '{name}'",
"spanish" : "{user}: '{option}' eliminado de '{name}'",
"na'vi": "{user}: '{option}'it 'aku '{name}'ta",
"welsh": "{user}: '{option}' wedi ei ddileu o '{name}'"
},
"av_voted": {
"english": "{user} voted '{vote}' in {poll}.",
"spanish": "{user} votó '{vote}' en {poll}.",
"na'vi": "{user}ìl '{vote}'it pìye'un '{poll}'mì.",
"welsh": "Pledleisiodd {user} am '{vote}' yn {poll}"
},
"av_changed_vote": {
"english": "{user} changed their vote in {poll} to '{vote}'.",
"spanish" : "{user} cambió su voto en {poll} a '{vote}'.",
"na'vi": "{user}ìl lìyatem ngeyä tìpa'unit '{poll}'mì, ngeyä tìpe'un '{vote} lu set.",
"welsh": "Newidiodd {user} eu pleidlais yn {poll} i '{vote}'"
},
"count": {
"english": "The running-order of poll '{poll}' ({description}) is: {places}.",
"na'vi": "Sute tsnì pole'un '{poll}'mì ({description}) lu: {places}.",
"welsh": "Trefn yr pôl '{poll}' ({description}) yw: {places}"
},
"url": {
"english": "http://{host}:{port}/{path}"
}