diff --git a/.gitignore b/.gitignore index 1a7610d..a49c313 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Ignore the user config files -config.json +./config.json # Ignore the user database db.json diff --git a/config.json.sample b/config.json.sample index d665e9c..31c11f6 100644 --- a/config.json.sample +++ b/config.json.sample @@ -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" } diff --git a/modules/admin.js b/modules/admin/admin.js similarity index 90% rename from modules/admin.js rename to modules/admin/admin.js index 173e270..d51474b 100644 --- a/modules/admin.js +++ b/modules/admin/admin.js @@ -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(); } diff --git a/modules/admin/config.json b/modules/admin/config.json new file mode 100644 index 0000000..e1a07bb --- /dev/null +++ b/modules/admin/config.json @@ -0,0 +1,3 @@ +{ + "dbKeys": [ "bans", "locks" ] +} diff --git a/modules/admin/strings.json b/modules/admin/strings.json new file mode 100644 index 0000000..8ecacd0 --- /dev/null +++ b/modules/admin/strings.json @@ -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}" + } +} diff --git a/modules/autoshorten.js b/modules/autoshorten.js deleted file mode 100644 index 7199ec8..0000000 --- a/modules/autoshorten.js +++ /dev/null @@ -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); -}; diff --git a/modules/command.js b/modules/command/command.js similarity index 89% rename from modules/command.js rename to modules/command/command.js index ea3043d..6342da2 100644 --- a/modules/command.js +++ b/modules/command/command.js @@ -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')); } diff --git a/modules/command/strings.json b/modules/command/strings.json new file mode 100644 index 0000000..47e1b11 --- /dev/null +++ b/modules/command/strings.json @@ -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" + } +} diff --git a/modules/dice.js b/modules/dice/dice.js similarity index 100% rename from modules/dice.js rename to modules/dice/dice.js diff --git a/modules/drama.js b/modules/drama.js deleted file mode 100644 index fc9aa3a..0000000 --- a/modules/drama.js +++ /dev/null @@ -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); -}; diff --git a/modules/ignore/config.json b/modules/ignore/config.json new file mode 100644 index 0000000..7a4c116 --- /dev/null +++ b/modules/ignore/config.json @@ -0,0 +1,3 @@ +{ + "dbKeys": [ "ignores" ] +} diff --git a/modules/ignore.js b/modules/ignore/ignore.js similarity index 100% rename from modules/ignore.js rename to modules/ignore/ignore.js diff --git a/modules/ignore/strings.json b/modules/ignore/strings.json new file mode 100644 index 0000000..e926a7a --- /dev/null +++ b/modules/ignore/strings.json @@ -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" + } +} diff --git a/modules/js.js b/modules/js/js.js similarity index 89% rename from modules/js.js rename to modules/js/js.js index 3ac75e4..76d5f91 100644 --- a/modules/js.js +++ b/modules/js/js.js @@ -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', diff --git a/modules/js/usage.json b/modules/js/usage.json new file mode 100644 index 0000000..6e5b47e --- /dev/null +++ b/modules/js/usage.json @@ -0,0 +1,4 @@ +{ + "~js": "~js [command]", + "~ajs": "~ajs [command]" +} diff --git a/modules/kick/config.json b/modules/kick/config.json new file mode 100644 index 0000000..10e1e76 --- /dev/null +++ b/modules/kick/config.json @@ -0,0 +1,3 @@ +{ + "dbKeys": [ "kicks", "kickers" ] +} diff --git a/modules/kick.js b/modules/kick/kick.js similarity index 95% rename from modules/kick.js rename to modules/kick/kick.js index 540f9b7..150fb55 100644 --- a/modules/kick.js +++ b/modules/kick/kick.js @@ -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; diff --git a/modules/kick/strings.json b/modules/kick/strings.json new file mode 100644 index 0000000..0fe8376 --- /dev/null +++ b/modules/kick/strings.json @@ -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}" + } +} diff --git a/modules/link.js b/modules/link/link.js similarity index 100% rename from modules/link.js rename to modules/link/link.js diff --git a/modules/poll.js b/modules/poll/poll.js similarity index 94% rename from modules/poll.js rename to modules/poll/poll.js index 2b82282..8c79a02 100644 --- a/modules/poll.js +++ b/modules/poll/poll.js @@ -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})); } @@ -214,13 +216,7 @@ var poll = function(dbot) { commands['~vote'].regex = [/~vote ([^ ]+) ([^ ]+)/, 3]; 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, diff --git a/modules/poll/strings.json b/modules/poll/strings.json new file mode 100644 index 0000000..459ea98 --- /dev/null +++ b/modules/poll/strings.json @@ -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}" + } +} diff --git a/modules/poll/usage.json b/modules/poll/usage.json new file mode 100644 index 0000000..1be3414 --- /dev/null +++ b/modules/poll/usage.json @@ -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]" +} diff --git a/modules/puns.js b/modules/puns/puns.js similarity index 90% rename from modules/puns.js rename to modules/puns/puns.js index 7144932..187a652 100644 --- a/modules/puns.js +++ b/modules/puns/puns.js @@ -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'; diff --git a/modules/quotes/config.json b/modules/quotes/config.json new file mode 100644 index 0000000..32c3324 --- /dev/null +++ b/modules/quotes/config.json @@ -0,0 +1,3 @@ +{ + "dbKeys": [ "quoteArrs" ] +} diff --git a/modules/quotes.js b/modules/quotes/quotes.js similarity index 88% rename from modules/quotes.js rename to modules/quotes/quotes.js index bb00730..abcc073 100644 --- a/modules/quotes.js +++ b/modules/quotes/quotes.js @@ -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') { diff --git a/modules/quotes/strings.json b/modules/quotes/strings.json new file mode 100644 index 0000000..c013ac3 --- /dev/null +++ b/modules/quotes/strings.json @@ -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]" + } +} diff --git a/modules/quotes/usage.json b/modules/quotes/usage.json new file mode 100644 index 0000000..083c727 --- /dev/null +++ b/modules/quotes/usage.json @@ -0,0 +1,7 @@ +{ + "~q": "~q [category]", + "~qsearch": "~qsearch [category]=[search]", + "~rm": "~rm [category]=[quote to delete]", + "~rmlast": "~rmlast [category]", + "~qadd": "~qadd [category]=[content]" +} diff --git a/modules/report.js b/modules/report/report.js similarity index 95% rename from modules/report.js rename to modules/report/report.js index f3f4c2f..1e6f03d 100644 --- a/modules/report.js +++ b/modules/report/report.js @@ -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', diff --git a/modules/report/usage.json b/modules/report/usage.json new file mode 100644 index 0000000..f0003eb --- /dev/null +++ b/modules/report/usage.json @@ -0,0 +1,3 @@ +{ + "~report": "~report [#channel] [username] [reason for reporting]" +} diff --git a/modules/spelling.js b/modules/spelling/spelling.js similarity index 100% rename from modules/spelling.js rename to modules/spelling/spelling.js diff --git a/modules/spelling/strings.json b/modules/spelling/strings.json new file mode 100644 index 0000000..057786e --- /dev/null +++ b/modules/spelling/strings.json @@ -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}" + } +} diff --git a/modules/web/config.json b/modules/web/config.json new file mode 100644 index 0000000..981e0f7 --- /dev/null +++ b/modules/web/config.json @@ -0,0 +1,4 @@ +{ + "webHost": "localhost", + "webPort": 8080 +} diff --git a/modules/web.js b/modules/web/web.js similarity index 67% rename from modules/web.js rename to modules/web/web.js index 1be542a..9f01c8d 100644 --- a/modules/web.js +++ b/modules/web/web.js @@ -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', diff --git a/modules/youare.js b/modules/youare/youare.js similarity index 100% rename from modules/youare.js rename to modules/youare/youare.js diff --git a/run.js b/run.js index fca7978..8a1087d 100644 --- a/run.js +++ b/run.js @@ -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); + + 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(); } - // 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 = {}; - } - // 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