diff --git a/modules/admin.js b/modules/admin.js index d20a488..36e3c1e 100644 --- a/modules/admin.js +++ b/modules/admin.js @@ -25,7 +25,7 @@ var adminCommands = function(dbot) { child = exec("git pull", function (error, stdout, stderr) { console.log(stderr); - dbot.say(data.channel, dbot.strings[dbot.language].gpull); + dbot.say(data.channel, dbot.t('gpull')); commands.reload(data, params); }.bind(this)); }, @@ -34,7 +34,7 @@ var adminCommands = function(dbot) { dbot.db = JSON.parse(fs.readFileSync('db.json', 'utf-8')); dbot.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8')); dbot.reloadModules(); - dbot.say(data.channel, dbot.strings[dbot.language].reload); + dbot.say(data.channel, dbot.t('reload')); }, 'say': function(data, params) { @@ -60,7 +60,7 @@ var adminCommands = function(dbot) { 'load': function(data, params) { dbot.moduleNames.push(params[1]); dbot.reloadModules(); - dbot.say(data.channel, dbot.strings[dbot.language].load_module.format({'moduleName': params[1]})); + dbot.say(data.channel, dbot.t('load_module', {'moduleName': params[1]})); }, 'unload': function(data, params) { @@ -72,9 +72,9 @@ var adminCommands = function(dbot) { dbot.moduleNames.splice(moduleIndex, 1); dbot.reloadModules(); - dbot.say(data.channel, dbot.strings[dbot.language].unload_module.format({'moduleName': params[1]})); + dbot.say(data.channel, dbot.t('unload_module', {'moduleName': params[1]})); } else { - dbot.say(data.channel, dbot.strings[dbot.language].unload_error.format({'moduleName': params[1]})); + dbot.say(data.channel, dbot.t('unload_error', {'moduleName': params[1]})); } }, @@ -84,31 +84,31 @@ var adminCommands = function(dbot) { } else { dbot.db.bans[params[2]] = [ params[1] ]; } - dbot.say(data.channel, dbot.strings[dbot.language].banned.format({'user': params[1], 'command': params[2]})); + dbot.say(data.channel, dbot.t('banned', {'user': params[1], 'command': params[2]})); }, 'unban': function(data, params) { if(dbot.db.bans.hasOwnProperty(params[2]) && dbot.db.bans[params[2]].include(params[1])) { dbot.db.bans[params[2]].splice(dbot.db.bans[params[2]].indexOf(params[1]), 1); - dbot.say(data.channel, dbot.strings[dbot.language].unbanned.format({'user': params[1], 'command': params[2]})); + dbot.say(data.channel, dbot.t('unbanned', {'user': params[1], 'command': params[2]})); } else { - dbot.say(data.channel, dbot.strings[dbot.language].unban_error.format({'user': params[1]})); + dbot.say(data.channel, dbot.t('unban_error', {'user': params[1]})); } }, 'modehate': function(data, params) { dbot.db.modehate.push(params[1]); - dbot.say(data.channel, dbot.strings[dbot.language].modehate.format({'user': params[1]})); + dbot.say(data.channel, dbot.t('modehate', {'user': params[1]})); }, 'unmodehate': function(data, params) { dbot.db.modehate.splice(dbot.db.modehate.indexOf(params[1]), 1); - dbot.say(data.channel, dbot.strings[dbot.language].unmodehate.format({'user': params[1]})); + dbot.say(data.channel, dbot.t('unmodehate', {'user': params[1]})); }, 'lock': function(data, params) { dbot.db.locks.push(params[1]); - dbot.say(data.channel, dbot.strings[dbot.language].qlock.format({'category': params[1]})); + dbot.say(data.channel, dbot.t('qlock', {'category': params[1]})); } }; @@ -134,7 +134,11 @@ var adminCommands = function(dbot) { } }, - 'on': 'PRIVMSG' + 'on': 'PRIVMSG', + + 'name': 'admin', + + 'ignorable': false }; }; diff --git a/modules/autoshorten.js b/modules/autoshorten.js new file mode 100644 index 0000000..ff4fc90 --- /dev/null +++ b/modules/autoshorten.js @@ -0,0 +1,44 @@ +var http = require('http'); + +var autoshorten = function(dbot) { + var name = 'autoshorten'; + var dbot = dbot; + + return { + 'listener': function(data) { + if((dbot.db.ignores.hasOwnProperty(data.user) && + dbot.db.ignores[data.user].include(name)) == false) { + var urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; + var urlMatches = data.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': 'nc.no.de', + 'port': 80, + 'path': '/mkurl?url=' + escape(url) + }; + + http.get(options, function(res) { + res.setEncoding('utf8'); + res.on('data', function (response) { + dbot.say(data.channel, dbot.t('shorten_link', {'user': data.user}) + JSON.parse(response).surl); + }); + }); + } + } + }, + + 'on': 'PRIVMSG', + + 'name': name, + + 'ignorable': true + }; +} + +exports.fetch = function(dbot) { + return autoshorten(dbot); +}; diff --git a/modules/badwords.js b/modules/badwords.js new file mode 100644 index 0000000..d53dab0 --- /dev/null +++ b/modules/badwords.js @@ -0,0 +1,56 @@ +// Find which badwords are currently enacted in the current channel +var badwords = function(dbot) { + var name = 'badwords'; + var dbot = dbot; + var badWordLock = false; + + var commands = { + '~badwords': function(data, params) { + if(badWordLock == true) { + dbot.say('reality', 'Another badwords query is in action. Try again in a few seconds.'); + } else { + data.channel = '#42'; + badWordLock = true; + + dbot.sessionData.badwords.waiting = true; + + dbot.say('bots', 'badwords ' + data.channel + ' list'); + dbot.instance.addListener('PRIVMSG', + dbot.sessionData.badwords = {}; + badWordLock = false; + } + } + }; + + return { + 'onLoad': function() { + if(!dbot.sessionData.hasOwnProperty('badwords')) { + dbot.sessionData.badwords = {}; + } + + return commands; + }, + + 'listener': function(data) { + if(data.channel === 'bots') { + if(data.message.indexOf('bad words list is empty') != -1) { + dbot.sessionData.badwords.count = 0; + dbot.sessionData.badwords.finished = true; + } else { + var wordMatch = data.message.valMatch(/\w([1-10])\w(.*)/, 2); + dbot.say('reality', wordMatch[1]); + } + } + }, + + 'on': 'PRIVMSG', + + 'name': name, + + 'ignorable': true + }; +}; + +exports.fetch = function(dbot) { + return badwords(dbot); +}; diff --git a/modules/command.js b/modules/command.js index 6f7f289..1da6b65 100644 --- a/modules/command.js +++ b/modules/command.js @@ -3,70 +3,88 @@ var command = function(dbot) { var dbot = dbot; - var ignoreCommands = function (data, params) { - if(data.channel == dbot.name) data.channel = data.user; - var targetCommand = params[1]; - var ignoreMins = parseFloat(params[2]); - - if(!dbot.sessionData.hasOwnProperty("ignoreCommands")) { - dbot.sessionData.ignoreCommands = {}; - } - if(!dbot.sessionData.ignoreCommands.hasOwnProperty(targetCommand)) { - dbot.sessionData.ignoreCommands[targetCommand] = []; - } - - if(dbot.sessionData.ignoreCommands[targetCommand].include(data.channel)) { - dbot.say(data.channel, "Already ignoring '" + targetCommand + "' in '" + data.channel + "'."); - } else { - dbot.sessionData.ignoreCommands[targetCommand].push(data.channel); - dbot.timers.addOnceTimer(ignoreMins * 60 * 1000, function() { - dbot.sessionData.ignoreCommands[targetCommand].splice(dbot.sessionData.ignoreCommands[targetCommand].indexOf(data.channel), 1); - dbot.say(data.channel, "No longer ignoring '" + targetCommand + "' in '" + data.channel + "'."); - }); - dbot.say(data.channel, "Ignoring '" + targetCommand + "' in '" + data.channel + "' for the next " + ignoreMins + " minute" + (ignoreMins == 1 ? "" : "s") + "."); - } - }; - return { 'onLoad': function() { return { - '~ignore': ignoreCommands + '~ignore': function(data, params) { + var ignorableModules = []; + for(var i=0;i 0) { - dbot.say(data.channel, dbot.strings[dbot.language].prune.format({'categories': pruned.join(", ")})); + dbot.say(data.channel, dbot.t('prune', {'categories': pruned.join(", ")})); } else { - dbot.say(data.channel, dbot.strings[dbot.language].no_prune); + dbot.say(data.channel, dbot.t('no_prune')); } } }; @@ -276,30 +278,37 @@ var quotes = function(dbot) { // For automatic quote retrieval 'listener': function(data, params) { - if(data.user == 'reality') { - var once = data.message.valMatch(/^I ([\d\w\s,'-]* once)/, 2); - } else { - var once = data.message.valMatch(/^reality ([\d\w\s,'-]* once)/, 2); - } - - if(once) { - if((dbot.db.bans.hasOwnProperty('~qadd') && - dbot.db.bans['~qadd'].include(data.user)) || - dbot.db.bans['*'].include(data.user)) { - dbot.say(data.channel, data.user + ' is banned from using this command. Commence incineration.'); + if((dbot.db.ignores.hasOwnProperty(data.user) && + dbot.db.ignores[data.user].include(name)) == false) { + if(data.user == 'reality') { + var once = data.message.valMatch(/^I ([\d\w\s,'-]* once)/, 2); } else { - if(!dbot.db.quoteArrs.hasOwnProperty('realityonce')) { - dbot.db.quoteArrs['realityonce'] = []; + var once = data.message.valMatch(/^reality ([\d\w\s,'-]* once)/, 2); + } + + if(once) { + if((dbot.db.bans.hasOwnProperty('~qadd') && + dbot.db.bans['~qadd'].include(data.user)) || + dbot.db.bans['*'].include(data.user)) { + dbot.say(data.channel, dbot.t('command_ban', {'user': data.user})); + } else { + if(!dbot.db.quoteArrs.hasOwnProperty('realityonce')) { + dbot.db.quoteArrs['realityonce'] = []; + } + dbot.db.quoteArrs['realityonce'].push('reality ' + once[1] + '.'); + addStack.push('realityonce'); + rmAllowed = true; + dbot.instance.say(data.channel, '\'reality ' + once[1] + '.\' saved.'); } - dbot.db.quoteArrs['realityonce'].push('reality ' + once[1] + '.'); - addStack.push('realityonce'); - rmAllowed = true; - dbot.instance.say(data.channel, '\'reality ' + once[1] + '.\' saved.'); } } }, - 'on': 'PRIVMSG' + 'on': 'PRIVMSG', + + 'name': name, + + 'ignorable': true }; }; diff --git a/modules/spelling.js b/modules/spelling.js index a50ed9a..37f3d51 100644 --- a/modules/spelling.js +++ b/modules/spelling.js @@ -1,4 +1,5 @@ var spelling = function(dbot) { + var name = 'spelling'; var dbot = dbot; var last = {}; @@ -38,27 +39,34 @@ var spelling = function(dbot) { return { 'listener': function(data, params) { - var q = data.message.valMatch(/^(?:\*\*?([\d\w\s']*)|([\d\w\s']*)\*\*?)$/, 3); - var otherQ = data.message.valMatch(/^([\d\w\s]*): (?:\*\*?([\d\w\s']*)|([\d\w\s']*)\*\*?)$/, 4); - if(q) { - correct(data, q[1] || q[2], data.user, function (e) { - dbot.say(data.channel, dbot.strings[dbot.language].spelling_self.format(e)); - }); - } else if(otherQ) { - correct(data, otherQ[2] || otherQ[3], otherQ[1], function (e) { - dbot.say(data.channel, dbot.strings[dbot.language].spelling_other.format(e)); - }); - } else { - if(last.hasOwnProperty(data.channel)) { - last[data.channel][data.user] = data.message; + if((dbot.db.ignores.hasOwnProperty(data.user) && + dbot.db.ignores[data.user].include(name)) == false) { + var q = data.message.valMatch(/^(?:\*\*?([\d\w\s']*)|([\d\w\s']*)\*\*?)$/, 3); + var otherQ = data.message.valMatch(/^([\d\w\s]*): (?:\*\*?([\d\w\s']*)|([\d\w\s']*)\*\*?)$/, 4); + if(q) { + correct(data, q[1] || q[2], data.user, function (e) { + dbot.say(data.channel, dbot.t('spelling_self', e)); + }); + } else if(otherQ) { + correct(data, otherQ[2] || otherQ[3], otherQ[1], function (e) { + dbot.say(data.channel, dbot.t('spelling_other', e)); + }); } else { - last[data.channel] = { }; - last[data.channel][data.user] = data.message; + if(last.hasOwnProperty(data.channel)) { + last[data.channel][data.user] = data.message; + } else { + last[data.channel] = { }; + last[data.channel][data.user] = data.message; + } } } }, - 'on': 'PRIVMSG' + 'on': 'PRIVMSG', + + 'name': name, + + 'ignorable': true } } diff --git a/modules/web.js b/modules/web.js index e3ac0fa..c11c516 100644 --- a/modules/web.js +++ b/modules/web.js @@ -42,7 +42,11 @@ var webInterface = function(dbot) { return { 'onDestroy': function() { app.close(); - } + }, + + 'name': 'web', + + 'ignorable': false }; }; diff --git a/modules/youare.js b/modules/youare.js index 062305a..2321a39 100644 --- a/modules/youare.js +++ b/modules/youare.js @@ -1,14 +1,23 @@ var youAre = function(dbot) { + var name = 'youare'; + return { 'listener': function(data) { - var key = data.message.valMatch(/(\bis\b|\bare\b)\s+([\w\s\d]*?)(\s+)?(,|\.|\band\b|$)/, 5); + if((dbot.db.ignores.hasOwnProperty(data.user) && + dbot.db.ignores[data.user].include(name)) == false) { + var key = data.message.valMatch(/(\bis\b|\bare\b)\s+([\w\s\d]*?)(\s+)?(,|\.|\band\b|$)/, 5); - if(key && key[2] != "" && Number.prototype.chanceIn(1, 100) && data.user != 'aisbot') { - dbot.say(data.channel, data.user + ': You\'re ' + key[2] + '.'); + if(key && key[2] != "" && Number.prototype.chanceIn(1, 100) && data.user != 'aisbot') { + dbot.say(data.channel, data.user + ': You\'re ' + key[2] + '.'); + } } }, - 'on': 'PRIVMSG' + 'on': 'PRIVMSG', + + 'name': name, + + 'ignorable': false }; }; diff --git a/run.js b/run.js index 33b6e9a..76935bb 100644 --- a/run.js +++ b/run.js @@ -39,6 +39,9 @@ var DBot = function(timers) { if(!this.db.hasOwnProperty("locks")) { this.db.locks = []; } + if(!this.db.hasOwnProperty("ignores")) { + this.db.ignores = {}; + } // Load the strings file this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8')); @@ -51,8 +54,8 @@ var DBot = function(timers) { this.server = this.config.server || 'elara.ivixor.net'; this.port = this.config.port || 6667; this.webPort = this.config.webPort || 443; - this.moduleNames = this.config.modules || [ 'command', 'js', 'admin', 'kick', 'modehate', 'quotes', 'puns', 'spelling', 'web', 'youare' ]; - this.language = this.config.language || 'en_GB'; + this.moduleNames = this.config.modules || [ 'command', 'js', 'admin', 'kick', 'modehate', 'quotes', 'puns', 'spelling', 'web', 'youare', 'autoshorten' ]; + this.language = this.config.language || 'english'; this.sessionData = {}; this.timers = timers.create(); @@ -75,6 +78,16 @@ DBot.prototype.say = function(channel, data) { this.instance.say(channel, data); }; +// 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"; + } + + return this.strings[string][lang].format(formatData); +}; + DBot.prototype.act = function(channel, data) { this.instance.send('PRIVMSG', channel, ':\001ACTION ' + data + '\001'); } @@ -97,6 +110,7 @@ DBot.prototype.reloadModules = function() { this.rawModules = []; this.modules = []; this.commands = {}; + this.commandMap = {}; // Map of which commands belong to which modules this.timers.clearTimers(); this.save(); @@ -111,35 +125,36 @@ DBot.prototype.reloadModules = function() { delete require.cache[path]; require('./snippets'); + this.instance.removeListeners(); + this.moduleNames.each(function(name) { var cacheKey = require.resolve('./modules/' + name); delete require.cache[cacheKey]; + try { - this.rawModules.push(require('./modules/' + name)); - } catch(err) { - console.log(this.strings[this.language].module_load_error.format({'moduleName': name})); - } - }.bind(this)); + var rawModule = require('./modules/' + name); + var module = rawModule.fetch(this); + this.rawModules.push(rawModule); - this.instance.removeListeners(); + if(module.listener) { + this.instance.addListener(module.on, module.listener); + } - this.modules = this.rawModules.collect(function(rawModule) { - var module = rawModule.fetch(this); - - if(module.listener) { - this.instance.addListener(module.on, module.listener); - } - - if(module.onLoad) { - var newCommands = module.onLoad(); - for(key in newCommands) { - if(newCommands.hasOwnProperty(key) && Object.prototype.isFunction(newCommands[key])) { - this.commands[key] = newCommands[key]; + if(module.onLoad) { + var newCommands = module.onLoad(); + for(key in newCommands) { + if(newCommands.hasOwnProperty(key) && Object.prototype.isFunction(newCommands[key])) { + this.commands[key] = newCommands[key]; + this.commandMap[key] = name; + } } } - } - return module; + this.modules.push(module); + } catch(err) { + console.log(this.strings[this.language].module_load_error.format({'moduleName': name})); + console.log(err); + } }.bind(this)); }; diff --git a/strings.json b/strings.json index 33564ee..84c63a0 100644 --- a/strings.json +++ b/strings.json @@ -1,74 +1,177 @@ { - "en_GB": { - "syntax_error": "Invalid syntax. Initiate incineration.", - "module_load_error": "Failed to load module: {moduleName}", - "category_not_found": "Nobody loves {category}", - "large_categories": "Largest categories: ", - "empty_category": "That category has no quotes in. Commence incineration.", - "no_results": "No results found.", - "locked_category": "{category} is locked. Commence incineration.", - "no_quotes": "No quotes exist under {category}", - "last_removed": "Last quote removed from {category}.", - "no_recent_adds": "No quotes were added recently.", - "rmlast_spam": "No spamming that shit. Try again in a few minutes...", - "removed_from": "'{quote}' removed from {category}", - "q_not_exist_under": "'{quote}' doesn't exist under '{category}'.", - "total_quotes": "Total quote count: {count}.", - "quote_exists": "Quote already in DB. Initiate incineration.", - "quote_saved": "Quote saved in '{category}' ({count}).", - "quote_replace": "No replacing arrays, you whore.", - "prune": "Pruning empty quote categories: {categories}", - "no_prune": "No empty quote categories. Commence incineration.", - "command_ban": " is banned from using this command. Commence incineration.", - "correction": "Did you mean: ", - "gpull": "Git pulled that shit.", - "reload": "Reloaded that shit.", - "load_module": "Loaded new module: {moduleName}", - "unload_module": "Turned off module: {moduleName}", - "unload_error": "{moduleName} isn't loaded. Idiot.", - "banned": "{user} banned from {command}", - "unbanned": "{user} unbanned from {command}", - "unban_error": "{user} wasn't banned from that command, fool.", - "modehate": "Hating on {user}", - "unmodehate": "No longer hating on {user}", - "qlock": "Locked quote category: {category}", - "spelling_self": "{correcter} meant: {fix}", - "spelling_other": "{correcter} thinks {candidate} meant: {fix}" + "syntax_error": { + "english": "Invalid syntax. Initiate incineration.", + "spanish": "Sintaxis no válida. Iniciar incineración." }, - "es": { - "syntax_error": "Sintaxis no válida. Iniciar incineración.", - "module_load_error": "No se pudó cargar el módulo: {moduleName}", - "category_not_found": "Nadie ama a {category}", - "large_categories": "Los categorías más grandes: ", - "empty_category": "Categoría vacía. Iniciar incineración.", - "no_results": "No hubo ningún resultado.", - "locked_category": "{category} está cerrada. Comenzar incineración.", - "no_quotes": "Ninguna cita existe en {category}", - "last_removed": "Última cita quitado de {category}.", - "no_recent_adds": "Ninguna cita fue añadido recientamente.", - "rmlast_spam": "No me inundes de mierda. Intenta otra vez en unos minutos.", - "removed_from": "'{quote}' quitado de {category}", - "q_not_exist_under": "'{quote}' no existe en '{category}'.", - "total_quotes": "Total de citas: {count}.", - "quote_exists": "Cita ya existe. Iniciar incineración.", - "quote_saved": "Cita guardada en '{category}' ({count})", - "quote_replace": "No sustituites arrays, hijo de puta.", - "prune": "Reduciendo categorías vacías {categories}", - "no_prune": "Ninguna categoría vacía. Comenzar incineracíon", - "command_ban": " está prohibido de usar esta instrucción. Comenzar incineración.", - "correction": "¿Querías decir: ", - "gpull": "Hecho git pull en esta mierda.", - "reload": "Recargado esta mierda.", - "load_module": "Cargado módulo nuevo: {moduleName}", - "unload_module": "Descargado modulo: {moduleName}", - "unload_error": "{moduleName} no está cargado. Idiota.", - "banned": "{user} está prohibido de usar {command}", - "unbanned": "{user} no está prohibido de user {command}", - "unban_error": "{user} no fue prohibido de esta instrucción, tont@..", - "modehate": "Odiando a {user}", - "unmodehate": "Ni siquera odiando a {user}", - "qlock": "Cerrado la categoría: {category}", - "spelling_self": "{correcter} quería decir: {fix}", - "spelling_other": "{correcter} piensa que {candidate} queria decir: {fix}" + "module_load_error": { + "english": "Failed to load module: {moduleName}", + "spanish": "No se pudó cargar el módulo: {moduleName}" + }, + "category_not_found": { + "english": "Nobody loves {category}", + "spanish": "Nadie ama a {category}" + }, + "large_categories": { + "english": "Largest categories: ", + "spanish": "Los categorías más grandes: " + }, + "empty_category": { + "english": "That category has no quotes in. Commence incineration.", + "spanish": "Categoría vacía. Iniciar incineración." + }, + "no_results": { + "english": "No results found.", + "spanish": "No hubo ningún resultado." + }, + "locked_category": { + "english": "{category} is locked. Commence incineration.", + "spanish": "{category} está cerrada. Comenzar incineración." + }, + "no_quotes": { + "english": "No quotes exist under {category}", + "spanish": "Ninguna cita existe en {category}" + }, + "last_removed": { + "english": "Last quote removed from {category}.", + "spanish": "Última cita quitado de {category}." + }, + "no_recent_adds": { + "english": "No quotes were added recently.", + "spanish": "Ninguna cita fue añadido recientamente." + }, + "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." + }, + "removed_from": { + "english": "'{quote}' removed from {category}", + "spanish": "'{quote}' quitado de {category}" + }, + "q_not_exist_under": { + "english": "'{quote}' doesn't exist under '{category}'.", + "spanish": "'{quote}' no existe en '{category}'." + }, + "total_quotes": { + "english": "Total quote count: {count}.", + "spanish": "Total de citas: {count}." + }, + "quote_exists": { + "english": "Quote already in DB. Initiate incineration.", + "spanish": "Cita ya existe. Iniciar incineración." + }, + "quote_saved": { + "english": "Quote saved in '{category}' ({count}).", + "spanish": "Cita guardada en '{category}' ({count})" + }, + "quote_replace": { + "english": "No replacing arrays, you whore.", + "spanish": "No sustituites arrays, hijo de puta." + }, + "quote_count": { + "english": "{category} has {count} quotes." + }, + "prune": { + "english": "Pruning empty quote categories: {categories}", + "spanish": "Reduciendo categorías vacías {categories}" + }, + "no_prune": { + "english": "No empty quote categories. Commence incineration.", + "spanish": "Ninguna categoría vacía. Comenzar incineracíon" + }, + "command_ban": { + "english": "{user} is banned from using this command. Commence incineration.", + "spanish": "{user} está prohibido de usar esta instrucción. Comenzar incineración." + }, + "correction": { + "english": "Did you mean: ", + "spanish": "¿Querías decir: " + }, + "gpull": { + "english": "Git pulled that shit.", + "spanish": "Hecho git pull en esta mierda." + }, + "reload": { + "english": "Reloaded that shit.", + "spanish": "Recargado esta mierda." + }, + "load_module": { + "english": "Loaded new module: {moduleName}", + "spanish": "Cargado módulo nuevo: {moduleName}" + }, + "unload_module": { + "english": "Turned off module: {moduleName}", + "spanish": "Descargado modulo: {moduleName}" + }, + "unload_error": { + "english": "{moduleName} isn't loaded. Idiot.", + "spanish": "{moduleName} no está cargado. Idiota." + }, + "banned": { + "english": "{user} banned from {command}", + "spanish": "{user} está prohibido de usar {command}" + }, + "unbanned": { + "english": "{user} unbanned from {command}", + "spanish": "{user} no está prohibido de user {command}" + }, + "unban_error": { + "english": "{user} wasn't banned from that command, fool.", + "spanish": "{user} no fue prohibido de esta instrucción, tont.." + }, + "modehate": { + "english": "Hating on {user}", + "spanish": "Odiando a {user}" + }, + "unmodehate": { + "english": "No longer hating on {user}", + "spanish": "Ni siquera odiando a {user}" + }, + "qlock": { + "english": "Locked quote category: {category}", + "spanish": "Cerrado la categoría: {category}" + }, + "spelling_self": { + "english": "{correcter} meant: {fix}", + "spanish": "{correcter} quería decir: {fix}" + }, + "spelling_other": { + "english": "{correcter} thinks {candidate} meant: {fix}", + "spanish": "{correcter} piensa que {candidate} queria decir: {fix}" + }, + "quote_link": { + "english": "Link to {category}" + }, + "shorten_link": { + "english": "Shortened link from {user}: " + }, + "ignore_usage": { + "english": "{user}: Usage: ~ignore [module]. Modules you can ignore are: {modules}." + }, + "already_ignoring": { + "english": "{user}: You're already ignoring that module." + }, + "ignored": { + "english": "{user}: Now ignoring {module}." + }, + "invalid_ignore": { + "english": "{user}: That isn't a valid module name." + }, + "unignore_usage": { + "english": "{user}: Usage: ~unignore [module]. Modules you are currently ignoring: {modules}." + }, + "invalid_unignore": { + "english": "{user}: You're not ignoring that module or it doesn't exist." + }, + "unignored": { + "english": "{user}: No longer ignoring {module}." + }, + "command_typo": { + "english": "Did you mean '{command}'? Learn to type." + }, + "user_kicks": { + "english": "{user} has been kicked {kicks} times and has kicked people {kicked} times." + }, + "kicked_dbot": { + "english": "Thou shalt not kick {botname}" } }