From b288487f239f0787a30b868431feffab227d8df4 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 12 Feb 2013 19:15:32 +0000 Subject: [PATCH 001/220] Provisional framework for database module using databank multiplexing. [#272] --- database.js | 28 ++++++++++++++++++++++++++++ run.js | 28 ++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 database.js diff --git a/database.js b/database.js new file mode 100644 index 0000000..4f191ea --- /dev/null +++ b/database.js @@ -0,0 +1,28 @@ +var databank = require('databank'), + Databank = databank.Databank, + DatabankObject = databank.DatabankObject; + //DatabankStore = require('connect-databank')(express); + +/** + * Multiplex databank objects + */ +var DatabaseDriver = function() { + this.databanks = {}; +}; + +/** + * Connect to or create a new DataBank + */ +DatabaseDriver.prototype.createDB = function(name, driver, callback, schema) { + var params = { 'schema': schema }; + this.databanks[name] = Databank.get(driver, params); + this.databanks[name].connect({}, function(err) { + if(err) { + console.log('Didn\'t manage to connect to the data source.'); + } else { + callback(this.databanks[name]); + } + }.bind(this)); +}; + +exports.DatabaseDriver = DatabaseDriver; diff --git a/run.js b/run.js index 48ad4d5..a5296ad 100644 --- a/run.js +++ b/run.js @@ -1,6 +1,7 @@ var fs = require('fs'), _ = require('underscore')._, - jsbot = require('./jsbot/jsbot'); + jsbot = require('./jsbot/jsbot'), + DatabaseDriver = require('./database').DatabaseDriver; require('./snippets'); var DBot = function() { @@ -22,6 +23,9 @@ var DBot = function() { this.db.config = {}; } + /*** Load the fancy DB ***/ + this.ddb = new DatabaseDriver(); + /*** Load the Config ***/ if(!fs.existsSync('config.json')) { @@ -198,15 +202,23 @@ DBot.prototype.reloadModules = function() { } }, this); } - - // Generate missing DB keys this.config[name] = config; - _.each(config.dbKeys, function(dbKey) { - if(!_.has(this.db, dbKey)) { - this.db[dbKey] = {}; - } - }, this); + // Groovy funky database shit + if(!_.has(config, 'dbType') || config.dbType == 'olde') { + // Generate missing DB keys + _.each(config.dbKeys, function(dbKey) { + if(!_.has(this.db, dbKey)) { + this.db[dbKey] = {}; + } + }, this); + } else { + // Just use the name of the module for now, add dbKey iteration later + this.ddb.createDB(name, config.dbType, function(db) { + module.db = db; + }.bind(this), {}); + } + // Load the module itself var rawModule = require(moduleDir + name); var module = rawModule.fetch(this); From 07f8a129d5b84f33703e075d4d545ffa04ad470b Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 16 Feb 2013 17:37:23 +0000 Subject: [PATCH 002/220] provisional poll thing. only commiting so i can switch branch w/e [#272] --- database.js | 6 +++-- modules/poll/commands.js | 49 +++++++++++++++++++++------------------- modules/poll/config.json | 9 +++++++- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/database.js b/database.js index 4f191ea..15f0e8d 100644 --- a/database.js +++ b/database.js @@ -1,7 +1,6 @@ var databank = require('databank'), Databank = databank.Databank, DatabankObject = databank.DatabankObject; - //DatabankStore = require('connect-databank')(express); /** * Multiplex databank objects @@ -15,10 +14,13 @@ var DatabaseDriver = function() { */ DatabaseDriver.prototype.createDB = function(name, driver, callback, schema) { var params = { 'schema': schema }; + + if(driver == 'disk') params.dir = 'db'; + this.databanks[name] = Databank.get(driver, params); this.databanks[name].connect({}, function(err) { if(err) { - console.log('Didn\'t manage to connect to the data source.'); + console.log('Didn\'t manage to connect to the data source - ' + err); } else { callback(this.databanks[name]); } diff --git a/modules/poll/commands.js b/modules/poll/commands.js index ac36252..dca7c60 100644 --- a/modules/poll/commands.js +++ b/modules/poll/commands.js @@ -7,30 +7,33 @@ var commands = function(dbot) { var name = event.input[1].toLowerCase(), options = event.input[2].toLowerCase().split(','), description = event.input[3]; - - if(_.has(polls, name)) { - event.reply(dbot.t('poll_exists', { 'name': name })); - } else { - polls[name] = { - 'name': name, - 'description': description, - 'owner': dbot.api.users.resolveUser(event.server, event.user), - 'votes': {}, - 'votees': {} - }; - for(var i=0;i Date: Fri, 15 Mar 2013 23:12:21 +0000 Subject: [PATCH 003/220] update stats or something idk --- modules/stats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/stats b/modules/stats index e296082..eee5861 160000 --- a/modules/stats +++ b/modules/stats @@ -1 +1 @@ -Subproject commit e2960823d8c82c0ff5f0a360c9acfacc024fb85a +Subproject commit eee5861dca00f0d2b2f146820870abb888ed8f4a From 54e3b84902aae5ae019913258b32606633f65423 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 16 Mar 2013 00:02:35 +0000 Subject: [PATCH 004/220] Poll module now functional using databank. What of it? [#272] --- modules/poll/commands.js | 232 +++++++++++++++++++++------------------ 1 file changed, 127 insertions(+), 105 deletions(-) diff --git a/modules/poll/commands.js b/modules/poll/commands.js index dca7c60..155d9f6 100644 --- a/modules/poll/commands.js +++ b/modules/poll/commands.js @@ -1,4 +1,7 @@ -var _ = require('underscore')._; +var _ = require('underscore')._, + databank = require('databank'), + AlreadyExistsError = databank.AlreadyExistsError; + NoSuchThingError = databank.NoSuchThingError; var commands = function(dbot) { var polls = dbot.db.polls; @@ -13,7 +16,7 @@ var commands = function(dbot) { votes[options[i]] = 0; } - this.db.create(poll, name, { + this.db.create('poll', name, { 'description': description, 'owner': dbot.api.users.resolveUser(event.server, event.user), 'votes': votes, @@ -25,8 +28,8 @@ var commands = function(dbot) { 'name': name, 'description': description, 'url': dbot.t('url', { - 'host': dbot.config.web.webHost, - 'port': dbot.config.web.webPort, + 'host': 'test.com', + 'port': 80, 'path': 'polls/' + name }) })); @@ -41,31 +44,37 @@ var commands = function(dbot) { option = event.input[2].toLowerCase(), user = dbot.api.users.resolveUser(event.server, event.user); - if(_.has(polls, name)) { - if(polls[name].owner === user) { - if(!_.has(polls[name].votes, option)) { - polls[name]['votes'][option] = 0; - event.reply(dbot.t('option_added', { - 'user': event.user, - 'name': name, - 'option': option - })); + this.db.read('poll', name, function(err, poll) { + if(!err) { + if(poll.owner === user) { + if(!_.has(poll.votes, option)) { + poll.votes[option] = 0; + this.db.save('poll', name, poll, function(err) { + event.reply(dbot.t('option_added', { + 'user': event.user, + 'name': name, + 'option': option + })); + }.bind(this)); + } else { + event.reply(dbot.t('option_exists', { + 'option': option, + 'name': name, + 'user': event.user + })); + } } else { - event.reply(dbot.t('option_exists', { - 'option': option, - 'name': name, - 'user': event.user + event.reply(dbot.t('not_poll_owner', { + 'user': event.user, + 'name': name })); } } else { - event.reply(dbot.t('not_poll_owner', { - 'user': event.user, - 'name': name - })); + if(err instanceof NoSuchThingError) { + event.reply(dbot.t('poll_unexistent', { 'name': name })); + } } - } else { - event.reply(dbot.t('poll_unexistent', {'name': name})); - } + }.bind(this)); }, '~rmoption': function(event) { @@ -73,24 +82,31 @@ var commands = function(dbot) { option = event.input[2].toLowerCase(), user = dbot.api.users.resolveUser(event.server, event.user); - if(_.has(polls, name)) { - if(polls[name].owner === user) { - if(_.has(polls[name].votes, option)) { - delete polls[name]['votes'][option]; - event.reply(dbot.t('option_removed', { - 'user': event.user, - 'name': name, - 'option': option - })); + this.db.read('poll', name, function(err, poll) { + if(!err) { + if(poll.owner === user) { + if(_.has(poll.votes, option)) { + delete poll.votes[option]; + + this.db.save('poll', name, poll, function(err) { + event.reply(dbot.t('option_removed', { + 'user': event.user, + 'name': name, + 'option': option + })); + }.bind(this)); + } else { + event.reply(dbot.t('invalid_vote', { 'vote': option })); + } } else { - event.reply(dbot.t('invalid_vote', { 'vote': option })); + event.reply(dbot.t('not_poll_owner', { 'name': name })); } } else { - event.reply(dbot.t('not_poll_owner', { 'name': name })); + if(err instanceof NoSuchThingError) { + event.reply(dbot.t('poll_unexistent', { 'name': name })); + } } - } else { - event.reply(dbot.t('poll_unexistent', { 'name': name })); - } + }.bind(this)); }, '~vote': function(event) { @@ -98,91 +114,97 @@ var commands = function(dbot) { vote = event.input[2].toLowerCase(), user = dbot.api.users.resolveUser(event.server, event.user); - if(_.has(polls, name)) { - if(_.has(polls[name].votes, vote)) { - if(_.has(polls[name].votees, user)) { - var oldVote = polls[name].votees[user]; - polls[name].votes[oldVote]--; - polls[name].votes[vote]++; - polls[name].votees[user] = vote; + this.db.read('poll', name, function(err, poll) { + if(!err) { + if(_.has(poll.votes, vote)) { + if(_.has(poll.votees, user)) { + var oldVote = poll.votees[user]; + poll.votes[oldVote]--; + poll.votes[vote]++; + poll.votees[user] = vote; + } else { + poll.votes[vote]++; + poll.votees[user] = vote; + } - event.reply(dbot.t('changed_vote', { - 'vote': vote, - 'poll': name, - 'count': polls[name].votes[vote], - 'user': event.user - })); + this.db.save('poll', name, poll, function(err) { + event.reply(dbot.t('voted', { + 'vote': vote, + 'poll': name, + 'count': poll.votes[vote], + 'user': event.user + })); + }.bind(this)); } else { - polls[name].votes[vote]++; - polls[name].votees[user] = vote; - event.reply(dbot.t('voted', { - 'vote': vote, - 'poll': name, - 'count': polls[name].votes[vote], - 'user': event.user - })); + event.reply(dbot.t('invalid_vote', { 'vote': vote })); } } else { - event.reply(dbot.t('invalid_vote', { 'vote': vote })); + if(err instanceof NoSuchThingError) { + event.reply(dbot.t('poll_unexistent', { 'name': name })); + } } - } else { - event.reply(dbot.t('poll_unexistent', { 'name': name })); - } + }.bind(this)); }, '~pdesc': function(event) { var name = event.input[1].toLowerCase(); + this.db.read('poll', name, function(err, poll) { + if(!err) { + var options = _.keys(poll.votes); + var optionString = " Choices: "; + for(var i=0;i Date: Sat, 16 Mar 2013 13:45:58 +0000 Subject: [PATCH 005/220] Started working on transforming quotes. Need more input from evan and that before continuing I think. [#272] --- modules/poll/commands.js | 2 +- modules/quotes/commands.js | 109 ++++++++++++++++++++----------------- 2 files changed, 59 insertions(+), 52 deletions(-) diff --git a/modules/poll/commands.js b/modules/poll/commands.js index 155d9f6..276cc94 100644 --- a/modules/poll/commands.js +++ b/modules/poll/commands.js @@ -1,6 +1,6 @@ var _ = require('underscore')._, databank = require('databank'), - AlreadyExistsError = databank.AlreadyExistsError; + AlreadyExistsError = databank.AlreadyExistsError, NoSuchThingError = databank.NoSuchThingError; var commands = function(dbot) { diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index dbcbe73..90951cb 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -1,4 +1,7 @@ -var _ = require('underscore')._; +var _ = require('underscore')._, + databank = require('databank'), + AlreadyExistsError = databank.AlreadyExistsError, + NoSuchThingError = databank.NoSuchThingError; var commands = function(dbot) { var quotes = dbot.db.quoteArrs; @@ -41,20 +44,22 @@ var commands = function(dbot) { { 'count': rmCacheCount })); }, - // Retrieve quote from a category in the database. - '~q': function(event) { - var key = event.input[1].trim().toLowerCase(); - var quote = this.api.getQuote(event, event.input[1]); - if(quote) { - event.reply(key + ': ' + quote); - } else { - event.reply(dbot.t('category_not_found', {'category': key})); - } + '~q': function(event) { + var name = event.input[1].trim().toLowerCase(); + this.db.read('quote_category', name, function(err, category) { + if(!err) { + var quoteIndex = _.random(0, category.length - 1); + event.reply(key + ': ' + category[quoteIndex]); + } else if(err instanceof AlreadyExistsError) { + event.reply(dbot.t('category_not_found', { 'category': name })); + } + }); }, // Shows a list of the biggest categories '~qstats': function(event) { + this.db.readAll('quote_category) var qSizes = _.chain(quotes) .pairs() .sortBy(function(category) { return category[1].length }) @@ -122,23 +127,22 @@ var commands = function(dbot) { var key = event.input[1].trim().toLowerCase(); var quote = event.input[2]; - if(_.has(quotes, key)) { - var category = quotes[key]; - var index = category.indexOf(quote); - if(index !== -1) { - category.splice(index, 1); - if(category.length === 0) { - delete quotes[key]; - } + this.db.remove('quote_category', key, quote, function(err) { + if(!err) { this.internalAPI.resetRemoveTimer(event, key, quote); - - event.reply(dbot.t('removed_from', {'category': key, 'quote': quote})); - } else { - event.reply(dbot.t('q_not_exist_under', {'category': key, 'quote': quote})); + event.reply(dbot.t('removed_from', { + 'category': key, + 'quote': quote + })); + } else if(err instanceof NoSuchThingError) { + event.reply(dbot.t('category_not_found', { 'category': key })); + } else if(err instanceof NoSuchItemError) { + event.reply(dbot.t('q_not_exist_under', { + 'category': key, + 'quote': quote + })); } - } else { - event.reply(dbot.t('category_not_found', {'category': key})); - } + }.bind(this)); } else { event.reply(dbot.t('rmlast_spam')); } @@ -148,15 +152,17 @@ var commands = function(dbot) { var input = event.message.valMatch(/^~qcount ([\d\w\s-]*)/, 2); if(input) { // Give quote count for named category var key = input[1].trim().toLowerCase(); - if(_.has(quotes, key)) { - event.reply(dbot.t('quote_count', { - 'category': key, - 'count': quotes[key].length - })); - } else { - event.reply(dbot.t('no_quotes', { 'category': key })); - } - } else { // Give total quote count + this.db.get('quote_category', key, function(err, category) { + if(!err) { + event.reply(dbot.t('quote_count', { + 'category': key, + 'count': category.length + })); + } else if(err instanceof AlreadyExistsError) { + event.reply(dbot.t('category_not_found', { 'category': name })); + } + }.bind(this)); + } else { // TODO: databankise total quote count var totalQuoteCount = _.reduce(quotes, function(memo, category) { return memo + category.length; }, 0); @@ -166,24 +172,25 @@ var commands = function(dbot) { '~qadd': function(event) { var key = event.input[1].toLowerCase(); - var text = event.input[2]; - if(!_.isArray(quotes[key])) { - quotes[key] = []; - } + var quote = event.input[2]; - if(_.include(quotes[key], text)) { - event.reply(dbot.t('quote_exists')); - } else { - quotes[key].push(text); - this.rmAllowed = true; - event.reply(dbot.t('quote_saved', { - 'category': key, - 'count': quotes[key].length - })); - - return { 'key': key, 'text': text }; - } - return false; + this.db.indexOf('quote_category', key, text, function(err, index) { + if(index == -1) { + this.db.append('quote_category', key, quote, function(err) { + this.rmAllowed = true; + dbot.api.event.emit('~qadd', { + 'key': key, + 'text': text + }); + event.reply(dbot.t('quote_saved', { + 'category': key, + 'count': 0 // TODO: Figure out a way to get the count in the shim + })); + }.bind(this)); + } else { + event.reply(dbot.t('quote_exists')); + } + }.bind(this)); }, '~rq': function(event) { From 7bcb136e266711f1d5adfd05239f5f72c5e9dce4 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 22 Mar 2013 11:44:27 +0000 Subject: [PATCH 006/220] some initial work on users api over to databank [#272] --- modules/users/api.js | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/modules/users/api.js b/modules/users/api.js index 19c62a6..4d13814 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -7,9 +7,21 @@ var api = function(dbot) { var api = { 'resolveUser': function(server, nick, useLowerCase) { - var knownUsers = this.getServerUsers(server); var user = nick; + if(this.api.isPrimaryUser(nick)) { + return user; + } else { + this.db.search('user', { 'server': server }, function(user) { + if(_.include(user.aliases, nick)) user = user.primaryNick; + }.bind(this), function(err) { + if(err instanceof NotImplementedError) { + // QQ + } + }); + return user; + } + /** TODO: Re-add lowercase support if(!useLowerCase) { if(!_.include(knownUsers.users, nick) && _.has(knownUsers.aliases, nick)) { user = knownUsers.aliases[nick]; @@ -34,9 +46,11 @@ var api = function(dbot) { } } return user; + **/ }, 'getRandomChannelUser': function(server, channel) { + this.db.get('channel_users', { '' }) var channelUsers = this.getServerUsers(server).channelUsers[channel]; if(!_.isUndefined(channelUsers)) { return channelUsers[_.random(0, channelUsers.length - 1)]; @@ -46,7 +60,16 @@ var api = function(dbot) { }, 'getServerUsers': function(server) { - return dbot.db.knownUsers[server].users; + var users = []; + this.db.search('user', { 'server': server }, function(user) { + users.push(user.primaryNick); + }.bind(this), function(err) { + if(err instanceof NotImplementedError) { + // QQ + } + }); + + return users; }, 'getAllUsers': function() { From 71c0bdb760a971490930c48a5c66c31765ba27be Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 23 Mar 2013 13:24:13 +0000 Subject: [PATCH 007/220] all commands but ~qstats and ~rq in quotes use databank [#272] --- modules/quotes/commands.js | 230 +++++++++++++++++++++---------------- 1 file changed, 130 insertions(+), 100 deletions(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index 90951cb..c1abaee 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -6,11 +6,30 @@ var _ = require('underscore')._, var commands = function(dbot) { var quotes = dbot.db.quoteArrs; var commands = { - // Alternative syntax to ~q + + /*** Quote Retrieval ***/ + + // Alternative ~q syntax '~': function(event) { commands['~q'].bind(this)(event); }, + // Retrieve quote from a category in the database. + '~q': function(event) { + var name = event.input[1].trim().toLowerCase(); + this.db.read('quote_category', name, function(err, category) { + if(!err) { + var quoteIndex = _.random(0, category.length - 1); + event.reply(name + ': ' + category[quoteIndex]); + } else if(err instanceof NoSuchThingError) { + event.reply(dbot.t('category_not_found', { 'category': name })); + } + }); + }, + + /*** Quote Removal ***/ + + // Show number of quotes in removal cache '~rmstatus': function(event) { var rmCacheCount = this.rmCache.length; if(rmCacheCount < dbot.config.quotes.rmLimit) { @@ -22,6 +41,7 @@ var commands = function(dbot) { } }, + // Confirm removal of quote cache '~rmconfirm': function(event) { var rmCacheCount = this.rmCache.length; this.rmCache.length = 0; @@ -29,99 +49,46 @@ var commands = function(dbot) { { 'count': rmCacheCount })); }, + // Reinstate all quotes in removal cache '~rmdeny': function(event) { var rmCache = this.rmCache; var rmCacheCount = rmCache.length; - for(var i=0;i Date: Sun, 24 Mar 2013 11:34:52 +0000 Subject: [PATCH 008/220] Changed users API to databank [#272] Behavioural changes: * API functions no longer return values, callbacks must be submitted. These will be documented soon. * resolveUser now returns the user record instead of just a resolved username. This means many less search operations. * resolveUser now returns false instead of the original nick passed to it in the case of being unable to find a user. * getServerUsers has been removed, as it is now unnecessary. --- modules/users/api.js | 75 +++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/modules/users/api.js b/modules/users/api.js index 635f748..7e8434f 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -11,19 +11,18 @@ var api = function(dbot) { }; var api = { + // Return a user record given a primary nick or an alias 'resolveUser': function(server, nick, callback) { - if(this.api.isPrimaryUser(nick)) { - callback(nick); - } else { - var user = false; - this.db.search('user', { 'server': server }, function(user) { - if(_.include(user.aliases, nick)) user = user.primaryNick; - }, function(err) { - if(!err) { - callback(user); - } - }); - } + var user = false; + this.db.search('user', { 'server': server }, function(result) { + if(result.primaryNick == nick || _.include(result.aliases, nick)) { + user = result; + } + }, function(err) { + if(!err) { + callback(user); + } + }); }, 'getRandomChannelUser': function(server, channel, callback) { @@ -36,7 +35,10 @@ var api = function(dbot) { }, function(err) { if(!err) { if(!_.isUndefined(channel.users)) { - callback(channel.users[_.random(0, channel.users.length - 1)]); + var randomUser = channel.users[_.random(0, channel.users.length - 1)]; + this.api.resolveUser(server, randomUser, function(user) { + callback(user); + }); } else { callback(false); } @@ -44,17 +46,6 @@ var api = function(dbot) { }); }, - 'getServerUsers': function(server, callback) { - var users = []; - this.db.search('users', { 'server': server }, function(user) { - users.push(user); - }, function(err) { - if(!err) { - callback(users); - } - }); - }, - 'getAllUsers': function(callback) { var users = []; this.db.scan('users', function(user) { @@ -102,29 +93,27 @@ var api = function(dbot) { }); }, - 'isOnline': function(server, user, channel, callback) { - var user = this.api.resolveUser(server, user, useLowerCase); - var possiNicks = [user].concat(this.api.getAliases(server, user)); + 'isOnline': function(server, nick, channel, callback) { + this.api.resolveUser(server, nick, function(user) { + var possiNicks = [user].concat(user.aliases); - if(!_.has(dbot.instance.connections[server].channels, channel)) return false; - var onlineNicks = dbot.instance.connections[server].channels[channel].nicks; + if(_.has(dbot.instance.connections[server].channels, channel)) { + var onlineNicks = dbot.instance.connections[server].channels[channel].nicks; + var isOnline = _.any(onlineNicks, function(nick) { + nick = nick.name; + return _.include(possiNicks, nick); + }, this); - var isOnline = _.any(onlineNicks, function(nick) { - nick = nick.name; - return _.include(possiNicks, nick); - }, this); - - callback(isOnline); + callback(isOnline); + } + }); }, - 'isChannelUser': function(server, user, channel) { - var knownUsers = this.getServerUsers(server); - var user = this.api.resolveUser(server, user, useLowerCase); - - if(!_.has(knownUsers.channelUsers, channel)) { - return false; - } - return _.include(knownUsers.channelUsers[channel], user); + 'isChannelUser': function(server, nick, channel, callback) { + this.api.resolveUser(server, nick, function(user) { + var isChannelUser = _.include(user.channels, channel); + callback(isChannelUser); + }); } }; From aa6a5fce42294fa1a8846fe2b7748d3c803b99fd Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 24 Mar 2013 12:26:33 +0000 Subject: [PATCH 009/220] databankise users listener, add getChannel to users api [#272] --- modules/users/api.js | 14 ++++++++ modules/users/users.js | 75 ++++++++++++++++++++++++------------------ 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/modules/users/api.js b/modules/users/api.js index 7e8434f..7d6c30d 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -25,6 +25,20 @@ var api = function(dbot) { }); }, + 'getChannel': function(server, channel, callback) { + var channel = false; + this.db.search('channel_users', { + 'server': server, + 'name': channel + }, function(result) { + channel = result; + }, function(err) { + if(!err) { + callback(channel); + } + }); + }, + 'getRandomChannelUser': function(server, channel, callback) { var channel; this.db.search('channel_users', { diff --git a/modules/users/users.js b/modules/users/users.js index 5e713de..6e38ad6 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -6,16 +6,6 @@ var _ = require('underscore')._; var users = function(dbot) { this.knownUsers = dbot.db.knownUsers; - this.getServerUsers = function(server) { - var knownUsers = this.knownUsers; - if(!_.has(knownUsers, server)) { - knownUsers[server] = { 'users': [], 'aliases': {}, 'channelUsers': {} }; - } - if(!_.has(knownUsers[server], 'channelUsers')) { - knownUsers[server].channelUsers = {}; - } - return knownUsers[server]; - }; this.updateAliases = function(event, oldUser, newUser) { var knownUsers = this.getServerUsers(event.server); @@ -35,32 +25,53 @@ var users = function(dbot) { }; this.listener = function(event) { - /*var knownUsers = this.getServerUsers(event.server); - var nick = event.user; - if(event.action == 'JOIN' && nick != dbot.config.name) { - if(!_.has(knownUsers.channelUsers, event.channel.name)) { - knownUsers.channelUsers[event.channel.name] = []; - } - var channelUsers = knownUsers.channelUsers[event.channel.name]; - - if(this.api.isKnownUser(event.server, nick)) { - nick = this.api.resolveUser(event.server, nick); - } else { - knownUsers.users.push(nick); - dbot.api.event.emit('new_user', [ event.server, nick ]); - } - - if(!_.include(channelUsers, nick)) { - channelUsers.push(nick); + this.api.resolveUser(event.server, event.user, function(user) { + if(!user) { // User does not yet exist + var id = uuid.v4(); + this.db.create('users', id, { + 'uuid': id, + 'primaryNick': event.user, + 'currentNick': event.user, + 'server': event.server, + 'channels': [ event.channel ], + 'aliases': [] + }, function(err, result) { + if(!err) { + user = result; + dbot.api.event.emit('new_user', [ user ]); + } + }); + } + + if(!_.include(user.channels, event.channel)) { // User not yet channel user + user.channels.push(event.channel); + this.db.save('users', user.id, user, function(err) { + if(!err) { + this.api.getChannel(event.server, event.channel, function(channel) { + channel.users.push(user.primaryNick); + this.db.save('channel_users', channel.id, channel, function(err)) { + if(!err) { + dbot.api.event.emit('new_channel_user', [ user ]); + } + }); + } + } + }); + } } } else if(event.action == 'NICK') { - var newNick = event.newNick; - if(!this.api.isKnownUser(newNick)) { - knownUsers.aliases[newNick] = this.api.resolveUser(event.server, event.user); - dbot.api.event.emit('nick_change', [ event.server, newNick ]); + if(!this.api.isKnownUser(event.newNick)) { + this.api.resolveUser(event.server, event.user, function(user) { + user.aliases.push(event.newNick); + this.db.save('users', user.id, function(err) { + if(!err) { + dbot.api.event.emit('new_user_alias', [ user, event.newNick ]); + } + }); + }); } - }*/ + } }.bind(this); this.on = ['JOIN', 'NICK']; From edcbe501e8495bae151886d88d4165e82eac8060 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 24 Mar 2013 12:54:19 +0000 Subject: [PATCH 010/220] users onLoad and nick/join listener now databankised [#272] --- modules/users/users.js | 125 ++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index 6e38ad6..e83dd6b 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -23,41 +23,53 @@ var users = function(dbot) { channelUsers[channelName].push(newUser); }, this); }; - + + this.internalAPI = { + 'createUser': function(server, nick, channel, callback) { + var id = uuid.v4(); + this.db.create('users', id, { + 'uuid': id, + 'primaryNick': nick, + 'currentNick': nick, + 'server': server, + 'channels': [ channel ], + 'aliases': [] + }, function(err, result) { + if(!err) { + dbot.api.event.emit('new_user', [ user ]); + callback(result); + } + }); + }, + + 'addChannelUser': function(user, channelName) { + user.channels.push(channelName); + this.db.save('users', user.id, user, function(err) { + if(!err) { + this.api.getChannel(user.server, channelName, function(channel) { + channel.users.push(user.primaryNick); + this.db.save('channel_users', channel.id, channel, function(err) { + if(!err) { + dbot.api.event.emit('new_channel_user', [ user, channel]); + } + }); + }); + } + }); + } + }; + this.listener = function(event) { if(event.action == 'JOIN' && nick != dbot.config.name) { this.api.resolveUser(event.server, event.user, function(user) { if(!user) { // User does not yet exist - var id = uuid.v4(); - this.db.create('users', id, { - 'uuid': id, - 'primaryNick': event.user, - 'currentNick': event.user, - 'server': event.server, - 'channels': [ event.channel ], - 'aliases': [] - }, function(err, result) { - if(!err) { - user = result; - dbot.api.event.emit('new_user', [ user ]); - } + this.internalAPI.createUser(event.server, event.user, event.channel, function(result) { + user = result; }); } if(!_.include(user.channels, event.channel)) { // User not yet channel user - user.channels.push(event.channel); - this.db.save('users', user.id, user, function(err) { - if(!err) { - this.api.getChannel(event.server, event.channel, function(channel) { - channel.users.push(user.primaryNick); - this.db.save('channel_users', channel.id, channel, function(err)) { - if(!err) { - dbot.api.event.emit('new_channel_user', [ user ]); - } - }); - } - } - }); + this.internalAPI.addChannelUser(user, event.channel); } } } else if(event.action == 'NICK') { @@ -74,34 +86,45 @@ var users = function(dbot) { } }.bind(this); this.on = ['JOIN', 'NICK']; - + this.onLoad = function() { - /* Trigger updateNickLists to stat current users in channel dbot.instance.addListener('366', 'users', function(event) { - var knownUsers = this.getServerUsers(event.server); - if(!_.has(knownUsers.channelUsers, event.channel.name)) { - knownUsers.channelUsers[event.channel.name] = []; - } - var channelUsers = knownUsers.channelUsers[event.channel.name]; - - _.each(event.channel.nicks, function(nick) { - nick = nick.name; - if(this.api.isKnownUser(event.server, nick)) { - nick = this.api.resolveUser(event.server, nick); - } else { - knownUsers.users.push(nick); - dbot.api.event.emit('new_user', [ event.server, nick ]); + this.api.getChannel(event.server, event.channel, function(channel) { + if(!channel) { // Channel does not yet exist + var id = uuid.v4(); + this.db.create('channel_users', id, { + 'uuid': id, + 'server': event.server, + 'name': event.channel, + 'users': [] + }, function(err, result) { + if(!err) { + channel = result; + dbot.api.event.emit('new_channel', [ channel ]); + } + }); } - if(!_.include(channelUsers, nick)) { - channelUsers.push(nick); - } - }, this); - }.bind(this)); - var connections = dbot.instance.connections; - _.each(connections, function(connection) { - connection.updateNickLists(); - });*/ + _.each(event.channel.nicks, function(nick) { + this.api.resolveUser(event.server, nick, function(user) { + if(!user) { + this.internalAPI.createUser(event.server, nick, event.channel, function(result) { + user = result; + }); + } + + if(!_.include(user.channels, event.channel)) { + this.internalAPI.addChannelUser(user, event.channel); + } + }); + }, this); + }); + + var connections = dbot.instance.connections; + _.each(connections, function(connection) { + connection.updateNickLists(); + }); + }); }; }; From ef9f5f26461d50cbf2123989b6683cd4c9e1b559 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 24 Mar 2013 15:57:42 +0000 Subject: [PATCH 011/220] update js --- jsbot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsbot b/jsbot index ba70bf1..217d7c8 160000 --- a/jsbot +++ b/jsbot @@ -1 +1 @@ -Subproject commit ba70bf1b9d8d7459dbcfa05a39b47de63a024494 +Subproject commit 217d7c8f865e9097b06df3d6a3a58e544e79ac8e From 3814df98f62a71b670addf6e7cd421c4d63b1732 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 24 Mar 2013 16:04:01 +0000 Subject: [PATCH 012/220] users module almost fully operational with databank (few kinks in moderation commands still) [#272] --- modules/users/api.js | 7 +- modules/users/commands.js | 155 +++++++++++++++++++------------------- modules/users/users.js | 115 +++++++++++++++------------- 3 files changed, 144 insertions(+), 133 deletions(-) diff --git a/modules/users/api.js b/modules/users/api.js index 7d6c30d..b187e8c 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -14,7 +14,8 @@ var api = function(dbot) { // Return a user record given a primary nick or an alias 'resolveUser': function(server, nick, callback) { var user = false; - this.db.search('user', { 'server': server }, function(result) { + this.db.search('users', { 'server': server }, function(result) { + console.log(result.primaryNick); if(result.primaryNick == nick || _.include(result.aliases, nick)) { user = result; } @@ -25,11 +26,11 @@ var api = function(dbot) { }); }, - 'getChannel': function(server, channel, callback) { + 'getChannel': function(server, channelName, callback) { var channel = false; this.db.search('channel_users', { 'server': server, - 'name': channel + 'name': channelName }, function(result) { channel = result; }, function(err) { diff --git a/modules/users/commands.js b/modules/users/commands.js index 57452c1..4b5fc46 100644 --- a/modules/users/commands.js +++ b/modules/users/commands.js @@ -3,98 +3,95 @@ var _ = require('underscore')._; var commands = function(dbot) { var commands = { '~alias': function(event) { - var knownUsers = this.getServerUsers(event.server), - alias = event.params[1].trim(); + var nick = event.params[1].trim(); + this.api.resolveUser(event.server, nick, function(user) { + if(user) { + if(nick == user.primaryNick) { + var aliases = _.first(user.aliases, 10); + var including = 'including: ' + aliases.join(', ') + '.'; - if(_.include(knownUsers.users, alias)) { - var aliases = this.api.getAliases(event.server, alias); - var aliasCount = aliases.length; - - if(aliasCount != 0) { - var aliases = _.first(aliases, 10); - var including = 'including: ' + aliases.join(', ') + '.'; - - event.reply(dbot.t('primary', { - 'user': alias, - 'count': aliasCount - }) + including); + if(user.aliases.length != 0) { + event.reply(dbot.t('primary', { + 'user': nick, + 'count': user.aliases.length, + }) + including); + } else { + event.reply(dbot.t('primary', { + 'user': nick, + 'count': user.aliases.length + }).slice(0, -2) + "."); + } + } else { + event.reply(dbot.t('alias', { + 'alias': nick, + 'user': user.primaryNick + })); + } } else { - event.reply(dbot.t('primary', { - 'user': alias, - 'count': aliasCount - }).slice(0, -2) + "."); + event.reply(dbot.t('unknown_alias', { 'alias': nick })); } - } else if(_.has(knownUsers.aliases, alias)) { - event.reply(dbot.t('alias', { - 'alias': alias, - 'user': knownUsers.aliases[alias] - })); - } else { - event.reply(dbot.t('unknown_alias', { 'alias': alias })); - } + }); }, '~setaliasparent': function(event) { - var knownUsers = this.getServerUsers(event.server); - var newParent = event.params[1]; + var newPrimary = event.params[1].trim(); + this.api.resolveUser(event.server, newPrimary, function(user) { + if(user) { + var newAlias = user.primaryNick; + user.primaryNick = newPrimary; + user.aliases = _.without(user.aliases, newPrimary).push(newAlias); + this.internalAPI.updateChannelPrimaryUser(event.server, newAlias, newPrimary); - if(_.has(knownUsers.aliases, newParent)) { - var newAlias = knownUsers.aliases[newParent]; - - // Replace user entry - knownUsers.users = _.without(knownUsers.users, newAlias); - knownUsers.users.push(newParent); - - // Replace channels entries with new primary user - this.updateChannels(event, newAlias, newParent); - - // Remove alias for new parent & add alias for new alias - delete knownUsers.aliases[newParent]; - knownUsers.aliases[newAlias] = newParent; - - // Update aliases to point to new primary user - this.updateAliases(event, newAlias, newParent); - - event.reply(dbot.t('aliasparentset', { - 'newParent': newParent, - 'newAlias': newAlias - })); - - return { - 'server': event.server, - 'alias': newAlias - }; - } else { - event.reply(dbot.t('unknown_alias', { 'alias': newParent })); - } - return false; + this.db.save('users', user.id, user, function(err) { + if(!err) { + dbot.api.event.emit('~setaliasparent', { + 'server': event.server, + 'alias': newAlias + }); + } + }); + } else { + event.reply(dbot.t('unknown_alias', { 'alias': newParent })); + } + }.bind(this)); }, '~mergeusers': function(event) { - var knownUsers = this.getServerUsers(event.server); var primaryUser = event.params[1]; var secondaryUser = event.params[2]; - if(_.include(knownUsers.users, primaryUser) && _.include(knownUsers.users, secondaryUser)) { - knownUsers.users = _.without(knownUsers.users, secondaryUser); - knownUsers.aliases[secondaryUser] = primaryUser; - this.updateAliases(event, secondaryUser, primaryUser); - this.updateChannels(event, secondaryUser, primaryUser); - - event.reply(dbot.t('merged_users', { - 'old_user': secondaryUser, - 'new_user': primaryUser - })); - - return { - 'server': event.server, - 'secondary': secondaryUser - }; - } else { - event.reply(dbot.t('unprimary_error')); - } - return false; - } + this.api.resolveUser(event.server, primaryUser, function(user) { + if(user) { + this.api.resolveUser(event.server, secondaryUser, function(secondaryUser) { + if(secondaryUser) { + user.aliases.push(secondaryUser.primaryNick); + user.aliases.concat(secondaryUser.aliases); + this.db.del('users', secondaryUser.id, function(err) { + if(!err) { + this.db.save('users', user.id, user, function(err) { + if(!err) { + this.updateChannels(event, secondaryUser, primaryUser); + event.reply(dbot.t('merged_users', { + 'old_user': secondaryUser, + 'new_user': primaryUser + })); + dbot.api.event.emit('~mergeusers', { + 'server': event.server, + 'secondary': secondaryUser + }); + } + }); + } + }); + } else { + event.reply(dbot.t('unprimary_error')); + } + }); + } else { + event.reply(dbot.t('unprimary_error')); + } + }); + } }; commands['~alias'].regex = [/^~alias ([\d\w[\]{}^|\\`_-]+?)/, 2]; diff --git a/modules/users/users.js b/modules/users/users.js index e83dd6b..b1d1177 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -2,28 +2,12 @@ * Name: Users * Description: Track known users */ -var _ = require('underscore')._; +var _ = require('underscore')._, + uuid = require('node-uuid'); var users = function(dbot) { - this.knownUsers = dbot.db.knownUsers; - - this.updateAliases = function(event, oldUser, newUser) { - var knownUsers = this.getServerUsers(event.server); - _.each(knownUsers.aliases, function(user, alias) { - if(user == oldUser) { - knownUsers.aliases[alias] = newUser; - } - }, this); - }; - - this.updateChannels = function(event, oldUser, newUser) { - var channelUsers = this.getServerUsers(event.server).channelUsers; - channelUsers = _.each(channelUsers, function(channel, channelName) { - channelUsers[channelName] = _.without(channel, oldUser); - channelUsers[channelName].push(newUser); - }, this); - }; + /*** Internal API ***/ this.internalAPI = { 'createUser': function(server, nick, channel, callback) { var id = uuid.v4(); @@ -36,14 +20,17 @@ var users = function(dbot) { 'aliases': [] }, function(err, result) { if(!err) { - dbot.api.event.emit('new_user', [ user ]); + dbot.api.event.emit('new_user', [ result ]); callback(result); + dbot.say('aberwiki', '#realitest', result.server); + dbot.say('aberwiki', '#realitest', result.primaryNick); } }); - }, + }.bind(this), 'addChannelUser': function(user, channelName) { user.channels.push(channelName); + dbot.say('aberwiki', '#realitest', user.id); this.db.save('users', user.id, user, function(err) { if(!err) { this.api.getChannel(user.server, channelName, function(channel) { @@ -56,46 +43,68 @@ var users = function(dbot) { }); } }); - } + }.bind(this), + + 'updateChannelPrimaryUser': function(server, oldUser, newUser) { + this.db.search('channel_users', { 'server': server }, function(channel) { + channel.users = _.without(channel.users, oldUser); + if(!_.include(channel.users, newUser)) channel.users.push(newUser); + this.db.save('channel_users', channel.id, channel, function(err) { + if(err) { + // QQ + } + }); + }.bind(this), function(err) { + if(err) { + // QQ + } + }); + }.bind(this) }; this.listener = function(event) { - if(event.action == 'JOIN' && nick != dbot.config.name) { + if(event.action == 'JOIN' && event.user != dbot.config.name) { this.api.resolveUser(event.server, event.user, function(user) { if(!user) { // User does not yet exist this.internalAPI.createUser(event.server, event.user, event.channel, function(result) { user = result; - }); - } - - if(!_.include(user.channels, event.channel)) { // User not yet channel user - this.internalAPI.addChannelUser(user, event.channel); - } - } - } else if(event.action == 'NICK') { - if(!this.api.isKnownUser(event.newNick)) { - this.api.resolveUser(event.server, event.user, function(user) { - user.aliases.push(event.newNick); - this.db.save('users', user.id, function(err) { - if(!err) { - dbot.api.event.emit('new_user_alias', [ user, event.newNick ]); + if(!_.include(user.channels, event.channel)) { // User not yet channel user + this.internalAPI.addChannelUser(user, event.channel.name); } }); - }); - } + } else { + if(!_.include(user.channels, event.channel)) { // User not yet channel user + this.internalAPI.addChannelUser(user, event.channel.name); + } + } + }.bind(this)); + } else if(event.action == 'NICK') { + this.api.isKnownUser(event.server, event.newNick, function(isKnown) { + if(!isKnown) { + this.api.resolveUser(event.server, event.user, function(user) { + dbot.say('aberwiki', '#realitest', event.newNick); + user.aliases.push(event.newNick); + this.db.save('users', user.id, user, function(err) { + if(!err) { + dbot.api.event.emit('new_user_alias', [ user, event.newNick ]); + } + }); + }.bind(this)); + } + }.bind(this)); } }.bind(this); this.on = ['JOIN', 'NICK']; this.onLoad = function() { dbot.instance.addListener('366', 'users', function(event) { - this.api.getChannel(event.server, event.channel, function(channel) { + this.api.getChannel(event.server, event.channel.name, function(channel) { if(!channel) { // Channel does not yet exist var id = uuid.v4(); this.db.create('channel_users', id, { 'uuid': id, 'server': event.server, - 'name': event.channel, + 'name': event.channel.name, 'users': [] }, function(err, result) { if(!err) { @@ -106,24 +115,28 @@ var users = function(dbot) { } _.each(event.channel.nicks, function(nick) { + var nick = nick.name; this.api.resolveUser(event.server, nick, function(user) { if(!user) { this.internalAPI.createUser(event.server, nick, event.channel, function(result) { user = result; + if(!_.include(user.channels, event.channel)) { + this.internalAPI.addChannelUser(user, event.channel.name); + } }); + } else { + if(!_.include(user.channels, event.channel)) { + this.internalAPI.addChannelUser(user, event.channel.name); + } } - - if(!_.include(user.channels, event.channel)) { - this.internalAPI.addChannelUser(user, event.channel); - } - }); + }.bind(this)); }, this); - }); + }.bind(this)); + }.bind(this)); - var connections = dbot.instance.connections; - _.each(connections, function(connection) { - connection.updateNickLists(); - }); + var connections = dbot.instance.connections; + _.each(connections, function(connection) { + connection.updateNickLists(); }); }; }; From 17c2c4b317cac74168313f535cea31145a7f9a36 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 24 Mar 2013 16:59:26 +0000 Subject: [PATCH 013/220] Fix ~setaliasparent [#272] --- modules/users/api.js | 1 - modules/users/commands.js | 19 ++++++++++++------- modules/users/users.js | 3 +-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/modules/users/api.js b/modules/users/api.js index b187e8c..f779941 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -15,7 +15,6 @@ var api = function(dbot) { 'resolveUser': function(server, nick, callback) { var user = false; this.db.search('users', { 'server': server }, function(result) { - console.log(result.primaryNick); if(result.primaryNick == nick || _.include(result.aliases, nick)) { user = result; } diff --git a/modules/users/commands.js b/modules/users/commands.js index 4b5fc46..8dbead1 100644 --- a/modules/users/commands.js +++ b/modules/users/commands.js @@ -36,14 +36,19 @@ var commands = function(dbot) { '~setaliasparent': function(event) { var newPrimary = event.params[1].trim(); this.api.resolveUser(event.server, newPrimary, function(user) { - if(user) { + if(user && user.primaryNick != newPrimary) { var newAlias = user.primaryNick; user.primaryNick = newPrimary; - user.aliases = _.without(user.aliases, newPrimary).push(newAlias); + user.aliases = _.without(user.aliases, newPrimary); + user.aliases.push(newAlias); this.internalAPI.updateChannelPrimaryUser(event.server, newAlias, newPrimary); this.db.save('users', user.id, user, function(err) { if(!err) { + event.reply(dbot.t('aliasparentset', { + 'newParent': newPrimary, + 'newAlias': newAlias + })); dbot.api.event.emit('~setaliasparent', { 'server': event.server, 'alias': newAlias @@ -51,7 +56,7 @@ var commands = function(dbot) { } }); } else { - event.reply(dbot.t('unknown_alias', { 'alias': newParent })); + event.reply(dbot.t('unknown_alias', { 'alias': newPrimary })); } }.bind(this)); }, @@ -80,17 +85,17 @@ var commands = function(dbot) { 'secondary': secondaryUser }); } - }); + }.bind(this)); } - }); + }.bind(this)); } else { event.reply(dbot.t('unprimary_error')); } - }); + }.bind(this)); } else { event.reply(dbot.t('unprimary_error')); } - }); + }.bind(this)); } }; diff --git a/modules/users/users.js b/modules/users/users.js index b1d1177..d32f4c0 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -42,7 +42,7 @@ var users = function(dbot) { }); }); } - }); + }.bind(this)); }.bind(this), 'updateChannelPrimaryUser': function(server, oldUser, newUser) { @@ -82,7 +82,6 @@ var users = function(dbot) { this.api.isKnownUser(event.server, event.newNick, function(isKnown) { if(!isKnown) { this.api.resolveUser(event.server, event.user, function(user) { - dbot.say('aberwiki', '#realitest', event.newNick); user.aliases.push(event.newNick); this.db.save('users', user.id, user, function(err) { if(!err) { From 9443970c89bd01d436deb7f5087887218a7e0aa7 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 24 Mar 2013 18:05:57 +0000 Subject: [PATCH 014/220] FIXED THAT MOTHERFUCKING BASTID BUG I AM THE RESURRECTION YEAAAAAAAAA [#272] --- modules/users/users.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index d32f4c0..2972089 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -12,7 +12,7 @@ var users = function(dbot) { 'createUser': function(server, nick, channel, callback) { var id = uuid.v4(); this.db.create('users', id, { - 'uuid': id, + 'id': id, 'primaryNick': nick, 'currentNick': nick, 'server': server, @@ -22,15 +22,12 @@ var users = function(dbot) { if(!err) { dbot.api.event.emit('new_user', [ result ]); callback(result); - dbot.say('aberwiki', '#realitest', result.server); - dbot.say('aberwiki', '#realitest', result.primaryNick); } }); }.bind(this), 'addChannelUser': function(user, channelName) { user.channels.push(channelName); - dbot.say('aberwiki', '#realitest', user.id); this.db.save('users', user.id, user, function(err) { if(!err) { this.api.getChannel(user.server, channelName, function(channel) { @@ -40,7 +37,7 @@ var users = function(dbot) { dbot.api.event.emit('new_channel_user', [ user, channel]); } }); - }); + }.bind(this)); } }.bind(this)); }.bind(this), @@ -101,7 +98,7 @@ var users = function(dbot) { if(!channel) { // Channel does not yet exist var id = uuid.v4(); this.db.create('channel_users', id, { - 'uuid': id, + 'id': id, 'server': event.server, 'name': event.channel.name, 'users': [] From e9c44bf702f770973e31c70d1cc19cc474a61f10 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 24 Mar 2013 19:58:28 +0000 Subject: [PATCH 015/220] bump jsbot --- jsbot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsbot b/jsbot index 217d7c8..84a4783 160000 --- a/jsbot +++ b/jsbot @@ -1 +1 @@ -Subproject commit 217d7c8f865e9097b06df3d6a3a58e544e79ac8e +Subproject commit 84a4783db76bdd729bd720c43485893ebe78a8c9 From e7be2f6b8740ba4bf880134006d5182d927d5ec6 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 25 Mar 2013 13:55:47 +0000 Subject: [PATCH 016/220] users module now tracks current nick, appropriate output in ~alias --- modules/users/commands.js | 2 ++ modules/users/strings.json | 2 +- modules/users/users.js | 30 ++++++++++++++++++++---------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/modules/users/commands.js b/modules/users/commands.js index 8dbead1..6a31979 100644 --- a/modules/users/commands.js +++ b/modules/users/commands.js @@ -13,11 +13,13 @@ var commands = function(dbot) { if(user.aliases.length != 0) { event.reply(dbot.t('primary', { 'user': nick, + 'currentNick': user.currentNick, 'count': user.aliases.length, }) + including); } else { event.reply(dbot.t('primary', { 'user': nick, + 'currentNick': user.currentNick, 'count': user.aliases.length }).slice(0, -2) + "."); } diff --git a/modules/users/strings.json b/modules/users/strings.json index a46e7dc..a73263d 100644 --- a/modules/users/strings.json +++ b/modules/users/strings.json @@ -4,7 +4,7 @@ "na'vi": "ayfko syaw {user} {alias} nìteng" }, "primary": { - "en": "{user} is a primary user with {count} aliases, ", + "en": "{user} is a primary user (currently {currentNick}) with {count} aliases, ", "na'vi": "{user} lu txin ulte {count}a stxo lu poru, " }, "unknown_alias": { diff --git a/modules/users/users.js b/modules/users/users.js index 2972089..78b2c69 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -73,20 +73,30 @@ var users = function(dbot) { if(!_.include(user.channels, event.channel)) { // User not yet channel user this.internalAPI.addChannelUser(user, event.channel.name); } + + user.currentNick = event.user; + this.db.save(users, user.id, user, function(err) { + if(err) { + // QQ + } + }); } }.bind(this)); } else if(event.action == 'NICK') { - this.api.isKnownUser(event.server, event.newNick, function(isKnown) { - if(!isKnown) { - this.api.resolveUser(event.server, event.user, function(user) { + this.api.resolveUser(event.server, event.user, function(user) { + this.api.isKnownUser(event.server, event.newNick, function(isKnown) { + user.currentNick = event.newNick; + + if(!isKnown) { user.aliases.push(event.newNick); - this.db.save('users', user.id, user, function(err) { - if(!err) { - dbot.api.event.emit('new_user_alias', [ user, event.newNick ]); - } - }); - }.bind(this)); - } + } + + this.db.save('users', user.id, user, function(err) { + if(!err) { + dbot.api.event.emit('new_user_alias', [ user, event.newNick ]); + } + }); + }.bind(this)); }.bind(this)); } }.bind(this); From 14e03313ec587da50ea30477ed5b45383d1d3a6e Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 9 Apr 2013 00:10:08 +0000 Subject: [PATCH 017/220] Provisional/example ~ignore functionality using databank [#331] --- modules/ignore/config.json | 1 + modules/ignore/ignore.js | 52 ++++++++++++++++++++++++++------------ modules/users/users.js | 2 +- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/modules/ignore/config.json b/modules/ignore/config.json index 14e12c2..94f16ed 100644 --- a/modules/ignore/config.json +++ b/modules/ignore/config.json @@ -2,5 +2,6 @@ "ignorable": false, "dependencies": [ "command" ], "dbKeys": [ "ignores", "bans" ], + "dbType": "memory", "help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md" } diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index 3e3d974..cc09904 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -5,7 +5,9 @@ * this information, since that actually performs the ignorance. Also provides * commands for moderators to choose the bot to ignore certain channels. */ -var _ = require('underscore')._; +var _ = require('underscore')._, + databank = require('databank'), + NoSuchThingError = databank.NoSuchThingError; var ignore = function(dbot) { var commands = { @@ -25,21 +27,39 @@ var ignore = function(dbot) { })); } else { if(module == '*' || _.include(ignorableModules, module)) { - if(_.has(dbot.db.ignores, event.user) && _.include(dbot.db.ignores[event.user], module)) { - event.reply(dbot.t('already_ignoring', { 'user': event.user })); - } else { - if(_.has(dbot.db.ignores, module)) { - dbot.db.ignores[event.user].push(module); - } else { - dbot.db.ignores[event.user] = [module]; - } - - dbot.instance.ignoreTag(event.user, module); - event.reply(dbot.t('ignored', { - 'user': event.user, - 'module': module - })); - } + dbot.api.users.resolveUser(event.server, event.user, function(user) { + this.db.read('ignores', user.id, function(err, ignores) { + if(err == NoSuchThingError) { + this.db.create('ignores', user.id, { + 'id': user.id, + 'ignores': [ module ] + }, function(err, result) { + if(!err) { + dbot.instance.ignoreTag(event.user, module); + event.reply(dbot.t('ignored', { + 'user': event.user, + 'module': module + })); + } + }); + } else { + if(!_.include(ignores.ignores, module)) { + ignores.ignores.push(module); + this.db.save('ignores', user.id, function(err) { + if(!err) { + dbot.instance.ignoreTag(event.user, module); + event.reply(dbot.t('ignored', { + 'user': event.user, + 'module': module + })); + } + }); + } else { + event.reply(dbot.t('already_ignoring', { 'user': event.user })); + } + } + }); + }); } else { event.reply(dbot.t('invalid_ignore', { 'user': event.user })); } diff --git a/modules/users/users.js b/modules/users/users.js index 78b2c69..ec0e3a4 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -75,7 +75,7 @@ var users = function(dbot) { } user.currentNick = event.user; - this.db.save(users, user.id, user, function(err) { + this.db.save('users', user.id, user, function(err) { if(err) { // QQ } From 9952e4583ce546f244a53a86edbfc4a7b741b215 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 9 Apr 2013 23:16:00 +0000 Subject: [PATCH 018/220] Get user by UUID API function [#331] --- modules/users/api.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/users/api.js b/modules/users/api.js index f779941..207b4d3 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -25,6 +25,14 @@ var api = function(dbot) { }); }, + // Return a user record given a UUID + 'getUser': function(uuid, callback) { + this.db.get('users', uuid, function(err, user) { + if(err) user = false; + callback(user); + }); + }, + 'getChannel': function(server, channelName, callback) { var channel = false; this.db.search('channel_users', { From 5c489710346b828cf82bb2080c1bff04083b75c8 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 9 Apr 2013 23:16:40 +0000 Subject: [PATCH 019/220] Provisional onLoad and ~unignore for ignores module. Needs testing. [#331] --- modules/ignore/ignore.js | 47 +++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index cc09904..a3ff341 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -79,16 +79,28 @@ var ignore = function(dbot) { 'modules': ignoredModules.join(', ') })); } else { - if(_.include(ignoredModules, module)) { - dbot.db.ignores[event.user].splice(dbot.db.ignores[event.user].indexOf(module), 1); - dbot.instance.removeIgnore(event.user, module) - event.reply(dbot.t('unignored', { - 'user': event.user, - 'module': module - })); - } else { - event.reply(dbot.t('invalid_unignore', { 'user': event.user })); - } + dbot.api.users.resolveUser(event.server, event.user, function(user) { + this.db.read('ignores', user.id, function(err, ignores) { + if(!err) { + if(_.include(ignores.ignores, module)) { + ignores.ignores = _.without(ignores.ignores, module); + this.db.save('ignores', user.id, function(err) { + if(!err) { + dbot.instance.removeIgnore(event.user, module) + event.reply(dbot.t('unignored', { + 'user': event.user, + 'module': module + })); + } + }); + } else { + event.reply(dbot.t('invalid_unignore', { 'user': event.user })); + } + } else if(err == NoSuchThingError) { + event.reply(dbot.t('invalid_unignore', { 'user': event.user })); + } + }); + }); } }, @@ -207,11 +219,16 @@ var ignore = function(dbot) { this.onLoad = function() { dbot.instance.clearIgnores(); - _.each(dbot.db.ignores, function(ignores, item) { - _.each(ignores, function(ignore) { - dbot.instance.ignoreTag(item, ignore); - }, this); - }, this); + + this.db.scan('ignores', function(ignores) { + dbot.api.users.getUser(ignores.id, function(user) { + if(user) { + _.each(ignores.ignores, function(module) { + dbot.instance.ignoreTag(user.primaryNick, module); + }); + } + }); + }, function(err) { }); }; }; From 228a2611a5ae202e5dec1707612945ab6db5859c Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 10 Apr 2013 00:19:56 +0000 Subject: [PATCH 020/220] Hacked up run.js so db is definitely loaded by time onLoad is run. Need to clear up --- database.js | 2 +- run.js | 243 ++++++++++++++++++++++++++-------------------------- 2 files changed, 122 insertions(+), 123 deletions(-) diff --git a/database.js b/database.js index 15f0e8d..363bbef 100644 --- a/database.js +++ b/database.js @@ -12,7 +12,7 @@ var DatabaseDriver = function() { /** * Connect to or create a new DataBank */ -DatabaseDriver.prototype.createDB = function(name, driver, callback, schema) { +DatabaseDriver.prototype.createDB = function(name, driver, schema, callback) { var params = { 'schema': schema }; if(driver == 'disk') params.dir = 'db'; diff --git a/run.js b/run.js index 855b18f..40ecc0f 100644 --- a/run.js +++ b/run.js @@ -171,135 +171,136 @@ DBot.prototype.reloadModules = function() { try { var webKey = require.resolve(moduleDir + 'web'); - } catch(err) { - } + } catch(err) { } if(webKey) { delete require.cache[webKey]; } + // Load the module config data + var config = {}; + + if(_.has(this.db.config, name)) { + config = _.clone(this.db.config[name]); + } + try { - // Load the module config data - var config = {}; - - if(_.has(this.db.config, name)) { - config = _.clone(this.db.config[name]); - } - + var defaultConfig = fs.readFileSync(moduleDir + 'config.json', 'utf-8'); try { - var defaultConfig = fs.readFileSync(moduleDir + 'config.json', 'utf-8'); - try { - defaultConfig = JSON.parse(defaultConfig); - } catch(err) { // syntax error - this.status[name] = 'Error parsing config: ' + err + ' ' + err.stack.split('\n')[2].trim(); - return; - } - config = _.defaults(config, defaultConfig); - } catch(err) { - // Invalid or no config data + defaultConfig = JSON.parse(defaultConfig); + } catch(err) { // syntax error + this.status[name] = 'Error parsing config: ' + err + ' ' + err.stack.split('\n')[2].trim(); + return; } - - // Don't shit out if dependencies not met - if(_.has(config, 'dependencies')) { - _.each(config.dependencies, function(dependency) { - if(!_.include(moduleNames, dependency)) { - console.log('Warning: Automatically loading ' + dependency); - moduleNames.push(dependency); - } - }, this); - } - this.config[name] = config; - - // Groovy funky database shit - if(!_.has(config, 'dbType') || config.dbType == 'olde') { - // Generate missing DB keys - _.each(config.dbKeys, function(dbKey) { - if(!_.has(this.db, dbKey)) { - this.db[dbKey] = {}; - } - }, this); - } else { - // Just use the name of the module for now, add dbKey iteration later - this.ddb.createDB(name, config.dbType, function(db) { - module.db = db; - }.bind(this), {}); - } - - // Load the module itself - var rawModule = require(moduleDir + name); - var module = rawModule.fetch(this); - module.name = name; - this.rawModules.push(rawModule); - - module.config = this.config[name]; - - // Load the module data - _.each([ 'commands', 'pages', 'api' ], function(property) { - var propertyObj = {}; - - if(fs.existsSync(moduleDir + property + '.js')) { - try { - var propertyKey = require.resolve(moduleDir + property); - if(propertyKey) delete require.cache[propertyKey]; - propertyObj = require(moduleDir + property).fetch(this); - } catch(err) { - this.status[name] = 'Error loading ' + propertyKey + ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); - console.log('Module error (' + module.name + ') in ' + property + ': ' + err); - } - } - - if(!_.has(module, property)) module[property] = {}; - _.extend(module[property], propertyObj); - _.each(module[property], function(item, itemName) { - item.module = name; - if(_.has(config, property) && _.has(config[property], itemName)) { - _.extend(item, config[property][itemName]); - } - module[property][itemName] = _.bind(item, module); - _.extend(module[property][itemName], item); - }, this); - - if(property == 'api') { - this[property][name] = module[property]; - } else { - _.extend(this[property], module[property]); - } - }, this); - - // Load the module listener - if(module.listener) { - if(!_.isArray(module.on)) { - module.on = [ module.on ]; - } - _.each(module.on, function(on) { - this.instance.addListener(on, module.name, module.listener); - }, this); - } - - // Load string data for the module - _.each([ 'usage', 'strings' ], function(property) { - var propertyData = {}; - try { - propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); - } catch(err) {}; - _.extend(this[property], propertyData); - }, this); - - // Provide toString for module name - module.toString = function() { - return this.name; - } - - this.modules[module.name] = module; + config = _.defaults(config, defaultConfig); } catch(err) { - console.log(this.t('module_load_error', {'moduleName': name})); - this.status[name] = err + ' - ' + err.stack.split('\n')[1].trim(); - if(this.config.debugMode) { - console.log('MODULE ERROR (' + name + '): ' + err.stack ); - } else { - console.log('MODULE ERROR (' + name + '): ' + err ); - } + // Invalid or no config data + } + + // Don't shit out if dependencies not met + if(_.has(config, 'dependencies')) { + _.each(config.dependencies, function(dependency) { + if(!_.include(moduleNames, dependency)) { + console.log('Warning: Automatically loading ' + dependency); + moduleNames.push(dependency); + } + }, this); + } + this.config[name] = config; + + // Groovy funky database shit + if(!_.has(config, 'dbType') || config.dbType == 'olde') { + // Generate missing DB keys + _.each(config.dbKeys, function(dbKey) { + if(!_.has(this.db, dbKey)) { + this.db[dbKey] = {}; + } + }, this); + this.loadModule(name, this.db); + } else { + // Just use the name of the module for now, add dbKey iteration later + this.ddb.createDB(name, config.dbType, {}, function(db) { + this.loadModule(name, db); + }.bind(this)); } }.bind(this)); + + this.save(); +}; + +// Load the module itself +DBot.prototype.loadModule = function(name, db) { + var moduleDir = './modules/' + name + '/'; + var rawModule = require(moduleDir + name); + var module = rawModule.fetch(this); + this.rawModules.push(rawModule); + + module.name = name; + module.db = db; + module.config = this.config[name]; + + // Load the module data + _.each([ 'commands', 'pages', 'api' ], function(property) { + var propertyObj = {}; + + if(fs.existsSync(moduleDir + property + '.js')) { + try { + var propertyKey = require.resolve(moduleDir + property); + if(propertyKey) delete require.cache[propertyKey]; + propertyObj = require(moduleDir + property).fetch(this); + } catch(err) { + this.status[name] = 'Error loading ' + propertyKey + + ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); + console.log('Module error (' + module.name + ') in ' + + property + ': ' + err); + } + } + + if(!_.has(module, property)) module[property] = {}; + _.extend(module[property], propertyObj); + _.each(module[property], function(item, itemName) { + item.module = name; + if(_.has(module.config, property) && _.has(module.config[property], itemName)) { + _.extend(item, module.config[property][itemName]); + } + module[property][itemName] = _.bind(item, module); + _.extend(module[property][itemName], item); + }, this); + + if(property == 'api') { + this[property][name] = module[property]; + } else { + _.extend(this[property], module[property]); + } + }, this); + + // Load the module listener + if(module.listener) { + if(!_.isArray(module.on)) { + module.on = [ module.on ]; + } + _.each(module.on, function(on) { + this.instance.addListener(on, module.name, module.listener); + }, this); + } + + // Load string data for the module + _.each([ 'usage', 'strings' ], function(property) { + var propertyData = {}; + try { + propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); + } catch(err) {}; + _.extend(this[property], propertyData); + }, this); + + // Provide toString for module name + module.toString = function() { + return this.name; + } + + console.log(module); + console.log(this); + + this.modules[module.name] = module; if(_.has(this.modules, 'web')) this.modules.web.reloadPages(); @@ -313,9 +314,7 @@ DBot.prototype.reloadModules = function() { } } }, this); - - this.save(); -}; +} DBot.prototype.cleanNick = function(key) { key = key.toLowerCase(); From 384fe3024a59fe47fe3148c3d59aae637a900a99 Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 10 Apr 2013 00:32:30 +0000 Subject: [PATCH 021/220] ~ignore and ~unignore commands working on data storage/modification and listener execution prevention [#331] --- modules/ignore/ignore.js | 66 ++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index a3ff341..6e1e9d1 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -29,7 +29,7 @@ var ignore = function(dbot) { if(module == '*' || _.include(ignorableModules, module)) { dbot.api.users.resolveUser(event.server, event.user, function(user) { this.db.read('ignores', user.id, function(err, ignores) { - if(err == NoSuchThingError) { + if(ignores == null) { this.db.create('ignores', user.id, { 'id': user.id, 'ignores': [ module ] @@ -45,7 +45,7 @@ var ignore = function(dbot) { } else { if(!_.include(ignores.ignores, module)) { ignores.ignores.push(module); - this.db.save('ignores', user.id, function(err) { + this.db.save('ignores', user.id, ignores, function(err) { if(!err) { dbot.instance.ignoreTag(event.user, module); event.reply(dbot.t('ignored', { @@ -58,8 +58,8 @@ var ignore = function(dbot) { event.reply(dbot.t('already_ignoring', { 'user': event.user })); } } - }); - }); + }.bind(this)); + }.bind(this)); } else { event.reply(dbot.t('invalid_ignore', { 'user': event.user })); } @@ -67,41 +67,35 @@ var ignore = function(dbot) { }, '~unignore': function(event) { - var ignoredModules = []; - if(_.has(dbot.db.ignores, event.user)) { - ignoredModules = dbot.db.ignores[event.user]; - } var module = event.params[1]; - - if(_.isUndefined(module)) { - event.reply(dbot.t('unignore_usage', { - 'user': event.user, - 'modules': ignoredModules.join(', ') - })); - } else { - dbot.api.users.resolveUser(event.server, event.user, function(user) { - this.db.read('ignores', user.id, function(err, ignores) { - if(!err) { - if(_.include(ignores.ignores, module)) { - ignores.ignores = _.without(ignores.ignores, module); - this.db.save('ignores', user.id, function(err) { - if(!err) { - dbot.instance.removeIgnore(event.user, module) - event.reply(dbot.t('unignored', { - 'user': event.user, - 'module': module - })); - } - }); - } else { - event.reply(dbot.t('invalid_unignore', { 'user': event.user })); - } - } else if(err == NoSuchThingError) { + + dbot.api.users.resolveUser(event.server, event.user, function(user) { + this.db.read('ignores', user.id, function(err, ignores) { + if(!ignores) { + event.reply(dbot.t('invalid_unignore', { 'user': event.user })); + } else if(_.isUndefined(module)) { + event.reply(dbot.t('unignore_usage', { + 'user': event.user, + 'modules': ignores.ignores.join(', ') + })); + } else { + if(_.include(ignores.ignores, module)) { + ignores.ignores = _.without(ignores.ignores, module); + this.db.save('ignores', user.id, ignores, function(err) { + if(!err) { + dbot.instance.removeIgnore(event.user, module) + event.reply(dbot.t('unignored', { + 'user': event.user, + 'module': module + })); + } + }); + } else { event.reply(dbot.t('invalid_unignore', { 'user': event.user })); } - }); - }); - } + } + }.bind(this)); + }.bind(this)); }, '~ban': function(event) { From 6cea1256ce8951882fcbc4da37a8ea6d86330860 Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 10 Apr 2013 01:07:29 +0000 Subject: [PATCH 022/220] thats a little better on the module loader i suppose [#331] --- run.js | 175 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 87 insertions(+), 88 deletions(-) diff --git a/run.js b/run.js index 40ecc0f..2c7a21f 100644 --- a/run.js +++ b/run.js @@ -207,6 +207,90 @@ DBot.prototype.reloadModules = function() { } this.config[name] = config; + var loadModule = function(db) { + var rawModule = require(moduleDir + name); + var module = rawModule.fetch(this); + this.rawModules.push(rawModule); + + module.name = name; + module.db = db; + module.config = this.config[name]; + + // Load the module data + _.each([ 'commands', 'pages', 'api' ], function(property) { + var propertyObj = {}; + + if(fs.existsSync(moduleDir + property + '.js')) { + try { + var propertyKey = require.resolve(moduleDir + property); + if(propertyKey) delete require.cache[propertyKey]; + propertyObj = require(moduleDir + property).fetch(this); + } catch(err) { + this.status[name] = 'Error loading ' + propertyKey + + ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); + console.log('Module error (' + module.name + ') in ' + + property + ': ' + err); + } + } + + if(!_.has(module, property)) module[property] = {}; + _.extend(module[property], propertyObj); + _.each(module[property], function(item, itemName) { + item.module = name; + if(_.has(module.config, property) && _.has(module.config[property], itemName)) { + _.extend(item, module.config[property][itemName]); + } + module[property][itemName] = _.bind(item, module); + _.extend(module[property][itemName], item); + }, this); + + if(property == 'api') { + this[property][name] = module[property]; + } else { + _.extend(this[property], module[property]); + } + }, this); + + // Load the module listener + if(module.listener) { + if(!_.isArray(module.on)) { + module.on = [ module.on ]; + } + _.each(module.on, function(on) { + this.instance.addListener(on, module.name, module.listener); + }, this); + } + + // Load string data for the module + _.each([ 'usage', 'strings' ], function(property) { + var propertyData = {}; + try { + propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); + } catch(err) {}; + _.extend(this[property], propertyData); + }, this); + + // Provide toString for module name + module.toString = function() { + return this.name; + } + + this.modules[module.name] = module; + + if(_.has(this.modules, 'web')) this.modules.web.reloadPages(); + + _.each(this.modules, function(module, name) { + if(module.onLoad) { + try { + module.onLoad(); + } catch(err) { + this.status[name] = 'Error in onLoad: ' + err + ' ' + err.stack.split('\n')[1].trim(); + console.log('MODULE ONLOAD ERROR (' + name + '): ' + err ); + } + } + }, this); + }.bind(this); + // Groovy funky database shit if(!_.has(config, 'dbType') || config.dbType == 'olde') { // Generate missing DB keys @@ -215,12 +299,12 @@ DBot.prototype.reloadModules = function() { this.db[dbKey] = {}; } }, this); - this.loadModule(name, this.db); + loadModule(this.db); } else { // Just use the name of the module for now, add dbKey iteration later this.ddb.createDB(name, config.dbType, {}, function(db) { - this.loadModule(name, db); - }.bind(this)); + loadModule(db); + }); } }.bind(this)); @@ -229,93 +313,8 @@ DBot.prototype.reloadModules = function() { // Load the module itself DBot.prototype.loadModule = function(name, db) { - var moduleDir = './modules/' + name + '/'; - var rawModule = require(moduleDir + name); - var module = rawModule.fetch(this); - this.rawModules.push(rawModule); - - module.name = name; - module.db = db; - module.config = this.config[name]; - - // Load the module data - _.each([ 'commands', 'pages', 'api' ], function(property) { - var propertyObj = {}; - - if(fs.existsSync(moduleDir + property + '.js')) { - try { - var propertyKey = require.resolve(moduleDir + property); - if(propertyKey) delete require.cache[propertyKey]; - propertyObj = require(moduleDir + property).fetch(this); - } catch(err) { - this.status[name] = 'Error loading ' + propertyKey + - ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); - console.log('Module error (' + module.name + ') in ' + - property + ': ' + err); - } - } - - if(!_.has(module, property)) module[property] = {}; - _.extend(module[property], propertyObj); - _.each(module[property], function(item, itemName) { - item.module = name; - if(_.has(module.config, property) && _.has(module.config[property], itemName)) { - _.extend(item, module.config[property][itemName]); - } - module[property][itemName] = _.bind(item, module); - _.extend(module[property][itemName], item); - }, this); - - if(property == 'api') { - this[property][name] = module[property]; - } else { - _.extend(this[property], module[property]); - } - }, this); - - // Load the module listener - if(module.listener) { - if(!_.isArray(module.on)) { - module.on = [ module.on ]; - } - _.each(module.on, function(on) { - this.instance.addListener(on, module.name, module.listener); - }, this); } - // Load string data for the module - _.each([ 'usage', 'strings' ], function(property) { - var propertyData = {}; - try { - propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); - } catch(err) {}; - _.extend(this[property], propertyData); - }, this); - - // Provide toString for module name - module.toString = function() { - return this.name; - } - - console.log(module); - console.log(this); - - this.modules[module.name] = module; - - if(_.has(this.modules, 'web')) this.modules.web.reloadPages(); - - _.each(this.modules, function(module, name) { - if(module.onLoad) { - try { - module.onLoad(); - } catch(err) { - this.status[name] = 'Error in onLoad: ' + err + ' ' + err.stack.split('\n')[1].trim(); - console.log('MODULE ONLOAD ERROR (' + name + '): ' + err ); - } - } - }, this); -} - DBot.prototype.cleanNick = function(key) { key = key.toLowerCase(); while(key.endsWith("_")) { From b56ac4164ad91f53765b14715e26e57af8f7b150 Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 10 Apr 2013 01:28:53 +0000 Subject: [PATCH 023/220] isIgnoring now belongs in ignore.api, changes in command to reflect this. ~ignore now operational for commands. [#331] --- modules/command/api.js | 10 ------- modules/command/command.js | 55 +++++++++++++++++++------------------- modules/ignore/ignore.js | 2 +- modules/users/api.js | 2 +- 4 files changed, 29 insertions(+), 40 deletions(-) diff --git a/modules/command/api.js b/modules/command/api.js index dd19b9e..3261a65 100644 --- a/modules/command/api.js +++ b/modules/command/api.js @@ -35,16 +35,6 @@ var api = function(dbot) { return access; }, - /** - * Is item (user or channel) ignoring command? - */ - 'isIgnoring': function(item, command) { - var module = dbot.commands[command].module; - return (_.has(dbot.db.ignores, item) && - (_.include(dbot.db.ignores[item], module) || - _.include(dbot.db.ignores[item], '*'))); - }, - /** * Apply Regex to event message, store result. Return false if it doesn't * apply. diff --git a/modules/command/command.js b/modules/command/command.js index 935f6e0..1c636e5 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -24,37 +24,36 @@ var command = function(dbot) { if(this.api.isBanned(event.user, commandName)) { event.reply(dbot.t('command_ban', {'user': event.user})); } else { - if(!this.api.isIgnoring(event.user, commandName) && - !this.api.isIgnoring(event.channel, commandName) && - this.api.hasAccess(event.user, commandName) && - dbot.commands[commandName].disabled !== true) { - if(this.api.applyRegex(commandName, event)) { - try { - var command = dbot.commands[commandName]; - var results = command.apply(dbot.modules[command.module], [event]); - if(_.has(command, 'hooks') && results !== false) { - _.each(command['hooks'], function(hook) { - hook.apply(hook.module, _.values(results)); - }, this); + dbot.api.ignore.isUserIgnoring(event.server, event.user, commandName, function(isIgnoring) { + if(!isIgnoring && this.api.hasAccess(event.user, commandName) && dbot.commands[commandName].disabled !== true) { + if(this.api.applyRegex(commandName, event)) { + try { + var command = dbot.commands[commandName]; + var results = command.apply(dbot.modules[command.module], [event]); + if(_.has(command, 'hooks') && results !== false) { + _.each(command['hooks'], function(hook) { + hook.apply(hook.module, _.values(results)); + }, this); + } + } catch(err) { + if(dbot.config.debugMode == true) { + event.reply('- Error in ' + commandName + ':'); + event.reply('- Message: ' + err); + event.reply('- Top of stack: ' + err.stack.split('\n')[1].trim()); + } } - } catch(err) { - if(dbot.config.debugMode == true) { - event.reply('- Error in ' + commandName + ':'); - event.reply('- Message: ' + err); - event.reply('- Top of stack: ' + err.stack.split('\n')[1].trim()); + dbot.save(); + } else { + if(commandName !== '~') { + if(_.has(dbot.usage, commandName)) { + event.reply('Usage: ' + dbot.usage[commandName]); + } else { + event.reply(dbot.t('syntax_error')); + } } - } - dbot.save(); - } else { - if(commandName !== '~') { - if(_.has(dbot.usage, commandName)) { - event.reply('Usage: ' + dbot.usage[commandName]); - } else { - event.reply(dbot.t('syntax_error')); - } - } + } } - } + }.bind(this)); } }.bind(this); this.on = 'PRIVMSG'; diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index 6e1e9d1..ffe64e8 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -68,7 +68,7 @@ var ignore = function(dbot) { '~unignore': function(event) { var module = event.params[1]; - + dbot.api.users.resolveUser(event.server, event.user, function(user) { this.db.read('ignores', user.id, function(err, ignores) { if(!ignores) { diff --git a/modules/users/api.js b/modules/users/api.js index 207b4d3..ebfefea 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -1,5 +1,5 @@ var _ = require('underscore')._, - uuid = require('node-uuid'); + uuid = require('node-uuid'), databank = require('databank'), AlreadyExistsError = databank.AlreadyExistsError, NoSuchThingError = databank.NoSuchThingError, From 53c8ca96722dfee23062e06afb7055e2fcfe86fd Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 10 Apr 2013 07:50:47 +0000 Subject: [PATCH 024/220] Forgot to add ignore.api to last commit --- modules/ignore/api.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 modules/ignore/api.js diff --git a/modules/ignore/api.js b/modules/ignore/api.js new file mode 100644 index 0000000..fb2801d --- /dev/null +++ b/modules/ignore/api.js @@ -0,0 +1,30 @@ +var _ = require('underscore')._, + databank = require('databank'), + AlreadyExistsError = databank.AlreadyExistsError, + NoSuchThingError = databank.NoSuchThingError, + NotImplementedError = databank.NotImplementedError; + +var api = function(dbot) { + return { + 'isUserIgnoring': function(server, user, item, callback) { + dbot.api.users.resolveUser(server, user, function(user) { + this.db.read('ignores', user.id, function(err, ignores) { + var isIgnoring = false; + if(ignores) { + if(_.has(dbot.commands, item)) { + item = moduleName = dbot.commands[item].module; + } + if(_.include(ignores.ignores, item)) { + isIgnoring = true; + } + } + callback(isIgnoring); + }); + }.bind(this)); + } + }; +} + +exports.fetch = function(dbot) { + return api(dbot); +}; From 223b20b598d112cb68498270eaab5e850378367d Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 11 Apr 2013 20:12:29 +0000 Subject: [PATCH 025/220] * ~ban and ~unban now fully databankerised and tested [#331] * Refactored ~ignore and ~unignore * Refactored API * Command uses new ban/ignore APIs, removed its own isBanned * Ignore is now aware of servers [#188] --- modules/command/api.js | 12 --- modules/command/command.js | 16 +-- modules/ignore/api.js | 31 +++--- modules/ignore/ignore.js | 204 ++++++++++++++++++++----------------- 4 files changed, 140 insertions(+), 123 deletions(-) diff --git a/modules/command/api.js b/modules/command/api.js index 3261a65..e817022 100644 --- a/modules/command/api.js +++ b/modules/command/api.js @@ -2,18 +2,6 @@ var _ = require('underscore')._; var api = function(dbot) { return { - 'isBanned': function(user, command) { - var banned = false; - if(_.has(dbot.db.bans, user)) { - if(_.include(dbot.db.bans[user], command) || - _.include(dbot.db.bans[user], dbot.commands[command].module) || - _.include(dbot.db.bans[user], '*')) { - banned = true; - } - } - return banned; - }, - /** * Does the user have the correct access level to use the command? */ diff --git a/modules/command/command.js b/modules/command/command.js index 1c636e5..0f769f5 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -21,11 +21,13 @@ var command = function(dbot) { } } - if(this.api.isBanned(event.user, commandName)) { - event.reply(dbot.t('command_ban', {'user': event.user})); - } else { - dbot.api.ignore.isUserIgnoring(event.server, event.user, commandName, function(isIgnoring) { - if(!isIgnoring && this.api.hasAccess(event.user, commandName) && dbot.commands[commandName].disabled !== true) { + dbot.api.ignore.isUserIgnoring(event.server, event.user, commandName, function(isIgnoring) { + dbot.api.ignore.isUserBanned(event.server, event.user, commandName, function(isBanned) { + if(isBanned) { + event.reply(dbot.t('command_ban', {'user': event.user})); + } else if(!isIgnoring && + this.api.hasAccess(event.user, commandName) && + dbot.commands[commandName].disabled !== true) { if(this.api.applyRegex(commandName, event)) { try { var command = dbot.commands[commandName]; @@ -51,10 +53,10 @@ var command = function(dbot) { event.reply(dbot.t('syntax_error')); } } - } + } } }.bind(this)); - } + }.bind(this)); }.bind(this); this.on = 'PRIVMSG'; }; diff --git a/modules/ignore/api.js b/modules/ignore/api.js index fb2801d..5ee208c 100644 --- a/modules/ignore/api.js +++ b/modules/ignore/api.js @@ -5,21 +5,28 @@ var _ = require('underscore')._, NotImplementedError = databank.NotImplementedError; var api = function(dbot) { + return { + // Is user ignoring command/module? 'isUserIgnoring': function(server, user, item, callback) { + this.internalAPI.isUserImpeded(server, user, item, 'ignores', callback); + }, + + // Is user banned from command/module? + 'isUserBanned': function(server, user, item, callback) { + this.internalAPI.isUserImpeded(server, user, item, 'bans', callback); + }, + + // Resolve a nick and return their user and ignores object + 'getUserIgnores': function(server, user, callback) { dbot.api.users.resolveUser(server, user, function(user) { - this.db.read('ignores', user.id, function(err, ignores) { - var isIgnoring = false; - if(ignores) { - if(_.has(dbot.commands, item)) { - item = moduleName = dbot.commands[item].module; - } - if(_.include(ignores.ignores, item)) { - isIgnoring = true; - } - } - callback(isIgnoring); - }); + if(user) { + this.db.read('ignores', user.id, function(err, ignores) { + callback(false, user, ignores); + }); + } else { + callback(true, null, null); + } }.bind(this)); } }; diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index ffe64e8..f465c68 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -10,6 +10,23 @@ var _ = require('underscore')._, NoSuchThingError = databank.NoSuchThingError; var ignore = function(dbot) { + this.internalAPI = { + 'isUserImpeded': function(server, user, item, by, callback) { + this.api.getUserIgnores(server, user, function(err, user, ignores) { + var isImpeded = false; + if(!err && ignores) { + if(_.has(dbot.commands, item)) { + item = dbot.commands[item].module; + } + if(_.include(ignores[by], item)) { + isImpeded = true; + } + } + callback(isImpeded); + }); + }.bind(this) + }; + var commands = { '~ignore': function(event) { var module = event.params[1]; @@ -19,6 +36,15 @@ var ignore = function(dbot) { }) .pluck('name') .value(); + var ignoreCreated = function(err, result) { + if(!err) { + dbot.instance.ignoreTag(event.user, module); + event.reply(dbot.t('ignored', { + 'user': event.user, + 'module': module + })); + } + }; if(_.isUndefined(module)) { event.reply(dbot.t('ignore_usage', { @@ -27,38 +53,23 @@ var ignore = function(dbot) { })); } else { if(module == '*' || _.include(ignorableModules, module)) { - dbot.api.users.resolveUser(event.server, event.user, function(user) { - this.db.read('ignores', user.id, function(err, ignores) { - if(ignores == null) { + this.api.getUserIgnores(event.server, event.user, function(err, user, ignores) { + if(!err) { + if(!ignores) { this.db.create('ignores', user.id, { 'id': user.id, - 'ignores': [ module ] - }, function(err, result) { - if(!err) { - dbot.instance.ignoreTag(event.user, module); - event.reply(dbot.t('ignored', { - 'user': event.user, - 'module': module - })); - } - }); + 'ignores': [ module ], + 'bans': [] + }, ignoreCreated); } else { if(!_.include(ignores.ignores, module)) { ignores.ignores.push(module); - this.db.save('ignores', user.id, ignores, function(err) { - if(!err) { - dbot.instance.ignoreTag(event.user, module); - event.reply(dbot.t('ignored', { - 'user': event.user, - 'module': module - })); - } - }); + this.db.save('ignores', user.id, ignores, ignoreCreated); } else { event.reply(dbot.t('already_ignoring', { 'user': event.user })); } } - }.bind(this)); + } }.bind(this)); } else { event.reply(dbot.t('invalid_ignore', { 'user': event.user })); @@ -69,93 +80,99 @@ var ignore = function(dbot) { '~unignore': function(event) { var module = event.params[1]; - dbot.api.users.resolveUser(event.server, event.user, function(user) { - this.db.read('ignores', user.id, function(err, ignores) { - if(!ignores) { - event.reply(dbot.t('invalid_unignore', { 'user': event.user })); - } else if(_.isUndefined(module)) { - event.reply(dbot.t('unignore_usage', { - 'user': event.user, - 'modules': ignores.ignores.join(', ') - })); + this.api.getUserIgnores(event.server, event.user, function(err, user, ignores) { + if(err || !ignores || _.isUndefined(module)) { + event.reply(dbot.t('unignore_usage', { + 'user': event.user, + 'modules': ignores.ignores.join(', ') + })); + } else { + if(_.include(ignores.ignores, module)) { + ignores.ignores = _.without(ignores.ignores, module); + this.db.save('ignores', user.id, ignores, function(err) { + if(!err) { + dbot.instance.removeIgnore(event.user, module) + event.reply(dbot.t('unignored', { + 'user': event.user, + 'module': module + })); + } + }); } else { - if(_.include(ignores.ignores, module)) { - ignores.ignores = _.without(ignores.ignores, module); - this.db.save('ignores', user.id, ignores, function(err) { - if(!err) { - dbot.instance.removeIgnore(event.user, module) - event.reply(dbot.t('unignored', { - 'user': event.user, - 'module': module - })); - } - }); - } else { - event.reply(dbot.t('invalid_unignore', { 'user': event.user })); - } - } - }.bind(this)); + event.reply(dbot.t('invalid_unignore', { 'user': event.user })); + } + } }.bind(this)); }, '~ban': function(event) { - var user = event.params[1]; - var module = event.params[2]; - - if(_.isUndefined(user) || _.isUndefined(module)) { - event.reply(dbot.t('ban_usage', {'user': event.user})); - return; - } - - if(module == '*' || _.include(dbot.config.moduleNames, module) || _.include(dbot.commands, module)) { - if(_.has(dbot.db.bans, user) && _.include(dbot.db.bans[user], module)) { - event.reply(dbot.t('already_banned', { - 'user': event.user, - 'banned': user + var user = event.input[1], + item = event.input[2]; + var banCreated = function(err, result) { + if(!err) { + event.reply(dbot.t('banned_success', { + 'user': event.user, + 'banned': user, + 'module': item })); - return; } + }; - if(_.has(dbot.db.bans, event.params[1])) { - dbot.db.bans[event.params[1]].push(module); - } else { - dbot.db.bans[event.params[1]] = [module]; - } - - event.reply(dbot.t('banned_success', { - 'user': event.user, - 'banned': user, - 'module': module - })); + if(module == '*' || _.include(dbot.config.moduleNames, item) || _.include(dbot.commands, item)) { + this.api.getUserIgnores(event.server, user, function(err, user, ignores) { + if(!err) { + if(!ignores) { + this.db.create('ignores', user.id, { + 'id': user.id, + 'ignores': [], + 'bans': [ item ] + }, banCreated); + } else { + if(!_.include(ignores.bans, item)) { + ignores.bans.push(item); + this.db.save('ignores', user.id, ignores, banCreated); + } else { + event.reply(dbot.t('already_banned', { + 'user': event.user, + 'banned': user + })); + } + } + } + }.bind(this)); } else { - event.reply(dbot.t('invalid_ban', {'user': event.user})); + event.reply(dbot.t('invalid_ban', { 'user': event.user })); } }, '~unban': function(event) { - var bannedModules = []; + var nick = event.input[1]; + var item = event.input[2]; - var user = event.params[1]; - var module = event.params[2]; - - if(_.isUndefined(user) || _.isUndefined(module)) { - event.reply(dbot.t('unban_usage', {'user': event.user})); - } else { - if(_.has(dbot.db.bans, user) && _.include(dbot.db.bans[user], module)) { - dbot.db.bans[user].splice(dbot.db.bans[user].indexOf(module), 1); - - event.reply(dbot.t('unbanned_success', { - 'user': event.user, - 'banned': user, - 'module': module - })); - } else { + this.api.getUserIgnores(event.server, nick, function(err, user, ignores) { + if(err || !ignores) { event.reply(dbot.t('invalid_unban', { 'user': event.user, - 'banned': user + 'banned': nick })); + } else { + if(_.include(ignores.bans, item)) { + ignores.bans = _.without(ignores.bans, item); + this.db.save('ignores', user.id, ignores, function(err) { + event.reply(dbot.t('unbanned_success', { + 'user': event.user, + 'banned': nick, + 'module': item + })); + }); + } else { + event.reply(dbot.t('invalid_unban', { + 'user': event.user, + 'banned': nick + })); + } } - } + }.bind(this)); }, '~ignorechannel': function(event) { @@ -204,6 +221,9 @@ var ignore = function(dbot) { } }; + commands['~ban'].regex = [/^~ban ([^ ]+) ([^ ]+)$/, 3]; + commands['~unban'].regex = [/^~unban ([^ ]+) ([^ ]+)$/, 3]; + commands['~ban'].access = 'moderator'; commands['~unban'].access = 'moderator'; commands['~ignorechannel'].access = 'moderator'; From 65be2ebcb5d2d60a9266dd2cfc5c046c35ae7792 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 11 Apr 2013 20:17:14 +0000 Subject: [PATCH 026/220] remove useless imports from ignore api --- modules/ignore/api.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/ignore/api.js b/modules/ignore/api.js index 5ee208c..aa12ed4 100644 --- a/modules/ignore/api.js +++ b/modules/ignore/api.js @@ -1,8 +1,4 @@ -var _ = require('underscore')._, - databank = require('databank'), - AlreadyExistsError = databank.AlreadyExistsError, - NoSuchThingError = databank.NoSuchThingError, - NotImplementedError = databank.NotImplementedError; +var _ = require('underscore')._; var api = function(dbot) { From 96a339a8d4a3e9b192f743e4ec3348477d128675 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 11 Apr 2013 20:17:48 +0000 Subject: [PATCH 027/220] cleanup --- modules/ignore/api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/ignore/api.js b/modules/ignore/api.js index aa12ed4..e262ca1 100644 --- a/modules/ignore/api.js +++ b/modules/ignore/api.js @@ -1,7 +1,6 @@ var _ = require('underscore')._; var api = function(dbot) { - return { // Is user ignoring command/module? 'isUserIgnoring': function(server, user, item, callback) { From 6bae0f47bff2dbc3cd9ac79f7300b6c233b618c1 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 11 Apr 2013 21:21:12 +0000 Subject: [PATCH 028/220] ~ignorechannel and ~unignorechannel now databankerised. Fixed bug with not initialising chan ignores onLoad. Ignore now fully databankerised. [#331] --- modules/command/command.js | 2 +- modules/ignore/api.js | 19 +++++++ modules/ignore/ignore.js | 103 +++++++++++++++++++++++++------------ 3 files changed, 91 insertions(+), 33 deletions(-) diff --git a/modules/command/command.js b/modules/command/command.js index 0f769f5..df14456 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -20,7 +20,7 @@ var command = function(dbot) { return; } } - + dbot.api.ignore.isUserIgnoring(event.server, event.user, commandName, function(isIgnoring) { dbot.api.ignore.isUserBanned(event.server, event.user, commandName, function(isBanned) { if(isBanned) { diff --git a/modules/ignore/api.js b/modules/ignore/api.js index e262ca1..79b1102 100644 --- a/modules/ignore/api.js +++ b/modules/ignore/api.js @@ -12,6 +12,25 @@ var api = function(dbot) { this.internalAPI.isUserImpeded(server, user, item, 'bans', callback); }, + // Is channel ignoring module? + // TODO: Command support + 'isChannelIgnoring': function(server, channelName, item, callback) { + var isIgnoring = false, + channel = false; + + this.db.search('channel_ignores', { + 'server': server, + 'name': channel + }, function(result) { + channel = result; + }, function(err) { + if(!err && channel && _.include(channel.ignores, item)) { + isIgnoring = true; + } + callback(isIgnoring); + }); + }, + // Resolve a nick and return their user and ignores object 'getUserIgnores': function(server, user, callback) { dbot.api.users.resolveUser(server, user, function(user) { diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index f465c68..8cc4d70 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -7,6 +7,7 @@ */ var _ = require('underscore')._, databank = require('databank'), + uuid = require('node-uuid'), NoSuchThingError = databank.NoSuchThingError; var ignore = function(dbot) { @@ -176,53 +177,85 @@ var ignore = function(dbot) { }, '~ignorechannel': function(event) { - var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]); - var module = event.params[2]; + var channelName = event.input[1], + module = event.input[2]; + var ignoringChannel = function(err, result) { + dbot.instance.ignoreTag(channel, module); + event.reply(dbot.t('ignoring_channel', { + 'module': module, + 'channel': channelName + })); + }; // Ignoring the value of 'ignorable' at the moment if(module == '*' || _.include(dbot.config.moduleNames, module)) { - if(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = []; - if(!_.include(dbot.db.ignores[channel], module)) { - dbot.db.ignores[channel].push(module); - dbot.instance.ignoreTag(channel, module); - event.reply(dbot.t('ignoring_channel', { - 'module': module, - 'channel': channel - })); - } else { - event.reply(dbot.t('already_ignoring_channel', { - 'module': module, - 'channel': channel - })); - } + var channel = false; + + this.db.search('channel_ignores', { + 'server': event.server, + 'name': channelName + }, function(result) { + channel = result; + }, function(err) { + if(!channel) { + var id = uuid.v4(); + this.db.create('channel_ignores', id, { + 'id': id, + 'server': event.server, + 'name': channelName, + 'ignores': [ module ] + }, ignoringChannel); + } else { + if(!_.include(channel.ignores, module)) { + channel.ignores.push(module); + this.db.save('channel_ignores', channel.id, channel, ignoringChannel); + } else { + event.reply(dbot.t('already_ignoring_channel', { + 'module': module, + 'channel': channelName + })); + } + } + }.bind(this)); } else { event.reply(dbot.t('module_not_exist', { 'module': module })); } }, '~unignorechannel': function(event) { - var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]); - var module = event.params[2]; + var channelName = event.input[1], + module = event.input[2], + channel = false; - if(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = []; - if(_.include(dbot.db.ignores[channel], module)) { - dbot.db.ignores[channel] = _.without(dbot.db.ignores[channel], module); - dbot.instance.removeIgnore(channel, module); - event.reply(dbot.t('unignoring_channel', { - 'module': module, - 'channel': channel - })); - } else { - event.reply(dbot.t('not_ignoring_channel', { - 'module': module, - 'channel': channel - })); - } + this.db.search('channel_ignores', { + 'server': event.server, + 'name': channelName + }, function(result) { + channel = result; + }, function(err) { + if(channel && _.include(channel.ignores, module)) { + channel.ignores = _.without(channel.ignores, module); + this.db.save('channel_ignores', channel.id, channel, function(err) { + dbot.instance.removeIgnore(channel, module); + event.reply(dbot.t('unignoring_channel', { + 'module': module, + 'channel': channelName + })); + }); + } else { + event.reply(dbot.t('not_ignoring_channel', { + 'module': module, + 'channel': channelName + })); + } + }.bind(this)); } }; commands['~ban'].regex = [/^~ban ([^ ]+) ([^ ]+)$/, 3]; commands['~unban'].regex = [/^~unban ([^ ]+) ([^ ]+)$/, 3]; + commands['~ignorechannel'].regex = [/^~ignorechannel ([^ ]+) ([^ ]+)$/, 3]; + commands['~unignorechannel'].regex = [/^~unignorechannel ([^ ]+) ([^ ]+)$/, 3]; commands['~ban'].access = 'moderator'; commands['~unban'].access = 'moderator'; @@ -243,6 +276,12 @@ var ignore = function(dbot) { } }); }, function(err) { }); + + this.db.scan('channel_ignores', function(channel) { + _.each(channel.ignores, function(module) { + dbot.instance.ignoreTag(channel, module); + }); + }, function(err) { }); }; }; From b376a8fa54aa197fd47d3e878ee7973f3afb20b7 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 00:38:51 +0000 Subject: [PATCH 029/220] rewrote all of quotes commands because array shims just werent good enough [#331] --- modules/quotes/commands.js | 249 ++++++++++++++++++++++--------------- modules/quotes/config.json | 2 +- 2 files changed, 147 insertions(+), 104 deletions(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index 5fc8324..e9b6719 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -1,34 +1,45 @@ var _ = require('underscore')._, databank = require('databank'), - AlreadyExistsError = databank.AlreadyExistsError, - NoSuchThingError = databank.NoSuchThingError; + uuid = require('node-uuid'); var commands = function(dbot) { var quotes = dbot.db.quoteArrs; var commands = { - /*** Quote Addition ***/ // Add a quote to a category '~qadd': function(event) { - var key = event.input[1].toLowerCase(); - var quote = event.input[2]; + var key = event.input[1].toLowerCase().trim(), + quote = event.input[2], + newCount; + var quoteAdded = function(err, result) { + this.rmAllowed = true; + dbot.api.event.emit('~qadd', { + 'key': key, + 'text': quote + }); + event.reply(dbot.t('quote_saved', { + 'category': key, + 'count': newCount + })); + }.bind(this); - this.db.indexOf('quote_category', key, quote, function(err, index) { - if(index == null || index == -1) { - this.db.append('quote_category', key, quote, function(err, newCount) { - this.rmAllowed = true; - dbot.api.event.emit('~qadd', { - 'key': key, - 'text': quote - }); - event.reply(dbot.t('quote_saved', { - 'category': key, - 'count': newCount - })); - }.bind(this)); + var category = false; + this.db.search('quote_category', { 'name': key }, function(result) { + category = result; + }, function(err) { + if(!category) { + var id = uuid.v4(); + newCount = 1; + this.db.create('quote_category', id, { + 'id': id, + 'name': key, + 'quotes': [ quote ], + 'creator': event.user + }, quoteAdded); } else { - event.reply(dbot.t('quote_exists')); + newCount = category.quotes.push(quote); + this.db.save('quote_category', category.id, category, quoteAdded); } }.bind(this)); }, @@ -42,27 +53,38 @@ var commands = function(dbot) { // Retrieve quote from a category in the database. '~q': function(event) { - var name = event.input[1].trim().toLowerCase(); - this.db.read('quote_category', name, function(err, category) { - if(!err) { - var quoteIndex = _.random(0, category.length - 1); - event.reply(name + ': ' + category[quoteIndex]); - } else if(err instanceof NoSuchThingError) { + var name = event.input[1].trim().toLowerCase(), + category = false; + + this.db.search('quote_category', { 'name': name }, function(result) { + category = result; + }, function(err) { + if(category) { + var quotes = category.quotes; + var index = _.random(0, quotes.length - 1); + event.reply(name + ': ' + quotes[index]); + } else { event.reply(dbot.t('category_not_found', { 'category': name })); } }); }, + // Choose a random quote category and a random quote from that + // TODO: This is quite inefficient, but databank must evolve to do otherwise. '~rq': function(event) { - if(_.keys(quotes).length > 0) { - var category = _.keys(quotes)[_.random(0, _.size(quotes) -1)]; - event.reply(category + ': ' + this.internalAPI.interpolatedQuote(event.server, event.channel.name, category)); - } else { - event.reply(dbot.t('no_results')); - } + var categories = []; + this.db.scan('quote_category', function(result) { + categories.push(result); + }, function(err) { + var cIndex = _.random(0, _.size(categories) -1); + var qIndex = _.random(0, categories[cIndex].quotes.length - 1); + event.reply(categories[cIndex].name + ': ' + categories[cIndex].quotes[qIndex]); + }); }, - /*** Quote Removal ***/ + /*** Quote Removal + TODO: Remove empty quote categories + ***/ // Show number of quotes in removal cache '~rmstatus': function(event) { @@ -90,11 +112,10 @@ var commands = function(dbot) { var rmCacheCount = rmCache.length; _.each(rmCache, function(quote, index) { - this.db.append('quote_category', quote.key, quote.quote, function(err, length) { - if(err) { - // QQ - } - }); + //TODO: Add quote add API func + var qadd = _.clone(event); + qadd.message = '~qadd ' + quote.key + '=' + quote.quote; + dbot.instance.emit(qadd); }); rmCache.length = 0; @@ -105,16 +126,22 @@ var commands = function(dbot) { // Remove last quote from category '~rmlast': function(event) { if(this.rmAllowed === true || _.include(dbot.config.admins, event.user)) { - var key = event.input[1].trim().toLowerCase(); + var key = event.input[1].trim().toLowerCase(), + category = false; - this.db.slice('quote_category', key, -1, 1, function(err, removed) { - if(!err) { - this.internalAPI.resetRemoveTimer(event, key, removed); - event.reply(dbot.t('removed_from', { - 'quote': removed, - 'category': key - })); - } else if(err instanceof NoSuchThingError) { + this.db.search('quote_category', { 'name': key }, function(result) { + category = result; + }, function(err) { + if(category) { + var removedQuote = category.quotes.pop(); + this.db.save('quote_category', category.id, category, function(err) { + this.internalAPI.resetRemoveTimer(event, key, removedQuote); + event.reply(dbot.t('removed_from', { + 'quote': removedQuote, + 'category': key + })); + }.bind(this)); + } else { event.reply(dbot.t('category_not_found', { 'category': key })); } }.bind(this)); @@ -127,22 +154,30 @@ var commands = function(dbot) { '~rm': function(event) { if(this.rmAllowed == true || _.include(dbot.config.admins, event.user)) { var key = event.input[1].trim().toLowerCase(); - var quote = event.input[2]; + quote = event.input[2], + category = false; - this.db.remove('quote_category', key, quote, function(err) { - if(!err) { - this.internalAPI.resetRemoveTimer(event, key, quote); - event.reply(dbot.t('removed_from', { - 'category': key, - 'quote': quote - })); - } else if(err instanceof NoSuchThingError) { + this.db.search('quote_category', { 'name': key }, function(result) { + category = result; + }, function(err) { + if(category) { + if(category.quotes.indexOf(quote) != -1) { + category.quotes = _.without(category.quotes, quote); + this.db.save('quote_category', category.id, category, function(err) { + this.internalAPI.resetRemoveTimer(event, key, quote); + event.reply(dbot.t('removed_from', { + 'category': key, + 'quote': quote + })); + }.bind(this)); + } else { + event.reply(dbot.t('q_not_exist_under', { + 'category': key, + 'quote': quote + })); + } + } else { event.reply(dbot.t('category_not_found', { 'category': key })); - } else if(err instanceof NoSuchItemError) { - event.reply(dbot.t('q_not_exist_under', { - 'category': key, - 'quote': quote - })); } }.bind(this)); } else { @@ -156,39 +191,39 @@ var commands = function(dbot) { '~qstats': function(event) { var quoteSizes = {}; this.db.scan('quote_category', function(category) { - // TODO: get name? - quoteSizes[name] = category.length; - }.bind(this), function(err) { - if(err) { - // QQ + if(category) { + quoteSizes[category.name] = category.quotes.length; } + }.bind(this), function(err) { + var qSizes = _.chain(quoteSizes) + .pairs() + .sortBy(function(category) { return category[1] }) + .reverse() + .first(10) + .value(); + + var qString = dbot.t('large_categories'); + for(var i=0;i Date: Fri, 12 Apr 2013 17:30:56 +0000 Subject: [PATCH 030/220] update ignore to use save instead of save|create [#331] --- modules/ignore/ignore.js | 121 +++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 61 deletions(-) diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index 8cc4d70..8edd5e8 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -37,15 +37,6 @@ var ignore = function(dbot) { }) .pluck('name') .value(); - var ignoreCreated = function(err, result) { - if(!err) { - dbot.instance.ignoreTag(event.user, module); - event.reply(dbot.t('ignored', { - 'user': event.user, - 'module': module - })); - } - }; if(_.isUndefined(module)) { event.reply(dbot.t('ignore_usage', { @@ -57,19 +48,29 @@ var ignore = function(dbot) { this.api.getUserIgnores(event.server, event.user, function(err, user, ignores) { if(!err) { if(!ignores) { - this.db.create('ignores', user.id, { + ignores = { 'id': user.id, - 'ignores': [ module ], + 'ignores': [], 'bans': [] - }, ignoreCreated); - } else { - if(!_.include(ignores.ignores, module)) { - ignores.ignores.push(module); - this.db.save('ignores', user.id, ignores, ignoreCreated); - } else { - event.reply(dbot.t('already_ignoring', { 'user': event.user })); - } + }; } + + if(!_.include(ignores.ignores, module)) { + ignores.ignores.push(module); + this.db.save('ignores', user.id, ignores, function(err) { + if(!err) { + dbot.instance.ignoreTag(event.user, module); + event.reply(dbot.t('ignored', { + 'user': event.user, + 'module': module + })); + } + }); + } else { + event.reply(dbot.t('already_ignoring', { 'user': event.user })); + } + } else { + // User doesn't exist } }.bind(this)); } else { @@ -107,37 +108,36 @@ var ignore = function(dbot) { }, '~ban': function(event) { - var user = event.input[1], + var nick = event.input[1], item = event.input[2]; - var banCreated = function(err, result) { - if(!err) { - event.reply(dbot.t('banned_success', { - 'user': event.user, - 'banned': user, - 'module': item - })); - } - }; if(module == '*' || _.include(dbot.config.moduleNames, item) || _.include(dbot.commands, item)) { - this.api.getUserIgnores(event.server, user, function(err, user, ignores) { + this.api.getUserIgnores(event.server, nick, function(err, user, ignores) { if(!err) { if(!ignores) { - this.db.create('ignores', user.id, { + ignores = { 'id': user.id, 'ignores': [], - 'bans': [ item ] - }, banCreated); + 'bans': [] + }; + } + + if(!_.include(ignores.bans, item)) { + ignores.bans.push(item); + this.db.save('ignores', user.id, ignores, function(err) { + if(!err) { + event.reply(dbot.t('banned_success', { + 'user': event.user, + 'banned': nick, + 'module': item + })); + } + }); } else { - if(!_.include(ignores.bans, item)) { - ignores.bans.push(item); - this.db.save('ignores', user.id, ignores, banCreated); - } else { - event.reply(dbot.t('already_banned', { - 'user': event.user, - 'banned': user - })); - } + event.reply(dbot.t('already_banned', { + 'user': event.user, + 'banned': nick + })); } } }.bind(this)); @@ -147,8 +147,8 @@ var ignore = function(dbot) { }, '~unban': function(event) { - var nick = event.input[1]; - var item = event.input[2]; + var nick = event.input[1], + item = event.input[2]; this.api.getUserIgnores(event.server, nick, function(err, user, ignores) { if(err || !ignores) { @@ -179,13 +179,6 @@ var ignore = function(dbot) { '~ignorechannel': function(event) { var channelName = event.input[1], module = event.input[2]; - var ignoringChannel = function(err, result) { - dbot.instance.ignoreTag(channel, module); - event.reply(dbot.t('ignoring_channel', { - 'module': module, - 'channel': channelName - })); - }; // Ignoring the value of 'ignorable' at the moment if(module == '*' || _.include(dbot.config.moduleNames, module)) { @@ -199,22 +192,28 @@ var ignore = function(dbot) { }, function(err) { if(!channel) { var id = uuid.v4(); - this.db.create('channel_ignores', id, { + channel = { 'id': id, 'server': event.server, 'name': channelName, - 'ignores': [ module ] - }, ignoringChannel); - } else { - if(!_.include(channel.ignores, module)) { - channel.ignores.push(module); - this.db.save('channel_ignores', channel.id, channel, ignoringChannel); - } else { - event.reply(dbot.t('already_ignoring_channel', { + 'ignores': [] + }; + } + + if(!_.include(channel.ignores, module)) { + channel.ignores.push(module); + this.db.save('channel_ignores', channel.id, channel, function(err) { + dbot.instance.ignoreTag(channel, module); + event.reply(dbot.t('ignoring_channel', { 'module': module, 'channel': channelName })); - } + }); + } else { + event.reply(dbot.t('already_ignoring_channel', { + 'module': module, + 'channel': channelName + })); } }.bind(this)); } else { From 58b58aa15fe26e15a3a25341a35d8102ff1ff23d Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 17:33:13 +0000 Subject: [PATCH 031/220] ~qadd uses only save rather than save|create [#331] --- modules/quotes/commands.js | 40 ++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index e9b6719..f126360 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -11,36 +11,34 @@ var commands = function(dbot) { '~qadd': function(event) { var key = event.input[1].toLowerCase().trim(), quote = event.input[2], - newCount; - var quoteAdded = function(err, result) { - this.rmAllowed = true; - dbot.api.event.emit('~qadd', { - 'key': key, - 'text': quote - }); - event.reply(dbot.t('quote_saved', { - 'category': key, - 'count': newCount - })); - }.bind(this); + newCount, + category = false; - var category = false; this.db.search('quote_category', { 'name': key }, function(result) { category = result; }, function(err) { if(!category) { var id = uuid.v4(); - newCount = 1; - this.db.create('quote_category', id, { + category = { 'id': id, 'name': key, - 'quotes': [ quote ], + 'quotes': [], 'creator': event.user - }, quoteAdded); - } else { - newCount = category.quotes.push(quote); - this.db.save('quote_category', category.id, category, quoteAdded); - } + }; + } + + newCount = category.quotes.push(quote); + this.db.save('quote_category', category.id, category, function(err) { + this.rmAllowed = true; + dbot.api.event.emit('~qadd', { + 'key': key, + 'text': quote + }); + event.reply(dbot.t('quote_saved', { + 'category': key, + 'count': newCount + })); + }); }.bind(this)); }, From 38c18366a35a9524772fa99cabbf854b3cc8b160 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 17:42:11 +0000 Subject: [PATCH 032/220] Stop command execution syntax running if line is not a command. Note [#337] was fixed a few commits ago too. --- modules/command/command.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/command/command.js b/modules/command/command.js index df14456..5a7ccee 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -13,6 +13,9 @@ var command = function(dbot) { */ this.listener = function(event) { var commandName = event.params[0]; + if(commandName.charAt(0) != '~') { + return; + } if(!_.has(dbot.commands, commandName)) { if(_.has(dbot.modules, 'quotes')) { commandName = '~'; From 11dcaac44c3ad2222a6dd812b86b51fe227aa4f3 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 17:59:51 +0000 Subject: [PATCH 033/220] last commit meant admin commands couldnt be run. will rethink later. --- modules/command/command.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/command/command.js b/modules/command/command.js index 5a7ccee..df14456 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -13,9 +13,6 @@ var command = function(dbot) { */ this.listener = function(event) { var commandName = event.params[0]; - if(commandName.charAt(0) != '~') { - return; - } if(!_.has(dbot.commands, commandName)) { if(_.has(dbot.modules, 'quotes')) { commandName = '~'; From 0098b076709eea0af2d23f7edf368462fe7f8d57 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 18:03:52 +0000 Subject: [PATCH 034/220] ~qrename command to rename quote categories [Close #345] --- modules/quotes/commands.js | 30 ++++++++++++++++++++++++++++++ modules/quotes/strings.json | 6 ++++++ 2 files changed, 36 insertions(+) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index f126360..e96b358 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -270,6 +270,34 @@ var commands = function(dbot) { } }, + // Rename a quote category + '~qrename': function(event) { + var oldName = event.input[1], + newName = event.input[2], + oldCategory = false, + newCategory = false; + + this.db.search('quote_category', { 'name': newName }, function(result) { + newCategory = result; + }, function(err) { + if(!newCategory) { + this.db.search('quote_category', { 'name': oldName }, function(result) { + oldCategory = result; + }, function(err) { + oldCategory.name = newName; + this.db.save('quote_category', oldCategory.id, oldCategory, function(err) { + event.reply(dbot.t('category_renamed', { + 'oldName': oldName, + 'newName': newName + })); + }); + }.bind(this)); + } else { + event.reply(dbot.t('newcat_exists', { 'newcat': newName })); + } + }.bind(this)); + }, + // Link to quote web page '~link': function(event) { var key = event.input[1].toLowerCase(), @@ -304,10 +332,12 @@ var commands = function(dbot) { commands['~rm'].regex = [/^~rm ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2]; commands['~qadd'].regex = [/^~qadd ([\d\w-]+[\d\w\s-]*)[ ]?=[ ]?(.+)$/, 3]; + commands['~qrename'].regex = [/^~qrename ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; commands['~link'].regex = [/^~link ([\d\w\s-]*)/, 2]; commands['~rmconfirm'].access = 'moderator'; commands['~rmdeny'].access = 'moderator'; + commands['~qrename'].access = 'moderator'; return commands; }; diff --git a/modules/quotes/strings.json b/modules/quotes/strings.json index 2622f68..50e9a71 100644 --- a/modules/quotes/strings.json +++ b/modules/quotes/strings.json @@ -129,5 +129,11 @@ }, "web_not_configured": { "en": "Cannot link to category. Web module is either not loaded or misconfigured." + }, + "category_renamed": { + "en": "Category ~{oldName} renamed to ~{newName}." + }, + "newcat_exists": { + "en": "Category ~{newcat} already exists. Delete that first or use ~qmerge." } } From 5892bd83aac718b41a5a8497ce889911dd1f8508 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 18:20:39 +0000 Subject: [PATCH 035/220] ~qmerge command [Close #347] --- modules/quotes/commands.js | 37 ++++++++++++++++++++++++++++++++++++- modules/quotes/strings.json | 3 +++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index e96b358..ef90295 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -255,7 +255,7 @@ var commands = function(dbot) { 'count': category.quotes.length })); } else { - event.reply(dbot.t('category_not_found', { 'category': name })); + event.reply(dbot.t('category_not_found', { 'category': key })); } }); } else { @@ -298,6 +298,40 @@ var commands = function(dbot) { }.bind(this)); }, + // Merge a quote category insto another + '~qmerge': function(event) { + var primaryName = event.input[1], + secondName = event.input[2], + primary = false, + secondary = false; + + this.db.search('quote_category', { 'name': primaryName }, function(result) { + primary = result; + }, function(err) { + if(primary) { + this.db.search('quote_category', { 'name': secondName }, function(result) { + secondary = result; + }, function(err) { + if(secondary) { + primary.quotes = _.union(primary.quotes, secondary.quotes); + this.db.save('quote_category', primary.id, primary, function(err) { + this.db.del('quote_category', secondary.id, function(err) { + event.reply(dbot.t('categories_merged', { + 'from': secondName, + 'into': primaryName + })); + }); + }.bind(this)); + } else { + event.reply(dbot.t('category_not_found', { 'category': secondName })); + } + }.bind(this)); + } else { + event.reply(dbot.t('category_not_found', { 'category': primaryName })); + } + }.bind(this)); + }, + // Link to quote web page '~link': function(event) { var key = event.input[1].toLowerCase(), @@ -333,6 +367,7 @@ var commands = function(dbot) { commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2]; commands['~qadd'].regex = [/^~qadd ([\d\w-]+[\d\w\s-]*)[ ]?=[ ]?(.+)$/, 3]; commands['~qrename'].regex = [/^~qrename ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; + commands['~qmerge'].regex = [/^~qmerge ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; commands['~link'].regex = [/^~link ([\d\w\s-]*)/, 2]; commands['~rmconfirm'].access = 'moderator'; diff --git a/modules/quotes/strings.json b/modules/quotes/strings.json index 50e9a71..c1aac84 100644 --- a/modules/quotes/strings.json +++ b/modules/quotes/strings.json @@ -135,5 +135,8 @@ }, "newcat_exists": { "en": "Category ~{newcat} already exists. Delete that first or use ~qmerge." + }, + "categories_merged": { + "en": "Category ~{from} and its quotes merged into ~{into}." } } From 7ceba078e231e2373913d814575602326f4f0505 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 19:28:23 +0000 Subject: [PATCH 036/220] Empty quote category records are now removed [#331][#346] --- jsbot | 2 +- modules/github | 2 +- modules/quotes/commands.js | 47 +++++++++++++++++++++++--------------- modules/stats | 2 +- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/jsbot b/jsbot index 84a4783..2be1731 160000 --- a/jsbot +++ b/jsbot @@ -1 +1 @@ -Subproject commit 84a4783db76bdd729bd720c43485893ebe78a8c9 +Subproject commit 2be1731911bf2a207b963ac79656f626e09eac6f diff --git a/modules/github b/modules/github index 93337f4..e9e9089 160000 --- a/modules/github +++ b/modules/github @@ -1 +1 @@ -Subproject commit 93337f4ddf6b9cfa28f2972b4ac893b672d3227e +Subproject commit e9e9089f282b0455a481460ebec17a4672617ceb diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index ef90295..e770309 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -80,9 +80,7 @@ var commands = function(dbot) { }); }, - /*** Quote Removal - TODO: Remove empty quote categories - ***/ + /*** Quote Removal ***/ // Show number of quotes in removal cache '~rmstatus': function(event) { @@ -125,20 +123,26 @@ var commands = function(dbot) { '~rmlast': function(event) { if(this.rmAllowed === true || _.include(dbot.config.admins, event.user)) { var key = event.input[1].trim().toLowerCase(), - category = false; + category = false, + removedQuote; + var quoteRemoved = function(err) { + this.internalAPI.resetRemoveTimer(event, key, removedQuote); + event.reply(dbot.t('removed_from', { + 'quote': removedQuote, + 'category': key + })); + }.bind(this); this.db.search('quote_category', { 'name': key }, function(result) { category = result; }, function(err) { if(category) { - var removedQuote = category.quotes.pop(); - this.db.save('quote_category', category.id, category, function(err) { - this.internalAPI.resetRemoveTimer(event, key, removedQuote); - event.reply(dbot.t('removed_from', { - 'quote': removedQuote, - 'category': key - })); - }.bind(this)); + removedQuote = category.quotes.pop(); + if(category.quotes.length == 0) { + this.db.del('quote_category', category.id, quoteRemoved); + } else { + this.db.save('quote_category', category.id, category, quoteRemoved); + } } else { event.reply(dbot.t('category_not_found', { 'category': key })); } @@ -154,6 +158,13 @@ var commands = function(dbot) { var key = event.input[1].trim().toLowerCase(); quote = event.input[2], category = false; + var quoteRemoved = function(err) { + this.internalAPI.resetRemoveTimer(event, key, quote); + event.reply(dbot.t('removed_from', { + 'category': key, + 'quote': quote + })); + }.bind(this); this.db.search('quote_category', { 'name': key }, function(result) { category = result; @@ -161,13 +172,11 @@ var commands = function(dbot) { if(category) { if(category.quotes.indexOf(quote) != -1) { category.quotes = _.without(category.quotes, quote); - this.db.save('quote_category', category.id, category, function(err) { - this.internalAPI.resetRemoveTimer(event, key, quote); - event.reply(dbot.t('removed_from', { - 'category': key, - 'quote': quote - })); - }.bind(this)); + if(category.quotes.length == 0) { + this.db.del('quote_category', category.id, quoteRemoved); + } else { + this.db.save('quote_category', category.id, category, quoteRemoved); + } } else { event.reply(dbot.t('q_not_exist_under', { 'category': key, diff --git a/modules/stats b/modules/stats index eee5861..e5519f3 160000 --- a/modules/stats +++ b/modules/stats @@ -1 +1 @@ -Subproject commit eee5861dca00f0d2b2f146820870abb888ed8f4a +Subproject commit e5519f353abf00e4ec25702f8e02231c9b1f5258 From b8a25062b5e67082fbebde900b125d4355dceffb Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 21:08:11 +0000 Subject: [PATCH 037/220] Interpolated quotes revived and plugged into ~q. Also a event inspecific getQuote API function implemented. [#331] --- modules/quotes/commands.js | 16 +++----- modules/quotes/quotes.js | 80 +++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 52 deletions(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index e770309..6979c73 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -51,18 +51,12 @@ var commands = function(dbot) { // Retrieve quote from a category in the database. '~q': function(event) { - var name = event.input[1].trim().toLowerCase(), - category = false; - - this.db.search('quote_category', { 'name': name }, function(result) { - category = result; - }, function(err) { - if(category) { - var quotes = category.quotes; - var index = _.random(0, quotes.length - 1); - event.reply(name + ': ' + quotes[index]); + var key = event.input[1]; + this.api.getInterpolatedQuote(event.server, event.channel, key, function(quote) { + if(quote) { + event.reply(key + ': ' + quote); } else { - event.reply(dbot.t('category_not_found', { 'category': name })); + event.reply(dbot.t('category_not_found', { 'category': key })); } }); }, diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index 269e252..8c0ee8f 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -9,37 +9,28 @@ var quotes = function(dbot) { this.rmTimer; this.internalAPI = { - // Retrieve a random quote from a given category, interpolating any quote - // references (~~QUOTE CATEGORY~~) within it - 'interpolatedQuote': function(server, channel, key, quoteTree) { - if(!_.isUndefined(quoteTree) && quoteTree.indexOf(key) != -1) { - return ''; - } else if(_.isUndefined(quoteTree)) { - quoteTree = []; - } - - var index = _.random(0, this.quotes[key].length - 1); - var quoteString = this.quotes[key][index]; - + 'interpolatedQuote': function(server, channel, key, quote, callback) { // Parse quote interpolations - var quoteRefs = quoteString.match(/~~([\d\w\s-]*)~~/g); - var thisRef; - - while(quoteRefs && (thisRef = quoteRefs.shift()) !== undefined) { - var cleanRef = dbot.cleanNick(thisRef.replace(/^~~/,'').replace(/~~$/,'').trim()); - if(cleanRef === '-nicks-') { - var randomNick = dbot.api.users.getRandomChannelUser(server, channel); - quoteString = quoteString.replace("~~" + cleanRef + "~~", randomNick); - quoteTree.pop(); - } else if(_.has(this.quotes, cleanRef)) { - quoteTree.push(key); - quoteString = quoteString.replace("~~" + cleanRef + "~~", - this.internalAPI.interpolatedQuote(server, channel, cleanRef, quoteTree.slice())); - quoteTree.pop(); + var quoteRefs = quote.match(/~~([\d\w\s-]*)~~/g); + if(quoteRefs) { + var ref = dbot.cleanNick(quoteRefs[0].replace(/^~~/,'').replace(/~~$/,'').trim()); + if(ref === '-nicks-') { + dbot.api.users.getRandomChannelUser(server, channel, function(user) { + quote = quote.replace('~~' + ref + '~~', randomNick); + this.internalAPI.interpolatedQuote(server, channel, key, quote, callback); + }.bind(this)); + } else { + this.api.getQuote(ref, function(interQuote) { + if(!interQuote || ref == key) { + interQuote = ''; + } + quote = quote.replace('~~' + ref + '~~', interQuote); + this.internalAPI.interpolatedQuote(server, channel, key, quote, callback); + }.bind(this)); } + } else { + callback(quote); } - - return quoteString; }.bind(this), 'resetRemoveTimer': function(event, key, quote) { @@ -67,22 +58,29 @@ var quotes = function(dbot) { }; this.api = { - 'getQuote': function(event, category) { - var key = category.trim().toLowerCase(); - var altKey; - if(key.split(' ').length > 0) { - altKey = key.replace(/ /g, '_'); - } + 'getQuote': function(key, callback) { + var category = false; + key = key.trim().toLowerCase(), - if(key.charAt(0) !== '_') { // lol - if(_.has(this.quotes, key)) { - return this.internalAPI.interpolatedQuote(event.server, event.channel.name, key); - } else if(_.has(this.quotes, altKey)) { - return this.internalAPI.interpolatedQuote(event.server, event.channel.name, altKey); + this.db.search('quote_category', { 'name': key }, function(result) { + category = result; + }, function(err) { + if(category) { + var quotes = category.quotes; + var index = _.random(0, quotes.length - 1); + callback(quotes[index]); } else { - return false; + callback(false); } - } + }); + }, + + 'getInterpolatedQuote': function(server, channel, key, callback) { + key = key.trim().toLowerCase(), + + this.api.getQuote(key, function(quote) { + this.internalAPI.interpolatedQuote(server, channel, key, quote, callback); + }.bind(this)); } }; From b1f450a3e1cf6d42b4146a3601e15e26dec72e15 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 21:16:56 +0000 Subject: [PATCH 038/220] quotes listener operational --- modules/quotes/quotes.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index 8c0ee8f..48e36cf 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -99,10 +99,11 @@ var quotes = function(dbot) { dbot.instance.emit(event); } } else if(event.action == 'JOIN') { - var userQuote = this.api.getQuote(event, event.user) - if(userQuote) { - event.reply(event.user + ': ' + this.api.getQuote(event, event.user)); - } + var userQuote = this.api.getQuote(event.user, function(quote) { + if(quote) { + event.reply(event.user + ': ' + quote); + } + }); } }.bind(this); this.on = ['PRIVMSG', 'JOIN']; From f17f926a3bd05f390ee68e17c6ca464947bb2cf3 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 21:52:46 +0000 Subject: [PATCH 039/220] ~qsearch can search all categories with * [#331] --- modules/quotes/commands.js | 66 +++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index 6979c73..69a5a79 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -217,29 +217,57 @@ var commands = function(dbot) { var haystack = event.input[1].trim().toLowerCase(), needle = event.input[2], category = false; - - this.db.search('quote_category', { 'name': haystack }, function(result) { - category = result; - }, function(err) { - if(category) { - var matches = _.filter(category.quotes, function(quote) { - return quote.indexOf(needle) != -1; - }); - - if(matches.length == 0) { - event.reply(dbot.t('no_results')); - } else { + + if(haystack == '*') { + var matches = []; + this.db.scan('quote_category', function(category) { + if(category) { + var theseMatches =_.each(category.quotes, function(quote) { + if(quote.indexOf(needle) != -1) { + matches.push({ + 'category': category.name, + 'quote': quote + }); + } + }); + } + }, function(err) { + if(matches.length > 0) { + console.log(matches); event.reply(dbot.t('search_results', { - 'category': haystack, + 'category': matches[0].category, 'needle': needle, - 'quote': matches[0], + 'quote': matches[0].quote, 'matches': matches.length })); + } else { + event.reply(dbot.t('no_results')); } - } else { - event.reply(dbot.t('empty_category')); - } - }); + }); + } else { + this.db.search('quote_category', { 'name': haystack }, function(result) { + category = result; + }, function(err) { + if(category) { + var matches = _.filter(category.quotes, function(quote) { + return quote.indexOf(needle) != -1; + }); + + if(matches.length == 0) { + event.reply(dbot.t('no_results')); + } else { + event.reply(dbot.t('search_results', { + 'category': haystack, + 'needle': needle, + 'quote': matches[0], + 'matches': matches.length + })); + } + } else { + event.reply(dbot.t('empty_category')); + } + }); + } }, // Count quotes in a given category or total quotes overall @@ -365,7 +393,7 @@ var commands = function(dbot) { commands['~'].regex = [/^~([\d\w\s-]*)/, 2]; commands['~q'].regex = [/^~q ([\d\w\s-]*)/, 2]; - commands['~qsearch'].regex = [/^~qsearch ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; + commands['~qsearch'].regex = [/^~qsearch ([\d\w\s*-]+?)[ ]?=[ ]?(.+)$/, 3]; commands['~rm'].regex = [/^~rm ([\d\w\s-]+?)[ ]?=[ ]?(.+)$/, 3]; commands['~rmlast'].regex = [/^~rmlast ([\d\w\s-]*)/, 2]; commands['~qadd'].regex = [/^~qadd ([\d\w-]+[\d\w\s-]*)[ ]?=[ ]?(.+)$/, 3]; From aad0b5e372654916ec910456484616930120aacc Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 12 Apr 2013 22:30:45 +0000 Subject: [PATCH 040/220] Some cleanup of quotes module postdatabank [#331] Addition of addQuote API and updated places what use it [#349] --- modules/quotes/commands.js | 47 +++++++++------------------------- modules/quotes/quotes.js | 52 ++++++++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 48 deletions(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index 69a5a79..d7e6de3 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -3,43 +3,24 @@ var _ = require('underscore')._, uuid = require('node-uuid'); var commands = function(dbot) { - var quotes = dbot.db.quoteArrs; var commands = { /*** Quote Addition ***/ // Add a quote to a category '~qadd': function(event) { - var key = event.input[1].toLowerCase().trim(), - quote = event.input[2], - newCount, - category = false; + var key = event.input[1].toLowerCase().trim(); + quote = event.input[2]; - this.db.search('quote_category', { 'name': key }, function(result) { - category = result; - }, function(err) { - if(!category) { - var id = uuid.v4(); - category = { - 'id': id, - 'name': key, - 'quotes': [], - 'creator': event.user - }; - } - - newCount = category.quotes.push(quote); - this.db.save('quote_category', category.id, category, function(err) { - this.rmAllowed = true; - dbot.api.event.emit('~qadd', { - 'key': key, - 'text': quote - }); - event.reply(dbot.t('quote_saved', { - 'category': key, - 'count': newCount - })); + this.api.addQuote(key, quote, event.user, function(newCount) { + dbot.api.event.emit('~qadd', { + 'key': key, + 'text': quote }); - }.bind(this)); + event.reply(dbot.t('quote_saved', { + 'category': key, + 'count': newCount + })); + }); }, /*** Quote Retrieval ***/ @@ -102,10 +83,7 @@ var commands = function(dbot) { var rmCacheCount = rmCache.length; _.each(rmCache, function(quote, index) { - //TODO: Add quote add API func - var qadd = _.clone(event); - qadd.message = '~qadd ' + quote.key + '=' + quote.quote; - dbot.instance.emit(qadd); + this.api.addQuote(quote.key, quote.quote, event.user, function(newCount) { }); }); rmCache.length = 0; @@ -233,7 +211,6 @@ var commands = function(dbot) { } }, function(err) { if(matches.length > 0) { - console.log(matches); event.reply(dbot.t('search_results', { 'category': matches[0].category, 'needle': needle, diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index 48e36cf..b996614 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -1,16 +1,16 @@ -var _ = require('underscore')._; +var _ = require('underscore')._, + uuid = require('node-uuid'); var quotes = function(dbot) { dbot.sessionData.rmCache = []; - this.quotes = dbot.db.quoteArrs, - this.addStack = [], - this.rmAllowed = true, - this.rmCache = dbot.sessionData.rmCache, + this.rmCache = dbot.sessionData.rmCache; + this.quotes = dbot.db.quoteArrs; + this.rmAllowed = true; this.rmTimer; this.internalAPI = { + // Parse quote interpolations 'interpolatedQuote': function(server, channel, key, quote, callback) { - // Parse quote interpolations var quoteRefs = quote.match(/~~([\d\w\s-]*)~~/g); if(quoteRefs) { var ref = dbot.cleanNick(quoteRefs[0].replace(/^~~/,'').replace(/~~$/,'').trim()); @@ -58,9 +58,36 @@ var quotes = function(dbot) { }; this.api = { + 'addQuote': function(key, quote, user, callback) { + var key = key.toLowerCase().trim(), + newCount, + category = false; + + this.db.search('quote_category', { 'name': key }, function(result) { + category = result; + }, function(err) { + if(!category) { + var id = uuid.v4(); + category = { + 'id': id, + 'name': key, + 'quotes': [], + 'owner': user + }; + } + + newCount = category.quotes.push(quote); + this.db.save('quote_category', category.id, category, function(err) { + this.rmAllowed = true; + callback(newCount); + }.bind(this)); + }.bind(this)); + + }, + 'getQuote': function(key, callback) { - var category = false; - key = key.trim().toLowerCase(), + var category = false, + key = key.trim().toLowerCase(); this.db.search('quote_category', { 'name': key }, function(result) { category = result; @@ -93,13 +120,12 @@ var quotes = function(dbot) { } if(once) { - event.message = '~qadd realityonce=reality ' + once[1]; - event.action = 'PRIVMSG'; - event.params = event.message.split(' '); - dbot.instance.emit(event); + this.api.addQuote('realityonce', 'reality' + once[1], event.user, function(newCount) { + event.reply('\'reality ' + once[1] + '\' saved (' + newCount + ').'); + }); } } else if(event.action == 'JOIN') { - var userQuote = this.api.getQuote(event.user, function(quote) { + var userQuote = this.api.addQuote(event.user, function(quote) { if(quote) { event.reply(event.user + ': ' + quote); } From b31d26b91235bbf4a1048772fdf5c0479aa85109 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 13 Apr 2013 14:59:50 +0000 Subject: [PATCH 041/220] make ~qmerge a moderator command [#347] --- modules/quotes/commands.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index fdd35f5..9641086 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -387,6 +387,7 @@ var commands = function(dbot) { commands['~rmconfirm'].access = 'moderator'; commands['~rmdeny'].access = 'moderator'; commands['~qrename'].access = 'moderator'; + commands['~qmerge'].access = 'moderator'; return commands; }; From a4cb96a6a425254d0ee7f006a212029cd55c4696 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Apr 2013 15:16:38 +0000 Subject: [PATCH 042/220] bump jsbot --- jsbot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsbot b/jsbot index 2be1731..11cbb75 160000 --- a/jsbot +++ b/jsbot @@ -1 +1 @@ -Subproject commit 2be1731911bf2a207b963ac79656f626e09eac6f +Subproject commit 11cbb75b504fbb703450a2f8c938d5a81680109c From ce092b688e2ad90417912db241d84c345f1b2a13 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Apr 2013 15:33:55 +0000 Subject: [PATCH 043/220] update ban and quiet in kick.api to use configured chanserv [#261] --- modules/kick/config.json | 3 ++- modules/kick/kick.js | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/kick/config.json b/modules/kick/config.json index d765613..c32561f 100644 --- a/modules/kick/config.json +++ b/modules/kick/config.json @@ -3,5 +3,6 @@ "dependencies": [ "command", "report", "users" ], "help": "http://github.com/reality/depressionbot/blob/master/modules/kick/README.md", "ignorable": true, - "countSilently": true + "countSilently": true, + "chanserv": "ChanServ" } diff --git a/modules/kick/kick.js b/modules/kick/kick.js index 5308615..a5210a1 100644 --- a/modules/kick/kick.js +++ b/modules/kick/kick.js @@ -4,7 +4,11 @@ var kick = function(dbot) { this.api = { 'ban': function(server, user, channel) { - dbot.instance.connections[server].send('MODE ' + channel + ' +b ' + user + '!*@*'); + dbot.say(event.server, this.config.chanserv, '!ban ' + user) + }, + + 'quiet': function(server, user, channel) { + dbot.say(event.server, this.config.chanserv, '!quiet ' + user) }, 'kick': function(server, user, channel, msg) { From 5420bd846b0ea677ab910bb9d4efd409c09b6410 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Apr 2013 20:00:53 +0000 Subject: [PATCH 044/220] modify data structures and fix a bunch of broken async stuff in users [#331] --- modules/users/api.js | 6 +++ modules/users/users.js | 96 ++++++++++++++++++++++-------------------- 2 files changed, 56 insertions(+), 46 deletions(-) diff --git a/modules/users/api.js b/modules/users/api.js index ebfefea..bfec8d5 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -139,6 +139,12 @@ var api = function(dbot) { } }; + api['resolveUser'].external = true; + api['resolveUser'].extMap = [ 'server', 'nick', 'callback' ]; + + api['getChannel'].external = true; + api['getChannel'].extMap = [ 'server', 'channel', 'callback' ]; + return api; }; diff --git a/modules/users/users.js b/modules/users/users.js index ec0e3a4..8fa1717 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -26,19 +26,30 @@ var users = function(dbot) { }); }.bind(this), - 'addChannelUser': function(user, channelName) { - user.channels.push(channelName); - this.db.save('users', user.id, user, function(err) { + 'createChannel': function(server, name, callback) { + var id = uuid.v4(); + this.db.create('channel_users', id, { + 'id': id, + 'server': server, + 'name': name, + 'users': [] + }, function(err, result) { if(!err) { - this.api.getChannel(user.server, channelName, function(channel) { - channel.users.push(user.primaryNick); - this.db.save('channel_users', channel.id, channel, function(err) { - if(!err) { - dbot.api.event.emit('new_channel_user', [ user, channel]); - } - }); - }.bind(this)); + dbot.api.event.emit('new_channel', [ result ]); + callback(result); } + }); + }.bind(this), + + 'addChannelUser': function(user, channelName, callback) { + this.api.getChannel(user.server, channelName, function(channel) { + channel.users.push(user.id); + this.db.save('channel_users', channel.id, channel, function(err) { + if(!err) { + dbot.api.event.emit('new_channel_user', [ user, channel ]); + callback(); + } + }); }.bind(this)); }.bind(this), @@ -63,15 +74,13 @@ var users = function(dbot) { if(event.action == 'JOIN' && event.user != dbot.config.name) { this.api.resolveUser(event.server, event.user, function(user) { if(!user) { // User does not yet exist - this.internalAPI.createUser(event.server, event.user, event.channel, function(result) { - user = result; - if(!_.include(user.channels, event.channel)) { // User not yet channel user - this.internalAPI.addChannelUser(user, event.channel.name); - } - }); + this.internalAPI.createUser(event.server, event.user, event.channel.name, function(result) { + this.internalAPI.addChannelUser(result, event.channel.name, function(err) { }); + }.bind(this)); } else { - if(!_.include(user.channels, event.channel)) { // User not yet channel user - this.internalAPI.addChannelUser(user, event.channel.name); + if(!_.include(user.channels, event.channel.name)) { // User not yet channel user + users.channels.push(event.channel.name); + this.internalAPI.addChannelUser(user, event.channel.name, function(err) { }); } user.currentNick = event.user; @@ -105,38 +114,33 @@ var users = function(dbot) { this.onLoad = function() { dbot.instance.addListener('366', 'users', function(event) { this.api.getChannel(event.server, event.channel.name, function(channel) { - if(!channel) { // Channel does not yet exist - var id = uuid.v4(); - this.db.create('channel_users', id, { - 'id': id, - 'server': event.server, - 'name': event.channel.name, - 'users': [] - }, function(err, result) { - if(!err) { - channel = result; - dbot.api.event.emit('new_channel', [ channel ]); - } - }); - } - _.each(event.channel.nicks, function(nick) { - var nick = nick.name; - this.api.resolveUser(event.server, nick, function(user) { - if(!user) { - this.internalAPI.createUser(event.server, nick, event.channel, function(result) { - user = result; + var checkChannelUsers = function(channel) { + _.each(event.channel.nicks, function(nick) { + var nick = nick.name; + this.api.resolveUser(event.server, nick, function(user) { + if(!user) { + this.internalAPI.createUser(event.server, nick, event.channel.name, function(result) { + channel.users.push(result.id); + }.bind(this)); + } else { if(!_.include(user.channels, event.channel)) { - this.internalAPI.addChannelUser(user, event.channel.name); + channel.users.push(user.id); } - }); - } else { - if(!_.include(user.channels, event.channel)) { - this.internalAPI.addChannelUser(user, event.channel.name); } - } + }.bind(this)); + }, this); + + process.nextTick(function() { + this.db.save('channel_users', channel.id, channel, function(err) { }); }.bind(this)); - }, this); + }.bind(this); + + if(!channel) { // Channel does not yet exist + this.internalAPI.createChannel(event.server, event.channel.name, checkChannelUsers); + } else { + checkChannelUsers(channel); + } }.bind(this)); }.bind(this)); From 4319ee18e1605751e4cdcfe54c7b5378dff62d3a Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 20 Apr 2013 11:21:04 +0000 Subject: [PATCH 045/220] ~addalias command for adding non-used nicks to user alias records [#373] --- modules/users/commands.js | 27 +++++++++++++++++++++++++++ modules/users/strings.json | 6 ++++++ 2 files changed, 33 insertions(+) diff --git a/modules/users/commands.js b/modules/users/commands.js index 6a31979..8a89e97 100644 --- a/modules/users/commands.js +++ b/modules/users/commands.js @@ -35,6 +35,31 @@ var commands = function(dbot) { }); }, + '~addalias': function(event) { + var nick = event.input[1], + alias = event.input[2]; + + this.api.resolveUser(event.server, nick, function(user) { + if(user) { + if(!_.include(user.aliases, alias)) { + user.aliases.push(alias); + this.db.save('users', user.id, user, function(err) { + if(!err) { + event.reply(dbot.t('alias_added', { + 'user': user.primaryNick, + 'alias': alias + })); + } + }); + } else { + event.reply(dbot.t('alias_exists', { 'alias': alias })); + } + } else { + event.reply(dbot.t('unknown_alias', { 'alias': nick })); + } + }.bind(this)); + }, + '~setaliasparent': function(event) { var newPrimary = event.params[1].trim(); this.api.resolveUser(event.server, newPrimary, function(user) { @@ -104,9 +129,11 @@ var commands = function(dbot) { commands['~alias'].regex = [/^~alias ([\d\w[\]{}^|\\`_-]+?)/, 2]; commands['~setaliasparent'].regex = [/^~setaliasparent ([\d\w[\]{}^|\\`_-]+?)/, 2]; commands['~mergeusers'].regex = [/^~mergeusers ([\d\w[\]{}^|\\`_-]+?)\s*?([\d\w[\]{}^|\\`_-]+?)/, 3]; + commands['~addalias'].regex = [/^~addalias ([\d\w[\]{}^|\\`_-]+?) ([\d\w[\]{}^|\\`_-]+?)$/, 3]; commands['~setaliasparent'].access = 'moderator'; commands['~mergeusers'].access = 'moderator'; + commands['~addalias'].access = 'moderator'; return commands; }; diff --git a/modules/users/strings.json b/modules/users/strings.json index e7bbb94..96a1883 100644 --- a/modules/users/strings.json +++ b/modules/users/strings.json @@ -28,5 +28,11 @@ "en": "{old_user} and their aliases have been merged into {new_user}.", "na'vi": "{old_user} ulte stxo alahe {new_user} lu set.", "nl": "{old_user} en zijn aliassen zijn samengevoegd met {new_user}." + }, + "alias_exists": { + "en": "Alias {alias} already exists." + }, + "alias_added": { + "en": "Alias {alias} added to {user}." } } From 466cb12c9448280ad9616ae29a3c3f23781a0bf6 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 20 Apr 2013 13:50:47 +0000 Subject: [PATCH 046/220] getCurrentConfig, pushconfig, showconfig and setconfig databankerised [#331] --- modules/admin/admin.js | 29 +++++++ modules/admin/commands.js | 159 ++++++++++++++------------------------ modules/admin/config.json | 1 + 3 files changed, 89 insertions(+), 100 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index f1edaf3..23feda0 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -7,6 +7,35 @@ var fs = require('fs'), _ = require('underscore')._; var admin = function(dbot) { + this.internalAPI = { + 'getCurrentConfig': function(configKey, callback) { + if(configKey) { + this.db.read('config', configKey, function(err, cRecord) { + if(cRecord) { + callback(cRecord.value) + } else { + var configPath = dbot.config; + configKey = configKey.split('.'); + + for(var i=0;i " + newOption); - configPath['user'][configKey] = newOption; - dbot.reloadModules(); + event.reply(configPath + ": " + config + " -> " + newOption); + config = newOption; + this.db.save('config', configPath, { 'value': config }, function(err) { + dbot.reloadModules(); + }); + } else { + event.reply('Config path doesn\'t exist, bro.'); + } + }.bind(this)); } else { event.reply("This config option cannot be altered while the bot is running."); } }, 'pushconfig': function(event) { - var configPathString = event.params[1], - configKey = _.last(configPathString.split('.')), - newOption = event.params[2]; + var configPath = event.input[1], + newOption = event.input[2]; - if(!_.include(noChangeConfig, configKey)) { - var configPath = getCurrentConfig(configPathString); - if(configPath == false || _.isUndefined(configPath.value)) { - event.reply("Config key doesn't exist bro"); - return; - } - var currentArray = configPath.value; - - if(!_.isArray(currentArray)) { - event.reply("Config option is not an array. Try 'setconfig'."); - return - } - - event.reply(configPathString + ": " + currentArray + " << " + newOption); - currentArray.push(newOption); - dbot.reloadModules(); + if(!_.include(noChangeConfig, configPath)) { + this.internalAPI.getCurrentConfig(configPath, function(config) { + if(config) { + if(_.isArray(config)) { + event.reply(configPath + ": " + config + " << " + newOption); + config.push(newOption); + this.db.save('config', configPath, { 'value': config }, function(err) { + dbot.reloadModules(); + }); + } else { + event.reply("Config option is not an array. Try 'setconfig'."); + } + } else { + event.reply('Config path doesn\'t exist, bro.'); + } + }.bind(this)); + } else { + event.reply("This config option cannot be altered while the bot is running."); } }, 'showconfig': function(event) { - var configPathString = event.params[1]; - var configPath = getCurrentConfig(configPathString); - - if(configPathString) { - var configKey = _.last(configPathString.split('.')); - if(configKey == false) { - event.reply("Config path doesn't exist"); - return; - } - - if(_.isArray(configPath.value)) { - event.reply(configKey + ': ' + configPath.value); - } else if(_.isObject(configPath.value)) { - event.reply('Config keys in ' + configPathString + ': ' + Object.keys(configPath.value)); - } else { - event.reply(configKey + ': ' + configPath.value); - } + var configPath = event.params[1]; + if(configPath) { + this.internalAPI.getCurrentConfig(configPath, function(config) { + if(config) { + if(_.isArray(config)) { + event.reply('Config keys in ' + configPath + ': ' + config); + } else if(_.isObject(config)) { + event.reply('Config keys in ' + configPath + ': ' + _.keys(config)); + } else { + event.reply(configPath + ': ' + config); + } + } else { + event.reply('Config path doesn\'t exist, bro.'); + } + }); } else { - event.reply('Config keys in root: ' + Object.keys(configPath['default'])); + event.reply('Config keys in root: ' + _.keys(dbot.config)); } - } + } }; _.each(commands, function(command) { @@ -277,6 +233,9 @@ var commands = function(dbot) { commands['opme'].access = 'moderator'; commands['say'].access = 'moderator'; + commands['pushconfig'].regex = [/pushconfig ([^ ]+) ([^ ]+)/, 3]; + commands['setconfig'].regex = [/setconfig ([^ ]+) ([^ ]+)/, 3]; + return commands; }; diff --git a/modules/admin/config.json b/modules/admin/config.json index f87d4b9..cd5a001 100644 --- a/modules/admin/config.json +++ b/modules/admin/config.json @@ -1,5 +1,6 @@ { "ignorable": false, + "dbType": "redis", "dependencies": [ "command" ], "help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md" } From 3cd4513fe45c825738522639b2765f0512c0749f Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 20 Apr 2013 16:08:34 +0000 Subject: [PATCH 047/220] fix module loader. admin sets config keys onload. I am incredibly annoyed. [#331] --- modules/admin/admin.js | 19 ++++++++++ modules/admin/commands.js | 10 ++++-- run.js | 76 ++++++++++++++++++--------------------- 3 files changed, 61 insertions(+), 44 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index 23feda0..6923b19 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -36,6 +36,25 @@ var admin = function(dbot) { } }.bind(this) }; + + this.onLoad = function() { + var configMap = dbot.config; + this.db.scan('config', function(config) { + if(config) { + var currentPath = configMap, + key = config.key.split('.'), + value = config.value; + + for(var i=0;i " + newOption); config = newOption; - this.db.save('config', configPath, { 'value': config }, function(err) { + this.db.save('config', configPath, { + 'key': configPath, + 'value': config + }, function(err) { dbot.reloadModules(); }); } else { @@ -186,7 +189,10 @@ var commands = function(dbot) { if(_.isArray(config)) { event.reply(configPath + ": " + config + " << " + newOption); config.push(newOption); - this.db.save('config', configPath, { 'value': config }, function(err) { + this.db.save('config', configPath, { + 'key': configPath, + 'value': config + }, function(err) { dbot.reloadModules(); }); } else { diff --git a/run.js b/run.js index 2c7a21f..2568e96 100644 --- a/run.js +++ b/run.js @@ -131,12 +131,8 @@ DBot.prototype.reloadModules = function() { this.modules = {}; this.commands = {}; this.api = {}; - this.commandMap = {}; // Map of which commands belong to which modules this.usage = {}; - // Load config changes - _.extend(this.config, this.db.config); - try { this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8')); } catch(err) { @@ -157,7 +153,6 @@ DBot.prototype.reloadModules = function() { require('./snippets'); this.instance.removeListeners(); - _.each(moduleNames, function(name) { this.status[name] = true; var moduleDir = './modules/' + name + '/'; @@ -207,13 +202,29 @@ DBot.prototype.reloadModules = function() { } this.config[name] = config; - var loadModule = function(db) { + // Groovy funky database shit + if(!_.has(config, 'dbType') || config.dbType == 'olde') { + // Generate missing DB keys + _.each(config.dbKeys, function(dbKey) { + if(!_.has(this.db, dbKey)) { + this.db[dbKey] = {}; + } + }, this); + } else { + // Just use the name of the module for now, add dbKey iteration later + this.ddb.createDB(name, config.dbType, {}, function(db) {}); + } + }.bind(this)); + + process.nextTick(function() { + _.each(moduleNames, function(name) { + var moduleDir = './modules/' + name + '/'; var rawModule = require(moduleDir + name); var module = rawModule.fetch(this); this.rawModules.push(rawModule); module.name = name; - module.db = db; + module.db = this.ddb.databanks[name]; module.config = this.config[name]; // Load the module data @@ -276,45 +287,26 @@ DBot.prototype.reloadModules = function() { } this.modules[module.name] = module; - - if(_.has(this.modules, 'web')) this.modules.web.reloadPages(); - - _.each(this.modules, function(module, name) { - if(module.onLoad) { - try { - module.onLoad(); - } catch(err) { - this.status[name] = 'Error in onLoad: ' + err + ' ' + err.stack.split('\n')[1].trim(); - console.log('MODULE ONLOAD ERROR (' + name + '): ' + err ); - } - } - }, this); - }.bind(this); - - // Groovy funky database shit - if(!_.has(config, 'dbType') || config.dbType == 'olde') { - // Generate missing DB keys - _.each(config.dbKeys, function(dbKey) { - if(!_.has(this.db, dbKey)) { - this.db[dbKey] = {}; - } - }, this); - loadModule(this.db); - } else { - // Just use the name of the module for now, add dbKey iteration later - this.ddb.createDB(name, config.dbType, {}, function(db) { - loadModule(db); - }); - } + }.bind(this)); }.bind(this)); - + + process.nextTick(function() { + if(_.has(this.modules, 'web')) this.modules.web.reloadPages(); + _.each(this.modules, function(module, name) { + if(module.onLoad) { + try { + module.onLoad(); + } catch(err) { + this.status[name] = 'Error in onLoad: ' + err + ' ' + err.stack.split('\n')[1].trim(); + console.log('MODULE ONLOAD ERROR (' + name + '): ' + err ); + } + } + }, this); + }.bind(this)); + this.save(); }; -// Load the module itself -DBot.prototype.loadModule = function(name, db) { - } - DBot.prototype.cleanNick = function(key) { key = key.toLowerCase(); while(key.endsWith("_")) { From 135b6ecbbab26aa89aebe5c074535c9dfdf85fc8 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 20 Apr 2013 16:28:12 +0000 Subject: [PATCH 048/220] fix users not getting pushed to chan [#390] --- modules/users/users.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index 8fa1717..524be1e 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -79,7 +79,7 @@ var users = function(dbot) { }.bind(this)); } else { if(!_.include(user.channels, event.channel.name)) { // User not yet channel user - users.channels.push(event.channel.name); + user.channels.push(event.channel.name); this.internalAPI.addChannelUser(user, event.channel.name, function(err) { }); } @@ -114,7 +114,6 @@ var users = function(dbot) { this.onLoad = function() { dbot.instance.addListener('366', 'users', function(event) { this.api.getChannel(event.server, event.channel.name, function(channel) { - var checkChannelUsers = function(channel) { _.each(event.channel.nicks, function(nick) { var nick = nick.name; From ecd5b4b23c53e816d64eb228972f745400307365 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 20 Apr 2013 16:34:02 +0000 Subject: [PATCH 049/220] getallusers external --- modules/users/api.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/users/api.js b/modules/users/api.js index bfec8d5..d894f4c 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -145,6 +145,9 @@ var api = function(dbot) { api['getChannel'].external = true; api['getChannel'].extMap = [ 'server', 'channel', 'callback' ]; + api['getAllUsers'].external = true; + api['getAllUsers'].extMap = [ 'callback' ]; + return api; }; From bd2d0a89530fc30b67d949bcbea525f7853b2a9d Mon Sep 17 00:00:00 2001 From: Sam Nicholls Date: Sat, 20 Apr 2013 20:40:30 +0200 Subject: [PATCH 050/220] getUser get->read --- modules/users/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/users/api.js b/modules/users/api.js index d894f4c..830dd39 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -27,7 +27,7 @@ var api = function(dbot) { // Return a user record given a UUID 'getUser': function(uuid, callback) { - this.db.get('users', uuid, function(err, user) { + this.db.read('users', uuid, function(err, user) { if(err) user = false; callback(user); }); From ab0a110a8ec00dd12d5f24f461379a6196dd4dd9 Mon Sep 17 00:00:00 2001 From: Sam Nicholls Date: Sat, 20 Apr 2013 22:51:36 +0100 Subject: [PATCH 051/220] Initial databankerisation of profile [#331] * Stats functionality disabled until completion of SamStudio8/dbot-stats#98 * Profile grid currently only works with dbType set to memory * Merge user functionality temporarily disabled --- modules/profile/api.js | 117 ++++++++++++++++++-------------- modules/profile/commands.js | 42 ++++-------- modules/profile/config.json | 2 +- modules/profile/pages.js | 106 +++++++++++++++++------------ modules/profile/profile.js | 17 +---- views/profile/error.jade | 1 + views/profile/not_found.jade | 1 + views/profile/profile_grid.jade | 8 +-- 8 files changed, 150 insertions(+), 144 deletions(-) create mode 100644 views/profile/error.jade create mode 100644 views/profile/not_found.jade diff --git a/modules/profile/api.js b/modules/profile/api.js index b1c36d2..6e0b818 100644 --- a/modules/profile/api.js +++ b/modules/profile/api.js @@ -4,64 +4,77 @@ var api = function(dbot) { return { /** - * Create a profile for a new primary user on a given server. - * If the server does not already exist, create it. + * Create a new profile for a given "databanked" user. + * Typically only called as a hook to the new_user emit event. + * TODO(@samstudio8) Migrate to internalAPI */ - "createProfile": function(server, primary){ - var primaryLower = primary.toLowerCase(); - - if(!_.has(this.profiles, server)){ - this.profiles[server] = {}; - } - if(!_.has(this.profiles[server], primaryLower)){ - this.profiles[server][primaryLower] = { - "profile": {}, - "preferences": {} - }; - this.profiles[server][primaryLower].profile.primary = primary; - } - - // Ensure all profiles have the keys specified by config.json - //TODO(samstudio8) Currently only handles "top-level" - _.defaults(this.profiles[server][primaryLower].profile, this.config.schema.profile); - _.defaults(this.profiles[server][primaryLower].preferences, this.config.schema.preferences); - }, - - /** - * Given a server and "new" alias, resolve this alias to the user's - * new primary name and move profile data pertaining to the alias to - * the new primary name. - */ - 'renameProfile': function(server, alias){ - if(!_.has(this.profiles, server)) return; - var profiles = dbot.db.profiles[server]; - - if(_.has(profiles, alias)){ - var primary = dbot.api.users.resolveUser(server, alias, true); - var primaryLower = primary.toLowerCase(); - alias = alias.trim().toLowerCase(); - - profiles[primaryLower] = profiles[alias]; - profiles[primaryLower].profile.primary = primary; - delete profiles[alias]; + "createProfile": function(user, callback){ + if(user){ + this.db.create('profiles', user.id, { + 'id': user.id, + 'profile': dbot.config.profile.schema.profile, + 'preferences': dbot.config.profile.schema.preferences + }, function(err, result){ + if(err){ + console.log(err); + } + }); } }, + + //TODO(samstudio8) Merge Profiles + 'mergeProfile': function(server, nick, callback){ + console.log("mergeProfile not implemented"); + }, - /** - * Given a server and a primary username which has been converted to a - * secondary alias find and remove the profile for the alias. - */ - 'mergeProfile': function(server, mergeFromPrimary){ - if(!_.has(this.profiles, server)) return; - var profiles = dbot.db.profiles[server]; + 'getProfile': function(server, nick, callback){ + dbot.api.users.resolveUser(server, nick, function(user){ + if(user){ + this.db.read('profiles', user.id, function(err, profile){ + callback(false, user, profile); + }); + } + else{ + callback(true, null, null); + } + }.bind(this)); + }, - mergeFromPrimary = mergeFromPrimary.toLowerCase(); - var mergeToPrimary = dbot.api.users.resolveUser(server, mergeFromPrimary, true).toLowerCase(); - if(!_.has(profiles, mergeToPrimary) - || !_.has(profiles, mergeFromPrimary)) return; + 'getAllProfiles': function(callback){ + var profiles = []; + this.db.scan('profiles', function(profile){ + profiles.push(profile); + }, function(err){ + if(!err){ + callback(profiles); + } + else{ + console.log(err); + } + }); + }, - // Remove the profile of the alias - delete profiles[mergeFromPrimary]; + 'setProperty': function(server, nick, field, value, callback){ + this.api.getProfile(server, nick, function(err, user, profile){ + if(!err){ + profile.profile[field] = value; + this.db.save('profiles', user.id, profile, function(err){ + if(!err){ + callback("Ok!"); + } + }); + } + }.bind(this)); + }, + + 'getProperty': function(server, nick, field, callback){ + this.api.getProfile(server, nick, function(err, user, profile){ + if(!err){ + if(profile.profile[field]){ + callback(profile.profile[field]); + } + } + }.bind(this)); }, } }; diff --git a/modules/profile/commands.js b/modules/profile/commands.js index 609bcb6..f8c81a0 100644 --- a/modules/profile/commands.js +++ b/modules/profile/commands.js @@ -5,23 +5,10 @@ var commands = function(dbot){ "~getprop": function(event){ if(event.params[1]){ - var primary = dbot.api.users.resolveUser(event.server, event.user); - var res = dbot.db.profiles[event.server][primary.toLowerCase()].profile[event.params[1]]; - if(res){ - event.reply(res); - } - else{ - event.reply("Nope."); - } - } - }, - - "~setprop": function(event){ - if(event.input[1] && event.input[2]){ - if(_.has(this.config.schema.profile, event.input[1])){ - var primary = dbot.api.users.resolveUser(event.server, event.user); - dbot.db.profiles[event.server][primary.toLowerCase()].profile[event.input[1]] = event.input[2]; - event.reply("Property set, maybe?"); + if(_.has(this.config.schema.profile, event.params[1])){ + this.api.getProperty(event.server, event.user, event.params[1], function(reply){ + event.reply(reply); + }); } else{ event.reply("Invalid property. Go home."); @@ -29,23 +16,18 @@ var commands = function(dbot){ } }, - "~profile": function(event){ - if(event.params[1]){ - var primary = dbot.api.users.resolveUser(event.server, event.params[1]); - if(_.has(dbot.db.profiles[event.server], primary.toLowerCase())){ - event.reply(dbot.api.web.getUrl("profile/"+event.server+"/"+primary.toLowerCase())); + "~setprop": function(event){ + if(event.input[1] && event.input[2]){ + if(_.has(this.config.schema.profile, event.input[1])){ + this.api.setProperty(event.server, event.user, event.input[1], event.input[2], function(reply){ + event.reply(reply); + }); } else{ - event.reply("No profile found for "+event.params[1]); + event.reply("Invalid property. Go home."); } } - else{ - event.message = '~profile ' + event.user; - event.action = 'PRIVMSG'; - event.params = event.message.split(' '); - dbot.instance.emit(event); - } - } + }, }; commands['~setprop'].regex = [/~setprop ([^ ]+) (.+)/, 3]; diff --git a/modules/profile/config.json b/modules/profile/config.json index 24f5027..ce23b0f 100644 --- a/modules/profile/config.json +++ b/modules/profile/config.json @@ -1,6 +1,6 @@ { "ignorable": false, - "dbKeys": [ "profiles" ], + "dbType": "memory", "help": "https://github.com/reality/depressionbot/blob/master/modules/profile/README.md", "schema": { "profile": { diff --git a/modules/profile/pages.js b/modules/profile/pages.js index b01ed28..73b4c08 100644 --- a/modules/profile/pages.js +++ b/modules/profile/pages.js @@ -5,58 +5,80 @@ var pages = function(dbot) { return { '/profile/:connection/:user': function(req, res) { var connection = req.params.connection; - var user = dbot.cleanNick(req.params.user); + var nick = req.params.user; - var primary = dbot.api.users.resolveUser(connection, user, true); - //var profile = dbot.api.profile.getProfile(primary); - var profile = dbot.db.profiles[connection][primary.toLowerCase()].profile; - var stats = dbot.api.stats.getUserChansStats(connection, primary.toLowerCase(), [ - "lines", "words", "lincent", "wpl", "in_mentions"] - ); + dbot.api.users.resolveUser(connection, nick, function(user){ + if(user){ + dbot.api.profile.getProfile(connection, user.primaryNick, function(err, user, profile){ + if(!err){ + var stats = []; - res.render('profile', { - 'name': dbot.config.name, - 'connection': connection, - 'primary': primary, - 'profile': profile, - 'stats': stats.channels, + /*TODO(@samstudio8) + * stats functionality currently disabled as it has not been databanked + */ + //var stats = dbot.api.stats.getUserChansStats(connection, user.primaryNick, [ + // "lines", "words", "lincent", "wpl", "in_mentions"] + //); + + res.render('profile', { + 'name': dbot.config.name, + 'connection': connection, + 'primary': user.primaryNick, + 'profile': profile.profile, + 'stats': stats.channels, + }); + } + else{ + res.render('error', { + }); + } + }); + } + else{ + res.render('not_found', { + }); + } }); }, '/profile/:connection': function(req, res) { - var connection = req.params.connection; - var profiles = dbot.db.profiles[connection]; + dbot.api.profile.getAllProfiles(function(profiles){ + var thumbnails = []; + _.each(profiles, function(profile){ + var nick = dbot.api.users.getUser(profile.id, function(user){ + if(user){ - // TODO: Clean up - _.each(profiles, function(profile) { - if(_.has(dbot.db.quoteArrs, profile.profile.primary) && !profile.profile.avatar) { - var category = dbot.db.quoteArrs[profile.profile.primary]; - var avatar = _.find(category, function(quote) { - return quote.match(/(\.jpg|\.png|\.jpeg)$/i); + /*TODO(@tmenari / @samstudio8) + * if username has a quote array and no avatar: + * search their quote array for a jpg, png, jpeg or gif + * set this as their new avatar + */ + + if(profile.profile.avatar){ + thumbnails.push({ + "avatar": profile.profile.avatar, + "nick": user.primaryNick + }); + } + } }); - if(avatar) profile.profile.avatar = avatar; - } - }); + }); - var nicks = []; - for (var p in profiles) { - if (profiles.hasOwnProperty(p) && profiles[p].profile.avatar) { - nicks.push(p); - } - } - nicks.sort(function(a, b) { - var x = profiles[a].profile.primary.toLowerCase(); - var y = profiles[b].profile.primary.toLowerCase(); - if(x > y) return 1; - if(x < y) return -1; - return 0; - }); + process.nextTick(function(){ + thumbnails.sort(function(a, b) { + var x = a.nick.toLowerCase(); + var y = b.nick.toLowerCase(); + if(x > y) return 1; + if(x < y) return -1; + return 0; + }); - res.render('profile_grid', { - 'name': dbot.config.name, - 'connection': connection, - 'nicks': nicks, - 'profiles': profiles, + res.render('profile_grid', { + 'name': dbot.config.name, + 'connection': req.params.connection, + 'thumbnails': thumbnails, + }); + }); }); } } diff --git a/modules/profile/profile.js b/modules/profile/profile.js index 740790c..f2fb088 100644 --- a/modules/profile/profile.js +++ b/modules/profile/profile.js @@ -2,27 +2,14 @@ var _ = require('underscore')._; var profile = function(dbot) { - this.profiles = dbot.db.profiles; - - /** - * Iterate over known user profiles and ensure they contain all the - * required properties as defined in the configuation. - */ this.onLoad = function(){ var api = this.api; var schema = this.config.schema; - // Ensure all known users have a profile - _.each(dbot.api.users.getAllUsers(), function(server, serverName){ - _.each(server, function(primary, primaryi){ - api.createProfile(serverName, primary); - }); - }); - dbot.save(); - // Add API Hooks dbot.api.command.addHook('~setaliasparent', this.api.renameProfile); - dbot.api.command.addHook('~mergeusers', this.api.mergeProfile); + //TODO(@samstudio8) Profile Merging + //dbot.api.command.addHook('~mergeusers', this.api.mergeProfile); dbot.api.event.addHook('new_user', this.api.createProfile); }; }; diff --git a/views/profile/error.jade b/views/profile/error.jade new file mode 100644 index 0000000..d722b61 --- /dev/null +++ b/views/profile/error.jade @@ -0,0 +1 @@ +h1 Error diff --git a/views/profile/not_found.jade b/views/profile/not_found.jade new file mode 100644 index 0000000..b68964e --- /dev/null +++ b/views/profile/not_found.jade @@ -0,0 +1 @@ +h1 Not Found diff --git a/views/profile/profile_grid.jade b/views/profile/profile_grid.jade index ba7b108..7a335f1 100644 --- a/views/profile/profile_grid.jade +++ b/views/profile/profile_grid.jade @@ -18,9 +18,9 @@ block content a(href='../connections') « Connections ul.thumbnails - each nick in nicks + each thumbnail in thumbnails li.span2 - a.thumbnail(href='/profile/'+connection+'/'+encodeURIComponent(nick)) + a.thumbnail(href='/profile/'+connection+'/'+encodeURIComponent(thumbnail.nick)) div.imgwrap - img(src="#{profiles[nick].profile.avatar}", alt="#{profiles[nick].profile.primary}'s photo") - span.nicks #{profiles[nick].profile.primary} + img(src="#{thumbnail.avatar}", alt="#{thumbnail.nick}'s photo") + span.nicks #{thumbnail.nick} From 0d76ce4166669887b0498175ede6904998a42e14 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 21 Apr 2013 14:11:35 +0000 Subject: [PATCH 052/220] switch users to use redis driver [#331] --- modules/users/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/users/config.json b/modules/users/config.json index 07f200d..34927cb 100644 --- a/modules/users/config.json +++ b/modules/users/config.json @@ -3,5 +3,5 @@ "dependencies": [ "command", "event" ], "dbKeys": [ "knownUsers" ], "help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md", - "dbType": "memory" + "dbType": "redis" } From 5aaa9f8856264a05f7f9756ebfe01c6eb284d484 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 21 Apr 2013 14:17:29 +0000 Subject: [PATCH 053/220] additional channels are added to user records from 366 event [#331] --- modules/users/users.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/users/users.js b/modules/users/users.js index 524be1e..3fdab59 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -123,8 +123,10 @@ var users = function(dbot) { channel.users.push(result.id); }.bind(this)); } else { - if(!_.include(user.channels, event.channel)) { + if(!_.include(user.channels, event.channel.name)) { channel.users.push(user.id); + user.channels.push(event.channel.name); + this.db.save('users', user.id, user, function(err) { }); } } }.bind(this)); From 3130350f58efcc3b1789747cb39ca8d14cf2279f Mon Sep 17 00:00:00 2001 From: Sam Nicholls Date: Sun, 21 Apr 2013 15:27:08 +0100 Subject: [PATCH 054/220] Check getProfile read was successful --- modules/profile/api.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/profile/api.js b/modules/profile/api.js index 6e0b818..2bf7b05 100644 --- a/modules/profile/api.js +++ b/modules/profile/api.js @@ -31,7 +31,12 @@ var api = function(dbot) { dbot.api.users.resolveUser(server, nick, function(user){ if(user){ this.db.read('profiles', user.id, function(err, profile){ - callback(false, user, profile); + if(!err){ + callback(false, user, profile); + } + else{ + callback(true, null, null); + } }); } else{ From 65b410416cbd897aa74c2b5bc87e4eb2a3d3a4f5 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 21 Apr 2013 14:51:59 +0000 Subject: [PATCH 055/220] Module loader properly iterates all automatically loaded dependencies [#399] --- modules/command/config.json | 2 +- run.js | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/command/config.json b/modules/command/config.json index bace93b..6395f6d 100644 --- a/modules/command/config.json +++ b/modules/command/config.json @@ -1,5 +1,5 @@ { "ignorable": false, "help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md", - "dbKeys": [ "ignores", "bans" ] + "dbKeys": [ "ignores", "bans", "users" ] } diff --git a/run.js b/run.js index 2568e96..b6297b0 100644 --- a/run.js +++ b/run.js @@ -153,9 +153,13 @@ DBot.prototype.reloadModules = function() { require('./snippets'); this.instance.removeListeners(); - _.each(moduleNames, function(name) { + + var name, moduleDir, config; + for(i=0;i Date: Sun, 21 Apr 2013 16:10:24 +0100 Subject: [PATCH 056/220] Profile onLoad check [#331][Close #398] --- modules/profile/api.js | 18 +++++++++++++++++- modules/profile/config.json | 2 +- modules/profile/profile.js | 19 ++++++++++++++++--- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/modules/profile/api.js b/modules/profile/api.js index 2bf7b05..d9ac410 100644 --- a/modules/profile/api.js +++ b/modules/profile/api.js @@ -35,7 +35,7 @@ var api = function(dbot) { callback(false, user, profile); } else{ - callback(true, null, null); + callback(true, user, null); } }); } @@ -45,6 +45,22 @@ var api = function(dbot) { }.bind(this)); }, + 'getProfileByUUID': function(uuid, callback){ + if(uuid){ + this.db.read('profiles', uuid, function(err, profile){ + if(!err){ + callback(false, uuid, profile); + } + else{ + callback(true, uuid, null); + } + }); + } + else{ + callback(true, null, null); + } + }, + 'getAllProfiles': function(callback){ var profiles = []; this.db.scan('profiles', function(profile){ diff --git a/modules/profile/config.json b/modules/profile/config.json index ce23b0f..9984f3e 100644 --- a/modules/profile/config.json +++ b/modules/profile/config.json @@ -1,6 +1,6 @@ { "ignorable": false, - "dbType": "memory", + "dbType": "redis", "help": "https://github.com/reality/depressionbot/blob/master/modules/profile/README.md", "schema": { "profile": { diff --git a/modules/profile/profile.js b/modules/profile/profile.js index f2fb088..2a28d5c 100644 --- a/modules/profile/profile.js +++ b/modules/profile/profile.js @@ -3,14 +3,27 @@ var _ = require('underscore')._; var profile = function(dbot) { this.onLoad = function(){ - var api = this.api; var schema = this.config.schema; + // Ensure all users have a profile + dbot.api.users.getAllUsers(function(users){ + if(users){ + _.each(users, function(user){ + this.api.getProfileByUUID(user.id, function(err, uuid, profile){ + // If function returns an error and uuid, create a new profile + if(err && uuid){ + this.api.createProfile(user); + } + }.bind(this)); + }.bind(this)); + } + }.bind(this)); + // Add API Hooks - dbot.api.command.addHook('~setaliasparent', this.api.renameProfile); + dbot.api.event.addHook('new_user', this.api.createProfile); + //TODO(@samstudio8) Profile Merging //dbot.api.command.addHook('~mergeusers', this.api.mergeProfile); - dbot.api.event.addHook('new_user', this.api.createProfile); }; }; From 8e8953999d1ff57e78954315fd2c804c43153420 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 22 Apr 2013 14:22:35 +0000 Subject: [PATCH 057/220] Various database branch fixes [#331]: * Admin module doesn't try to use reload string when it's not there. * Fix dent event hookin * Fix quote retrieval (two ~q definitions and no false check before interpolate) * Change databankerised modules to use redis for testing --- modules/admin/admin.js | 1 + modules/admin/commands.js | 2 +- modules/dent/config.json | 2 +- modules/dent/dent.js | 2 +- modules/ignore/config.json | 2 +- modules/link/config.json | 2 +- modules/poll/config.json | 2 +- modules/quotes/commands.js | 20 ++++---------------- modules/quotes/quotes.js | 6 +++++- run.js | 4 ++-- 10 files changed, 18 insertions(+), 25 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index 6923b19..ce8d73a 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -12,6 +12,7 @@ var admin = function(dbot) { if(configKey) { this.db.read('config', configKey, function(err, cRecord) { if(cRecord) { + console.log('record found'); callback(cRecord.value) } else { var configPath = dbot.config; diff --git a/modules/admin/commands.js b/modules/admin/commands.js index 3f1f788..a0dae29 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -94,9 +94,9 @@ var commands = function(dbot) { // Reload DB, translations and modules. 'reload': function(event) { + event.reply(dbot.t('reload')); dbot.db = JSON.parse(fs.readFileSync('db.json', 'utf-8')); dbot.reloadModules(); - event.reply(dbot.t('reload')); }, // Say something in a channel diff --git a/modules/dent/config.json b/modules/dent/config.json index 8b0fd90..14eb3b3 100644 --- a/modules/dent/config.json +++ b/modules/dent/config.json @@ -4,5 +4,5 @@ "dependencies": [ "command" ], "ignorable": true, "help": "https://github.com/reality/depressionbot/blob/master/modules/dent/README.md", - "dentQuotes": false + "dentQuotes": true } diff --git a/modules/dent/dent.js b/modules/dent/dent.js index a990984..756b13d 100644 --- a/modules/dent/dent.js +++ b/modules/dent/dent.js @@ -58,7 +58,7 @@ var dent = function(dbot) { this.onLoad = function() { if(dbot.config.dent.dentQuotes === true && _.has(dbot.modules, 'quotes')) { - dbot.api.command.addHook('~qadd', function(key, text) { + dbot.api.event.addHook('~qadd', function(key, text) { if(text.indexOf('~~') == -1) { this.api.post(key + ': ' + text); } diff --git a/modules/ignore/config.json b/modules/ignore/config.json index 94f16ed..2a85c47 100644 --- a/modules/ignore/config.json +++ b/modules/ignore/config.json @@ -2,6 +2,6 @@ "ignorable": false, "dependencies": [ "command" ], "dbKeys": [ "ignores", "bans" ], - "dbType": "memory", + "dbType": "redis", "help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md" } diff --git a/modules/link/config.json b/modules/link/config.json index 9c3dc3e..2ce7ed4 100644 --- a/modules/link/config.json +++ b/modules/link/config.json @@ -1,5 +1,5 @@ { - "autoTitle": false, + "autoTitle": true, "dependencies": [ "command" ], "ignorable": true, "help": "http://github.com/reality/depressionbot/blob/master/modules/link/README.md" diff --git a/modules/poll/config.json b/modules/poll/config.json index 9f5ce60..a001437 100644 --- a/modules/poll/config.json +++ b/modules/poll/config.json @@ -1,6 +1,6 @@ { "help": "http://github.com/reality/depressionbot/blob/master/modules/poll/README.md", - "dbType": "disk", + "dbType": "redis", "dbKeys": [ "polls" ], "ignorable": true, "dependencies": [ "users", "command" ], diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index 9641086..fe3fc3e 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -12,10 +12,7 @@ var commands = function(dbot) { quote = event.input[2]; this.api.addQuote(key, quote, event.user, function(newCount) { - dbot.api.event.emit('~qadd', { - 'key': key, - 'text': quote - }); + dbot.api.event.emit('~qadd', [ key, quote ]); event.reply(dbot.t('quote_saved', { 'category': key, 'count': newCount @@ -47,7 +44,9 @@ var commands = function(dbot) { '~rq': function(event) { var categories = []; this.db.scan('quote_category', function(result) { - categories.push(result); + if(result) { + categories.push(result); + } }, function(err) { var cIndex = _.random(0, _.size(categories) -1); var qIndex = _.random(0, categories[cIndex].quotes.length - 1); @@ -91,17 +90,6 @@ var commands = function(dbot) { { 'count': rmCacheCount })); }, - // Retrieve quote from a category in the database. - '~q': function(event) { - var key = event.input[1].trim().toLowerCase(); - var quote = this.api.getQuote(event, event.input[1]); - if(quote) { - event.reply(key + ': ' + quote); - } else { - event.reply(dbot.t('category_not_found', {'category': key})); - } - }, - '~rmlast': function(event) { if(this.rmAllowed === true || _.include(dbot.config.admins, event.user)) { var key = event.input[1].trim().toLowerCase(), diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index cc66e18..e61ca15 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -106,7 +106,11 @@ var quotes = function(dbot) { key = key.trim().toLowerCase(), this.api.getQuote(key, function(quote) { - this.internalAPI.interpolatedQuote(server, channel, key, quote, callback); + if(quote) { + this.internalAPI.interpolatedQuote(server, channel, key, quote, callback); + } else { + callback(quote); + } }.bind(this)); } }; diff --git a/run.js b/run.js index b6297b0..f6bb8e8 100644 --- a/run.js +++ b/run.js @@ -281,8 +281,8 @@ DBot.prototype.reloadModules = function() { var propertyData = {}; try { propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); - } catch(err) {}; - _.extend(this[property], propertyData); + } catch(err) {}; + _.extend(this[property], propertyData); }, this); // Provide toString for module name From 5eba864f2247e044ecf44d326f09bafa8ad28f50 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 22 Apr 2013 14:38:03 +0000 Subject: [PATCH 058/220] fix imgur for now --- modules/imgur/imgur.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/imgur/imgur.js b/modules/imgur/imgur.js index 507e6f2..3bea45a 100644 --- a/modules/imgur/imgur.js +++ b/modules/imgur/imgur.js @@ -7,7 +7,6 @@ var _ = require('underscore')._, request = require('request'); var imgur = function(dbot) { - this.db = dbot.db.imgur; this.internalAPI = { 'infoString': function(imgData) { info = ''; @@ -45,11 +44,11 @@ var imgur = function(dbot) { var testUrl = 'http://i.imgur.com/' + testSlug + '.' + ext[_.random(0, ext.length - 1)]; - this.db.totalHttpRequests += 1; + dbot.db.imgur.totalHttpRequests += 1; var image = request(testUrl, function(error, response, body) { // 492 is body.length of a removed image if(!error && response.statusCode == 200 && body.length != 492) { - this.db.totalImages += 1; + dbot.db.imgur.totalImages += 1; callback(testUrl, testSlug); } else { this.api.getRandomImage(callback); @@ -71,7 +70,7 @@ var imgur = function(dbot) { 'Authorization': 'Client-ID ' + dbot.config.imgur.apikey } }, function(err, response, body) { - this.db.totalApiRequests += 1; + dbot.db.imgur.totalApiRequests += 1; callback(body); }.bind(this)); } From f905c588777bc94d3355635ec7ed04f23ca34974 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 22 Apr 2013 14:46:30 +0000 Subject: [PATCH 059/220] Fix setconfig, showconfig and pushconfig from being confused by false values [#331] --- modules/admin/admin.js | 3 +-- modules/admin/commands.js | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index ce8d73a..d596e51 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -12,7 +12,6 @@ var admin = function(dbot) { if(configKey) { this.db.read('config', configKey, function(err, cRecord) { if(cRecord) { - console.log('record found'); callback(cRecord.value) } else { var configPath = dbot.config; @@ -22,7 +21,7 @@ var admin = function(dbot) { if(_.has(configPath, configKey[i])) { configPath = configPath[configKey[i]]; } else { - callback(false); + callback(null); break; } } diff --git a/modules/admin/commands.js b/modules/admin/commands.js index a0dae29..e7172ba 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -156,7 +156,7 @@ var commands = function(dbot) { if(!_.include(noChangeConfig, configPath)) { this.internalAPI.getCurrentConfig(configPath, function(config) { - if(config) { + if(config !== null) { // Convert to boolean type if config item boolean if(_.isBoolean(config)) { newOption = (newOption == "true"); @@ -185,7 +185,7 @@ var commands = function(dbot) { if(!_.include(noChangeConfig, configPath)) { this.internalAPI.getCurrentConfig(configPath, function(config) { - if(config) { + if(config !== null) { if(_.isArray(config)) { event.reply(configPath + ": " + config + " << " + newOption); config.push(newOption); @@ -211,7 +211,7 @@ var commands = function(dbot) { var configPath = event.params[1]; if(configPath) { this.internalAPI.getCurrentConfig(configPath, function(config) { - if(config) { + if(config !== null) { if(_.isArray(config)) { event.reply('Config keys in ' + configPath + ': ' + config); } else if(_.isObject(config)) { From 099d278cbcc9abe32c9bb5629a2ba3de0d5f3792 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 22 Apr 2013 15:50:05 +0000 Subject: [PATCH 060/220] dont add quotes that already exist [#331] --- modules/quotes/commands.js | 14 +++++++++----- modules/quotes/quotes.js | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index fe3fc3e..e8205c7 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -12,11 +12,15 @@ var commands = function(dbot) { quote = event.input[2]; this.api.addQuote(key, quote, event.user, function(newCount) { - dbot.api.event.emit('~qadd', [ key, quote ]); - event.reply(dbot.t('quote_saved', { - 'category': key, - 'count': newCount - })); + if(newCount) { + dbot.api.event.emit('~qadd', [ key, quote ]); + event.reply(dbot.t('quote_saved', { + 'category': key, + 'count': newCount + })); + } else { + event.reply(dbot.t('quote_exists')); + } }); }, diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index e61ca15..36287f1 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -76,11 +76,15 @@ var quotes = function(dbot) { }; } - newCount = category.quotes.push(quote); - this.db.save('quote_category', category.id, category, function(err) { - this.rmAllowed = true; - callback(newCount); - }.bind(this)); + if(_.include(category.quotes, quote)) { + callback(false); + } else { + newCount = category.quotes.push(quote); + this.db.save('quote_category', category.id, category, function(err) { + this.rmAllowed = true; + callback(newCount); + }.bind(this)); + } }.bind(this)); }, From f98f7e435a00fc2fda8d8b2ea48dbf32124eac2c Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 22 Apr 2013 16:20:17 +0000 Subject: [PATCH 061/220] that should be all of the dependencies [#413] --- modules/command/config.json | 2 +- modules/dent/config.json | 2 +- modules/ignore/config.json | 2 +- modules/imgur/config.json | 2 +- modules/poll/config.json | 2 +- modules/profile/config.json | 2 +- modules/project/config.json | 2 +- modules/quotes/config.json | 2 +- modules/report/config.json | 2 +- modules/spotify/config.json | 2 +- modules/users/config.json | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/command/config.json b/modules/command/config.json index 6395f6d..0f059cd 100644 --- a/modules/command/config.json +++ b/modules/command/config.json @@ -1,5 +1,5 @@ { "ignorable": false, "help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md", - "dbKeys": [ "ignores", "bans", "users" ] + "dependencies": [ "ignore", "users" ] } diff --git a/modules/dent/config.json b/modules/dent/config.json index 14eb3b3..287fa94 100644 --- a/modules/dent/config.json +++ b/modules/dent/config.json @@ -1,7 +1,7 @@ { "username": "youruserhere", "password": "yourpasswordhere", - "dependencies": [ "command" ], + "dependencies": [ "link" ], "ignorable": true, "help": "https://github.com/reality/depressionbot/blob/master/modules/dent/README.md", "dentQuotes": true diff --git a/modules/ignore/config.json b/modules/ignore/config.json index 2a85c47..6d97f05 100644 --- a/modules/ignore/config.json +++ b/modules/ignore/config.json @@ -1,6 +1,6 @@ { "ignorable": false, - "dependencies": [ "command" ], + "dependencies": [ "users" ], "dbKeys": [ "ignores", "bans" ], "dbType": "redis", "help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md" diff --git a/modules/imgur/config.json b/modules/imgur/config.json index cc20a5d..1e7a352 100644 --- a/modules/imgur/config.json +++ b/modules/imgur/config.json @@ -1,6 +1,6 @@ { "dbKeys": [ "imgur" ], - "dependencies": [ "web", "api" ], + "dependencies": [ "web", "api", "link" ], "imagelength": 5, "nsfwwarn": true, "apikey": "86fd3a8da348b65", diff --git a/modules/poll/config.json b/modules/poll/config.json index a001437..409c1af 100644 --- a/modules/poll/config.json +++ b/modules/poll/config.json @@ -3,7 +3,7 @@ "dbType": "redis", "dbKeys": [ "polls" ], "ignorable": true, - "dependencies": [ "users", "command" ], + "dependencies": [ "users", "web" ], "schema": { "poll": { "pkey": "name", diff --git a/modules/profile/config.json b/modules/profile/config.json index 9984f3e..704e38a 100644 --- a/modules/profile/config.json +++ b/modules/profile/config.json @@ -17,5 +17,5 @@ "timezone": null } }, - "dependencies": [ "quotes", "users", "command" ] + "dependencies": [ "web", "quotes", "users" ] } diff --git a/modules/project/config.json b/modules/project/config.json index 0725dea..9c3f593 100644 --- a/modules/project/config.json +++ b/modules/project/config.json @@ -1,3 +1,3 @@ { - "dependencies": ["web", "quotes", "github"] + "dependencies": [ "web", "quotes", "github" ] } diff --git a/modules/quotes/config.json b/modules/quotes/config.json index c93010a..03c77f4 100644 --- a/modules/quotes/config.json +++ b/modules/quotes/config.json @@ -1,6 +1,6 @@ { "dbType": "redis", - "dependencies": [ "command", "users" ], + "dependencies": [ "users", "event" ], "rmLimit": 10, "ignorable": true, "help": "http://github.com/reality/depressionbot/blob/master/modules/quotes/README.md" diff --git a/modules/report/config.json b/modules/report/config.json index c495082..e79966d 100644 --- a/modules/report/config.json +++ b/modules/report/config.json @@ -1,6 +1,6 @@ { "ignorable": true, "notifyVoice": false, - "dependencies": [ "command", "users" ], + "dependencies": [ "users" ], "help": "http://github.com/reality/depressionbot/blob/master/modules/report/README.md" } diff --git a/modules/spotify/config.json b/modules/spotify/config.json index a051064..97cfbfc 100644 --- a/modules/spotify/config.json +++ b/modules/spotify/config.json @@ -1,4 +1,4 @@ { - "dependencies": [ "command" ], + "dependencies": [ "link" ], "ignorable": true } diff --git a/modules/users/config.json b/modules/users/config.json index 34927cb..2c23325 100644 --- a/modules/users/config.json +++ b/modules/users/config.json @@ -1,6 +1,6 @@ { "ignorable": false, - "dependencies": [ "command", "event" ], + "dependencies": [ "event" ], "dbKeys": [ "knownUsers" ], "help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md", "dbType": "redis" From 41f4a830b2c733386dcaa4ae6722f76031fa8a75 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 23 Apr 2013 17:26:44 +0000 Subject: [PATCH 062/220] Fix quotes web component [Close #419] --- modules/quotes/pages.js | 35 ++++++++++++++++++++++------------- modules/quotes/quotes.js | 27 +++++++++++++++++++++------ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/modules/quotes/pages.js b/modules/quotes/pages.js index 7800cd0..0f0c977 100644 --- a/modules/quotes/pages.js +++ b/modules/quotes/pages.js @@ -3,24 +3,33 @@ var pages = function(dbot) { return { // Lists quotes in a category '/quotes/:key': function(req, res) { - var key = req.params.key.toLowerCase(); - if(_.has(dbot.db.quoteArrs, key)) { - res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[key], locals: { 'url_regex': RegExp.prototype.url_regex() } }); - } else { - res.render('error', { 'name': dbot.config.name, 'message': 'No quotes under that key.' }); - } + this.api.getQuoteCategory(req.params.key, function(category) { + if(category) { + res.render('quotes', { + 'name': dbot.config.name, + 'quotes': category.quotes, + 'locals': { + 'url_regex': RegExp.prototype.url_regex() + } + }); + } else { + res.render('error', { + 'name': dbot.config.name, + 'message': 'No quotes under that key.' + }); + } + }); }, // Show quote list. '/quotes': function(req, res) { - res.render('quotelist', { 'name': dbot.config.name, 'quotelist': Object.keys(dbot.db.quoteArrs) }); + this.api.getCategoryKeys(function(keys) { + res.render('quotelist', { + 'name': dbot.config.name, + 'quotelist': keys + }); + }); }, - - // Load random quote category page - '/rq': function(req, res) { - var rCategory = Object.keys(dbot.db.quoteArrs).random(); - res.render('quotes', { 'name': dbot.config.name, 'quotes': dbot.db.quoteArrs[rCategory], locals: { 'url_regex': RegExp.prototype.url_regex() } }); - } } }; diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index 36287f1..1d0b842 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -90,12 +90,7 @@ var quotes = function(dbot) { }, 'getQuote': function(key, callback) { - var category = false, - key = key.trim().toLowerCase(); - - this.db.search('quote_category', { 'name': key }, function(result) { - category = result; - }, function(err) { + this.api.getQuoteCategory(key, function(category) { if(category) { var quotes = category.quotes; var index = _.random(0, quotes.length - 1); @@ -116,6 +111,26 @@ var quotes = function(dbot) { callback(quote); } }.bind(this)); + }, + + 'getQuoteCategory': function(key, callback) { + var category = false, + key = key.trim().toLowerCase(); + + this.db.search('quote_category', { 'name': key }, function(result) { + category = result; + }, function(err) { + callback(category); + }); + }, + + 'getCategoryKeys': function(callback) { + var keys = []; + this.db.scan('quote_category', function(result) { + if(result) keys.push(result.name); + }, function(err) { + callback(keys); + }); } }; From 9f211c4da04e16fffbf74d0ab5300a636400a175 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 23 Apr 2013 18:27:25 +0000 Subject: [PATCH 063/220] Module and API function to check nickserv authentication. [#421] --- modules/nickserv/config.json | 9 +++++++++ modules/nickserv/nickserv.js | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 modules/nickserv/config.json create mode 100644 modules/nickserv/nickserv.js diff --git a/modules/nickserv/config.json b/modules/nickserv/config.json new file mode 100644 index 0000000..3bcaece --- /dev/null +++ b/modules/nickserv/config.json @@ -0,0 +1,9 @@ +{ + "servers": { + "nc": { + "matcher": "STATUS ([^ ]+) (\\d)$", + "acceptableState": 3, + "infoCommand": "status" + } + } +} diff --git a/modules/nickserv/nickserv.js b/modules/nickserv/nickserv.js new file mode 100644 index 0000000..28f20ae --- /dev/null +++ b/modules/nickserv/nickserv.js @@ -0,0 +1,37 @@ +var nickserv = function(dbot) { + this.authStack = {}; + + this.api = { + 'auth': function(server, nick, callback) { + var nickserv = dbot.config.servers[server].nickserv, + infoCommand = this.config.servers[server].infoCommand; + + if(!_.has(this.authStack, server)) this.authStack[server] = {}; + this.authStack[server][nick] = callback; + + dbot.say(server, nickserv, infoCommand + ' ' + nick); + } + }; + + this.listener = function(event) { + var nickserv = dbot.config.servers[event.server].nickserv, + statusRegex = this.config.servers[event.server].matcher, + acceptableState = this.config.servers[event.server].acceptableState; + + if(event.user == nickserv) { + var info = event.params.match(statusRegex); + if(info && _.has(this.authStack, event.server)) { + if(info[2] == acceptableState ) { + this.authStack[event.server][info[1]](true); + } else { + this.authStack[event.server][info[1]](false); + } + } + } + }.bind(this); + this.on = 'NOTICE'; +}; + +exports.fetch = function(dbot) { + return new nickserv(dbot); +}; From 40583ed7a35689554ce1a6dde9223a36342d626c Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 24 Apr 2013 20:49:44 +0000 Subject: [PATCH 064/220] bump github --- modules/github | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/github b/modules/github index 7e38c6b..86227ce 160000 --- a/modules/github +++ b/modules/github @@ -1 +1 @@ -Subproject commit 7e38c6be750a071724763872175f1a9445297b76 +Subproject commit 86227ce8fca8e24f56a24cf50c1b4823ab1c5071 From 7c31d5bbe81b84e322da02b4a0dac450af20eea5 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 30 Apr 2013 14:04:21 +0000 Subject: [PATCH 065/220] Remove a bunch of useless users API functions, finish documentation [#352] --- modules/users/README.md | 5 +++++ modules/users/api.js | 43 ----------------------------------------- 2 files changed, 5 insertions(+), 43 deletions(-) diff --git a/modules/users/README.md b/modules/users/README.md index ee157de..032d7cd 100644 --- a/modules/users/README.md +++ b/modules/users/README.md @@ -50,6 +50,11 @@ channel was found from the given parameters. Get a list of all users the bot currently knows about. Callback is called with one argument, a list of user records. +#### isOnline +Is the given nick on the given server currently in the given channel. Callback +is called with one argument, a boolean as to whether the nick is currently in +the specified place. + ### Data #### User Object diff --git a/modules/users/api.js b/modules/users/api.js index 830dd39..53f3727 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -79,42 +79,6 @@ var api = function(dbot) { }); }, - 'isKnownUser': function(server, nick, callback) { - this.api.resolveUser(server, nick, function(isKnown) { - if(isKnown == false) { - callback(false); - } else { - callback(true); - } - }); - }, - - 'isPrimaryUser': function(server, nick, callback) { - var isPrimaryUser = false; - this.db.search('users', { - 'server': server, - 'primaryNick': nick - }, function(user) { - isPrimaryUser = true; - }, function(err) { - if(!err) { - callback(isPrimaryUser); - } - }); - }, - - 'getAliases': function(server, nick, callback) { - var aliases; - this.db.search('users', { - 'server': server, - 'primaryNick': nick - }, function(result) { - aliases = result.aliases; - }, function(err) { - callback(aliases); - }); - }, - 'isOnline': function(server, nick, channel, callback) { this.api.resolveUser(server, nick, function(user) { var possiNicks = [user].concat(user.aliases); @@ -129,13 +93,6 @@ var api = function(dbot) { callback(isOnline); } }); - }, - - 'isChannelUser': function(server, nick, channel, callback) { - this.api.resolveUser(server, nick, function(user) { - var isChannelUser = _.include(user.channels, channel); - callback(isChannelUser); - }); } }; From b08e12560f97def3c589c8235de88dc99a136ee0 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 30 Apr 2013 17:10:21 +0000 Subject: [PATCH 066/220] merge earlier --- run.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/run.js b/run.js index b63613f..2af040c 100644 --- a/run.js +++ b/run.js @@ -295,19 +295,7 @@ DBot.prototype.reloadModules = function() { } this.modules[module.name] = module; -<<<<<<< HEAD }.bind(this)); -======= - } catch(err) { - console.log(this.t('module_load_error', { 'moduleName': name })); - this.status[name] = err + ' - ' + err.stack.split('\n')[1].trim(); - if(this.config.debugMode) { - console.log('MODULE ERROR (' + name + '): ' + err.stack ); - } else { - console.log('MODULE ERROR (' + name + '): ' + err ); - } - } ->>>>>>> 2afb1c6ba37eb92f875124c754453bb063f42277 }.bind(this)); process.nextTick(function() { From 22704a21583a5bb8b4062f62ec9ea94c8c542225 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 30 Apr 2013 17:19:23 +0000 Subject: [PATCH 067/220] move dbot.cleanNick to quotes.internalAPI.cleanRef [#270] --- modules/quotes/quotes.js | 10 +++++++++- run.js | 11 ----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index 1d0b842..0bc18c3 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -13,7 +13,7 @@ var quotes = function(dbot) { 'interpolatedQuote': function(server, channel, key, quote, callback) { var quoteRefs = quote.match(/~~([\d\w\s-]*)~~/g); if(quoteRefs) { - var ref = dbot.cleanNick(quoteRefs[0].replace(/^~~/,'').replace(/~~$/,'').trim()); + var ref = this.internalAPI.cleanRef(quoteRefs[0].replace(/^~~/,'').replace(/~~$/,'').trim()); if(ref === '-nicks-') { dbot.api.users.getRandomChannelUser(server, channel, function(user) { quote = quote.replace('~~' + ref + '~~', randomNick); @@ -33,6 +33,14 @@ var quotes = function(dbot) { } }.bind(this), + 'cleanRef': function(key) { + key = key.toLowerCase(); + while(key.endsWith("_")) { + key = key.substring(0, key.length-1); + } + return key; + }, + 'resetRemoveTimer': function(event, key, quote) { this.rmAllowed = false; setTimeout(function() { diff --git a/run.js b/run.js index 2af040c..ced9144 100644 --- a/run.js +++ b/run.js @@ -315,15 +315,4 @@ DBot.prototype.reloadModules = function() { this.save(); }; -DBot.prototype.cleanNick = function(key) { - key = key.toLowerCase(); - while(key.endsWith("_")) { - if(_.has(this.db.quoteArrs, key)) { - return key; - } - key = key.substring(0, key.length-1); - } - return key; -} - new DBot(); From e426f4fae9cf3ff95c00c012a504498cde213ef8 Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 1 May 2013 19:53:37 +0000 Subject: [PATCH 068/220] bump github --- modules/github | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/github b/modules/github index 6e841d9..e3616ec 160000 --- a/modules/github +++ b/modules/github @@ -1 +1 @@ -Subproject commit 6e841d96df413a8039b15a53ef0c6b77630b552a +Subproject commit e3616ec9b8c66f38d8bf13021d2be7a0f8900936 From da5e79ebeb760a16a033fb363340c43186c251b0 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 2 May 2013 18:25:10 +0000 Subject: [PATCH 069/220] Efficiency improvements in users, return of isKnownUser API function [#331] --- modules/users/api.js | 10 ++++++++++ modules/users/strings.json | 2 +- modules/users/users.js | 40 +++++++++++++++++++++++++------------- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/modules/users/api.js b/modules/users/api.js index 53f3727..1d5ffc3 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -93,6 +93,16 @@ var api = function(dbot) { callback(isOnline); } }); + }, + + 'isKnownUser': function(server, nick, callback) { + this.api.resolveUser(server, nick, function(isKnown) { + if(isKnown == false) { + callback(false); + } else { + callback(true); + } + }); } }; diff --git a/modules/users/strings.json b/modules/users/strings.json index 96a1883..a8f60f1 100644 --- a/modules/users/strings.json +++ b/modules/users/strings.json @@ -5,7 +5,7 @@ "nl": "{alias} is een alias van {user}" }, "primary": { - "en": "{user} ({currentNick}) is a primary user with {count} aliases, ", + "en": "{user} (currently {currentNick}) is a primary user with {count} aliases, ", "na'vi": "{user} ({currentNick}) lu txin ulte {count}a stxo lu poru, ", "nl": "{user} ({currentNick}) is een primaire gebruiker met {count} aliassen, " }, diff --git a/modules/users/users.js b/modules/users/users.js index 3fdab59..03d2fc5 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -73,22 +73,34 @@ var users = function(dbot) { this.listener = function(event) { if(event.action == 'JOIN' && event.user != dbot.config.name) { this.api.resolveUser(event.server, event.user, function(user) { - if(!user) { // User does not yet exist - this.internalAPI.createUser(event.server, event.user, event.channel.name, function(result) { - this.internalAPI.addChannelUser(result, event.channel.name, function(err) { }); - }.bind(this)); - } else { - if(!_.include(user.channels, event.channel.name)) { // User not yet channel user - user.channels.push(event.channel.name); - this.internalAPI.addChannelUser(user, event.channel.name, function(err) { }); - } + var needsUpdating = false; + if(!user) { // User does not yet exist + user = { + 'id': uuid.v4(), + 'primaryNick': event.user, + 'currentNick': event.user, + 'server': event.server, + 'channels': [], + 'aliases': [] + }; + this.internalAPI.addChannelUser(user, event.channel.name, function(err) { }); + needsUpdating = true; + } + + if(!_.include(user.channels, event.channel.name)) { // User not yet channel user + user.channels.push(event.channel.name); + this.internalAPI.addChannelUser(user, event.channel.name, function(err) { }); + needsUpdating = true; + } + + if(user.currentNick != event.user) { user.currentNick = event.user; - this.db.save('users', user.id, user, function(err) { - if(err) { - // QQ - } - }); + needsUpdating = true; + } + + if(needsUpdating == true) { + this.db.save('users', user.id, user, function(err) { }); } }.bind(this)); } else if(event.action == 'NICK') { From 090f15e738fbdf71497604ce0dc34e5f43deb920 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 6 May 2013 15:36:35 +0000 Subject: [PATCH 070/220] remove unecessary code from module loading, fix [#432] --- run.js | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/run.js b/run.js index ced9144..aa168ec 100644 --- a/run.js +++ b/run.js @@ -157,7 +157,6 @@ DBot.prototype.reloadModules = function() { var name, moduleDir, config; for(i=0;i Date: Mon, 6 May 2013 15:53:42 +0000 Subject: [PATCH 071/220] Fix [#433] --- modules/admin/commands.js | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/modules/admin/commands.js b/modules/admin/commands.js index 176c81a..16238ab 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -82,9 +82,15 @@ var commands = function(dbot) { if(_.has(dbot.status, moduleName)) { var status = dbot.status[moduleName]; if(status === true) { - event.reply(dbot.t("status_good",{"module":moduleName, "reason": status})); + event.reply(dbot.t('status_good', { + 'module': moduleName, + 'reason': status + })); } else { - event.reply(dbot.t("status_bad",{"module":moduleName, "reason": status})); + event.reply(dbot.t('status_bad', { + 'module': moduleName, + 'reason': status + })); } } else { event.reply(dbot.t("status_unloaded")); @@ -93,9 +99,11 @@ var commands = function(dbot) { // Reload DB, translations and modules. 'reload': function(event) { - event.reply(dbot.t('reload')); dbot.db = JSON.parse(fs.readFileSync('db.json', 'utf-8')); dbot.reloadModules(); + process.nextTick(function() { + event.reply(dbot.t('reload')); + }); }, // Say something in a channel @@ -114,16 +122,18 @@ var commands = function(dbot) { if(!_.include(dbot.config.moduleNames, moduleName)) { dbot.config.moduleNames.push(moduleName); dbot.reloadModules(); - if(dbot.status[moduleName] === true) { - event.reply(dbot.t('load_module', {'moduleName': moduleName})); - } else { - event.reply(dbot.t("load_failed",{"module": moduleName})); - } + process.nextTick(function() { + if(dbot.status[moduleName] === true) { + event.reply(dbot.t('load_module', { 'moduleName': moduleName })); + } else { + event.reply(dbot.t('load_failed', { 'module': moduleName })); + } + }); } else { if(moduleName == 'web') { event.reply(dbot.t('already_loaded_web')); } else { - event.reply(dbot.t('already_loaded', {'moduleName': moduleName})); + event.reply(dbot.t('already_loaded', { 'moduleName': moduleName })); } } }, @@ -141,9 +151,11 @@ var commands = function(dbot) { dbot.config.moduleNames = _.without(dbot.config.moduleNames, moduleName); dbot.reloadModules(); - event.reply(dbot.t('unload_module', {'moduleName': moduleName})); + process.nextTick(function() { + event.reply(dbot.t('unload_module', { 'moduleName': moduleName })); + }); } else { - event.reply(dbot.t('unload_error', {'moduleName': moduleName})); + event.reply(dbot.t('unload_error', { 'moduleName': moduleName })); } }, From 33b9b8d1b0f8f10062483db068cd4a063cb22a6c Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 6 May 2013 18:12:25 +0000 Subject: [PATCH 072/220] poll web list works [#420] some commands using new users [#434] --- modules/poll/commands.js | 163 +++++++++++++++++++-------------------- modules/poll/pages.js | 15 ++-- views/poll/polllist.jade | 2 +- 3 files changed, 91 insertions(+), 89 deletions(-) diff --git a/modules/poll/commands.js b/modules/poll/commands.js index 1df1a6e..b643ebb 100644 --- a/modules/poll/commands.js +++ b/modules/poll/commands.js @@ -4,73 +4,73 @@ var _ = require('underscore')._, NoSuchThingError = databank.NoSuchThingError; var commands = function(dbot) { - var polls = dbot.db.polls; var commands = { '~newpoll': function(event) { var name = event.input[1].toLowerCase(), options = event.input[2].toLowerCase().split(','), description = event.input[3]; - - var votes = {}; - for(var i=0;i Date: Mon, 6 May 2013 19:43:14 +0000 Subject: [PATCH 073/220] Poll web interface now working [#420] --- modules/poll/pages.js | 55 +++++++++++++++++++++++++++---------------- views/poll/polls.jade | 2 +- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/modules/poll/pages.js b/modules/poll/pages.js index 2f7d721..9fc08b8 100644 --- a/modules/poll/pages.js +++ b/modules/poll/pages.js @@ -5,28 +5,43 @@ var pages = function(dbot) { // Shows the results of a poll '/poll/:key': function(req, res) { var key = req.params.key.toLowerCase(); - if(_.has(dbot.db.polls, key)) { - var totalVotes = _.reduce(dbot.db.polls[key].votes, - function(memo, option) { + this.db.read('poll', key, function(err, poll) { + if(!err) { + var totalVotes = _.reduce(poll.votes, function(memo, option) { return memo += option; }, 0); - res.render('polls', { - 'name': dbot.config.name, - 'description': dbot.db.polls[key].description, - 'votees': Object.keys(dbot.db.polls[key].votees), - 'options': dbot.db.polls[key].votes, - locals: { - 'totalVotes': totalVotes, - 'url_regex': RegExp.prototype.url_regex() - } - }); - } else { - res.render('error', { - 'name': dbot.config.name, - 'message': 'No polls under that key.' - }); - } - }, + + var voterNicks = []; + /* TODO: Fix stupid fucking async issue bullshit + var voterNicks = _.map(poll.votees, function(vote, id) { + dbot.api.users.getUser(id, function(user) { + return user.primaryNick; + }); + });*/ + + process.nextTick(function() { + console.log(voterNicks); + res.render('polls', { + 'name': dbot.config.name, + 'description': poll.description, + 'votees': voterNicks, + 'options': poll.votes, + locals: { + 'totalVotes': totalVotes, + 'url_regex': RegExp.prototype.url_regex() + } + }); + }); + } else { + console.log(err); + console.log("the thing the thing"); + res.render('error', { + 'name': dbot.config.name, + 'message': 'No polls under that key.' + }); + } + }); + }, // Lists all of the polls '/poll': function(req, res) { diff --git a/views/poll/polls.jade b/views/poll/polls.jade index 80e25f6..72f654e 100644 --- a/views/poll/polls.jade +++ b/views/poll/polls.jade @@ -2,7 +2,7 @@ extends ../layout block content div#backlink - a(href='/polls/') « Poll list + a(href='/poll/') « Poll list h2 #{description} p Voters (#{locals.totalVotes}): -each voter in votees From 5b0f4d3ae83b81da5c9fd074a75f233ef3fd5b69 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 6 May 2013 20:00:31 +0000 Subject: [PATCH 074/220] finish off poll using new users api [#434] --- modules/poll/commands.js | 47 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/modules/poll/commands.js b/modules/poll/commands.js index b643ebb..fafb62f 100644 --- a/modules/poll/commands.js +++ b/modules/poll/commands.js @@ -70,38 +70,39 @@ var commands = function(dbot) { } } }.bind(this)); - }); + }.bind(this)); }, '~rmoption': function(event) { var name = event.input[1].toLowerCase(), - option = event.input[2].toLowerCase(), - user = dbot.api.users.resolveUser(event.server, event.user); - - this.db.read('poll', name, function(err, poll) { - if(!err) { - if(poll.owner === user) { - if(_.has(poll.votes, option)) { - delete poll.votes[option]; + option = event.input[2].toLowerCase(); - this.db.save('poll', name, poll, function(err) { - event.reply(dbot.t('option_removed', { - 'user': event.user, - 'name': name, - 'option': option - })); - }.bind(this)); + dbot.api.users.resolveUser(event.server, event.user, function(user) { + this.db.read('poll', name, function(err, poll) { + if(!err) { + if(poll.owner === user.id) { + if(_.has(poll.votes, option)) { + delete poll.votes[option]; + + this.db.save('poll', name, poll, function(err) { + event.reply(dbot.t('option_removed', { + 'user': event.user, + 'name': name, + 'option': option + })); + }.bind(this)); + } else { + event.reply(dbot.t('invalid_vote', { 'vote': option })); + } } else { - event.reply(dbot.t('invalid_vote', { 'vote': option })); + event.reply(dbot.t('not_poll_owner', { 'name': name })); } } else { - event.reply(dbot.t('not_poll_owner', { 'name': name })); + if(err instanceof NoSuchThingError) { + event.reply(dbot.t('poll_unexistent', { 'name': name })); + } } - } else { - if(err instanceof NoSuchThingError) { - event.reply(dbot.t('poll_unexistent', { 'name': name })); - } - } + }.bind(this)); }.bind(this)); }, From e8537a93b2ce1cee4836c016765934df03a1a389 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 6 May 2013 20:09:19 +0000 Subject: [PATCH 075/220] Remove leading slash in url api maker [#435] --- modules/web/web.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/web/web.js b/modules/web/web.js index 25f4997..81a15ed 100644 --- a/modules/web/web.js +++ b/modules/web/web.js @@ -60,12 +60,10 @@ var webInterface = function(dbot) { this.api = { 'getUrl': function(path) { - console.log(path); + if(path.charAt(0) == '/') path = path.substr(1); if(this.config.externalPath) { - console.log('external'); return this.config.externalPath + '/' + path; } else { - console.log('internal'); return 'http://' + this.config.webHost + ':' + this.config.webPort + '/' + path; } } From 0259584c259de8ec86d6c696f8da43fd95d57581 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 10 May 2013 18:12:40 +0000 Subject: [PATCH 076/220] savemodules command [#438] --- modules/admin/commands.js | 12 +++++++++++- modules/admin/strings.json | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/modules/admin/commands.js b/modules/admin/commands.js index 16238ab..3cd10c6 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -258,7 +258,17 @@ var commands = function(dbot) { "value": _.keys(dbot.config) })); } - } + }, + + 'savemodules': function(event) { + fs.readFile('config.json', 'utf-8', function(err, config) { + config = JSON.parse(config); + config.moduleNames = _.keys(dbot.modules); + fs.writeFile('config.json', JSON.stringify(config, null, ' '), function() { + event.reply(dbot.t('modules_saved', { 'modules': _.keys(dbot.modules) })); + }); + }); + } }; _.each(commands, function(command) { diff --git a/modules/admin/strings.json b/modules/admin/strings.json index 0f3e5a0..3172912 100644 --- a/modules/admin/strings.json +++ b/modules/admin/strings.json @@ -125,5 +125,8 @@ }, "config_keys_location": { "en": "Config keys in {path}: {value}" + }, + "modules_saved": { + "en": "Currently loaded modules now default: {modules}" } } From ccc962d9f2f62079a213dcabfd8b576f6d629d0e Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 10 May 2013 18:38:57 +0000 Subject: [PATCH 077/220] update admin docs [#351] --- modules/admin/README.md | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/modules/admin/README.md b/modules/admin/README.md index 0a0583c..6aff5a4 100644 --- a/modules/admin/README.md +++ b/modules/admin/README.md @@ -26,6 +26,15 @@ channel, it will attempt to give the caller ops in the current channel. Perform a git pull, and then execute the 'reload' command. Saves a lot of time updating! +#### version [module] +Shows the git version of the currently loaded revision of DBot. If module is +provided, it will attempt to get the revision of the module (this is only useful +for submodules). + +#### status [module] +Show the recorded status for a given module, this is helpful for debugging +issues when loading or for checking if a module is loaded. + #### reload Reload all of the modules currently in use by DBot. By using this, all module functionality should be reloadable and replaceable without having to restart the @@ -46,12 +55,18 @@ loaded by the standard DBot process. Unload a currently loaded module. This removes the module, and then triggers a reload of all modules. -#### ban [user] [command] -Ban a user from using a command. Command may be replaced with '\*,' which will -ban a user from use of all commands. Users banned from all commands will still -be subject to module listeners. +#### setconfig [path] [value] +Set a config value at path to be a certain value persistently. For example, if +you want to change the web module to listen on port 9001, you can run _setconfig +web.webPort 9001_. -#### unban [user] [command] -Unban a user from using a given command. If a user was previously banned using -the '\*' wildcard, they may also be unbanned from such by replacing command with -an asterisk here as well. +#### pushconfig [path] [value] +Push a new value to an existing config array. For example, if you want to add +the user 'batman62' to the DBot moderators, you can run _pushconfig moderators +batman62_. + +#### showconfig [path] +Use this to explore and view the DBot configuration. If called without a path, +it will display the config keys in the root; if the path is a subkey, it will +show all config keys under that key. If you give it an actual key, it'll show you +the currently effective config value. From eac0083beac678ba493229bd767f950fdcd18bf5 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 17 May 2013 07:34:25 +0000 Subject: [PATCH 078/220] Build help link automatically [#439] --- modules/admin/config.json | 3 +-- modules/command/config.json | 1 - modules/ctcp/config.json | 3 +-- modules/dent/config.json | 1 - modules/dns/config.json | 3 --- modules/event/config.json | 3 --- modules/flashy/config.json | 3 --- modules/ignore/config.json | 3 +-- modules/js/config.json | 3 +-- modules/kick/config.json | 1 - modules/link/config.json | 3 +-- modules/nickserv/config.json | 3 +-- modules/poll/config.json | 1 - modules/profile/config.json | 1 - modules/quotes/config.json | 3 +-- modules/rain/config.json | 1 - modules/regex/config.json | 3 +-- modules/report/config.json | 3 +-- modules/spelling/config.json | 3 +-- modules/timers/config.json | 3 --- modules/users/config.json | 1 - modules/web/config.json | 3 +-- 22 files changed, 11 insertions(+), 41 deletions(-) delete mode 100644 modules/dns/config.json delete mode 100644 modules/event/config.json delete mode 100644 modules/flashy/config.json delete mode 100644 modules/timers/config.json diff --git a/modules/admin/config.json b/modules/admin/config.json index cd5a001..3a85186 100644 --- a/modules/admin/config.json +++ b/modules/admin/config.json @@ -1,6 +1,5 @@ { "ignorable": false, "dbType": "redis", - "dependencies": [ "command" ], - "help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md" + "dependencies": [ "command" ] } diff --git a/modules/command/config.json b/modules/command/config.json index 0d14f1b..08bcfe1 100644 --- a/modules/command/config.json +++ b/modules/command/config.json @@ -1,6 +1,5 @@ { "ignorable": false, - "help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md", "dependencies": [ "ignore", "users" ], "useNickserv": false } diff --git a/modules/ctcp/config.json b/modules/ctcp/config.json index b300d9f..c945e96 100644 --- a/modules/ctcp/config.json +++ b/modules/ctcp/config.json @@ -1,4 +1,3 @@ { - "ignorable": true, - "help": "https://github.com/reality/depressionbot/blob/master/modules/ctcp/README.md" + "ignorable": true } diff --git a/modules/dent/config.json b/modules/dent/config.json index 287fa94..e5715fe 100644 --- a/modules/dent/config.json +++ b/modules/dent/config.json @@ -3,6 +3,5 @@ "password": "yourpasswordhere", "dependencies": [ "link" ], "ignorable": true, - "help": "https://github.com/reality/depressionbot/blob/master/modules/dent/README.md", "dentQuotes": true } diff --git a/modules/dns/config.json b/modules/dns/config.json deleted file mode 100644 index 644956e..0000000 --- a/modules/dns/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "help": "https://github.com/reality/depressionbot/blob/master/modules/dns/README.md" -} diff --git a/modules/event/config.json b/modules/event/config.json deleted file mode 100644 index 55c9c57..0000000 --- a/modules/event/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "help": "https://github.com/reality/depressionbot/blob/master/modules/event/README.md" -} diff --git a/modules/flashy/config.json b/modules/flashy/config.json deleted file mode 100644 index 39287b4..0000000 --- a/modules/flashy/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "help": "https://github.com/reality/depressionbot/blob/master/modules/flashy/README.md" -} diff --git a/modules/ignore/config.json b/modules/ignore/config.json index 6d97f05..b9df2fc 100644 --- a/modules/ignore/config.json +++ b/modules/ignore/config.json @@ -2,6 +2,5 @@ "ignorable": false, "dependencies": [ "users" ], "dbKeys": [ "ignores", "bans" ], - "dbType": "redis", - "help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md" + "dbType": "redis" } diff --git a/modules/js/config.json b/modules/js/config.json index 084df95..41bb0ec 100644 --- a/modules/js/config.json +++ b/modules/js/config.json @@ -5,6 +5,5 @@ } }, "dependencies": [ "command" ], - "ignorable": true, - "help": "http://github.com/reality/depressionbot/blob/master/modules/js/README.md" + "ignorable": true } diff --git a/modules/kick/config.json b/modules/kick/config.json index bf4cd1d..ce9638e 100644 --- a/modules/kick/config.json +++ b/modules/kick/config.json @@ -1,7 +1,6 @@ { "dbKeys": [ "kicks", "kickers" ], "dependencies": [ "command", "report", "users" ], - "help": "http://github.com/reality/depressionbot/blob/master/modules/kick/README.md", "ignorable": true, "countSilently": true, "admin_channels": { diff --git a/modules/link/config.json b/modules/link/config.json index 2ce7ed4..d57c4cf 100644 --- a/modules/link/config.json +++ b/modules/link/config.json @@ -1,6 +1,5 @@ { "autoTitle": true, "dependencies": [ "command" ], - "ignorable": true, - "help": "http://github.com/reality/depressionbot/blob/master/modules/link/README.md" + "ignorable": true } diff --git a/modules/nickserv/config.json b/modules/nickserv/config.json index 06ef457..3bcaece 100644 --- a/modules/nickserv/config.json +++ b/modules/nickserv/config.json @@ -5,6 +5,5 @@ "acceptableState": 3, "infoCommand": "status" } - }, - "help": "https://github.com/reality/depressionbot/blob/master/modules/nickserv/README.md" + } } diff --git a/modules/poll/config.json b/modules/poll/config.json index 409c1af..6047e33 100644 --- a/modules/poll/config.json +++ b/modules/poll/config.json @@ -1,5 +1,4 @@ { - "help": "http://github.com/reality/depressionbot/blob/master/modules/poll/README.md", "dbType": "redis", "dbKeys": [ "polls" ], "ignorable": true, diff --git a/modules/profile/config.json b/modules/profile/config.json index 704e38a..70b7210 100644 --- a/modules/profile/config.json +++ b/modules/profile/config.json @@ -1,7 +1,6 @@ { "ignorable": false, "dbType": "redis", - "help": "https://github.com/reality/depressionbot/blob/master/modules/profile/README.md", "schema": { "profile": { "primary": null, diff --git a/modules/quotes/config.json b/modules/quotes/config.json index 03c77f4..371bc8f 100644 --- a/modules/quotes/config.json +++ b/modules/quotes/config.json @@ -2,6 +2,5 @@ "dbType": "redis", "dependencies": [ "users", "event" ], "rmLimit": 10, - "ignorable": true, - "help": "http://github.com/reality/depressionbot/blob/master/modules/quotes/README.md" + "ignorable": true } diff --git a/modules/rain/config.json b/modules/rain/config.json index f176f2a..afffe93 100644 --- a/modules/rain/config.json +++ b/modules/rain/config.json @@ -1,6 +1,5 @@ { "dependencies": [ "command" ], "ignorable": true, - "help": "http://github.com/reality/depressionbot/blob/master/modules/rain/README.md", "apikey": "7707e78c7125741e" } diff --git a/modules/regex/config.json b/modules/regex/config.json index a2a42c7..c945e96 100644 --- a/modules/regex/config.json +++ b/modules/regex/config.json @@ -1,4 +1,3 @@ { - "ignorable": true, - "help": "http://github.com/reality/depressionbot/blob/master/modules/regex/README.md" + "ignorable": true } diff --git a/modules/report/config.json b/modules/report/config.json index e79966d..121ef4a 100644 --- a/modules/report/config.json +++ b/modules/report/config.json @@ -1,6 +1,5 @@ { "ignorable": true, "notifyVoice": false, - "dependencies": [ "users" ], - "help": "http://github.com/reality/depressionbot/blob/master/modules/report/README.md" + "dependencies": [ "users" ] } diff --git a/modules/spelling/config.json b/modules/spelling/config.json index 3a54ca9..c945e96 100644 --- a/modules/spelling/config.json +++ b/modules/spelling/config.json @@ -1,4 +1,3 @@ { - "ignorable": true, - "help": "http://github.com/reality/depressionbot/blob/master/modules/spelling/README.md" + "ignorable": true } diff --git a/modules/timers/config.json b/modules/timers/config.json deleted file mode 100644 index 9cc23c8..0000000 --- a/modules/timers/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "help": "https://github.com/reality/depressionbot/blob/master/modules/timers/README.md" -} diff --git a/modules/users/config.json b/modules/users/config.json index 2c23325..c9b6aa2 100644 --- a/modules/users/config.json +++ b/modules/users/config.json @@ -2,6 +2,5 @@ "ignorable": false, "dependencies": [ "event" ], "dbKeys": [ "knownUsers" ], - "help": "https://github.com/reality/depressionbot/blob/master/modules/users/README.md", "dbType": "redis" } diff --git a/modules/web/config.json b/modules/web/config.json index e6b635e..a92a66f 100644 --- a/modules/web/config.json +++ b/modules/web/config.json @@ -1,6 +1,5 @@ { "webHost": "nourishedcloud.com", "webPort": 8080, - "externalPath": false, - "help": "https://github.com/reality/depressionbot/blob/master/modules/web/README.md" + "externalPath": false } From 33f8b21edd975b7f7a19d40dd642c755c42113c4 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 17 May 2013 12:02:38 +0000 Subject: [PATCH 079/220] config rather than currentOption --- modules/admin/commands.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/admin/commands.js b/modules/admin/commands.js index 3cd10c6..55adce9 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -174,11 +174,11 @@ var commands = function(dbot) { } // Convert to integer type is config item integer - if(_.isNumber(currentOption)) { + if(_.isNumber(config)) { newOption = parseInt(newOption); } - if(_.isArray(currentOption)) { + if(_.isArray(config)) { event.reply(dbot.t("config_array", { "alternate": "pushconfig" })); } From 1e52809e06952655e096892d489705a63458ef03 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 17 May 2013 16:57:47 +0000 Subject: [PATCH 080/220] nickserv thing --- modules/nickserv/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nickserv/config.json b/modules/nickserv/config.json index 3bcaece..5d7d7c5 100644 --- a/modules/nickserv/config.json +++ b/modules/nickserv/config.json @@ -1,6 +1,6 @@ { "servers": { - "nc": { + "aberwiki": { "matcher": "STATUS ([^ ]+) (\\d)$", "acceptableState": 3, "infoCommand": "status" From 6dfa5de47897a0c596df0767e28f63194663dc5d Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 17 May 2013 17:04:19 +0000 Subject: [PATCH 081/220] youare doesnt need snippets [#135] --- modules/youare/youare.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/youare/youare.js b/modules/youare/youare.js index 2aa4ecd..407b95f 100644 --- a/modules/youare/youare.js +++ b/modules/youare/youare.js @@ -2,7 +2,7 @@ var youAre = function(dbot) { this.listener = function(event) { var key = event.message.valMatch(/(\bis\b|\bare\b)\s+([\w\s\d]*?)(\s+)?(,|\.|\band\b|$)/, 5); - if(key && key[2] != "" && Number.prototype.chanceIn(1, 100) && event.user != 'aisbot') { + if(key && key[2] != "" && (Math.floor(Math.random() * (101)) / 1) == 1) { event.reply(event.user + ': You\'re ' + key[2] + '.'); } }.bind(this); From 5bcd1d9c27993171544b1a439ad2fe5a9faa3f7b Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 17 May 2013 17:04:55 +0000 Subject: [PATCH 082/220] remove chancein --- snippets.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/snippets.js b/snippets.js index 3aca93f..caf4b60 100644 --- a/snippets.js +++ b/snippets.js @@ -24,13 +24,6 @@ String.prototype.format = function() { // format takes either multiple indexed a return targetStr; }; -/*** Integer ***/ - -Number.prototype.chanceIn = function(x, y) { - var num = Math.floor(Math.random() * (y + 1)) / x; - return num == 1; -}; - /*** Regex ***/ RegExp.prototype.url_regex = function() { var reg = new RegExp( From e8c2db54881dfea82cb058576c6e65c0557e25ab Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 17 May 2013 17:23:39 +0000 Subject: [PATCH 083/220] Update documentation for users [#351] --- modules/quotes/README.md | 72 +++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/modules/quotes/README.md b/modules/quotes/README.md index c397a6c..4c14323 100644 --- a/modules/quotes/README.md +++ b/modules/quotes/README.md @@ -11,42 +11,31 @@ This is the original reason that DBot was created, stores and displays quotes. #### rmLimit: 10 Amount of quotes which can be removed before admin approval is required. -### Commands +#### quotesOnJoin: false +Show quotes for users when they enter channels. + +### Commands: Quote Addition + +#### ~qadd [category] = [quote] +Add a new quote to the database under the given category. + +### Commands: Quote Retrieval + +#### ~[category] +Alias for ~q. #### ~q [category] Display a random quote from a given category. -#### ~qadd [category] = [quote] -Add a new quote to the database. +#### ~rq +Show a random quote from the database. -#### ~qstats -Show a list of the biggest quote categories. - -#### ~qsearch [category] = [needle] -Search a category for quotes including the given text. - -#### ~rmlast [category] -Remove the last quote added to a given category. +### Commands: Quote Removal #### ~rmstatus Show how many quotes are currently in the removal cache, and whether they will be randomly removed. -#### ~rm [category] = [quote] -Remove a given quote from the given category. - -#### ~qcount [category] -Show the number of quotes stored in the given category, or if called without a -category it will show the total number of quotes in the database. - -#### ~rq -Show a random quote from the database. - -#### ~link [category] -Show a link to the page on the web interface which shows this category's quotes. - -### Admin-only Commands - #### ~rmconfirm Confirm that the quotes currently in the removal cache are okay to be removed, and permanently delete them. @@ -55,6 +44,37 @@ and permanently delete them. Re-instate the quotes that are currently in the removal cache back into the main quote database. +#### ~rmlast [category] +Remove the last quote added to a given category. + +#### ~rm [category] = [quote] +Remove a given quote from the given category. + +### Commands: Stats & Searching + +#### ~qstats +Show a list of the biggest quote categories. + +#### ~qsearch [category] = [needle] +Search a category for quotes including the given text. If category is given as +_*_, then all categories will be searched for the given text. + +#### ~qcount [category] +Show the number of quotes stored in the given category, or if called without a +category it will show the total number of quotes in the database. + +#### ~qrename [oldName] [newName] +Rename a quote category. + +#### ~qmerge [primary] [secondary] +Merge two quote categories into one. + +#### ~link [category] +Show a link to the page on the web interface which shows this category's quotes. + +### Admin-only Commands + + ### API #### getQuote(event, category) From 449ad684ada8bf039595be45431dae44a26f88b1 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 17 May 2013 17:57:21 +0000 Subject: [PATCH 084/220] More quotes docs updates [#351] --- modules/quotes/README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/modules/quotes/README.md b/modules/quotes/README.md index 4c14323..fbb551d 100644 --- a/modules/quotes/README.md +++ b/modules/quotes/README.md @@ -72,13 +72,20 @@ Merge two quote categories into one. #### ~link [category] Show a link to the page on the web interface which shows this category's quotes. -### Admin-only Commands - - ### API -#### getQuote(event, category) -Returns a random quote from the given category. +#### addQuote(key, quote, user, callback) +Add the given quote to the category stored under the given key. If it's a new +quote category, then the owner of the category will be recorded as the given +user. The callback is called with one argument, the new quote count of the given +category. + +#### getQuote (key, callback) +Get a random quote from the given category. Callback is called with one +argument, either a random quote under the given key, or false if the category +doesn't exist. This getQuote function does not require a server argument, and as +such does not run the quote through the interpolation function (does not parse +~~category~~ etc). ### Removal Spam Protection From 3541534b76d6828e22c4f11a9903be01a424ed90 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 19 May 2013 09:52:14 +0000 Subject: [PATCH 085/220] this should fix [#453] --- modules/imgur/imgur.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgur/imgur.js b/modules/imgur/imgur.js index 92cacde..f9ec547 100644 --- a/modules/imgur/imgur.js +++ b/modules/imgur/imgur.js @@ -11,7 +11,7 @@ var imgur = function(dbot) { this.internalAPI = { 'infoString': function(imgData) { info = ''; - if(imgData && _.has(imgData, 'data')) { + if(imgData && _.has(imgData, 'data') && !_.isUndefined(imgData.type)) { imgData = imgData.data; if(imgData.title) { info += imgData.title + ' - '; From 0bc0a1bdb7f18e58f4d8114236649e5ee6c6c145 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 20 May 2013 15:40:13 +0000 Subject: [PATCH 086/220] quote add for db branch in imgur --- modules/imgur/imgur.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgur/imgur.js b/modules/imgur/imgur.js index e5bc058..018234f 100644 --- a/modules/imgur/imgur.js +++ b/modules/imgur/imgur.js @@ -58,8 +58,8 @@ var imgur = function(dbot) { if (_.contains(category, testUrl)){ // there's probably less than 62^5 chance of this happening } else { - if(!_.has(dbot.db.quoteArrs, category)) dbot.db.quoteArrs[category] = []; - dbot.db.quoteArrs[category].push(testUrl); + dbot.api.quotes.addQuote(category, testUrl, + dbot.config.name, function() { }); } } } From 6d9f3b644c78a54001bc9aee854c1f8ce33d3382 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 20 May 2013 19:51:09 +0000 Subject: [PATCH 087/220] fix ~rmdeny and add web route /quoteremovals [#455] --- modules/quotes/commands.js | 2 +- modules/quotes/pages.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index e8205c7..1ce726a 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -87,7 +87,7 @@ var commands = function(dbot) { _.each(rmCache, function(quote, index) { this.api.addQuote(quote.key, quote.quote, event.user, function(newCount) { }); - }); + }.bind(this)); rmCache.length = 0; event.reply(dbot.t('quote_cache_reinstated', diff --git a/modules/quotes/pages.js b/modules/quotes/pages.js index 0f0c977..abdd4c3 100644 --- a/modules/quotes/pages.js +++ b/modules/quotes/pages.js @@ -30,6 +30,13 @@ var pages = function(dbot) { }); }); }, + + '/quoteremovals': function(req, res) { + res.render('quotes', { + 'name': dbot.config.name, + 'quotes': _.pluck(this.rmCache, 'quote') + }); + } } }; From 11b23ffc85355217132c26dc3bf8b290270fe1d6 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 21 May 2013 16:05:20 +0000 Subject: [PATCH 088/220] fix for the bug with infostring i introduced fixing undefinedxundefined --- modules/imgur/imgur.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgur/imgur.js b/modules/imgur/imgur.js index 018234f..7dc387d 100644 --- a/modules/imgur/imgur.js +++ b/modules/imgur/imgur.js @@ -11,7 +11,7 @@ var imgur = function(dbot) { this.internalAPI = { 'infoString': function(imgData) { info = ''; - if(imgData && _.has(imgData, 'data') && !_.isUndefined(imgData.type)) { + if(imgData && _.has(imgData, 'data') && !_.isUndefined(imgData.data.type)) { imgData = imgData.data; if(imgData.title) { info += imgData.title + ' - '; From a446999285285ce7e91ca6cb1037abb3c2dccd7f Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 21 May 2013 17:32:26 +0000 Subject: [PATCH 089/220] fix merge properly --- run.js | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/run.js b/run.js index ce62d0c..53e86ff 100644 --- a/run.js +++ b/run.js @@ -136,10 +136,7 @@ DBot.prototype.reloadModules = function() { this.modules = {}; this.commands = {}; this.api = {}; -<<<<<<< HEAD -======= this.stringMap = {}; ->>>>>>> 36d40f65a309f6911bae95bf0428d332c32a496a this.usage = {}; try { @@ -221,7 +218,6 @@ DBot.prototype.reloadModules = function() { } } -<<<<<<< HEAD process.nextTick(function() { _.each(moduleNames, function(name) { try { @@ -235,21 +231,6 @@ DBot.prototype.reloadModules = function() { console.log('Error loading module: ' + err + ' ' + stack); return; } -======= - // Load string data for the module - _.each([ 'usage', 'strings' ], function(property) { - var propertyData = {}; - try { - propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); - } catch(err) {}; - _.extend(this[property], propertyData); - if(property == 'strings') { - _.each(_.keys(propertyData), function(string) { - this.stringMap[string] = name; - }.bind(this)); - } - }, this); ->>>>>>> 36d40f65a309f6911bae95bf0428d332c32a496a module.name = name; module.db = this.ddb.databanks[name]; @@ -307,6 +288,11 @@ DBot.prototype.reloadModules = function() { propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); } catch(err) {}; _.extend(this[property], propertyData); + if(property == 'strings') { + _.each(_.keys(propertyData), function(string) { + this.stringMap[string] = name; + }.bind(this)); + } }, this); // Provide toString for module name From a140c19483fabe021ce3b24fe3c667078ad37ade Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 21 May 2013 18:32:59 +0000 Subject: [PATCH 090/220] blue link --- modules/link/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/link/config.json b/modules/link/config.json index a7ccc37..aff6d75 100644 --- a/modules/link/config.json +++ b/modules/link/config.json @@ -1,6 +1,6 @@ { "autoTitle": true, "ignorable": true, - "outputPrefix": "\u00034link\u000f", + "outputPrefix": "\u00032link\u000f", "help": "http://github.com/reality/depressionbot/blob/master/modules/link/README.md" } From e8757347ba8649c9d77c51f57addeec5db201b4e Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 21 May 2013 18:39:11 +0000 Subject: [PATCH 091/220] eventsdocumentation in users [#351] --- modules/users/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/users/README.md b/modules/users/README.md index 032d7cd..90ac175 100644 --- a/modules/users/README.md +++ b/modules/users/README.md @@ -79,8 +79,14 @@ the specified place. ### Events -#### nick_changed(server, newNick) -This is executed when a new alias is added for a user. +#### new_user(user) +This is executed when a new user is added to the known users DB. -#### new_user(server, nick) -This is executed when a new primary user is added to the known users DB. +#### new_user_alias(user, newNick) +When a new user alias is added. + +#### new_channel(channel) +Executed when DBot creates a new channel object. + +#### new_channel_user(user, channel) +Executed when DBot creates a new channel object. From 61bd1312a6fde11ab4f4a4569cecf11b030d02a7 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 21 May 2013 20:17:22 +0000 Subject: [PATCH 092/220] Fix fucking async hell and add getAllChannels --- modules/users/api.js | 14 ++++++++++++++ modules/users/users.js | 24 ++++++++++++++---------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/modules/users/api.js b/modules/users/api.js index 1d5ffc3..8fc537a 100644 --- a/modules/users/api.js +++ b/modules/users/api.js @@ -79,6 +79,17 @@ var api = function(dbot) { }); }, + 'getAllChannels': function(callback) { + var channels = []; + this.db.scan('channel_users', function(channel) { + channels.push(channel); + }, function(err) { + if(!err) { + callback(channels); + } + }); + }, + 'isOnline': function(server, nick, channel, callback) { this.api.resolveUser(server, nick, function(user) { var possiNicks = [user].concat(user.aliases); @@ -115,6 +126,9 @@ var api = function(dbot) { api['getAllUsers'].external = true; api['getAllUsers'].extMap = [ 'callback' ]; + api['getAllChannels'].external = true; + api['getAllChannels'].extMap = [ 'callback' ]; + return api; }; diff --git a/modules/users/users.js b/modules/users/users.js index 03d2fc5..b40f937 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -84,7 +84,6 @@ var users = function(dbot) { 'channels': [], 'aliases': [] }; - this.internalAPI.addChannelUser(user, event.channel.name, function(err) { }); needsUpdating = true; } @@ -127,26 +126,31 @@ var users = function(dbot) { dbot.instance.addListener('366', 'users', function(event) { this.api.getChannel(event.server, event.channel.name, function(channel) { var checkChannelUsers = function(channel) { - _.each(event.channel.nicks, function(nick) { - var nick = nick.name; + var i = 0; + var checkChannelNicks = function(chanicks) { + if(i == chanicks.length) return; + var nick = chanicks[i]; i++; this.api.resolveUser(event.server, nick, function(user) { if(!user) { this.internalAPI.createUser(event.server, nick, event.channel.name, function(result) { - channel.users.push(result.id); + this.internalAPI.addChannelUser(result, event.channel.name, function(err) { + checkChannelNicks(chanicks); + }); }.bind(this)); } else { if(!_.include(user.channels, event.channel.name)) { - channel.users.push(user.id); + this.internalAPI.addChannelUser(user, event.channel.name, function(err) { + checkChannelNicks(chanicks); + }); user.channels.push(event.channel.name); this.db.save('users', user.id, user, function(err) { }); + } else { + checkChannelNicks(chanicks); } } }.bind(this)); - }, this); - - process.nextTick(function() { - this.db.save('channel_users', channel.id, channel, function(err) { }); - }.bind(this)); + }.bind(this); + checkChannelNicks(_.keys(event.channel.nicks)); }.bind(this); if(!channel) { // Channel does not yet exist From b71c9e4504af85df944e0706d1c2423b4f1d917a Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 25 May 2013 21:06:32 +0000 Subject: [PATCH 093/220] link dependency for status --- modules/reddit/config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/reddit/config.json b/modules/reddit/config.json index f934fa5..5a94458 100644 --- a/modules/reddit/config.json +++ b/modules/reddit/config.json @@ -1,3 +1,4 @@ { - "outputPrefix": "\u000312reddit\u000f" + "outputPrefix": "\u000312reddit\u000f", + "dependencies": [ "link" ] } From 5bf6088453a70a1b10cf174fc4adc685c308868f Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 25 May 2013 21:34:11 +0000 Subject: [PATCH 094/220] fix command emit on reload --- modules/command/command.js | 2 +- modules/command/config.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/command/command.js b/modules/command/command.js index 3ad891c..a950199 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -50,7 +50,7 @@ var command = function(dbot) { }); } } - dbot.api.event.emit('command', [ event ]); + if(commandName != 'reload') dbot.api.event.emit('command', [ event ]); dbot.save(); } else { if(commandName !== '~') { diff --git a/modules/command/config.json b/modules/command/config.json index 08bcfe1..ead0df9 100644 --- a/modules/command/config.json +++ b/modules/command/config.json @@ -1,5 +1,5 @@ { "ignorable": false, - "dependencies": [ "ignore", "users" ], + "dependencies": [ "event", "ignore", "users" ], "useNickserv": false } From 2fc5fc699204c53ac08bbb2d6568674371f566a0 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 25 May 2013 22:09:07 +0000 Subject: [PATCH 095/220] remove command hooks [#471] --- modules/command/api.js | 10 ---------- modules/command/command.js | 5 ----- modules/poll/poll.js | 4 ++-- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/modules/command/api.js b/modules/command/api.js index 4cf92a9..adaedac 100644 --- a/modules/command/api.js +++ b/modules/command/api.js @@ -53,16 +53,6 @@ var api = function(dbot) { applies = true; } return applies; - }, - - 'addHook': function(command, callback) { - console.log('adding hook'); - if(_.has(dbot.commands, command)) { - if(!_.has(dbot.commands[command], 'hooks')) { - dbot.commands[command].hooks = []; - } - dbot.commands[command].hooks.push(callback); - } } }; }; diff --git a/modules/command/command.js b/modules/command/command.js index a950199..1066018 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -32,11 +32,6 @@ var command = function(dbot) { try { var command = dbot.commands[commandName]; var results = command.apply(dbot.modules[command.module], [event]); - if(_.has(command, 'hooks') && results !== false) { - _.each(command['hooks'], function(hook) { - hook.apply(hook.module, _.values(results)); - }, this); - } } catch(err) { if(dbot.config.debugMode == true) { var stack = err.stack.split('\n').slice(1, dbot.config.debugLevel + 1); diff --git a/modules/poll/poll.js b/modules/poll/poll.js index 1110faa..d54e8f1 100644 --- a/modules/poll/poll.js +++ b/modules/poll/poll.js @@ -15,8 +15,8 @@ var poll = function(dbot) { }; this.onLoad = function() { - dbot.api.command.addHook('~setaliasparent', this.internalAPI.updatePollNicks); - dbot.api.command.addHook('~mergeusers', this.internalAPI.updatePollNicks); + // dbot.api.command.addHook('~setaliasparent', this.internalAPI.updatePollNicks); + // dbot.api.command.addHook('~mergeusers', this.internalAPI.updatePollNicks); }.bind(this); }; From 5dddae4f00e5873adb62c61e11f8c4b65e8a40cd Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 12:37:37 +0000 Subject: [PATCH 096/220] mergeChannelUsers internal API function in users + mergeusers seems to be working [#470] --- modules/users/commands.js | 17 +++++++++-------- modules/users/strings.json | 2 +- modules/users/users.js | 21 ++++++++++++++++++++- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/modules/users/commands.js b/modules/users/commands.js index 8a89e97..1a96e53 100644 --- a/modules/users/commands.js +++ b/modules/users/commands.js @@ -83,7 +83,7 @@ var commands = function(dbot) { } }); } else { - event.reply(dbot.t('unknown_alias', { 'alias': newPrimary })); + event.reply(dbot.t('unknown_alias', { 'alias': newPrimarj })); } }.bind(this)); }, @@ -94,15 +94,16 @@ var commands = function(dbot) { this.api.resolveUser(event.server, primaryUser, function(user) { if(user) { - this.api.resolveUser(event.server, secondaryUser, function(secondaryUser) { + this.api.resolveUser(event.server, secondaryUser, function(oldUser) { if(secondaryUser) { - user.aliases.push(secondaryUser.primaryNick); - user.aliases.concat(secondaryUser.aliases); - this.db.del('users', secondaryUser.id, function(err) { + user.aliases.push(oldUser.primaryNick); + user.aliases.concat(oldUser.aliases); + this.internalAPI.mergeChannelUsers(event.server, oldUser, primaryUser); + this.db.del('users', oldUser.id, function(err) { if(!err) { this.db.save('users', user.id, user, function(err) { if(!err) { - this.updateChannels(event, secondaryUser, primaryUser); + this.internalAPI.mergeChannelUsers(event.server, secondaryUser, primaryUser); event.reply(dbot.t('merged_users', { 'old_user': secondaryUser, 'new_user': primaryUser @@ -116,11 +117,11 @@ var commands = function(dbot) { } }.bind(this)); } else { - event.reply(dbot.t('unprimary_error')); + event.reply(dbot.t('unprimary_error', { 'nick': secondaryUser })); } }.bind(this)); } else { - event.reply(dbot.t('unprimary_error')); + event.reply(dbot.t('unprimary_error', { 'nick': primaryUser })); } }.bind(this)); } diff --git a/modules/users/strings.json b/modules/users/strings.json index a8f60f1..fe9f79d 100644 --- a/modules/users/strings.json +++ b/modules/users/strings.json @@ -20,7 +20,7 @@ "nl": "{newParent} is nu de bovenliggende gebruiker, en {newAlias} is een alias." }, "unprimary_error": { - "en": "One of those users isn't currently recorded as a primary user.", + "en": "{nick} isn't recorded as a primary user.", "na'vi": "fo sute txin ke lu.", "nl": "Een van deze gebruikers is nog niet bekend als een primaire gebruiker." }, diff --git a/modules/users/users.js b/modules/users/users.js index b40f937..5612521 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -67,7 +67,26 @@ var users = function(dbot) { // QQ } }); - }.bind(this) + }.bind(this), + + 'mergeChannelUsers': function(server, oldUser, newUser) { + newUser.channels = _.union(oldUser.channels, newUser.channels); + _.each(newUser.channels, function(name) { + this.api.getChannel(server, name, function(channel) { + if(_.include(channel.users, oldUser.id)) { + channel.users = _.without(channel.users, oldUser.id); + } + if(!_.include(channel.users, newUser.id)) { + channel.users.push(newUser.id); + } + this.db.save('channel_users', channel.id, channel, function(err) { + if(err) { + // QQ + } + }); + }); + }, this); + } }; this.listener = function(event) { From f69f99911878e37969152fcc5c05ca4fb5c754cd Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 13:11:09 +0000 Subject: [PATCH 097/220] fix various mergeusers hooks [#472] --- modules/poll/config.json | 2 +- modules/poll/poll.js | 28 ++++++++++++++++------------ modules/users/commands.js | 11 ++++++----- modules/users/users.js | 4 ++-- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/modules/poll/config.json b/modules/poll/config.json index 6047e33..ee19c00 100644 --- a/modules/poll/config.json +++ b/modules/poll/config.json @@ -2,7 +2,7 @@ "dbType": "redis", "dbKeys": [ "polls" ], "ignorable": true, - "dependencies": [ "users", "web" ], + "dependencies": [ "users", "web", "event" ], "schema": { "poll": { "pkey": "name", diff --git a/modules/poll/poll.js b/modules/poll/poll.js index d54e8f1..13bebcf 100644 --- a/modules/poll/poll.js +++ b/modules/poll/poll.js @@ -1,22 +1,26 @@ var poll = function(dbot) { this.internalAPI = { - 'updatePollNicks': function(server, oldNick) { - var newNick = dbot.api.users.resolveUser(server, oldNick); - _.each(dbot.db.polls, function(poll) { - if(poll.owner === oldNick) { - poll.owner = newNick; + 'updatePollNicks': function(server, oldUser, newUser) { + this.db.scan('poll', function(poll) { + var needsUpdating = false; + if(poll.owner == oldUser.id) { + poll.owner = newUser.id; + needsUpdating = true; } - if(_.has(poll.votees, oldNick)) { - poll.votees[newNick] = poll.votees[oldNick]; - delete poll.votees[oldNick]; + if(_.has(poll.votees, oldUser.id)) { + poll.votes[poll.votees[oldUser.id]]--; + delete poll.votees[oldUser.id]; + needsUpdating = true; } - }, this); - } + if(needsUpdating) { + this.db.save('poll', poll.name, poll, function(err) {}); + } + }.bind(this), function(err) {}); + }.bind(this) }; this.onLoad = function() { - // dbot.api.command.addHook('~setaliasparent', this.internalAPI.updatePollNicks); - // dbot.api.command.addHook('~mergeusers', this.internalAPI.updatePollNicks); + dbot.api.event.addHook('~mergeusers', this.internalAPI.updatePollNicks); }.bind(this); }; diff --git a/modules/users/commands.js b/modules/users/commands.js index 1a96e53..ac78de1 100644 --- a/modules/users/commands.js +++ b/modules/users/commands.js @@ -98,7 +98,7 @@ var commands = function(dbot) { if(secondaryUser) { user.aliases.push(oldUser.primaryNick); user.aliases.concat(oldUser.aliases); - this.internalAPI.mergeChannelUsers(event.server, oldUser, primaryUser); + this.internalAPI.mergeChannelUsers(event.server, oldUser, user); this.db.del('users', oldUser.id, function(err) { if(!err) { this.db.save('users', user.id, user, function(err) { @@ -108,10 +108,11 @@ var commands = function(dbot) { 'old_user': secondaryUser, 'new_user': primaryUser })); - dbot.api.event.emit('~mergeusers', { - 'server': event.server, - 'secondary': secondaryUser - }); + dbot.api.event.emit('~mergeusers', [ + event.server, + oldUser, + user + ]); } }.bind(this)); } diff --git a/modules/users/users.js b/modules/users/users.js index 5612521..4d372ef 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -84,9 +84,9 @@ var users = function(dbot) { // QQ } }); - }); + }.bind(this)); }, this); - } + }.bind(this) }; this.listener = function(event) { From d9850d19d54d85bc35c3ff04c0d1eb2d72695f6b Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 13:29:21 +0000 Subject: [PATCH 098/220] fix some more mergeuser issues [#470] --- modules/users/commands.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/users/commands.js b/modules/users/commands.js index ac78de1..1011249 100644 --- a/modules/users/commands.js +++ b/modules/users/commands.js @@ -95,9 +95,9 @@ var commands = function(dbot) { this.api.resolveUser(event.server, primaryUser, function(user) { if(user) { this.api.resolveUser(event.server, secondaryUser, function(oldUser) { - if(secondaryUser) { + if(oldUser) { user.aliases.push(oldUser.primaryNick); - user.aliases.concat(oldUser.aliases); + user.aliases = _.union(user.aliases, oldUser.aliases); this.internalAPI.mergeChannelUsers(event.server, oldUser, user); this.db.del('users', oldUser.id, function(err) { if(!err) { From 9847a05301192f42b4175e3ab99978f5d0e00e4d Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 14:14:01 +0000 Subject: [PATCH 099/220] Add accessOutput command to tell users when they are not authorised to run a command [#467] --- modules/command/command.js | 10 ++++++---- modules/command/config.json | 3 ++- modules/command/strings.json | 3 +++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/modules/command/command.js b/modules/command/command.js index 1066018..b238ce7 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -25,9 +25,11 @@ var command = function(dbot) { dbot.api.ignore.isUserBanned(event.server, event.user, commandName, function(isBanned) { if(isBanned) { event.reply(dbot.t('command_ban', {'user': event.user})); - } else if(!isIgnoring && - hasAccess && - dbot.commands[commandName].disabled !== true) { + } else if(!hasAccess) { + if(this.config.accessOutput) { + event.reply(dbot.t('access_denied', { 'user': event.user })); + } + } else if(!isIgnoring && !dbot.commands[commandName].disabled) { if(this.api.applyRegex(commandName, event)) { try { var command = dbot.commands[commandName]; @@ -45,7 +47,7 @@ var command = function(dbot) { }); } } - if(commandName != 'reload') dbot.api.event.emit('command', [ event ]); + if(_.include(commandName, ['reload', 'load', 'unload'])) dbot.api.event.emit('command', [ event ]); dbot.save(); } else { if(commandName !== '~') { diff --git a/modules/command/config.json b/modules/command/config.json index ead0df9..3cb33e0 100644 --- a/modules/command/config.json +++ b/modules/command/config.json @@ -1,5 +1,6 @@ { "ignorable": false, "dependencies": [ "event", "ignore", "users" ], - "useNickserv": false + "useNickserv": false, + "accessOutput": false } diff --git a/modules/command/strings.json b/modules/command/strings.json index d13553a..26f1b6c 100644 --- a/modules/command/strings.json +++ b/modules/command/strings.json @@ -36,5 +36,8 @@ "loaded_modules": { "en": "Loaded modules: {modules}.", "nl": "Geladen modules: {modules}." + }, + "access_denied": { + "en": "{user}: You don't have the access level to run this command." } } From 3148b3e4348cbbdbd4a659637d12cd89b609881c Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 14:16:56 +0000 Subject: [PATCH 100/220] document new command config features [#467][#351] --- modules/command/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/command/README.md b/modules/command/README.md index 619fa04..e0115bc 100644 --- a/modules/command/README.md +++ b/modules/command/README.md @@ -21,6 +21,17 @@ Command flow: This is the only module which is force loaded, even if it's not specified in the configuration file. +### Config + +#### useNickserv: false +Use the nickserv module to ensure a user is logged into their account before +running any elevated commands. Note you will still have to load and configure +the nickserv module yourself. + +#### accessOutput: false +Show a message to a user if they attempt to run a command they don't have the +access level for. + ### Commands #### ~usage [command] From bc7bac121876f2a52892061917631d337e952ac0 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 15:21:13 +0000 Subject: [PATCH 101/220] Do not continue to load module if data file syntax error occurs [#466] --- run.js | 158 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 80 insertions(+), 78 deletions(-) diff --git a/run.js b/run.js index 53e86ff..6324072 100644 --- a/run.js +++ b/run.js @@ -186,7 +186,7 @@ DBot.prototype.reloadModules = function() { defaultConfig = JSON.parse(defaultConfig); } catch(err) { // syntax error this.status[name] = 'Error parsing config: ' + err + ' ' + err.stack.split('\n')[2].trim(); - return; + continue; } config = _.defaults(config, defaultConfig); } catch(err) { @@ -220,87 +220,89 @@ DBot.prototype.reloadModules = function() { process.nextTick(function() { _.each(moduleNames, function(name) { - try { - var moduleDir = './modules/' + name + '/'; - var rawModule = require(moduleDir + name); - var module = rawModule.fetch(this); - this.rawModules.push(rawModule); - } catch(err) { - var stack = err.stack.split('\n')[2].trim(); - this.status[name] = 'Error loading module: ' + err + ' ' + stack; - console.log('Error loading module: ' + err + ' ' + stack); - return; - } - - module.name = name; - module.db = this.ddb.databanks[name]; - module.config = this.config[name]; - - // Load the module data - _.each([ 'commands', 'pages', 'api' ], function(property) { - var propertyObj = {}; - - if(fs.existsSync(moduleDir + property + '.js')) { - try { - var propertyKey = require.resolve(moduleDir + property); - if(propertyKey) delete require.cache[propertyKey]; - propertyObj = require(moduleDir + property).fetch(this); - } catch(err) { - this.status[name] = 'Error loading ' + propertyKey + - ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); - console.log('Module error (' + module.name + ') in ' + - property + ': ' + err); - } - } - - if(!_.has(module, property)) module[property] = {}; - _.extend(module[property], propertyObj); - _.each(module[property], function(item, itemName) { - item.module = name; - if(_.has(module.config, property) && _.has(module.config[property], itemName)) { - _.extend(item, module.config[property][itemName]); - } - module[property][itemName] = _.bind(item, module); - _.extend(module[property][itemName], item); - }, this); - - if(property == 'api') { - this[property][name] = module[property]; - } else { - _.extend(this[property], module[property]); - } - }, this); - - // Load the module listener - if(module.listener) { - if(!_.isArray(module.on)) { - module.on = [ module.on ]; - } - _.each(module.on, function(on) { - this.instance.addListener(on, module.name, module.listener); - }, this); - } - - // Load string data for the module - _.each([ 'usage', 'strings' ], function(property) { - var propertyData = {}; + if(this.status[name] === true) { try { - propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); - } catch(err) {}; - _.extend(this[property], propertyData); - if(property == 'strings') { - _.each(_.keys(propertyData), function(string) { - this.stringMap[string] = name; - }.bind(this)); + var moduleDir = './modules/' + name + '/'; + var rawModule = require(moduleDir + name); + var module = rawModule.fetch(this); + this.rawModules.push(rawModule); + } catch(err) { + var stack = err.stack.split('\n')[2].trim(); + this.status[name] = 'Error loading module: ' + err + ' ' + stack; + console.log('Error loading module: ' + err + ' ' + stack); + return; } - }, this); - // Provide toString for module name - module.toString = function() { - return this.name; + module.name = name; + module.db = this.ddb.databanks[name]; + module.config = this.config[name]; + + // Load the module data + _.each([ 'commands', 'pages', 'api' ], function(property) { + var propertyObj = {}; + + if(fs.existsSync(moduleDir + property + '.js')) { + try { + var propertyKey = require.resolve(moduleDir + property); + if(propertyKey) delete require.cache[propertyKey]; + propertyObj = require(moduleDir + property).fetch(this); + } catch(err) { + this.status[name] = 'Error loading ' + propertyKey + + ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); + console.log('Module error (' + module.name + ') in ' + + property + ': ' + err); + } + } + + if(!_.has(module, property)) module[property] = {}; + _.extend(module[property], propertyObj); + _.each(module[property], function(item, itemName) { + item.module = name; + if(_.has(module.config, property) && _.has(module.config[property], itemName)) { + _.extend(item, module.config[property][itemName]); + } + module[property][itemName] = _.bind(item, module); + _.extend(module[property][itemName], item); + }, this); + + if(property == 'api') { + this[property][name] = module[property]; + } else { + _.extend(this[property], module[property]); + } + }, this); + + // Load the module listener + if(module.listener) { + if(!_.isArray(module.on)) { + module.on = [ module.on ]; + } + _.each(module.on, function(on) { + this.instance.addListener(on, module.name, module.listener); + }, this); + } + + // Load string data for the module + _.each([ 'usage', 'strings' ], function(property) { + var propertyData = {}; + try { + propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); + } catch(err) {}; + _.extend(this[property], propertyData); + if(property == 'strings') { + _.each(_.keys(propertyData), function(string) { + this.stringMap[string] = name; + }.bind(this)); + } + }, this); + + // Provide toString for module name + module.toString = function() { + return this.name; + } + + this.modules[module.name] = module; } - - this.modules[module.name] = module; }.bind(this)); }.bind(this)); From 1ce4b059324fc0d3e1f8d85fc30d6685a84c0573 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 15:38:48 +0000 Subject: [PATCH 102/220] documentation for the spotify module --- modules/spotify/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 modules/spotify/README.md diff --git a/modules/spotify/README.md b/modules/spotify/README.md new file mode 100644 index 0000000..ec0839f --- /dev/null +++ b/modules/spotify/README.md @@ -0,0 +1,28 @@ +## spotify + +Various Spotify functionality. + +### Description +This module posts information on Spotify links, as well as providing Spotify +search functionality. + +## Commands + +### ~spotify [query] +Search spotify for a song. + +### ~syt [youtube link] +Attempt to get a Spotify link from a YouTube link. If no link is provided with +the commands, it will attempt to use the last link posted in the channel. + +## API + +#### spotifySearch(query, callback) +Run a search query on Spotify. If no results are found, the callback will pass +false. If a result is found, the callback takes two arguments: data about the +found track, and a link to the track. + +### Hooks + +#### link +Posts information about a Spotify link when one is posted in a channel. From d8191c8232bf64cd938cbda36079003a0af60c08 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 15:49:44 +0000 Subject: [PATCH 103/220] Update install.sh modules and update web docs [#464][#351] --- install.sh | 2 +- modules/web/README.md | 24 +++++++----------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/install.sh b/install.sh index d175afb..dd90ab1 100755 --- a/install.sh +++ b/install.sh @@ -14,7 +14,7 @@ then exit 1 fi -npm install underscore request sandbox express moment jade@0.25 +npm install node-uuid underscore request sandbox express moment jade databank databank-redis ent cd public/ wget http://twitter.github.com/bootstrap/assets/bootstrap.zip diff --git a/modules/web/README.md b/modules/web/README.md index c00af25..0f729c0 100644 --- a/modules/web/README.md +++ b/modules/web/README.md @@ -7,31 +7,21 @@ Web interface It's a web interface for DBot. What of it? ## Requirements -###Express and Jade@0.25 + +### Express and Jade ``` -npm install express -npm install jade@0.25 +npm install express jade ``` -###Express Patch -Express currently needs to be patched, edit ~/node_modules/express/lib/express.js as thus; -``` - 52 for (var key in connect.middleware) { -**53 if( !Object.prototype.hasOwnProperty(key) ) { - 54 Object.defineProperty( - 55 exports - 56 , key - 57 , Object.getOwnPropertyDescriptor(connect.middleware, key)); -**58 } - 59 } -``` -###Twitter Bootstrap + +### Twitter Bootstrap ``` cd depressionbot/public/ wget http://twitter.github.com/bootstrap/assets/bootstrap.zip unzip bootstrap.zip rm bootstrap.zip ``` -###d3.js + +### d3.js ``` cd depressionbot/public/ mkdir d3 From 1bb266d23ab2f8c680f24d7d3169352e4f029664 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 15:55:20 +0000 Subject: [PATCH 104/220] updat readme main install instructions --- README.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 3b3264a..1f6a3b5 100644 --- a/README.md +++ b/README.md @@ -11,18 +11,11 @@ given I started it rather a long time after I began development of the project. Please don't judge me too harshly for this as I am, in fact, mildly allergic to writing documentation. -Requirements: +## Getting Started -- Node JS -- [JSBot](http://github.com/reality/JSBot "JSBot"), a Javascript library which - handles the IRC protocol -- Underscore JS library -- Various modules have their own requirements also. +You can install DBot's dependencies, configure and run the bot for the first +time with the following command: -### External Modules - -JSBot and externally developed modules can be imported by running the following -commands in the cloned repository: - - git submodule init - git submodule update +``` +sh install.sh +``` From 7e4ae2460a73b0c98d1d1ce9f9bf6a2c6567d1d3 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 26 May 2013 20:24:05 +0000 Subject: [PATCH 105/220] Automatic callback for ~ajs [#476] --- modules/js/js.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules/js/js.js b/modules/js/js.js index d6094ff..023db38 100644 --- a/modules/js/js.js +++ b/modules/js/js.js @@ -21,6 +21,16 @@ var js = function(dbot) { // Run JS code un-sandboxed, with access to DBot memory (admin-only). '~ajs': function(event) { + var callback = function() { + var args = Array.prototype.slice.call(arguments); + for(var i=0;i Date: Mon, 27 May 2013 17:45:30 +0000 Subject: [PATCH 106/220] banOutput option in command [#460] --- modules/command/command.js | 4 +++- modules/command/config.json | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/command/command.js b/modules/command/command.js index b238ce7..4a68692 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -24,7 +24,9 @@ var command = function(dbot) { dbot.api.ignore.isUserIgnoring(event.server, event.user, commandName, function(isIgnoring) { dbot.api.ignore.isUserBanned(event.server, event.user, commandName, function(isBanned) { if(isBanned) { - event.reply(dbot.t('command_ban', {'user': event.user})); + if(this.config.banOutput === true && commandName != '~') { + event.reply(dbot.t('command_ban', {'user': event.user})); + } } else if(!hasAccess) { if(this.config.accessOutput) { event.reply(dbot.t('access_denied', { 'user': event.user })); diff --git a/modules/command/config.json b/modules/command/config.json index 3cb33e0..9374a66 100644 --- a/modules/command/config.json +++ b/modules/command/config.json @@ -2,5 +2,6 @@ "ignorable": false, "dependencies": [ "event", "ignore", "users" ], "useNickserv": false, - "accessOutput": false + "accessOutput": false, + "banOutput": false } From 3726be64b7482e3b818c40b9902794fb40cde0fb Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 27 May 2013 17:48:36 +0000 Subject: [PATCH 107/220] yee --- modules/command/command.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/command/command.js b/modules/command/command.js index 4a68692..a5f2b33 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -24,7 +24,7 @@ var command = function(dbot) { dbot.api.ignore.isUserIgnoring(event.server, event.user, commandName, function(isIgnoring) { dbot.api.ignore.isUserBanned(event.server, event.user, commandName, function(isBanned) { if(isBanned) { - if(this.config.banOutput === true && commandName != '~') { + if(this.config.banOutput && commandName != '~') { event.reply(dbot.t('command_ban', {'user': event.user})); } } else if(!hasAccess) { From 150821cbb3b32c55a45579f05dc63c6f74df8748 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 28 May 2013 17:40:25 +0000 Subject: [PATCH 108/220] fix db pointer for imgur olDB --- modules/imgur/imgur.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/imgur/imgur.js b/modules/imgur/imgur.js index 583ed6e..6168875 100644 --- a/modules/imgur/imgur.js +++ b/modules/imgur/imgur.js @@ -196,6 +196,7 @@ var imgur = function(dbot) { if(!_.has(dbot.db.imgur, 'totalHttpRequests')) dbot.db.imgur.totalHttpRequests = 0; if(!_.has(dbot.db.imgur, 'totalApiRequests')) dbot.db.imgur.totalApiRequests = 0; if(!_.has(dbot.db.imgur, 'totalImages')) dbot.db.imgur.totalImages = 0; + this.db = dbot.db.imgur; }.bind(this); }; From b4581b19955b867cac3f8b58cd364ca917ed39fb Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 1 Jun 2013 15:55:48 +0000 Subject: [PATCH 109/220] remove extra head --- modules/quotes/quotes.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index 8192baf..ffa5372 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -9,7 +9,6 @@ var quotes = function(dbot) { this.rmTimer; this.internalAPI = { -<<<<<<< HEAD // Parse quote interpolations 'interpolatedQuote': function(server, channel, key, quote, callback) { var quoteRefs = quote.match(/~~([\d\w\s-]*)~~/g); From adc4f5c71015760e7235c2e50116e7c64b5adee1 Mon Sep 17 00:00:00 2001 From: Sam Nicholls Date: Sat, 1 Jun 2013 20:13:43 +0200 Subject: [PATCH 110/220] Possible project page fix --- views/project/project.jade | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/views/project/project.jade b/views/project/project.jade index 5dca431..70bc2be 100644 --- a/views/project/project.jade +++ b/views/project/project.jade @@ -79,8 +79,7 @@ html(lang='#{curr839}') #{thanks} ul#credits each author in authors - li - #{author} + li #{author} section#config h2 #{config} ul From 94e9355e7c26f784c3530ed6ed70ac1f71d563b6 Mon Sep 17 00:00:00 2001 From: Sam Nicholls Date: Sat, 1 Jun 2013 20:15:29 +0200 Subject: [PATCH 111/220] Possible project page fix reprise --- views/project/project.jade | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/views/project/project.jade b/views/project/project.jade index 70bc2be..826c7c4 100644 --- a/views/project/project.jade +++ b/views/project/project.jade @@ -19,12 +19,9 @@ html(lang='#{curr839}') h2 #{development} p#pullreq a(href="https://github.com/"+repo+"/pulls") #{pullreqs} - p#revnum - #{revnum} - pre#gitdiff - #{diff} - p#branch - #{branch} + p#revnum #{revnum} + pre#gitdiff #{diff} + p#branch #{branch} h3 #{milestonehead} table#milestones.center tr From 5ff5c8a464b366086b89a5b04e73eb1940843338 Mon Sep 17 00:00:00 2001 From: Sam Nicholls Date: Sat, 1 Jun 2013 20:30:53 +0200 Subject: [PATCH 112/220] Possible project page fix finale --- views/project/project.jade | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/views/project/project.jade b/views/project/project.jade index 826c7c4..51e5858 100644 --- a/views/project/project.jade +++ b/views/project/project.jade @@ -13,8 +13,7 @@ html(lang='#{curr839}') div#page div#title #{pagetitle} div.container#main - p.intro - #{dquote} + p.intro #{dquote} section#git h2 #{development} p#pullreq From 2471e4bca3ef46ae17eea2662c8f8b748910b488 Mon Sep 17 00:00:00 2001 From: Sam Nicholls Date: Sat, 1 Jun 2013 20:33:04 +0200 Subject: [PATCH 113/220] Possible project page anniversary remake --- views/project/project.jade | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/views/project/project.jade b/views/project/project.jade index 51e5858..1cbf597 100644 --- a/views/project/project.jade +++ b/views/project/project.jade @@ -41,8 +41,7 @@ html(lang='#{curr839}') print #{Math.round(wdth)+"%"} td #{milestone.open_issues} td #{milestone.closed_issues} - a(href="https://github.com/"+repo+"/") - #{propaganda} + a(href="https://github.com/"+repo+"/") #{propaganda} h3 #{languagetranshead} table#translations tr @@ -88,5 +87,4 @@ html(lang='#{curr839}') each module in modules li #{module} section#footer - p - #{currver} + p #{currver} From 4a7fcd57b3a182480d5cc85302f9083b00f717ae Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 3 Jun 2013 23:00:23 +0000 Subject: [PATCH 114/220] Module config now loaded from config.json , rleloaded upon reloading and various module changes to make it work right [#474] [#489] --- modules/admin/admin.js | 4 +- modules/dent/dent.js | 7 ++-- modules/project/pages.js | 4 +- modules/project/project.js | 12 +++--- modules/web/web.js | 5 ++- run.js | 80 +++++++++++++++++--------------------- 6 files changed, 52 insertions(+), 60 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index d596e51..93a0ae5 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -38,7 +38,7 @@ var admin = function(dbot) { }; this.onLoad = function() { - var configMap = dbot.config; + /*var configMap = dbot.config; this.db.scan('config', function(config) { if(config) { var currentPath = configMap, @@ -53,7 +53,7 @@ var admin = function(dbot) { currentPath[key[i]] = value; } - }, function(err) { }); + }, function(err) { });*/ }.bind(this); }; diff --git a/modules/dent/dent.js b/modules/dent/dent.js index 756b13d..9b03b45 100644 --- a/modules/dent/dent.js +++ b/modules/dent/dent.js @@ -2,7 +2,6 @@ var request = require('request'); _ = require('underscore')._; var dent = function(dbot) { - this.dbot = dbot; this.StatusRegex = { identica: /\bhttps?:\/\/identi\.ca\/notice\/(\d+)\b/ig, twitter: /\bhttps?:\/\/twitter\.com\/\w+\/status\/(\d+)\b/ig @@ -15,8 +14,8 @@ var dent = function(dbot) { this.api = { 'post': function(content) { - var username = dbot.config.dent.username, - password = dbot.config.dent.password, + var username = this.config.username, + password = this.config.password, info, auth = "Basic " + new Buffer(username + ":" + password).toString("base64"); @@ -57,7 +56,7 @@ var dent = function(dbot) { this.commands['~dent'].regex = [/^~dent (.+)$/, 2]; this.onLoad = function() { - if(dbot.config.dent.dentQuotes === true && _.has(dbot.modules, 'quotes')) { + if(this.config.dentQuotes === true && _.has(dbot.modules, 'quotes')) { dbot.api.event.addHook('~qadd', function(key, text) { if(text.indexOf('~~') == -1) { this.api.post(key + ': ' + text); diff --git a/modules/project/pages.js b/modules/project/pages.js index 929d7a8..a713f8a 100644 --- a/modules/project/pages.js +++ b/modules/project/pages.js @@ -30,7 +30,7 @@ var pages = function(dbot) { /* TODO: merge back into github module */ var milestones; - request({"url":"https://api.github.com/repos/" + dbot.config.github.defaultrepo + "/milestones?state=open","headers":{"User-Agent":"reality/depressionbot (project module)"}}, function(error, response, body){ + request({"url":"https://api.github.com/repos/" + dbot.config.modules.github.defaultrepo + "/milestones?state=open","headers":{"User-Agent":"reality/depressionbot (project module)"}}, function(error, response, body){ milestones = JSON.parse(body); }); @@ -53,7 +53,7 @@ var pages = function(dbot) { "botname": dbot.config.name }), "curr839": dbot.config.language, - "repo": dbot.config.github.defaultrepo, + "repo": dbot.config.modules.github.defaultrepo, "branch": dbot.t("branch",{ "branch": branch }), diff --git a/modules/project/project.js b/modules/project/project.js index 5bb291e..13a6b9d 100644 --- a/modules/project/project.js +++ b/modules/project/project.js @@ -14,30 +14,30 @@ var project = function(dbot) { var list = []; if(_.has(dbot.modules,'dent')){ list.push(dbot.t("dent-account", { - "username": dbot.config.dent.username + "username": dbot.config.modules.dent.username })); - if(_.has(dbot.config.dent.dentQuotes)) { + if(_.has(dbot.config.modules.dent.dentQuotes)) { list.push(dbot.t("dent-push")); } } if(_.has(dbot.modules,'link')){ - if(dbot.config.link.autoTitle){ + if(dbot.config.modules.link.autoTitle){ list.push(dbot.t("link-autotitle")); } } if(_.has(dbot.modules,'quotes')){ list.push(dbot.t("quote-rmlimit", { - "limit": dbot.config.quotes.rmLimit + "limit": dbot.config.modules.quotes.rmLimit })); } if(_.has(dbot.modules,'report')){ - if(dbot.config.report.notifyVoice){ + if(dbot.config.modules.report.notifyVoice){ list.push(dbot.t("report-notifyvoice")); } } if(_.has(dbot.modules,'web')){ list.push(dbot.t("web-port", { - "port": dbot.config.web.webPort + "port": dbot.config.modules.web.webPort })); } return list; diff --git a/modules/web/web.js b/modules/web/web.js index 81a15ed..75d3c08 100644 --- a/modules/web/web.js +++ b/modules/web/web.js @@ -3,13 +3,14 @@ var express = require('express'), fs = require('fs'); var webInterface = function(dbot) { + this.config = dbot.config.modules.web; this.pub = 'public'; this.app = express(); this.app.use(express.static(this.pub)); this.app.set('view engine', 'jade'); - - var server = this.app.listen(dbot.config.web.webPort); + + var server = this.app.listen(this.config.webPort); this.reloadPages = function() { var pages = dbot.pages; diff --git a/run.js b/run.js index 7210c3f..a78d525 100644 --- a/run.js +++ b/run.js @@ -19,37 +19,10 @@ var DBot = function() { this.db = {}; } - if(!_.has(this.db, 'config')) { - this.db.config = {}; - } - /*** Load the fancy DB ***/ this.ddb = new DatabaseDriver(); - /*** Load the Config ***/ - - if(!fs.existsSync('config.json')) { - console.log('Error: config.json file does not exist. Stopping'); - process.exit(); - } - - this.config = _.clone(this.db.config); - try { - _.defaults(this.config, JSON.parse(fs.readFileSync('config.json', 'utf-8'))); - } catch(err) { - console.log('Config file is invalid. Stopping: ' + err); - process.exit(); - } - - try { - var defaultConfig = JSON.parse(fs.readFileSync('config.json.sample', 'utf-8')); - } catch(err) { - console.log('Error loading sample config. Bugger off this should not even be edited. Stopping.'); - process.exit(); - } - - // Load missing config directives from sample file - _.defaults(this.config, defaultConfig); + this.reloadConfig(); /*** Load main strings ***/ @@ -83,6 +56,33 @@ var DBot = function() { this.instance.connectAll(); }; +DBot.prototype.reloadConfig = function() { + this.config = {}; + + if(!fs.existsSync('config.json')) { + console.log('Error: config.json file does not exist. Stopping'); + process.exit(); + } + + try { + this.config = JSON.parse(fs.readFileSync('config.json', 'utf-8')); + } catch(err) { + console.log('Config file is invalid. Stopping: ' + err); + process.exit(); + } + + try { + var defaultConfig = JSON.parse(fs.readFileSync('config.json.sample', 'utf-8')); + } catch(err) { + console.log('Error loading sample config. Bugger off this should not even be edited. Stopping.'); + process.exit(); + } + + // Load missing config directives from sample file + if(!_.has(this.config, 'modules')) this.config.modules = {}; + _.defaults(this.config, defaultConfig); +}; + // Say something in a channel DBot.prototype.say = function(server, channel, message) { this.instance.say(server, channel, message); @@ -138,6 +138,7 @@ DBot.prototype.reloadModules = function() { this.api = {}; this.stringMap = {}; this.usage = {}; + this.reloadConfig(); try { this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8')); @@ -173,25 +174,17 @@ DBot.prototype.reloadModules = function() { continue; } - // Load the module config data - config = {}; - - if(_.has(this.db.config, name)) { - config = _.clone(this.db.config[name]); - } - - try { - var defaultConfig = fs.readFileSync(moduleDir + 'config.json', 'utf-8'); + if(!_.has(this.config.modules, name)) this.config.modules[name] = {}; + if(fs.existsSync(moduleDir + 'config.json')) { try { - defaultConfig = JSON.parse(defaultConfig); - } catch(err) { // syntax error + var defaultConfig = JSON.parse(fs.readFileSync(moduleDir + 'config.json', 'utf-8')); + } catch(err) { // Syntax error this.status[name] = 'Error parsing config: ' + err + ' ' + err.stack.split('\n')[2].trim(); continue; } - config = _.defaults(config, defaultConfig); - } catch(err) { - // Invalid or no config data + this.config.modules[name] = _.defaults(this.config.modules[name], defaultConfig); } + var config = this.config.modules[name]; // Don't shit out if dependencies not met if(_.has(config, 'dependencies')) { @@ -202,7 +195,6 @@ DBot.prototype.reloadModules = function() { } }, this); } - this.config[name] = config; // Groovy funky database shit if(!_.has(config, 'dbType') || config.dbType == 'olde') { @@ -235,7 +227,7 @@ DBot.prototype.reloadModules = function() { module.name = name; module.db = this.ddb.databanks[name]; - module.config = this.config[name]; + module.config = this.config.modules[name]; // Load the module data _.each([ 'commands', 'pages', 'api' ], function(property) { From a25620bf9e931ba7eb1175f4ce1acd29a2012f60 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 4 Jun 2013 00:06:41 +0000 Subject: [PATCH 115/220] recursively call showconfig [#489] --- modules/admin/admin.js | 55 +++++++++----------------------------- modules/admin/commands.js | 10 ++++--- modules/admin/strings.json | 6 ++--- 3 files changed, 22 insertions(+), 49 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index 93a0ae5..77e7668 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -9,52 +9,21 @@ var fs = require('fs'), var admin = function(dbot) { this.internalAPI = { 'getCurrentConfig': function(configKey, callback) { - if(configKey) { - this.db.read('config', configKey, function(err, cRecord) { - if(cRecord) { - callback(cRecord.value) - } else { - var configPath = dbot.config; - configKey = configKey.split('.'); + var configPath = dbot.config; + configKey = configKey.split('.'); - for(var i=0;i Date: Tue, 4 Jun 2013 00:10:12 +0000 Subject: [PATCH 116/220] Fixes for config path in some place [#489] --- modules/link/link.js | 2 +- run.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/link/link.js b/modules/link/link.js index 9d24134..4d27ef9 100644 --- a/modules/link/link.js +++ b/modules/link/link.js @@ -126,7 +126,7 @@ var link = function(dbot) { var urlMatches = event.message.match(this.urlRegex); if(urlMatches !== null) { this.links[event.channel.name] = urlMatches[0]; - if(dbot.config.link.autoTitle == true) { + if(this.config.autoTitle == true) { var handlerFound = false; for(var i=0;i Date: Wed, 5 Jun 2013 20:13:40 +0000 Subject: [PATCH 117/220] fix config pointers in admin and imgur [#489] --- modules/admin/admin.js | 13 +++++++++++++ modules/imgur/imgur.js | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index 77e7668..25768a9 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -22,6 +22,19 @@ var admin = function(dbot) { } callback(configPath); + }, + + 'setConfig': function(configKey, newOption, callback) { + var configPath = dbot.config; + configKey = configKey.split('.'); + + for(var i=0;i Date: Wed, 5 Jun 2013 21:00:52 +0000 Subject: [PATCH 118/220] save a seperate customconfig so not everything is saved to config.json. create saveconfig internal api function for admin [#489] --- modules/admin/admin.js | 5 +++++ run.js | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index 25768a9..72a3c03 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -35,6 +35,11 @@ var admin = function(dbot) { return; } } + }, + + 'saveConfig': function() { + var config = dbot.customConfig; + fs.writeFileSync('config.json', JSON.stringify(config, null, ' ')); } }; }; diff --git a/run.js b/run.js index 48ff6f8..eb72912 100644 --- a/run.js +++ b/run.js @@ -7,7 +7,6 @@ require('./snippets'); var DBot = function() { /*** Load the DB ***/ - if(fs.existsSync('db.json')) { try { this.db = JSON.parse(fs.readFileSync('db.json', 'utf-8')); @@ -25,7 +24,6 @@ var DBot = function() { this.reloadConfig(); /*** Load main strings ***/ - try { this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8')); } catch(err) { @@ -65,7 +63,9 @@ DBot.prototype.reloadConfig = function() { } try { - this.config = JSON.parse(fs.readFileSync('config.json', 'utf-8')); + var configFile = fs.readFileSync('config.json', 'utf-8'); + this.config = JSON.parse(configFile); + this.customConfig = JSON.parse(configFile); } catch(err) { console.log('Config file is invalid. Stopping: ' + err); process.exit(); @@ -79,7 +79,10 @@ DBot.prototype.reloadConfig = function() { } // Load missing config directives from sample file - if(!_.has(this.config, 'modules')) this.config.modules = {}; + if(!_.has(this.customConfig, 'modules')) { + this.customConfig.modules = {}; + this.config.modules = {}; + } _.defaults(this.config, defaultConfig); }; From 97907603f57f894986780bffe9db8b17b408e8ce Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 5 Jun 2013 21:14:21 +0000 Subject: [PATCH 119/220] automatically save module load changes [#489] --- modules/admin/admin.js | 6 +++++- modules/admin/commands.js | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index 72a3c03..9f45f13 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -25,7 +25,7 @@ var admin = function(dbot) { }, 'setConfig': function(configKey, newOption, callback) { - var configPath = dbot.config; + var configPath = dbot.customConfig; configKey = configKey.split('.'); for(var i=0;i Date: Wed, 5 Jun 2013 21:41:20 +0000 Subject: [PATCH 120/220] admin.internalAPI.setConfig operational [#489] --- modules/admin/admin.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index 9f45f13..113cb0d 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -1,7 +1,7 @@ /** * Module Name: Admin * Description: Set of commands which only one who is a DepressionBot - * administrator can run - as such, it has its own command execution listener. + * administrator can run. */ var fs = require('fs'), _ = require('underscore')._; @@ -25,21 +25,26 @@ var admin = function(dbot) { }, 'setConfig': function(configKey, newOption, callback) { - var configPath = dbot.customConfig; + var configPath = dbot.customConfig, + oldOption = null; configKey = configKey.split('.'); for(var i=0;i Date: Wed, 5 Jun 2013 21:52:14 +0000 Subject: [PATCH 121/220] setconfig working + msg if new key is being created [#489] --- modules/admin/commands.js | 16 ++++++---------- modules/admin/strings.json | 3 +++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/admin/commands.js b/modules/admin/commands.js index e5954ee..66bdb63 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -184,18 +184,14 @@ var commands = function(dbot) { if(_.isArray(config)) { event.reply(dbot.t("config_array", { "alternate": "pushconfig" })); } - - event.reply(configPath + ": " + config + " -> " + newOption); - config = newOption; - this.db.save('config', configPath, { - 'key': configPath, - 'value': config - }, function(err) { - dbot.reloadModules(); - }); } else { - event.reply(dbot.t("no_config_key", {'path': configPath})); + event.reply(dbot.t('new_config_key', { 'key': configPath })); + config = null; } + + this.internalAPI.setConfig(configPath, newOption, function(err) { + event.reply(configPath + ": " + config + " -> " + newOption); + }); }.bind(this)); } else { event.reply(dbot.t("config_lock")); diff --git a/modules/admin/strings.json b/modules/admin/strings.json index 1099d4e..1c117cf 100644 --- a/modules/admin/strings.json +++ b/modules/admin/strings.json @@ -160,6 +160,9 @@ "cy": "Nid yw llwybr cyfluniad yn bodoli, fy mrawd", "de": "Konfigurationspfad nicht vorhanden, Bruder" }, + "new_config_key": { + "en": "Warning: Creating new config key: {key}." + }, "config_keys_location": { "en": "Config keys in {path}: {value}", "cy": "Allweddi cyfluniad yn {path}: {value}", From 7592a6caa42f89d354c24e0312ff4d5ad00aca18 Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 5 Jun 2013 22:15:17 +0000 Subject: [PATCH 122/220] pushconfig operational [#489] --- modules/admin/commands.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/modules/admin/commands.js b/modules/admin/commands.js index 66bdb63..beb9119 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -208,17 +208,12 @@ var commands = function(dbot) { if(_.isArray(config)) { event.reply(configPath + ": " + config + " << " + newOption); config.push(newOption); - this.db.save('config', configPath, { - 'key': configPath, - 'value': config - }, function(err) { - dbot.reloadModules(); - }); + this.internalAPI.setConfig(configPath, config, function(err) {}); } else { event.reply(dbot.t("config_array", { "alternate": "setconfig" })); } } else { - event.reply(dbot.t("no_config_key")); + event.reply(dbot.t("no_config_key", { 'path': configPath })); } }.bind(this)); } else { From 9927f7add33d9d63a4a3129c3fb9fe1987ca9858 Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 5 Jun 2013 22:47:13 +0000 Subject: [PATCH 123/220] update github --- modules/github | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/github b/modules/github index ee6e9ba..5f4e3dc 160000 --- a/modules/github +++ b/modules/github @@ -1 +1 @@ -Subproject commit ee6e9ba9279e993567ebecb961184245a2a07ecf +Subproject commit 5f4e3dc8335000e97af528fee289b880a3c99e81 From 9093a699075e86758871e08016a5cb545f259239 Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 5 Jun 2013 22:59:37 +0000 Subject: [PATCH 124/220] auto reload on setconfig [#489] --- modules/admin/admin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/admin/admin.js b/modules/admin/admin.js index 113cb0d..74e4af7 100644 --- a/modules/admin/admin.js +++ b/modules/admin/admin.js @@ -42,7 +42,7 @@ var admin = function(dbot) { configPath[configKey[i]] = newOption; this.internalAPI.saveConfig(); - dbot.reloadConfig(); + dbot.reloadModules(); callback(null, oldOption); }.bind(this), From b201c1aaad746cff2c35164c35fc863bc51f21cf Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 13 Jun 2013 18:59:14 +0000 Subject: [PATCH 125/220] fix profile config pointers --- modules/profile/api.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/profile/api.js b/modules/profile/api.js index d9ac410..24059b0 100644 --- a/modules/profile/api.js +++ b/modules/profile/api.js @@ -12,8 +12,8 @@ var api = function(dbot) { if(user){ this.db.create('profiles', user.id, { 'id': user.id, - 'profile': dbot.config.profile.schema.profile, - 'preferences': dbot.config.profile.schema.preferences + 'profile': this.config.schema.profile, + 'preferences': this.config.schema.preferences }, function(err, result){ if(err){ console.log(err); From 96a566290d94203db8108e4b6e985c3784684b45 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 21 Jun 2013 17:55:29 +0000 Subject: [PATCH 126/220] update jsbot --- jsbot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsbot b/jsbot index 11cbb75..6742d6c 160000 --- a/jsbot +++ b/jsbot @@ -1 +1 @@ -Subproject commit 11cbb75b504fbb703450a2f8c938d5a81680109c +Subproject commit 6742d6c94736a2674828eadb9a17fb96bb206d6f From efe54b5e351da9711ef1a9240f9129c8030eb044 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 21 Jun 2013 18:11:22 +0000 Subject: [PATCH 127/220] event.rUser contains resolved user object from users module [#507] --- modules/users/users.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/users/users.js b/modules/users/users.js index 4d372ef..b96ea2b 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -142,6 +142,15 @@ var users = function(dbot) { this.on = ['JOIN', 'NICK']; this.onLoad = function() { + dbot.instance.addPreEmitHook(function(event, callback) { + if(event.user) { + this.api.resolveUser(event.server, event.user, function(user) { + event.rUser = user; + callback(false); + }); + } + }.bind(this)); + dbot.instance.addListener('366', 'users', function(event) { this.api.getChannel(event.server, event.channel.name, function(channel) { var checkChannelUsers = function(channel) { From 520be40504674e4c65521780a8435048cc3defba Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 21 Jun 2013 18:40:00 +0000 Subject: [PATCH 128/220] rChannel [#507] --- modules/users/users.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/users/users.js b/modules/users/users.js index b96ea2b..f41f432 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -150,6 +150,15 @@ var users = function(dbot) { }); } }.bind(this)); + + dbot.instance.addPreEmitHook(function(event, callback) { + if(event.channel) { + this.api.getChannel(event.server, event.channel.name, function(channel) { + event.rChannel = channel; + callback(false); + }); + } + }.bind(this)); dbot.instance.addListener('366', 'users', function(event) { this.api.getChannel(event.server, event.channel.name, function(channel) { From bfd11c5d4dcb6440c3576f6997f082577b8e47ef Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 22 Jun 2013 14:37:21 +0000 Subject: [PATCH 129/220] fix showconfig recursion --- modules/admin/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/admin/commands.js b/modules/admin/commands.js index 2cef092..db87f8f 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -247,7 +247,7 @@ var commands = function(dbot) { configPath = configPath.split('.'); configPath.pop(); event.params[1] = configPath.join('.'); - this.commands['showconfig'](event); + this.commands['~showconfig'](event); } }.bind(this)); } else { From b3b91f189f1b191633456bfb66f43c35be153b12 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 22 Jun 2013 15:22:23 +0000 Subject: [PATCH 130/220] Draft of new users listener [#511][#480] --- modules/users/users.js | 48 ++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index f41f432..8df25f3 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -161,41 +161,25 @@ var users = function(dbot) { }.bind(this)); dbot.instance.addListener('366', 'users', function(event) { - this.api.getChannel(event.server, event.channel.name, function(channel) { - var checkChannelUsers = function(channel) { - var i = 0; - var checkChannelNicks = function(chanicks) { - if(i == chanicks.length) return; - var nick = chanicks[i]; i++; - this.api.resolveUser(event.server, nick, function(user) { - if(!user) { - this.internalAPI.createUser(event.server, nick, event.channel.name, function(result) { - this.internalAPI.addChannelUser(result, event.channel.name, function(err) { - checkChannelNicks(chanicks); - }); - }.bind(this)); + var checkChannel = function(channel) { + async.eachSeries(event.channel.nicks, function(nick, next) { + this.api.resolveUser(event.server, nick, function(user) { + var checkChannelUser = function(user) { + if(!_.inlude(channel.users, user.id)) { + this.internalAPI.addChannelUser(channel, user, next); } else { - if(!_.include(user.channels, event.channel.name)) { - this.internalAPI.addChannelUser(user, event.channel.name, function(err) { - checkChannelNicks(chanicks); - }); - user.channels.push(event.channel.name); - this.db.save('users', user.id, user, function(err) { }); - } else { - checkChannelNicks(chanicks); - } + next(); } - }.bind(this)); - }.bind(this); - checkChannelNicks(_.keys(event.channel.nicks)); - }.bind(this); + }.bind(this); - if(!channel) { // Channel does not yet exist - this.internalAPI.createChannel(event.server, event.channel.name, checkChannelUsers); - } else { - checkChannelUsers(channel); - } - }.bind(this)); + if(user) { + checkChannelUser(user); + } else { + this.internalAPI.createUser(event.server, nick, channel.id, checkChannelUser); + } + }.bind(this)); + }); + }; }.bind(this)); var connections = dbot.instance.connections; From 66f5b1df43dfe018571871c1013c931be64fc803 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 22 Jun 2013 16:25:31 +0000 Subject: [PATCH 131/220] rewrite JOIN users listener --- modules/users/users.js | 79 +++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 51 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index 8df25f3..ec4debe 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -41,16 +41,20 @@ var users = function(dbot) { }); }.bind(this), - 'addChannelUser': function(user, channelName, callback) { - this.api.getChannel(user.server, channelName, function(channel) { + 'addChannelUser': function(channel, user, callback) { + if(!_.include(channel.users, user.id)) { channel.users.push(user.id); + } + if(!_.include(user.channels, channel.id) { + user.channels.push(channel.id); + } + + this.db.save('users', user.id, user, function(err) { this.db.save('channel_users', channel.id, channel, function(err) { - if(!err) { - dbot.api.event.emit('new_channel_user', [ user, channel ]); - callback(); - } + dbot.api.event.emit('new_channel_user', [ user, channel ]); + callback(err); }); - }.bind(this)); + }); }.bind(this), 'updateChannelPrimaryUser': function(server, oldUser, newUser) { @@ -90,52 +94,26 @@ var users = function(dbot) { }; this.listener = function(event) { + // TODO: If user joins channel with alias if(event.action == 'JOIN' && event.user != dbot.config.name) { - this.api.resolveUser(event.server, event.user, function(user) { - var needsUpdating = false; - - if(!user) { // User does not yet exist - user = { - 'id': uuid.v4(), - 'primaryNick': event.user, - 'currentNick': event.user, - 'server': event.server, - 'channels': [], - 'aliases': [] - }; - needsUpdating = true; - } - - if(!_.include(user.channels, event.channel.name)) { // User not yet channel user - user.channels.push(event.channel.name); - this.internalAPI.addChannelUser(user, event.channel.name, function(err) { }); - needsUpdating = true; - } - - if(user.currentNick != event.user) { - user.currentNick = event.user; - needsUpdating = true; - } - - if(needsUpdating == true) { - this.db.save('users', user.id, user, function(err) { }); - } - }.bind(this)); + if(!event.rUser) { + this.internalAPI.createUser(event.server, event.user, event.channel.name, function(user) { + this.internalAPI.addChannelUser(channel, user, function() {}); + }); + } else if(!_.include(event.rUser.channels, event.rChannel.id)) { + this.internalAPI.addChannelUser(channel, user, function() {}); + } } else if(event.action == 'NICK') { - this.api.resolveUser(event.server, event.user, function(user) { - this.api.isKnownUser(event.server, event.newNick, function(isKnown) { - user.currentNick = event.newNick; + this.api.isKnownUser(event.server, event.newNick, function(isKnown) { + event.rUser.currentNick = event.newNick; - if(!isKnown) { - user.aliases.push(event.newNick); - } + if(!isKnown) { + event.rUser.aliases.push(event.newNick); + } - this.db.save('users', user.id, user, function(err) { - if(!err) { - dbot.api.event.emit('new_user_alias', [ user, event.newNick ]); - } - }); - }.bind(this)); + this.db.save('users', event.rUser.id, event.rUser, function(err) { + dbot.api.event.emit('new_user_alias', [ event.rUser, event.newNick ]); + }); }.bind(this)); } }.bind(this); @@ -182,8 +160,7 @@ var users = function(dbot) { }; }.bind(this)); - var connections = dbot.instance.connections; - _.each(connections, function(connection) { + _.each(dbot.instance.connections, function(connection) { connection.updateNickLists(); }); }; From df1404b3ae2d06e0808ebd1b918badff38f87825 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 22 Jun 2013 16:32:18 +0000 Subject: [PATCH 132/220] dont pass channel info to createUser --- modules/users/users.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index ec4debe..b24c008 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -9,14 +9,13 @@ var users = function(dbot) { /*** Internal API ***/ this.internalAPI = { - 'createUser': function(server, nick, channel, callback) { - var id = uuid.v4(); + 'createUser': function(server, nick, callback) { this.db.create('users', id, { - 'id': id, + 'id': uuid.v4(), 'primaryNick': nick, 'currentNick': nick, 'server': server, - 'channels': [ channel ], + 'channels': [ ], 'aliases': [] }, function(err, result) { if(!err) { @@ -97,7 +96,7 @@ var users = function(dbot) { // TODO: If user joins channel with alias if(event.action == 'JOIN' && event.user != dbot.config.name) { if(!event.rUser) { - this.internalAPI.createUser(event.server, event.user, event.channel.name, function(user) { + this.internalAPI.createUser(event.server, event.user, function(user) { this.internalAPI.addChannelUser(channel, user, function() {}); }); } else if(!_.include(event.rUser.channels, event.rChannel.id)) { @@ -153,7 +152,7 @@ var users = function(dbot) { if(user) { checkChannelUser(user); } else { - this.internalAPI.createUser(event.server, nick, channel.id, checkChannelUser); + this.internalAPI.createUser(event.server, nick, checkChannelUser); } }.bind(this)); }); From 39db5423df89eab0f98d3425f37b81e1584c7170 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 22 Jun 2013 17:19:04 +0000 Subject: [PATCH 133/220] finish users rewrite --- modules/users/users.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index b24c008..a6b4bbf 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -3,7 +3,8 @@ * Description: Track known users */ var _ = require('underscore')._, - uuid = require('node-uuid'); + uuid = require('node-uuid'), + async = require('async'); var users = function(dbot) { @@ -26,9 +27,8 @@ var users = function(dbot) { }.bind(this), 'createChannel': function(server, name, callback) { - var id = uuid.v4(); this.db.create('channel_users', id, { - 'id': id, + 'id': uuid.v4(), 'server': server, 'name': name, 'users': [] From a65c96138e01aa64d8796f052ace2071fe955986 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 22 Jun 2013 20:23:47 +0000 Subject: [PATCH 134/220] fix a bunch of shit --- modules/users/users.js | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index a6b4bbf..e102f87 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -11,8 +11,9 @@ var users = function(dbot) { /*** Internal API ***/ this.internalAPI = { 'createUser': function(server, nick, callback) { + var id = uuid.v4(); this.db.create('users', id, { - 'id': uuid.v4(), + 'id': id, 'primaryNick': nick, 'currentNick': nick, 'server': server, @@ -27,8 +28,9 @@ var users = function(dbot) { }.bind(this), 'createChannel': function(server, name, callback) { + var id = uuid.v4(); this.db.create('channel_users', id, { - 'id': uuid.v4(), + 'id': id, 'server': server, 'name': name, 'users': [] @@ -44,7 +46,7 @@ var users = function(dbot) { if(!_.include(channel.users, user.id)) { channel.users.push(user.id); } - if(!_.include(user.channels, channel.id) { + if(!_.include(user.channels, channel.id)) { user.channels.push(channel.id); } @@ -53,7 +55,7 @@ var users = function(dbot) { dbot.api.event.emit('new_channel_user', [ user, channel ]); callback(err); }); - }); + }.bind(this)); }.bind(this), 'updateChannelPrimaryUser': function(server, oldUser, newUser) { @@ -97,10 +99,10 @@ var users = function(dbot) { if(event.action == 'JOIN' && event.user != dbot.config.name) { if(!event.rUser) { this.internalAPI.createUser(event.server, event.user, function(user) { - this.internalAPI.addChannelUser(channel, user, function() {}); - }); + this.internalAPI.addChannelUser(event.rChannel, user, function() {}); + }.bind(this)); } else if(!_.include(event.rUser.channels, event.rChannel.id)) { - this.internalAPI.addChannelUser(channel, user, function() {}); + this.internalAPI.addChannelUser(event.rChannel, event.rUser, function() {}); } } else if(event.action == 'NICK') { this.api.isKnownUser(event.server, event.newNick, function(isKnown) { @@ -116,7 +118,7 @@ var users = function(dbot) { }.bind(this)); } }.bind(this); - this.on = ['JOIN', 'NICK']; + this.on = ['JOIN', 'NICK']; this.onLoad = function() { dbot.instance.addPreEmitHook(function(event, callback) { @@ -125,6 +127,8 @@ var users = function(dbot) { event.rUser = user; callback(false); }); + } else { + callback(false); } }.bind(this)); @@ -134,15 +138,17 @@ var users = function(dbot) { event.rChannel = channel; callback(false); }); + } else { + callback(false); } }.bind(this)); dbot.instance.addListener('366', 'users', function(event) { var checkChannel = function(channel) { - async.eachSeries(event.channel.nicks, function(nick, next) { + async.eachSeries(_.keys(event.channel.nicks), function(nick, next) { this.api.resolveUser(event.server, nick, function(user) { var checkChannelUser = function(user) { - if(!_.inlude(channel.users, user.id)) { + if(!_.include(channel.users, user.id)) { this.internalAPI.addChannelUser(channel, user, next); } else { next(); @@ -155,8 +161,14 @@ var users = function(dbot) { this.internalAPI.createUser(event.server, nick, checkChannelUser); } }.bind(this)); - }); - }; + }.bind(this), function(err) {}); + }.bind(this); + + if(!event.rChannel) { + this.internalAPI.createChannel(event.server, event.channel.name, checkChannel); + } else { + checkChannel(event.rChannel); + } }.bind(this)); _.each(dbot.instance.connections, function(connection) { From fe76718780dfa328300bd6f9200294c362c73c8e Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 22 Jun 2013 20:46:17 +0000 Subject: [PATCH 135/220] update jsbot --- jsbot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsbot b/jsbot index 6742d6c..bb1e72b 160000 --- a/jsbot +++ b/jsbot @@ -1 +1 @@ -Subproject commit 6742d6c94736a2674828eadb9a17fb96bb206d6f +Subproject commit bb1e72b173a136816287bc8d90509cc38a0986e3 From 4ffff09381354b033c69a2ac020331957a72beb4 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 23 Jun 2013 11:37:01 +0000 Subject: [PATCH 136/220] Rewrite warning module for databank [#508] --- modules/warning/config.json | 2 +- modules/warning/pages.js | 59 +++++++++++++++++-------- modules/warning/warning.js | 87 ++++++++++++++++++++++--------------- 3 files changed, 93 insertions(+), 55 deletions(-) diff --git a/modules/warning/config.json b/modules/warning/config.json index 914c1d7..9fb677f 100644 --- a/modules/warning/config.json +++ b/modules/warning/config.json @@ -1,4 +1,4 @@ { "dependencies": [ "report", "users", "web" ], - "dbKeys": [ "warnings" ] + "dbType": "redis" } diff --git a/modules/warning/pages.js b/modules/warning/pages.js index e60a634..72c5129 100644 --- a/modules/warning/pages.js +++ b/modules/warning/pages.js @@ -1,4 +1,5 @@ -var _ = require('underscore')._; +var _ = require('underscore')._, + async = require('async'); var pages = function(dbot) { this.warnings = dbot.db.warnings; @@ -7,37 +8,59 @@ var pages = function(dbot) { '/warning': function(req, res) { res.render('servers', { 'name': dbot.config.name, - 'servers': _.keys(this.warnings) + 'servers': _.keys(dbot.config.servers) }); }, '/warning/:server': function(req, res) { - var server = req.params.server; + var server = req.params.server, + userIds = [], + userNicks = []; - if(_.has(this.warnings, server)) { - res.render('users', { - 'name': dbot.config.name, - 'server': server, - 'users': _.keys(this.warnings[server]) + this.db.search('warnings', { 'server': server }, function(warning) { + if(!_.include(userIds, warning.warnee)) userIds.push(warning.warnee); + }, function(err) { + async.eachSeries(userIds, function(id, callback) { + dbot.api.users.getUser(id, function(user) { + userNicks.push(user.primaryNick); + callback(false); + }); + }, function(err) { + res.render('users', { + 'name': dbot.config.name, + 'server': server, + 'users': userNicks + }); }); - } else { - res.render('error'); - } + }); }, '/warning/:server/:user': function(req, res) { var server = req.params.server, user = req.params.user; - if(_.has(this.warnings, server) && _.has(this.warnings[server], user)) { - res.render('warnings', { - 'name': dbot.config.name, + dbot.api.users.resolveUser(server, user, function(user) { + var warnings = []; + this.db.search('warnings', { 'server': server, - 'warnings': this.warnings[server][user] + 'warnee': user.id + }, function(warning) { + warnings.push(warning); + }, function(err) { + async.eachSeries(warnings, function(warning, callback) { + dbot.api.users.getUser(warning.warner, function(user) { + warning.warner = user.primaryNick; + callback(false); + }); + }, function(err) { + res.render('warnings', { + 'name': dbot.config.name, + 'server': server, + 'warnings': warnings + }); + }); }); - } else { - res.render('error'); - } + }.bind(this)); } }; }; diff --git a/modules/warning/warning.js b/modules/warning/warning.js index cbea752..34398e0 100644 --- a/modules/warning/warning.js +++ b/modules/warning/warning.js @@ -1,54 +1,69 @@ var _ = require('underscore')._; + uuid = require('node-uuid'); var warning = function(dbot) { - this.warnings = dbot.db.warnings; - this.commands = { '~warn': function(event) { - var warner = event.user, + var warner = event.rUser, server = event.server, - warnee = dbot.api.users.resolveUser(server, event.input[1]), reason = event.input[2], adminChannel = dbot.config.servers[server].admin_channel; - // Store the warn - if(!_.has(this.warnings, server)) this.warnings[server] = {}; - if(!_.has(this.warnings[server], warnee)) this.warnings[server][warnee] = []; - - this.warnings[server][warnee].push({ - 'warner': warner, - 'reason': reason, - 'time': new Date().getTime() - }); - - // Notify interested parties - var notifyString = dbot.t('warn_notify', { - 'warner': warner, - 'warnee': warnee, - 'reason': reason, - 'url': dbot.api.web.getUrl('warning/' + server + '/' + warnee) - }); - if(!_.isUndefined(adminChannel)) { - adminChannel = event.channel.name; - } - dbot.api.report.notify(server, adminChannel, notifyString); - dbot.say(server, adminChannel, notifyString); - dbot.say(server, warnee, notifyString); + dbot.api.users.resolveUser(server, event.input[1], function(warnee) { + if(warnee) { + var id = uuid.v4(); + this.db.save('warnings', id, { + 'id': id, + 'server': event.server, + 'warnee': warnee.id, + 'warner': warner.id, + 'reason': reason, + 'time': new Date().getTime() + }, function(err) { + var notifyString = dbot.t('warn_notify', { + 'warner': warner.primaryNick, + 'warnee': warnee.primaryNick, + 'reason': reason, + 'url': dbot.api.web.getUrl('warning/' + server + '/' + + warnee.primaryNick) + }); + if(_.isUndefined(adminChannel)) { + adminChannel = event.channel.name; + } + dbot.api.report.notify(server, adminChannel, notifyString); + dbot.say(server, adminChannel, notifyString); + dbot.say(server, warnee.currentNick, notifyString); + }); + } else { + event.reply(dbot.t('warnee_not_found', { 'user': event.input[1] })); + } + }.bind(this)); }, '~warnings': function(event) { var warnee = event.params[1], server = event.server; - if(_.has(this.warnings, server) && _.has(this.warnings[server], warnee)) { - event.reply(dbot.t('warning_info', { - 'user': warnee, - 'num': this.warnings[server][warnee].length, - 'url': dbot.api.web.getUrl('warning/' + server + '/' + warnee) - })); - } else { - event.reply(dbot.t('no_warnings', { 'user': warnee })); - } + dbot.api.users.resolveUser(server, warnee, function(warnee) { + var warnings = 0; + this.db.search('warnings', { + 'server': server, + 'warnee': warnee.id + }, function(warning) { + warnings++; + }, function(err) { + if(warnings > 0) { + event.reply(dbot.t('warning_info', { + 'user': warnee.primaryNick, + 'num': warnings, + 'url': dbot.api.web.getUrl('warning/' + server + '/' + + warnee.primaryNick) + })); + } else { + event.reply(dbot.t('no_warnings', { 'user': warnee })); + } + }); + }.bind(this)); } }; From 3021601c528de0744a595dc643d2c3c21cf958a1 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 15:26:21 +0000 Subject: [PATCH 137/220] fix quotes --- modules/quotes/quotes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/quotes/quotes.js b/modules/quotes/quotes.js index ffa5372..4f3e86c 100644 --- a/modules/quotes/quotes.js +++ b/modules/quotes/quotes.js @@ -35,7 +35,7 @@ var quotes = function(dbot) { 'cleanRef': function(key) { key = key.toLowerCase(); - while(key.endsWith("_")) { + while(key.slice(-1) == '_') { key = key.substring(0, key.length-1); } return key; @@ -53,7 +53,7 @@ var quotes = function(dbot) { }); clearTimeout(this.rmTimer); - if(this.rmCache.length < dbot.config.quotes.rmLimit) { + if(this.rmCache.length < this.config.rmLimit) { this.rmTimer = setTimeout(function() { this.rmCache.length = 0; // lol what }.bind(this), 600000); From 68b0977bae38421e3c1eb2918f9723f181233d85 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 15:33:18 +0000 Subject: [PATCH 138/220] ignore uses event.rUser [#511][#514] --- modules/command/command.js | 4 +- modules/ignore/api.js | 24 +++--- modules/ignore/ignore.js | 164 +++++++++++++++++++----------------- modules/ignore/strings.json | 10 ++- 4 files changed, 107 insertions(+), 95 deletions(-) diff --git a/modules/command/command.js b/modules/command/command.js index a5f2b33..fd0f494 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -21,8 +21,8 @@ var command = function(dbot) { } this.api.hasAccess(event.server, event.user, commandName, function(hasAccess) { - dbot.api.ignore.isUserIgnoring(event.server, event.user, commandName, function(isIgnoring) { - dbot.api.ignore.isUserBanned(event.server, event.user, commandName, function(isBanned) { + dbot.api.ignore.isUserIgnoring(event.rUser, commandName, function(isIgnoring) { + dbot.api.ignore.isUserBanned(event.rUser, commandName, function(isBanned) { if(isBanned) { if(this.config.banOutput && commandName != '~') { event.reply(dbot.t('command_ban', {'user': event.user})); diff --git a/modules/ignore/api.js b/modules/ignore/api.js index 79b1102..43fa89f 100644 --- a/modules/ignore/api.js +++ b/modules/ignore/api.js @@ -3,18 +3,18 @@ var _ = require('underscore')._; var api = function(dbot) { return { // Is user ignoring command/module? - 'isUserIgnoring': function(server, user, item, callback) { - this.internalAPI.isUserImpeded(server, user, item, 'ignores', callback); + 'isUserIgnoring': function(user, item, callback) { + this.internalAPI.isUserImpeded(user, item, 'ignores', callback); }, // Is user banned from command/module? - 'isUserBanned': function(server, user, item, callback) { - this.internalAPI.isUserImpeded(server, user, item, 'bans', callback); + 'isUserBanned': function(user, item, callback) { + this.internalAPI.isUserImpeded(user, item, 'bans', callback); }, // Is channel ignoring module? // TODO: Command support - 'isChannelIgnoring': function(server, channelName, item, callback) { + 'isChannelIgnoring': function(channelName, item, callback) { var isIgnoring = false, channel = false; @@ -32,16 +32,14 @@ var api = function(dbot) { }, // Resolve a nick and return their user and ignores object - 'getUserIgnores': function(server, user, callback) { - dbot.api.users.resolveUser(server, user, function(user) { - if(user) { - this.db.read('ignores', user.id, function(err, ignores) { - callback(false, user, ignores); - }); + 'getUserIgnores': function(user, callback) { + this.db.read('ignores', user.id, function(err, ignores) { + if(!err && ignores) { + callback(false, ignores); } else { - callback(true, null, null); + callback(true, null); } - }.bind(this)); + }); } }; } diff --git a/modules/ignore/ignore.js b/modules/ignore/ignore.js index 8edd5e8..7f52078 100644 --- a/modules/ignore/ignore.js +++ b/modules/ignore/ignore.js @@ -12,8 +12,8 @@ var _ = require('underscore')._, var ignore = function(dbot) { this.internalAPI = { - 'isUserImpeded': function(server, user, item, by, callback) { - this.api.getUserIgnores(server, user, function(err, user, ignores) { + 'isUserImpeded': function(user, item, by, callback) { + this.api.getUserIgnores(user, function(err, ignores) { var isImpeded = false; if(!err && ignores) { if(_.has(dbot.commands, item)) { @@ -33,7 +33,7 @@ var ignore = function(dbot) { var module = event.params[1]; var ignorableModules = _.chain(dbot.modules) .filter(function(module, name) { - return dbot.config[module].ignorable === true; + return dbot.config.modules[module].ignorable === true; }) .pluck('name') .value(); @@ -45,32 +45,28 @@ var ignore = function(dbot) { })); } else { if(module == '*' || _.include(ignorableModules, module)) { - this.api.getUserIgnores(event.server, event.user, function(err, user, ignores) { - if(!err) { - if(!ignores) { - ignores = { - 'id': user.id, - 'ignores': [], - 'bans': [] - }; - } + this.api.getUserIgnores(event.rUser, function(err, ignores) { + if(!ignores) { + ignores = { + 'id': event.rUser.id, + 'ignores': [], + 'bans': [] + }; + } - if(!_.include(ignores.ignores, module)) { - ignores.ignores.push(module); - this.db.save('ignores', user.id, ignores, function(err) { - if(!err) { - dbot.instance.ignoreTag(event.user, module); - event.reply(dbot.t('ignored', { - 'user': event.user, - 'module': module - })); - } - }); - } else { - event.reply(dbot.t('already_ignoring', { 'user': event.user })); - } + if(!_.include(ignores.ignores, module)) { + ignores.ignores.push(module); + this.db.save('ignores', event.rUser.id, ignores, function(err) { + if(!err) { + dbot.instance.ignoreTag(event.user, module); + event.reply(dbot.t('ignored', { + 'user': event.user, + 'module': module + })); + } + }); } else { - // User doesn't exist + event.reply(dbot.t('already_ignoring', { 'user': event.user })); } }.bind(this)); } else { @@ -82,16 +78,22 @@ var ignore = function(dbot) { '~unignore': function(event) { var module = event.params[1]; - this.api.getUserIgnores(event.server, event.user, function(err, user, ignores) { + this.api.getUserIgnores(event.rUser, function(err, ignores) { if(err || !ignores || _.isUndefined(module)) { - event.reply(dbot.t('unignore_usage', { - 'user': event.user, - 'modules': ignores.ignores.join(', ') - })); + if(ignores) { + event.reply(dbot.t('unignore_usage', { + 'user': event.user, + 'modules': ignores.ignores.join(', ') + })); + } else { + event.reply(dbot.t('empty_unignore_usage', { + 'user': event.user + })); + } } else { if(_.include(ignores.ignores, module)) { ignores.ignores = _.without(ignores.ignores, module); - this.db.save('ignores', user.id, ignores, function(err) { + this.db.save('ignores', event.rUser.id, ignores, function(err) { if(!err) { dbot.instance.removeIgnore(event.user, module) event.reply(dbot.t('unignored', { @@ -112,35 +114,37 @@ var ignore = function(dbot) { item = event.input[2]; if(module == '*' || _.include(dbot.config.moduleNames, item) || _.include(dbot.commands, item)) { - this.api.getUserIgnores(event.server, nick, function(err, user, ignores) { - if(!err) { - if(!ignores) { - ignores = { - 'id': user.id, - 'ignores': [], - 'bans': [] - }; - } + dbot.api.users.resolveUser(event.server, nick, function(user) { + this.api.getUserIgnores(user, function(err, ignores) { + if(!err) { + if(!ignores) { + ignores = { + 'id': user.id, + 'ignores': [], + 'bans': [] + }; + } - if(!_.include(ignores.bans, item)) { - ignores.bans.push(item); - this.db.save('ignores', user.id, ignores, function(err) { - if(!err) { - event.reply(dbot.t('banned_success', { - 'user': event.user, - 'banned': nick, - 'module': item - })); - } - }); - } else { - event.reply(dbot.t('already_banned', { - 'user': event.user, - 'banned': nick - })); + if(!_.include(ignores.bans, item)) { + ignores.bans.push(item); + this.db.save('ignores', user.id, ignores, function(err) { + if(!err) { + event.reply(dbot.t('banned_success', { + 'user': event.user, + 'banned': nick, + 'module': item + })); + } + }); + } else { + event.reply(dbot.t('already_banned', { + 'user': event.user, + 'banned': nick + })); + } } - } - }.bind(this)); + }.bind(this)); + }); } else { event.reply(dbot.t('invalid_ban', { 'user': event.user })); } @@ -150,29 +154,31 @@ var ignore = function(dbot) { var nick = event.input[1], item = event.input[2]; - this.api.getUserIgnores(event.server, nick, function(err, user, ignores) { - if(err || !ignores) { - event.reply(dbot.t('invalid_unban', { - 'user': event.user, - 'banned': nick - })); - } else { - if(_.include(ignores.bans, item)) { - ignores.bans = _.without(ignores.bans, item); - this.db.save('ignores', user.id, ignores, function(err) { - event.reply(dbot.t('unbanned_success', { - 'user': event.user, - 'banned': nick, - 'module': item - })); - }); - } else { + dbot.api.users.resolveUser(event.server, nick, function(user) { + this.api.getUserIgnores(user, function(err, ignores) { + if(err || !ignores) { event.reply(dbot.t('invalid_unban', { 'user': event.user, - 'banned': nick + 'banned': nick })); + } else { + if(_.include(ignores.bans, item)) { + ignores.bans = _.without(ignores.bans, item); + this.db.save('ignores', user.id, ignores, function(err) { + event.reply(dbot.t('unbanned_success', { + 'user': event.user, + 'banned': nick, + 'module': item + })); + }); + } else { + event.reply(dbot.t('invalid_unban', { + 'user': event.user, + 'banned': nick + })); + } } - } + }.bind(this)); }.bind(this)); }, diff --git a/modules/ignore/strings.json b/modules/ignore/strings.json index abcdd07..a5763e6 100644 --- a/modules/ignore/strings.json +++ b/modules/ignore/strings.json @@ -39,6 +39,14 @@ "nl": "{user}: Gebruik: ~unignore [module]. Modules die momenteel worden genegeerd: {modules}.", "de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ignoriert werden: {modules}." }, + "empty_unignore_usage": { + "en": "{user}: Usage: ~unignore [module].", + "es": "{user}: Modo de empleo: ~unignore [módulo].", + "na'vi": "{user}: Sar: ~unignore ['u].", + "cy": "{user}: Defnydd: ~unignore [modiwl].", + "nl": "{user}: Gebruik: ~unignore [module].", + "de": "{user}: Benutzung: ~unignore [module]." + }, "invalid_unignore": { "en": "{user}: You're not ignoring that module or it doesn't exist.", "es": "{user}: No ignoras este módulo o no existe.", @@ -57,7 +65,7 @@ }, "ban_usage": { "en": "{user}: Usage: ~ban [user] [module/command]. Use * for all modules and commands.", - "cy": "{user}: Defnydd: ~ban [defnyddiwr] [modiwl/gorchymyn]. Defnyddio * am pob modiwlau a gorchmynion." + "cy": "{user}: Defnydd: ~ban [defnyddiwr] [modiwl/gorchymyn]. Defnyddio * am pob modiwlau a gorchmynion.", "nl": "{user}: Gebruik: ~ban [gebruiker] [module/commando]. Gebruik * voor alle modules en alle commandos.", "de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle." }, From e1629f3a164859d3d1af7aab558c425c72dd5121 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 16:51:32 +0000 Subject: [PATCH 139/220] Alias support for command.api.hasAccess [#515][#514][#511] --- modules/command/api.js | 6 +++--- modules/command/command.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/command/api.js b/modules/command/api.js index adaedac..f5be301 100644 --- a/modules/command/api.js +++ b/modules/command/api.js @@ -5,18 +5,18 @@ var api = function(dbot) { /** * Does the user have the correct access level to use the command? */ - 'hasAccess': function(server, user, command, callback) { + 'hasAccess': function(user, command, callback) { var accessNeeded = dbot.commands[command].access; if(accessNeeded == 'admin' || accessNeeded == 'moderator') { var allowedNicks = dbot.config.admins; if(accessNeeded == 'moderator') allowedNicks = _.union(allowedNicks, dbot.config.moderators); - if(!_.include(allowedNicks, user)) { + if(!_.include(allowedNicks, user.primaryNick)) { callback(false); } else { if(_.has(dbot.modules, 'nickserv') && this.config.useNickserv == true) { - dbot.api.nickserv.auth(server, user, function(result) { + dbot.api.nickserv.auth(user.server, user.currentNick, function(result) { callback(result); }); } else { diff --git a/modules/command/command.js b/modules/command/command.js index fd0f494..ba20716 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -20,7 +20,7 @@ var command = function(dbot) { } } - this.api.hasAccess(event.server, event.user, commandName, function(hasAccess) { + this.api.hasAccess(event.rUser, commandName, function(hasAccess) { dbot.api.ignore.isUserIgnoring(event.rUser, commandName, function(isIgnoring) { dbot.api.ignore.isUserBanned(event.rUser, commandName, function(isBanned) { if(isBanned) { From 7e2b717d0a5fbfc543d7e4fdeb7e39b8d235d01b Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 18:26:54 +0000 Subject: [PATCH 140/220] poll uses event.rUser [#511] --- modules/dns/dns.js | 1 + modules/kick/commands.js | 3 - modules/poll/commands.js | 176 +++++++++++++++++++-------------------- 3 files changed, 85 insertions(+), 95 deletions(-) diff --git a/modules/dns/dns.js b/modules/dns/dns.js index e061d83..fbc38cb 100644 --- a/modules/dns/dns.js +++ b/modules/dns/dns.js @@ -16,6 +16,7 @@ var dns = function(dbot) { } }); }, + '~rdns': function(event) { ip = event.params[1]; dnsmod.reverse(ip, function (error, domain) { diff --git a/modules/kick/commands.js b/modules/kick/commands.js index c64aa46..e04c5a2 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -55,9 +55,6 @@ var commands = function(dbot) { if(this.config.network_name[event.server]) { network = this.config.network_name[event.server]; } - console.log(timeout); - console.log(banee); - console.log(reason); dbot.api.nickserv.getUserHost(event.server, banee, function(host) { // Add host record entry diff --git a/modules/poll/commands.js b/modules/poll/commands.js index fafb62f..455656f 100644 --- a/modules/poll/commands.js +++ b/modules/poll/commands.js @@ -13,63 +13,59 @@ var commands = function(dbot) { _.each(options, function(item, index, list) { list[index] = [ item, 0 ]; }) votes = _.object(options); - dbot.api.users.resolveUser(event.server, event.user, function(user) { - this.db.create('poll', name, { - 'name': name, - 'description': description, - 'owner': user.id, - 'votes': votes, - 'votees': {} - }, function(err, value) { - if(!err) { - event.reply(dbot.t('poll_created', { - 'name': name, - 'description': description, - 'url': dbot.api.web.getUrl('poll/' + name) - })); - } else if(err instanceof AlreadyExistsError) { - event.reply(dbot.t('poll_exists', { 'name': name })); - } - }); - }.bind(this)); + this.db.create('poll', name, { + 'name': name, + 'description': description, + 'owner': event.rUser.id, + 'votes': votes, + 'votees': {} + }, function(err, value) { + if(!err) { + event.reply(dbot.t('poll_created', { + 'name': name, + 'description': description, + 'url': dbot.api.web.getUrl('poll/' + name) + })); + } else if(err instanceof AlreadyExistsError) { + event.reply(dbot.t('poll_exists', { 'name': name })); + } + }); }, '~addoption': function(event) { var name = event.input[1].toLowerCase(), option = event.input[2].toLowerCase(); - dbot.api.users.resolveUser(event.server, event.user, function(user) { - this.db.read('poll', name, function(err, poll) { - if(!err) { - if(poll.owner === user.id) { - if(!_.has(poll.votes, option)) { - poll.votes[option] = 0; - this.db.save('poll', name, poll, function(err) { - event.reply(dbot.t('option_added', { - 'user': event.user, - 'name': name, - 'option': option - })); - }); - } else { - event.reply(dbot.t('option_exists', { - 'option': option, + this.db.read('poll', name, function(err, poll) { + if(!err) { + if(poll.owner === event.rUser.id) { + if(!_.has(poll.votes, option)) { + poll.votes[option] = 0; + this.db.save('poll', name, poll, function(err) { + event.reply(dbot.t('option_added', { + 'user': event.user, 'name': name, - 'user': event.user + 'option': option })); - } + }); } else { - event.reply(dbot.t('not_poll_owner', { - 'user': event.user, - 'name': name + event.reply(dbot.t('option_exists', { + 'option': option, + 'name': name, + 'user': event.user })); } } else { - if(err instanceof NoSuchThingError) { - event.reply(dbot.t('poll_unexistent', { 'name': name })); - } + event.reply(dbot.t('not_poll_owner', { + 'user': event.user, + 'name': name + })); } - }.bind(this)); + } else { + if(err instanceof NoSuchThingError) { + event.reply(dbot.t('poll_unexistent', { 'name': name })); + } + } }.bind(this)); }, @@ -77,32 +73,30 @@ var commands = function(dbot) { var name = event.input[1].toLowerCase(), option = event.input[2].toLowerCase(); - dbot.api.users.resolveUser(event.server, event.user, function(user) { - this.db.read('poll', name, function(err, poll) { - if(!err) { - if(poll.owner === user.id) { - if(_.has(poll.votes, option)) { - delete poll.votes[option]; + this.db.read('poll', name, function(err, poll) { + if(!err) { + if(poll.owner === event.rUser.id) { + if(_.has(poll.votes, option)) { + delete poll.votes[option]; - this.db.save('poll', name, poll, function(err) { - event.reply(dbot.t('option_removed', { - 'user': event.user, - 'name': name, - 'option': option - })); - }.bind(this)); - } else { - event.reply(dbot.t('invalid_vote', { 'vote': option })); - } + this.db.save('poll', name, poll, function(err) { + event.reply(dbot.t('option_removed', { + 'user': event.user, + 'name': name, + 'option': option + })); + }.bind(this)); } else { - event.reply(dbot.t('not_poll_owner', { 'name': name })); + event.reply(dbot.t('invalid_vote', { 'vote': option })); } } else { - if(err instanceof NoSuchThingError) { - event.reply(dbot.t('poll_unexistent', { 'name': name })); - } + event.reply(dbot.t('not_poll_owner', { 'name': name })); } - }.bind(this)); + } else { + if(err instanceof NoSuchThingError) { + event.reply(dbot.t('poll_unexistent', { 'name': name })); + } + } }.bind(this)); }, @@ -110,37 +104,35 @@ var commands = function(dbot) { var name = event.input[1].toLowerCase(), vote = event.input[2].toLowerCase(); - dbot.api.users.resolveUser(event.server, event.user, function(user) { - this.db.read('poll', name, function(err, poll) { - if(!err) { - if(_.has(poll.votes, vote)) { - if(_.has(poll.votees, user.id)) { - var oldVote = poll.votees[user.id]; - poll.votes[oldVote]--; - poll.votes[vote]++; - poll.votees[user.id] = vote; - } else { - poll.votes[vote]++; - poll.votees[user.id] = vote; - } - - this.db.save('poll', name, poll, function(err) { - event.reply(dbot.t('voted', { - 'vote': vote, - 'poll': name, - 'count': poll.votes[vote], - 'user': event.user - })); - }.bind(this)); + this.db.read('poll', name, function(err, poll) { + if(!err) { + if(_.has(poll.votes, vote)) { + if(_.has(poll.votees, event.rUser.id)) { + var oldVote = poll.votees[event.rUser.id]; + poll.votes[oldVote]--; + poll.votes[vote]++; + poll.votees[event.rUser.id] = vote; } else { - event.reply(dbot.t('invalid_vote', { 'vote': vote })); + poll.votes[vote]++; + poll.votees[event.rUser.id] = vote; } + + this.db.save('poll', name, poll, function(err) { + event.reply(dbot.t('voted', { + 'vote': vote, + 'poll': name, + 'count': poll.votes[vote], + 'user': event.user + })); + }.bind(this)); } else { - if(err instanceof NoSuchThingError) { - event.reply(dbot.t('poll_unexistent', { 'name': name })); - } + event.reply(dbot.t('invalid_vote', { 'vote': vote })); } - }.bind(this)); + } else { + if(err instanceof NoSuchThingError) { + event.reply(dbot.t('poll_unexistent', { 'name': name })); + } + } }.bind(this)); }, From dd64b5955aaae0d17946c6264af4211bd7d007bd Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 18:28:35 +0000 Subject: [PATCH 141/220] fix ~help module thing --- modules/command/commands.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/command/commands.js b/modules/command/commands.js index 5bf355b..6fe31f8 100644 --- a/modules/command/commands.js +++ b/modules/command/commands.js @@ -48,8 +48,8 @@ var commands = function(dbot) { } else { var helpLink = dbot.config.repoRoot + 'blob/master/modules/' + moduleName + '/README.md'; - if(dbot.config[moduleName].help) { - helpLink = dbot.config[moduleName].help; + if(dbot.config.modules[moduleName].help) { + helpLink = dbot.config.modules[moduleName].help; } // TODO: Check it exists From 72200596de9349334d177c2992912bae592d67bd Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 18:43:52 +0000 Subject: [PATCH 142/220] reinstate ~profile command --- modules/profile/commands.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/modules/profile/commands.js b/modules/profile/commands.js index f8c81a0..8900e68 100644 --- a/modules/profile/commands.js +++ b/modules/profile/commands.js @@ -2,32 +2,34 @@ var _ = require('underscore')._; var commands = function(dbot){ var commands = { - - "~getprop": function(event){ + '~getprop': function(event){ if(event.params[1]){ if(_.has(this.config.schema.profile, event.params[1])){ this.api.getProperty(event.server, event.user, event.params[1], function(reply){ event.reply(reply); }); - } - else{ - event.reply("Invalid property. Go home."); + } else { + event.reply('Invalid property. Go home.'); } } }, - "~setprop": function(event){ + '~setprop': function(event){ if(event.input[1] && event.input[2]){ if(_.has(this.config.schema.profile, event.input[1])){ this.api.setProperty(event.server, event.user, event.input[1], event.input[2], function(reply){ event.reply(reply); }); - } - else{ - event.reply("Invalid property. Go home."); + } else { + event.reply('Invalid property. Go home.'); } } }, + + '~profile': function(event) { + var user = event.params[1] || event.user; + event.reply(dbot.api.web.getUrl('profile/' + event.server + '/' + user)); + } }; commands['~setprop'].regex = [/~setprop ([^ ]+) (.+)/, 3]; From 08d5f15679e8fcc49210a0328bee85fce03aa3e6 Mon Sep 17 00:00:00 2001 From: Sam Nicholls Date: Thu, 27 Jun 2013 19:55:45 +0100 Subject: [PATCH 143/220] Fix missing username --- views/profile/profile.jade | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/views/profile/profile.jade b/views/profile/profile.jade index 8ea224b..635dda5 100644 --- a/views/profile/profile.jade +++ b/views/profile/profile.jade @@ -40,8 +40,7 @@ block content }); div.page-header.profile_page-header - h1 - #{primary} + h1 #{primary} small if(profile.tagline) "#{profile.tagline}" From 6faedb59a8a5b75773bb30d4eb726a97f7b7fc3c Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 19:16:18 +0000 Subject: [PATCH 144/220] fix report [#511] --- modules/report/report.js | 47 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/modules/report/report.js b/modules/report/report.js index 9819f43..e123b2e 100644 --- a/modules/report/report.js +++ b/modules/report/report.js @@ -20,34 +20,35 @@ var report = function(dbot) { var commands = { '~report': function(event) { - var channelName = event.input[1]; - var nick = event.input[2]; - var reason = event.input[3]; + var channelName = event.input[1], + nick = event.input[2]; + reason = event.input[3]; - if(_.has(event.allChannels, channelName)) { - if(dbot.api.users.isChannelUser(event.server, nick, channelName, true)) { - nick = dbot.api.users.resolveUser(event.server, nick, true); - this.api.notify(event.server, channelName, dbot.t('report', { - 'reporter': event.user, - 'reported': nick, - 'channel': channelName, - 'reason': reason - })); - event.reply(dbot.t('reported', { 'reported': nick })); + dbot.api.users.resolveUser(event.server, nick, function(reportee) { + if(_.has(event.allChannels, channelName)) { + if(reportee) { + this.api.notify(event.server, channelName, dbot.t('report', { + 'reporter': event.user, + 'reported': nick, + 'channel': channelName, + 'reason': reason + })); + event.reply(dbot.t('reported', { 'reported': nick })); + } else { + event.reply(dbot.t('user_not_found', { + 'reported': nick, + 'channel': channelName + })); + } } else { - event.reply(dbot.t('user_not_found', { - 'reported': nick, - 'channel': channelName - })); - } - } else { - event.reply(dbot.t('not_in_channel', { 'channel': channelName })); - } + event.reply(dbot.t('not_in_channel', { 'channel': channelName })); + } + }.bind(this)); }, '~notify': function(event) { - var channelName = event.input[1]; - var message = event.input[2]; + var channelName = event.input[1], + message = event.input[2]; if(_.has(event.allChannels, channelName)) { this.api.notify(event.server, channelName, dbot.t('notify', { From 1aa1800ea2b794f3689215c30a9c56ab216b62f4 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 19:19:13 +0000 Subject: [PATCH 145/220] finish off auto resolve --- modules/users/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/users/commands.js b/modules/users/commands.js index 1011249..6409ab9 100644 --- a/modules/users/commands.js +++ b/modules/users/commands.js @@ -3,7 +3,7 @@ var _ = require('underscore')._; var commands = function(dbot) { var commands = { '~alias': function(event) { - var nick = event.params[1].trim(); + var nick = event.params[1].trim() || event.user; this.api.resolveUser(event.server, nick, function(user) { if(user) { if(nick == user.primaryNick) { From d650f2a10a1e697dda7ceaff8f5e1f8a8aaf92c4 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 27 Jun 2013 22:33:44 +0000 Subject: [PATCH 146/220] remove stats from db branch --- .gitmodules | 3 --- modules/stats | 1 - 2 files changed, 4 deletions(-) delete mode 160000 modules/stats diff --git a/.gitmodules b/.gitmodules index d47e162..cf2f023 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "modules/github"] path = modules/github url = git://github.com/zuzak/dbot-github.git -[submodule "modules/stats"] - path = modules/stats - url = git@github.com:SamStudio8/dbot-stats.git diff --git a/modules/stats b/modules/stats deleted file mode 160000 index f7599c7..0000000 --- a/modules/stats +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f7599c7564396a22a8ca9f05bd386d6531f41d1a From 8dcde520998722c493e1a00701a10c618ca60af7 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 30 Jun 2013 15:11:56 +0000 Subject: [PATCH 147/220] few small jimblings --- modules/poll/pages.js | 2 -- modules/quotes/commands.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/poll/pages.js b/modules/poll/pages.js index 9fc08b8..59309c8 100644 --- a/modules/poll/pages.js +++ b/modules/poll/pages.js @@ -33,8 +33,6 @@ var pages = function(dbot) { }); }); } else { - console.log(err); - console.log("the thing the thing"); res.render('error', { 'name': dbot.config.name, 'message': 'No polls under that key.' diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index f47c7ee..cc8b53b 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -8,7 +8,7 @@ var commands = function(dbot) { // Add a quote to a category '~qadd': function(event) { - var key = event.input[1].toLowerCase().trim(); + var key = event.input[1].toLowerCase().trim(), quote = event.input[2]; this.api.addQuote(key, quote, event.user, function(newCount) { From fee7fedbf7de51b116032282369cbd6382b7dbfb Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 30 Jun 2013 15:40:47 +0000 Subject: [PATCH 148/220] fix the project quotes thing --- modules/project/pages.js | 116 +++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/modules/project/pages.js b/modules/project/pages.js index a713f8a..529d634 100644 --- a/modules/project/pages.js +++ b/modules/project/pages.js @@ -3,8 +3,7 @@ var exec = require('child_process').exec, _ = require('underscore'); var pages = function(dbot) { - var quoteCat = dbot.db.quoteArrs[dbot.config.name], - rev, diff, branch, credit, authors = []; + var rev, diff, branch, credit, authors = []; exec("git log --format='%cN¬' | sort -u | tr -d '\n'", function (error, stdout, sderr) { var credit = stdout.split("¬"); // nobody uses ¬, do they? for (var i = 0; i < credit.length; i++) { @@ -37,65 +36,64 @@ var pages = function(dbot) { return { '/project': function(req, res) { - var quote = dbot.config.name; - if(quoteCat) { - quote = quoteCat[Math.floor(Math.random()*quoteCat.length)]; - } + dbot.api.quotes.getQuote(dbot.config.name, function(quote) { + if(!quote) quote = dbot.config.name; - res.render('project', { - "translation": dbot.modules.project.api.translationProgress(), - "configList": dbot.modules.project.api.configList(), - "authors": authors, - "credits": dbot.t("credits"), - "thanks": dbot.t("thanks"), - "name": dbot.config.name, - "intro": dbot.t("dbotintro", { - "botname": dbot.config.name - }), - "curr839": dbot.config.language, - "repo": dbot.config.modules.github.defaultrepo, - "branch": dbot.t("branch",{ - "branch": branch - }), - "currver": dbot.config.version, - "currlang": dbot.t("dbotspeaks",{ - "lang839": dbot.config.language, - "langen": dbot.strings[dbot.config.language]["en"], - "lang": dbot.t(dbot.config.language), - "name": dbot.config.name - }), - "projectstatus": dbot.t("projectstatus"), - "revnum": dbot.t("revnum",{ + res.render('project', { + "translation": dbot.modules.project.api.translationProgress(), + "configList": dbot.modules.project.api.configList(), + "authors": authors, + "credits": dbot.t("credits"), + "thanks": dbot.t("thanks"), "name": dbot.config.name, - "rev": rev - }), - "modules": dbot.config.moduleNames, - "loadmod": dbot.t("loadedmodules"), - "debugmode": dbot.t("debugmode-" + dbot.config.debugMode), - "milestones": milestones, - "milestoneprog": dbot.t("milestoneprog"), - "config": dbot.t("configoptions"), - "milestonename": dbot.t("milestonename"), - "openmilestone": dbot.t("openmilestone"), - "closedmilestone": dbot.t("closedmilestone"), - "development": dbot.t("development"), - "dquote": quote, - "diff": diff, - "pagetitle": dbot.t("pagetitle", { - "botname": dbot.config.name - }), - "git": dbot.t("git"), - "milestonehead": dbot.t("milestones"), - "propaganda": dbot.t("propaganda"), - "languagecurr": dbot.t(dbot.config.language), - "languagenati": dbot.t("langhead-native"), - "languageeng": dbot.t("en"), - "languageprog": dbot.t("langhead-progress"), - "languagetrans": dbot.t("langhead-translations"), - "languagetranshead": dbot.t("translations"), - "pullreqs": dbot.t("outstanding-pullreq") - }); - }, + "intro": dbot.t("dbotintro", { + "botname": dbot.config.name + }), + "curr839": dbot.config.language, + "repo": dbot.config.modules.github.defaultrepo, + "branch": dbot.t("branch",{ + "branch": branch + }), + "currver": dbot.config.version, + "currlang": dbot.t("dbotspeaks",{ + "lang839": dbot.config.language, + "langen": dbot.strings[dbot.config.language]["en"], + "lang": dbot.t(dbot.config.language), + "name": dbot.config.name + }), + "projectstatus": dbot.t("projectstatus"), + "revnum": dbot.t("revnum",{ + "name": dbot.config.name, + "rev": rev + }), + "modules": dbot.config.moduleNames, + "loadmod": dbot.t("loadedmodules"), + "debugmode": dbot.t("debugmode-" + dbot.config.debugMode), + "milestones": milestones, + "milestoneprog": dbot.t("milestoneprog"), + "config": dbot.t("configoptions"), + "milestonename": dbot.t("milestonename"), + "openmilestone": dbot.t("openmilestone"), + "closedmilestone": dbot.t("closedmilestone"), + "development": dbot.t("development"), + "dquote": quote, + "diff": diff, + "pagetitle": dbot.t("pagetitle", { + "botname": dbot.config.name + }), + "git": dbot.t("git"), + "milestonehead": dbot.t("milestones"), + "propaganda": dbot.t("propaganda"), + "languagecurr": dbot.t(dbot.config.language), + "languagenati": dbot.t("langhead-native"), + "languageeng": dbot.t("en"), + "languageprog": dbot.t("langhead-progress"), + "languagetrans": dbot.t("langhead-translations"), + "languagetranshead": dbot.t("translations"), + "pullreqs": dbot.t("outstanding-pullreq") + }); + }); + } }; }; From 2c2e1aefa23c1bde68776c5035d195e23220397a Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 30 Jun 2013 17:22:16 +0000 Subject: [PATCH 149/220] kick uses root admin_channel directive [#513] --- modules/kick/commands.js | 44 +++++++++++++++++++++------------------- modules/kick/kick.js | 20 ++++++++++-------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/modules/kick/commands.js b/modules/kick/commands.js index e04c5a2..426970e 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -48,7 +48,7 @@ var commands = function(dbot) { timeout = event.input[1], banee = event.input[2], reason = event.input[3], - adminChannel = this.config.admin_channel[event.server]; + adminChannel = dbot.config.servers[server].admin_channel, channels = dbot.config.servers[server].channels, network = event.server; @@ -107,29 +107,31 @@ var commands = function(dbot) { } // Notify moderators, banee - if(this.config.admin_channel[event.server]) { + if(!_.isUndefined(adminChannel)) { channels = _.without(channels, adminChannel); + } else { + adminChannel = event.channel.name; + } - dbot.api.report.notify(server, adminChannel, notifyString); - dbot.say(event.server, adminChannel, notifyString); + dbot.api.report.notify(server, adminChannel, notifyString); + dbot.say(event.server, adminChannel, notifyString); - if(!_.isUndefined(timeout)) { - dbot.say(event.server, banee, dbot.t('tbanned_notify', { - 'network': network, - 'banner': banner, - 'reason': reason, - 'hours': timeout, - 'admin_channel': adminChannel - })); - } else { - dbot.say(event.server, banee, dbot.t('nbanned_notify', { - 'network': network, - 'banner': banner, - 'reason': reason, - 'hours': timeout, - 'admin_channel': adminChannel - })); - } + if(!_.isUndefined(timeout)) { + dbot.say(event.server, banee, dbot.t('tbanned_notify', { + 'network': network, + 'banner': banner, + 'reason': reason, + 'hours': timeout, + 'admin_channel': adminChannel + })); + } else { + dbot.say(event.server, banee, dbot.t('nbanned_notify', { + 'network': network, + 'banner': banner, + 'reason': reason, + 'hours': timeout, + 'admin_channel': adminChannel + })); } // Ban the user from all channels diff --git a/modules/kick/kick.js b/modules/kick/kick.js index 6197b0d..f90315e 100644 --- a/modules/kick/kick.js +++ b/modules/kick/kick.js @@ -24,22 +24,24 @@ var kick = function(dbot) { 'networkUnban': function(server, unbanee, unbanner, callback) { var channels = dbot.config.servers[server].channels, network = this.config.network_name[server] || server, - adminChannel = this.config.admin_channel[server]; + adminChannel = dbot.config.servers[server].admin_channel; if(_.has(this.hosts, server) && _.has(this.hosts[server], unbanee)) { var host = this.hosts[server][unbanee]; // Notify Staff - if(!_.isUndefined(adminChannel)) { - var notifyString = dbot.t('nunbanned', { - 'network': network, - 'unbanee': unbanee, - 'unbanner': unbanner - }); - dbot.api.report.notify(server, adminChannel, notifyString); - dbot.say(server, adminChannel, notifyString); + if(_.isUndefined(adminChannel)) { + adminChannel = event.channel.name; } + var notifyString = dbot.t('nunbanned', { + 'network': network, + 'unbanee': unbanee, + 'unbanner': unbanner + }); + dbot.api.report.notify(server, adminChannel, notifyString); + dbot.say(server, adminChannel, notifyString); + // Notify Unbanee dbot.say(server, unbanee, dbot.t('nunban_notify', { 'network': network, From 1d9c7fd40e548767fbadb160b6ebb7c5c8e08d88 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 30 Jun 2013 17:22:38 +0000 Subject: [PATCH 150/220] remove config directive for admin channel in kick --- modules/kick/config.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/kick/config.json b/modules/kick/config.json index 2ea10c4..f02f708 100644 --- a/modules/kick/config.json +++ b/modules/kick/config.json @@ -3,9 +3,6 @@ "dependencies": [ "command", "report", "users" ], "ignorable": true, "countSilently": true, - "admin_channel": { - "aberwiki": "#fishbox" - }, "network_name": { "aberwiki": "OAOSIDL" }, From c1a63d331acd5c01ccf9bf117fca4d037f2a0917 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 30 Jun 2013 18:25:45 +0000 Subject: [PATCH 151/220] auto modules prefix in ~showconfig [#520] --- modules/admin/commands.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/admin/commands.js b/modules/admin/commands.js index db87f8f..252c234 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -244,8 +244,14 @@ var commands = function(dbot) { } } else { event.reply(dbot.t("no_config_key", {'path': configPath})); + configPath = configPath.split('.'); - configPath.pop(); + if(_.has(dbot.config.modules, configPath[0])) { + configPath.splice(0, 0, 'modules'); + } else { + configPath.pop(); + } + event.params[1] = configPath.join('.'); this.commands['~showconfig'](event); } From b6a56e23f66485eaa0ced0dcced5f4ff3326ce05 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 4 Jul 2013 22:29:52 +0000 Subject: [PATCH 152/220] fix nickserv auth --- modules/nickserv/nickserv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nickserv/nickserv.js b/modules/nickserv/nickserv.js index 8ca294b..39c38b6 100644 --- a/modules/nickserv/nickserv.js +++ b/modules/nickserv/nickserv.js @@ -72,8 +72,8 @@ var nickserv = function(dbot) { if(match[1]) match[1] = match[1].replace('\*', ''); if(match && _.has(this.userStack, event.server) && _.has(this.userStack[event.server], match[1])) { - this.userStack[event.server][match[1]](match[3].trim()); delete this.userStack[event.server][match[1]]; + this.userStack[event.server][match[1]](match[3].trim()); } } }.bind(this); From a821547838c6eb4810070f6a92fb7b6baa06cc6c Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 4 Jul 2013 22:32:56 +0000 Subject: [PATCH 153/220] fix addquote --- modules/kick/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/kick/commands.js b/modules/kick/commands.js index fd02f16..8df71cf 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -145,7 +145,7 @@ var commands = function(dbot) { // Add qutoe category documenting ban if(this.config.document_bans && _.has(dbot.modules, 'quotes')) { - dbot.db.quoteArrs['ban_' + banee.toLowerCase()] = [ quoteString ]; + dbot.api.quotes.addQuote('ban_' + banee.toLowerCase(), quoteString, function() {}); notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee }); } From f105afad172c04e0ed3b7e3563f9dcf7193ec1db Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 4 Jul 2013 22:36:37 +0000 Subject: [PATCH 154/220] test --- modules/kick/commands.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/kick/commands.js b/modules/kick/commands.js index 8df71cf..2855295 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -144,10 +144,10 @@ var commands = function(dbot) { } // Add qutoe category documenting ban - if(this.config.document_bans && _.has(dbot.modules, 'quotes')) { - dbot.api.quotes.addQuote('ban_' + banee.toLowerCase(), quoteString, function() {}); - notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee }); - } + //if(this.config.document_bans && _.has(dbot.modules, 'quotes')) { + // dbot.api.quotes.addQuote('ban_' + banee.toLowerCase(), quoteString, function() {}); + // notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee }); + // } // Notify moderators, banee if(!_.isUndefined(adminChannel)) { From 53defaaeea41b8972b4910871785d4d070030991 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 4 Jul 2013 22:37:34 +0000 Subject: [PATCH 155/220] wtf --- modules/kick/commands.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/kick/commands.js b/modules/kick/commands.js index 2855295..8df71cf 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -144,10 +144,10 @@ var commands = function(dbot) { } // Add qutoe category documenting ban - //if(this.config.document_bans && _.has(dbot.modules, 'quotes')) { - // dbot.api.quotes.addQuote('ban_' + banee.toLowerCase(), quoteString, function() {}); - // notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee }); - // } + if(this.config.document_bans && _.has(dbot.modules, 'quotes')) { + dbot.api.quotes.addQuote('ban_' + banee.toLowerCase(), quoteString, function() {}); + notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee }); + } // Notify moderators, banee if(!_.isUndefined(adminChannel)) { From 6c3f3119ff889101d61708ff149bf687f0c09c85 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 4 Jul 2013 22:42:37 +0000 Subject: [PATCH 156/220] blah --- modules/kick/commands.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/kick/commands.js b/modules/kick/commands.js index 8df71cf..3b5781b 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -100,6 +100,7 @@ var commands = function(dbot) { } dbot.api.nickserv.getUserHost(event.server, banee, function(host) { + console.log(host); // Add host record entry if(host) { if(!_.has(this.hosts, event.server)) this.hosts[event.server] = {}; From b5d286b86efc91834943b08d8a7e11d1a95f84a5 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 4 Jul 2013 22:44:19 +0000 Subject: [PATCH 157/220] jawohl --- modules/kick/commands.js | 1 - modules/nickserv/nickserv.js | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/kick/commands.js b/modules/kick/commands.js index 3b5781b..8df71cf 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -100,7 +100,6 @@ var commands = function(dbot) { } dbot.api.nickserv.getUserHost(event.server, banee, function(host) { - console.log(host); // Add host record entry if(host) { if(!_.has(this.hosts, event.server)) this.hosts[event.server] = {}; diff --git a/modules/nickserv/nickserv.js b/modules/nickserv/nickserv.js index 39c38b6..628fed7 100644 --- a/modules/nickserv/nickserv.js +++ b/modules/nickserv/nickserv.js @@ -72,8 +72,9 @@ var nickserv = function(dbot) { if(match[1]) match[1] = match[1].replace('\*', ''); if(match && _.has(this.userStack, event.server) && _.has(this.userStack[event.server], match[1])) { + var callback = this.userStack[event.server][match[1]]; delete this.userStack[event.server][match[1]]; - this.userStack[event.server][match[1]](match[3].trim()); + callback(match[3].trim()); } } }.bind(this); From eec997a0ac51f859a17df5f335e4801131ea9b65 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 4 Jul 2013 22:46:03 +0000 Subject: [PATCH 158/220] whoops --- modules/kick/commands.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/kick/commands.js b/modules/kick/commands.js index 8df71cf..2fd16bb 100644 --- a/modules/kick/commands.js +++ b/modules/kick/commands.js @@ -145,7 +145,8 @@ var commands = function(dbot) { // Add qutoe category documenting ban if(this.config.document_bans && _.has(dbot.modules, 'quotes')) { - dbot.api.quotes.addQuote('ban_' + banee.toLowerCase(), quoteString, function() {}); + dbot.api.quotes.addQuote('ban_' + banee.toLowerCase(), + quoteString, banee, function() {}); notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee }); } From 134f2b76bbab371f2465cc9e99844bfbadc235b4 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 4 Jul 2013 23:20:09 +0000 Subject: [PATCH 159/220] fix web link api call for ~link --- modules/quotes/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quotes/commands.js b/modules/quotes/commands.js index cc8b53b..97229ad 100644 --- a/modules/quotes/commands.js +++ b/modules/quotes/commands.js @@ -361,7 +361,7 @@ var commands = function(dbot) { category = result; }, function(err) { if(category) { - if(_.has(dbot.config, 'web') && _.has(dbot.config.web, 'webHost')) { + if(_.has(dbot.modules, 'web')) { event.reply(dbot.t('quote_link', { 'category': key, 'url': dbot.api.web.getUrl('quotes/' + encodeURIComponent(key)) From 7dfa493f444b588f4e30ab08d7b5167fc465fcb1 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 6 Jul 2013 18:00:34 +0000 Subject: [PATCH 160/220] fix nunban --- modules/kick/kick.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/kick/kick.js b/modules/kick/kick.js index 9652be5..a4902a9 100644 --- a/modules/kick/kick.js +++ b/modules/kick/kick.js @@ -76,7 +76,7 @@ var kick = function(dbot) { } else { callback(true); // No host could be found } - }); + }.bind(this)); } } }; From c5448080bf603a4a10c45908458e3c456f24278b Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 6 Jul 2013 18:45:21 +0000 Subject: [PATCH 161/220] record notifies --- modules/report/pages.js | 44 ++++++++++++++++++++++++++++++++++++++ modules/report/report.js | 14 +++++++++++- views/report/channels.jade | 10 +++++++++ views/report/notifies.jade | 21 ++++++++++++++++++ views/report/servers.jade | 10 +++++++++ 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 modules/report/pages.js create mode 100644 views/report/channels.jade create mode 100644 views/report/notifies.jade create mode 100644 views/report/servers.jade diff --git a/modules/report/pages.js b/modules/report/pages.js new file mode 100644 index 0000000..8ecc841 --- /dev/null +++ b/modules/report/pages.js @@ -0,0 +1,44 @@ +var _ = require('underscore')._; + +var pages = function(dbot) { + return { + '/notify': function(req, res) { + res.render('servers', { + 'name': dbot.config.name, + 'servers': _.keys(dbot.config.servers) + }); + }, + + '/notify/:server': function(req, res) { + var server = req.params.server; + res.render('channels', { + 'name': dbot.config.name, + 'server': server, + 'channels': _.keys(dbot.instance.servers[server].channels) + }); + }, + + '/notify/:server/:user': function(req, res) { + var server = req.params.server, + channel = req.params.channel, + notifies = []; + + this.db.search('notifies', { + 'server': server, + 'channel': channel + }, function(notify) { + notifies.push(notify); + }, function(err) { + res.render('notifies', { + 'name': dbot.config.name, + 'server': server, + 'notifies': notifies + }); + }); + } + }; +}; + +exports.fetch = function(dbot) { + return pages(dbot); +}; diff --git a/modules/report/report.js b/modules/report/report.js index e123b2e..ceb327c 100644 --- a/modules/report/report.js +++ b/modules/report/report.js @@ -1,4 +1,5 @@ -var _ = require('underscore')._; +var _ = require('underscore')._, + uuid = require('node-uuid'); var report = function(dbot) { this.api = { @@ -56,6 +57,17 @@ var report = function(dbot) { 'notifier': event.user, 'message': message })); + + var id = uuid.v4(); + this.db.save('notifies', id, { + 'id': id, + 'server': event.server, + 'channel': channelName, + 'user': event.user, + 'time': new Date().getTime(), + 'message': message + }, function() {}); + event.reply(dbot.t('notified', { 'user': event.user, 'channel': channelName diff --git a/views/report/channels.jade b/views/report/channels.jade new file mode 100644 index 0000000..b2a0b7e --- /dev/null +++ b/views/report/channels.jade @@ -0,0 +1,10 @@ +extends ../layout + +block content + h3 Channels on #{server} + div#backlink + a(href='/warning') « Server List + ul#quotelist + -each channel in channels + a(href='/notify/'+server+'/'+encodeURIComponent(channel)) + li.quotes #{channel} diff --git a/views/report/notifies.jade b/views/report/notifies.jade new file mode 100644 index 0000000..1b4c04d --- /dev/null +++ b/views/report/notifies.jade @@ -0,0 +1,21 @@ +extends ../layout + +block content + div#backlink + a(href='/notify/'+server) « Server Channels + p + div#profile_datatable + table.table.table-hover.data + thead + tr + th Date + th Channel + th User + th Message + tbody + for notify, key in notifies + tr + td #{new Date(notify.time)} + td #{notify.channel} + td #{notify.user} + td #{notify.message} diff --git a/views/report/servers.jade b/views/report/servers.jade new file mode 100644 index 0000000..924eb19 --- /dev/null +++ b/views/report/servers.jade @@ -0,0 +1,10 @@ +extends ../layout + +block content + h3 Servers + div#backlink + a(href='/') « Home + ul#quotelist + -each server in servers + a(href='/notify/'+server) + li.quotes #{server} From 7e1818d8755255a0f5e7d6744cfca7f855194752 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 6 Jul 2013 18:47:47 +0000 Subject: [PATCH 162/220] update report slow --- modules/report/report.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/report/report.js b/modules/report/report.js index ceb327c..52e50c4 100644 --- a/modules/report/report.js +++ b/modules/report/report.js @@ -13,9 +13,15 @@ var report = function(dbot) { } }, this); - _.each(ops, function(user) { - dbot.say(server, user.name, message); - }, this); + var i = 0; + var notifyChannel = function(ops) { + if(i >= ops.length) return; + dbot.say(server, ops[i].name, message); + setTimeout(function() { + i++; notifyChannel(ops); + }, 1000); + }; + notifyChannel(ops); } }; From a42271dcf9acd54b360d225ed317ecd57b7424c3 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 6 Jul 2013 18:49:34 +0000 Subject: [PATCH 163/220] connections not servers lol --- modules/report/pages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/report/pages.js b/modules/report/pages.js index 8ecc841..b424763 100644 --- a/modules/report/pages.js +++ b/modules/report/pages.js @@ -14,7 +14,7 @@ var pages = function(dbot) { res.render('channels', { 'name': dbot.config.name, 'server': server, - 'channels': _.keys(dbot.instance.servers[server].channels) + 'channels': _.keys(dbot.instance.connections[server].channels) }); }, From 299aafea871958bd40221a5f0932f24c0dd72b38 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 6 Jul 2013 18:51:03 +0000 Subject: [PATCH 164/220] dbType redis --- modules/report/config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/report/config.json b/modules/report/config.json index 121ef4a..975bd13 100644 --- a/modules/report/config.json +++ b/modules/report/config.json @@ -1,5 +1,6 @@ { "ignorable": true, "notifyVoice": false, - "dependencies": [ "users" ] + "dependencies": [ "users" ], + "dbType": "redis" } From 9aec9f4df4f9a7572dc350f310ddce6738f92099 Mon Sep 17 00:00:00 2001 From: reality Date: Sat, 6 Jul 2013 18:52:31 +0000 Subject: [PATCH 165/220] req params channel --- modules/report/pages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/report/pages.js b/modules/report/pages.js index b424763..e8bbc89 100644 --- a/modules/report/pages.js +++ b/modules/report/pages.js @@ -18,7 +18,7 @@ var pages = function(dbot) { }); }, - '/notify/:server/:user': function(req, res) { + '/notify/:server/:channel': function(req, res) { var server = req.params.server, channel = req.params.channel, notifies = []; From 287b718b17d85c867036fd2659ce26620a62e4af Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 8 Jul 2013 10:06:34 +0000 Subject: [PATCH 166/220] fuck --- database.js | 7 +++++-- run.js | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/database.js b/database.js index 363bbef..3010140 100644 --- a/database.js +++ b/database.js @@ -1,11 +1,13 @@ var databank = require('databank'), Databank = databank.Databank, - DatabankObject = databank.DatabankObject; + DatabankObject = databank.DatabankObject, + _ = require('underscore')._; /** * Multiplex databank objects */ -var DatabaseDriver = function() { +var DatabaseDriver = function(config) { + this.config = config; this.databanks = {}; }; @@ -15,6 +17,7 @@ var DatabaseDriver = function() { DatabaseDriver.prototype.createDB = function(name, driver, schema, callback) { var params = { 'schema': schema }; + if(driver == 'redis' && _.has(this.config, 'redisPort')) params.port = this.config.redisPort; if(driver == 'disk') params.dir = 'db'; this.databanks[name] = Databank.get(driver, params); diff --git a/run.js b/run.js index eb72912..27bcc30 100644 --- a/run.js +++ b/run.js @@ -18,11 +18,11 @@ var DBot = function() { this.db = {}; } - /*** Load the fancy DB ***/ - this.ddb = new DatabaseDriver(); - this.reloadConfig(); + /*** Load the fancy DB ***/ + this.ddb = new DatabaseDriver(this.config); + /*** Load main strings ***/ try { this.strings = JSON.parse(fs.readFileSync('strings.json', 'utf-8')); From 62871dc80e47486095613ff7a8d5a39e38a4a8ed Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 8 Jul 2013 11:02:27 +0000 Subject: [PATCH 167/220] jimble command --- modules/words/words.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/words/words.js b/modules/words/words.js index eac90b0..d26a648 100644 --- a/modules/words/words.js +++ b/modules/words/words.js @@ -11,8 +11,15 @@ var words = function(dbot) { event.reply('No definitions found for ' + query); } }); - } + }, + + '~jimble': function(event) { + event.reply(event.params[1].split('').sort(function() { + return (Math.round(Math.random()) - 0.5); + }).join('')); + } }; + this.commands['~jimble'].regex = [/^~jimble (.+)$/, 2]; this.onLoad = function() { this.wn = new Wordnik({ From 291bff50daa8e2aa6e76ab396ffbaedae8775f50 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 9 Jul 2013 19:17:48 +0000 Subject: [PATCH 168/220] soundcloud module [#524] --- modules/soundcloud/config.json | 5 ++++ modules/soundcloud/soundcloud.js | 41 ++++++++++++++++++++++++++++++++ modules/soundcloud/strings.json | 5 ++++ 3 files changed, 51 insertions(+) create mode 100644 modules/soundcloud/config.json create mode 100644 modules/soundcloud/soundcloud.js create mode 100644 modules/soundcloud/strings.json diff --git a/modules/soundcloud/config.json b/modules/soundcloud/config.json new file mode 100644 index 0000000..50a1537 --- /dev/null +++ b/modules/soundcloud/config.json @@ -0,0 +1,5 @@ +{ + "client_id": "391bcf67b5ad70fd64c6a4f79374f2f4", + "outputPrefix": "\u000307soundcloud\u000f", + "dependencies": [ "link" ] +} diff --git a/modules/soundcloud/soundcloud.js b/modules/soundcloud/soundcloud.js new file mode 100644 index 0000000..97aab8c --- /dev/null +++ b/modules/soundcloud/soundcloud.js @@ -0,0 +1,41 @@ +/** + * Module Name: soundcloud + * Description: Various SoundCloud functionality + */ +var _ = require('underscore')._, + request = require('request'); + +var soundcloud = function(dbot) { + this.ApiRoot = 'http://api.soundcloud.com'; + + this.onLoad = function() { + dbot.api.link.addHandler(this.name, + /https?:\/\/(www\.)?soundcloud\.com\//, + function(event, match, name) { + var url = match.input; + request.get(this.ApiRoot + '/resolve.json', { + 'qs': { + 'client_id': this.config.client_id, + 'url': url + }, + 'json': true + }, function(error, response, body) { + if(response.statusCode == 200) { + if(body.kind == 'track') { + event.reply(dbot.t('sc_track', { + 'title': body.title, + 'artist': body.user.username, + 'genre': body.genre.trim(), + 'plays': body.playback_count, + 'favs': body.favoritings_count + })); + } + } + }); + }.bind(this)); + }.bind(this); +}; + +exports.fetch = function(dbot) { + return new soundcloud(dbot); +}; diff --git a/modules/soundcloud/strings.json b/modules/soundcloud/strings.json new file mode 100644 index 0000000..59c21d1 --- /dev/null +++ b/modules/soundcloud/strings.json @@ -0,0 +1,5 @@ +{ + "sc_track": { + "en": "[{title} by {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]" + } +} From 8688ee05ba4f9ef46cca0b24e5e9aa04e09000b5 Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 9 Jul 2013 21:08:55 +0000 Subject: [PATCH 169/220] soundcloud command [#524] --- modules/soundcloud/soundcloud.js | 27 +++++++++++++++++++++++++++ modules/soundcloud/strings.json | 3 +++ 2 files changed, 30 insertions(+) diff --git a/modules/soundcloud/soundcloud.js b/modules/soundcloud/soundcloud.js index 97aab8c..9308ae5 100644 --- a/modules/soundcloud/soundcloud.js +++ b/modules/soundcloud/soundcloud.js @@ -8,6 +8,33 @@ var _ = require('underscore')._, var soundcloud = function(dbot) { this.ApiRoot = 'http://api.soundcloud.com'; + this.commands = { + '~soundcloud': function(event) { + var query = event.input[1]; + request.get(this.ApiRoot + '/tracks.json', { + 'qs': { + 'client_id': this.config.client_id, + 'q': query + }, + 'json': true + }, function(error, response, body) { + if(body.length != 0) { + body = body[0]; + event.reply(dbot.t('sc_track', { + 'title': body.title, + 'artist': body.user.username, + 'genre': body.genre.trim(), + 'plays': body.playback_count, + 'favs': body.favoritings_count + }) + ' — ' + body.permalink_url); + } else { + event.reply(dbot.t('sc_notrack')); + } + }); + } + }; + this.commands['~soundcloud'].regex = [/^~soundcloud (.+)$/, 2]; + this.onLoad = function() { dbot.api.link.addHandler(this.name, /https?:\/\/(www\.)?soundcloud\.com\//, diff --git a/modules/soundcloud/strings.json b/modules/soundcloud/strings.json index 59c21d1..a3eb6d4 100644 --- a/modules/soundcloud/strings.json +++ b/modules/soundcloud/strings.json @@ -1,5 +1,8 @@ { "sc_track": { "en": "[{title} by {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]" + }, + "sc_notrack": { + "en": "No results found." } } From 7eeb687385189f55de41aecc51050d972c1e3fbc Mon Sep 17 00:00:00 2001 From: reality Date: Tue, 9 Jul 2013 21:16:41 +0000 Subject: [PATCH 170/220] doh --- modules/soundcloud/soundcloud.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/soundcloud/soundcloud.js b/modules/soundcloud/soundcloud.js index 9308ae5..65a3177 100644 --- a/modules/soundcloud/soundcloud.js +++ b/modules/soundcloud/soundcloud.js @@ -20,6 +20,7 @@ var soundcloud = function(dbot) { }, function(error, response, body) { if(body.length != 0) { body = body[0]; + if(!body.genre) body.genre = ''; event.reply(dbot.t('sc_track', { 'title': body.title, 'artist': body.user.username, @@ -49,6 +50,7 @@ var soundcloud = function(dbot) { }, function(error, response, body) { if(response.statusCode == 200) { if(body.kind == 'track') { + if(!body.genre) body.genre = ''; event.reply(dbot.t('sc_track', { 'title': body.title, 'artist': body.user.username, From 2beb87f86fbcd099537ca002c01249c2ed703aea Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 02:48:35 +0200 Subject: [PATCH 171/220] French translation --- strings.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/strings.json b/strings.json index de06c7f..690e18a 100644 --- a/strings.json +++ b/strings.json @@ -4,13 +4,15 @@ "es": "¿Querías decir: ", "na'vi": "Srake sweylu nga pamrel sivi: ", "cy": "A oeddech chi'n feddwl: ", - "de": "Meintest du: " + "de": "Meintest du: ", + "fr": "Vouliez-vous dire : " }, "module_load_error": { "en": "Failed to load module: {moduleName}", "es": "No se pudó cargar el módulo: {moduleName}", "na'vi": "Oeru Oel {moduleName}it sung.", "cy": "Wedi methu a llwytho modiwl: {moduleName}", - "de": "Konnte {moduleName} nicht laden" + "de": "Konnte {moduleName} nicht laden", + "fr": "Le module {moduleName} n'a pas pu être chargé" } } From c7c5fbb4efb8d017a98587b657dcc6ae4d23abee Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:08:54 +0200 Subject: [PATCH 172/220] French translation --- modules/admin/strings.json | 81 +++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/modules/admin/strings.json b/modules/admin/strings.json index 1c117cf..79f2440 100644 --- a/modules/admin/strings.json +++ b/modules/admin/strings.json @@ -5,7 +5,8 @@ "na'vi": "fpxäkìm {channel}(nemfa)", "cy": "Wedi ymuno {channel}", "nl": "{channel} binnengekomen", - "de": "{channel} beigetreten" + "de": "{channel} beigetreten", + "fr": "{channel} rejoint" }, "part": { "en": "Left {channel}", @@ -13,7 +14,8 @@ "na'vi": "Hum {channel}", "cy": "Wedi gadael {channel}", "nl": "{channel} verlaten", - "de": "{channel} verlassen" + "de": "{channel} verlassen", + "fr": "{channel} quitté" }, "gpull": { "en": "Git pulled that shit.", @@ -21,7 +23,8 @@ "na'vi": "Gìtìl fì'uti stamarsìm.", "cy": "Wedi tynnu git yr cach na i gyd", "nl": "Git heeft die zooi binnengehaald.", - "de": "Git hat es gezogen" + "de": "Git hat es gezogen", + "fr": "Git a pullé cette merde" }, "reload": { "en": "Reloaded that shit.", @@ -29,7 +32,8 @@ "na'vi": "Oel fìuti stìyeftxaw.", "cy": "Ail-lwytho'r cach na", "nl": "Die zooi opnieuw geladen.", - "de": "Neu geladen" + "de": "Neu geladen", + "fr": "Bordel rechargé" }, "load_module": { "en": "Loaded new module: {moduleName}", @@ -37,7 +41,8 @@ "na'vi": "Oel {moduleName}it amip stìyeftxaw.", "cy": "Wedi llwytho modiwl newydd: {moduleName}", "nl": "Nieuwe module geladen: {moduleName}", - "de": "Neues Modul geladen: {moduleName}" + "de": "Neues Modul geladen: {moduleName}", + "fr": "Nouveau module chargé : {moduleName}" }, "unload_module": { "en": "Turned off module: {moduleName}", @@ -45,7 +50,8 @@ "na'vi": "Oel {moduleName} tswìya'.", "cy": "Wedi troi ffwrdd y modiwl: {moduleName}", "nl": "Module uitgeschakeld: {moduleName}", - "de": "Modul ausgeschaltet: {moduleName}" + "de": "Modul ausgeschaltet: {moduleName}", + "fr": "Module déchargé : {moduleName}" }, "unload_error": { "en": "{moduleName} isn't loaded. Idiot.", @@ -53,7 +59,8 @@ "na'vi": "Oel {moduleName}it omum. Nga skxawng lu.", "cy": "Di {moduleName} ddim wedi llwytho. Twpsyn", "nl": "{moduleName} is niet geladen. Idioot.", - "de": "{moduleName} ist nicht geladen, du Idiot." + "de": "{moduleName} ist nicht geladen, du Idiot.", + "fr": "{moduleName} n'est pas chargé. Idiot." }, "banned": { "en": "{user} banned from {command}", @@ -61,7 +68,8 @@ "na'vi": "{command}ìri {user} ke tung.", "cy": "{user} wedi ei gohurio o {command}", "nl": "{user} mag {command} niet meer gebruiken", - "de": "{user} wurde von {command} gebannt" + "de": "{user} wurde von {command} gebannt", + "fr": "{user} a été interdit d'utiliser {command}" }, "unbanned": { "en": "{user} unbanned from {command}", @@ -69,7 +77,8 @@ "na'vi": "{command}ìri {user} tung set.", "cy": "{user} wedi ei dad-wahardd o {command}", "nl": "{user} mag {command} weer gebruiken", - "de": "{user} wurde von {command} entbannt" + "de": "{user} wurde von {command} entbannt", + "fr": "{user} peut de nouveau utiliser {command}" }, "unban_error": { "en": "{user} wasn't banned from that command, fool.", @@ -77,7 +86,8 @@ "na'vi": "{user} fìtsu'oti tamung srekrr, nga skxawng lu.", "cy": "Nid oedd {user} wedi ei wahardd o'r gorchymyn yna, twpsyn", "nl": "{user} mag dat commando sowieso al gebruiken, mafketel.", - "de": "{user} wurde nicht von {command} gebannt, du Trottel" + "de": "{user} wurde nicht von {command} gebannt, du Trottel", + "fr": "{user} n'a pas été interdit d'utiliser cette commande, imbécile." }, "qlock": { "en": "Locked quote category: {category}", @@ -85,90 +95,107 @@ "na'vi": "{category}ìri oel 'upxareti fmoli", "cy": "Categori wedi cloi: {category}", "nl": "Quote categorie vergrendeld: {category}", - "de": "Zitat-Kategorie geschlossen: {category}" + "de": "Zitat-Kategorie geschlossen: {category}", + "fr": "Catégorie de citations verouillée : {category}" }, "already_in_channel": { "en": "I'm already in {channel}", "na'vi": "Oel {channel}it tok li", "cy": "Rydw i eisoes yn {channel}", "nl": "Ik ben al in {channel}", - "de": "Ich bin schon in {channel}" + "de": "Ich bin schon in {channel}", + "fr": "Je suis déjà dans {channel}" }, "not_in_channel": { "en": "I'm not in {channel}", "na'vi": "Oel {channel}it ke tok", "cy": "Rydw i ddim yn {channel}", "nl": "Ik ben niet aanwezig in {channel}", - "de": "Ich bin noch nicht in {channel}" + "de": "Ich bin noch nicht in {channel}", + "fr": "Je ne suis pas dans {channel}" }, "already_loaded_web": { "en": "WHY CAN'T I LOAD ALL THIS WEB? (web already loaded)", "na'vi": "PELUN OEL KE TSUN OMUM FÌWETIT NÌWOTX (wetìri oe omum li)", "cy": "PAM ALLA I DDIM YN LWYTHO POB Y WE? (We eisoes yn lwytho)", "nl": "AL DIT WEB WORDT ME TOCH EEN BEETJE TE VEEL! (web is al geladen)", - "de": "WARUM KANN DAS NICHT GELADEN WERDEN? (bereits geladen)" + "de": "WARUM KANN DAS NICHT GELADEN WERDEN? (bereits geladen)", + "fr": "POURQUOI EST-CE QUE JE PEUX PAS CHARGER TOUT CE WEB? (web déjà chargé)" }, "already_loaded": { "en": "{moduleName} is already loaded.", "na'vi": "Oel omum teri {moduleName}it li.", "cy": "{moduleName} eisoes yn lwytho", "nl": "{moduleName} is al geladen.", - "de": "{moduleName} ist bereits geladen." + "de": "{moduleName} ist bereits geladen.", + "fr": "{moduleName} est déjà chargé." }, "no_version": { "en": "No version information or queried module not loaded.", "cy": "Dim gwybodaeth fersiwn neu modiwl holodd dim yn lwytho", - "de": "Keine Informationen verfügbar oder gewünschtes Modul wurde noch nicht geladen." + "de": "Keine Informationen verfügbar oder gewünschtes Modul wurde noch nicht geladen.", + "fr": "Aucune information de version ou module demandé non chargé." }, "status_good": { "en": "{module} status: Shit looks good", "cy": "{module} statws: Cachu yn edrych yn dda", - "de": "Sieht gut aus" + "de": "Sieht gut aus", + "fr": "Status de {module} : Cette merde tourne bien" }, "status_bad": { "en": "{module} status: Failed to load: {reason}", "cy": "{module} statws: Methu i lwytho: {reason}", - "de": "{module} Status: Konnte nicht geladen werden: {reason}" + "de": "{module} Status: Konnte nicht geladen werden: {reason}", + "fr": "Status de {module} : échec de chargement : {reason}" }, "status_unloaded": { "en": "Either that module wasn't on the roster or shit is totally fucked.", "cy": "Naill ai heb fod modiwl oedd ar y rhestr, neu cachu yn gwbl torrodd", - "de": "Entweder ist das Modul nicht auf der Liste oder die Kacke ist am dampfen" + "de": "Entweder ist das Modul nicht auf der Liste oder die Kacke ist am dampfen", + "fr": "Soit ce module n'est pas sur la liste, soit tout est complètement niqué" }, "load_failed": { "en": "Failed to load {module}. See 'status {module}'.", "cy": "Methu i lwytho {module}. Gwelwch 'status {module}'.", - "de": "Konnte {module} nicht laden. Siehe 'status {module}'." + "de": "Konnte {module} nicht laden. Siehe 'status {module}'.", + "fr:" "Echec du chargement de {module}. Voir 'status {module}'." }, "no_config_key": { "en": "{path} doesn't exist bro", "cy": "{path} cyfluniad yn bodoli, fy mrawd", - "de": "{path} existiert nicht, Bruder" + "de": "{path} existiert nicht, Bruder", + "fr": "{path} n'existe pas, fréro" }, "config_array": { "en": "Config option is an array. Try '{alternate}'.", "cy": "Opsiwn cyfluniad ydy'r amrywiaeth. Rhowch gynnig ar '{alternate}'.", - "de": "Einstellung ist ein Array, probiere '{alternate}' aus." + "de": "Einstellung ist ein Array, probiere '{alternate}' aus.", + "fr": "L'option de configuration est un array. Essaye '{alternate}'." }, "config_lock": { "en": "This config option cannot be altered while the bot is running.", "cy": "Ni all yr opsiwn cyfluniad yn cael ei newid tra bod y bot yn rhedeg.", - "de": "Diese Option kann während der Benutzung des Bots nicht verändert werden" + "de": "Diese Option kann während der Benutzung des Bots nicht verändert werden", + "fr": "Cette option de configuration ne peut pas être changée pendant que le bot est activé." }, "no_config_path": { "en": "Config path doesn't exist bro", "cy": "Nid yw llwybr cyfluniad yn bodoli, fy mrawd", - "de": "Konfigurationspfad nicht vorhanden, Bruder" + "de": "Konfigurationspfad nicht vorhanden, Bruder", + "fr": "Le chemin de configuration n'existe pas, fréro" }, "new_config_key": { - "en": "Warning: Creating new config key: {key}." + "en": "Warning: Creating new config key: {key}.", + "fr": "Attention : création d'une nouvelle clé de configuration : {key}." }, "config_keys_location": { "en": "Config keys in {path}: {value}", "cy": "Allweddi cyfluniad yn {path}: {value}", - "de": "Die Konfiguration in {path}: {value}" + "de": "Die Konfiguration in {path}: {value}", + "fr": "Clés de configuration dans {path}: {value}" }, "modules_saved": { - "en": "Currently loaded modules now default: {modules}" + "en": "Currently loaded modules now default: {modules}", + "fr": "Les modules actuellement chargés sont maintenant chargés par défaut : {modules}" } } From 12a2ae072836f4d628b2e28152e91828a94dfbd6 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:13:34 +0200 Subject: [PATCH 173/220] French translation --- modules/command/strings.json | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/modules/command/strings.json b/modules/command/strings.json index 62738db..d314848 100644 --- a/modules/command/strings.json +++ b/modules/command/strings.json @@ -1,11 +1,12 @@ { "command_ban": { "en": "{user} is banned from using this command. Commence incineration.", - "es": "{user} está prohibido de usar esta instrucción. Comenzar incineración.", + "es": "{user} está prohibido de usar esta instrucción. urrently loaded modules now default: {modules}.", "na'vi": "Tsu'ori {user} ke tung. Nga skxawng lu.", "cy": "Mae {user} wedi ei gohurio gan ddefnyddio'r gorchymun yma. Cychwyn orfflosgiad", "nl": "{user} mag dit commando niet meer gebruiken. Bereid het verbrandingsritueel voor.", - "de": "{user} wurde von diesem Befehl gebannt. Verbrennung einleiten" + "de": "{user} wurde von diesem Befehl gebannt. Verbrennung einleiten", + "fr": "{user} est interdit d'utiliser cette commande. Commencer l'incinération." }, "syntax_error": { "en": "Invalid syntax. Initiate incineration.", @@ -13,46 +14,54 @@ "na'vi": "Ngeyä pamrel keyawr lu. Nga skxawng lu.", "cy": "Cystrawen annilys. Cychwyn orfflosgiad", "nl": "Ongeldige syntax. Bereid het verbrandingsritueel voor.", - "de": "Syntax ungültig. Verbrennung einleiten" + "de": "Syntax ungültig. Verbrennung einleiten", + "fr": "Syntaxe invalide. Initier l'incinération." }, "usage": { "en": "Usage for {command}: {usage}.", "na'vi": "Nga tsun sivar ìlä {command}: {usage}.", "cy": "Defnydd o {command}: {usage}.", "nl": "{command} wordt op de volgende manier gebruikt: {usage}.", - "de": "Benutzung von {command}: [usage}." + "de": "Benutzung von {command}: [usage}.", + "fr": "Utilisation de {command}: {usage}." }, "no_usage_info": { "en": "No usage information found for {command}.", "na'vi": "Oel ke tsun sivar {comamnd}it", "cy": "Ni chanfuwyd gwybodaeth am ddefnydd o {command}", "nl": "Geen gebruiksinformatie gevonden voor {command}.", - "de": "Keine Gebrauchsanweisung gefunden für {command}." + "de": "Keine Gebrauchsanweisung gefunden für {command}.", + "fr": "Aucune information d'utilisation trouvée pour {command}" }, "help_link": { "en": "Help for {module}: {link}", "na'vi": "{module}ä srungìl {link} it tok", "cy": "Cymorth am {module}: {link}", "nl": "Hulp voor {module}: {link}", - "de": "Hilfe für {module}: {link}" + "de": "Hilfe für {module}: {link}", + "fr": "Aide pour {module}: {link}" }, "no_help": { "en": "No help found for {module}.", "na'vi": "Fì{module}ìri oel ke tsun run srungit", "cy": "Ni chanfuwyd cymorth am {module}", "nl": "Geen hulp gevonden voor {module}.", - "de": "Keine Hilfe gefunden für {module}." + "de": "Keine Hilfe gefunden für {module}.", + "fr": "Aucune aide trouvée pour {module}." }, "loaded_modules": { "en": "Loaded modules: {modules}.", "cy": "Modiwlau sy'n lwythodd: {modules}.", "nl": "Geladen modules: {modules}.", - "de": "Module geladen: {modules}." + "de": "Module geladen: {modules}.", + "fr": "Modules chargés: {modules}." }, "access_denied": { - "en": "{user}: You don't have the access level to run this command." + "en": "{user}: You don't have the access level to run this command.", + "fr": "{user}: Vous n'avez pas le niveau d'accès requis pour utiliser cette commande." }, "module_commands": { - "en": "Commands in {module}: {commands}." + "en": "Commands in {module}: {commands}.", + "fr": "Commandes de {module}: {commands}." } } From 5e4199b736f24861e916d42158e1615c59c3b858 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:16:52 +0200 Subject: [PATCH 174/220] French translation --- modules/dns/strings.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/dns/strings.json b/modules/dns/strings.json index e77a224..4a1fe02 100644 --- a/modules/dns/strings.json +++ b/modules/dns/strings.json @@ -3,21 +3,25 @@ "en": "{domain} is \u000303AVAILABLE! \u000314({code})", "cy": "{domain} \u000303AR GAEL! \u000314({code})", "nl": "{domain} is \u000303BESCHIKBAAR! \u000314({code})", - "de": "{domain} ist \u000303VERFÜGBAR! \u000314({code})" + "de": "{domain} ist \u000303VERFÜGBAR! \u000314({code})", + "fr": "{domain} est \u000303DISPONIBLE! \u000314({code})" }, "lookup": { "en": "{domain} is \u000305TAKEN! \u000314({address})", "cy": "Dydy {domain} \u000305DDIM AR GAEL! \u000314({address})", "nl": "{domain} is \u000305BEZET! \u000314({address})", - "de": "{domain} ist \u000305BELEGT! \u000314({address})" + "de": "{domain} ist \u000305BELEGT! \u000314({address})", + "fr": "{domain} est \u000305PRIS! \u000314({address})" }, "rdns": { - "en": "{ip} \u2192 {domain}" + "en": "{ip} \u2192 {domain}", + "fr": "{ip} \u2192 {domain}" }, "rdns-error": { "en": "Unable to lookup {ip}. \u000314({error})", "cy": "Methu am-edrych {ip}. \u000314({error})", "nl": "{ip} kan niet worden opgezocht. \u000314({error})", - "de": "Kann {ip} nicht auflösen. \u000314({error})" + "de": "Kann {ip} nicht auflösen. \u000314({error})", + "fr": "Impossible de rechercher {ip}. \u000314({error})" } } From 2b8f1e4a928778b0588905f602f8575d3990f6dc Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:27:11 +0200 Subject: [PATCH 175/220] French translation --- modules/ignore/strings.json | 60 ++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/modules/ignore/strings.json b/modules/ignore/strings.json index a5763e6..7075a5c 100644 --- a/modules/ignore/strings.json +++ b/modules/ignore/strings.json @@ -5,7 +5,8 @@ "na'vi": "{user}: Sar: ~ignore ['u]. U, nga ke tìng mikyun: {modules}.", "cy": "{user}: Defnydd: ~ignore [modiwl]. Modiwlau a allech anwybyddu yw: {modules}.", "nl": "{user}: Gebruik: ~ignore [module]. Modules die negeert kunnen worden zijn: {modules}.", - "de": "{user}: Benutzung: ~ignore [module]. Module, die ignoriert werden können: {modules}." + "de": "{user}: Benutzung: ~ignore [module]. Module, die ignoriert werden können: {modules}.", + "fr": "{user}: Utilisation: ~ignore [module]. Les modules que vous pouvez ignorer sont: {modules}." }, "already_ignoring": { "en": "{user}: You're already ignoring that module.", @@ -13,7 +14,8 @@ "na'vi": "{user}: 'uri nga ke tìng mikyun srekrr.", "cy": "{user}: Mi rwyt ti'n anwybyddu'r modiwl yna'n barod.", "nl": "{user}: Je negeert deze module al.", - "de": "{user}: Dieses Modul wird bereits ignoriert." + "de": "{user}: Dieses Modul wird bereits ignoriert.", + "fr": "{user}: Vous ignorez déjà ce module." }, "ignored": { "en": "{user}: Now ignoring {module}.", @@ -21,7 +23,8 @@ "na'vi": "{user}: Nga ke terìng mikyun {module}ne set.", "cy": "{user}: Nawr yn anwybyddu {module}", "nl": "{user}: {module} wordt nu genegeerd.", - "de": "{user}: {module} wird nun ignoriert." + "de": "{user}: {module} wird nun ignoriert.", + "fr": "{user}: {module} désormais ignoré." }, "invalid_ignore": { "en": "{user}: That isn't a valid module name.", @@ -29,7 +32,8 @@ "na'vi": "{user}: Tsatstxo eyawr ke lu.", "cy": "{user}: Nid oedd hwna'n modiwl dilys", "nl": "{user}: Dat is geen geldige modulenaam.", - "de": "{user}: Dies ist nicht der Name eines Moduls." + "de": "{user}: Dies ist nicht der Name eines Moduls.", + "fr": "{user}: Ceci ne correspond pas à un nom de module valide." }, "unignore_usage": { "en": "{user}: Usage: ~unignore [module]. Modules you are currently ignoring: {modules}.", @@ -37,7 +41,8 @@ "na'vi": "{user}: Sar: ~unignore ['u]. Uri, nga ke terìng mikyun: {modules}.", "cy": "{user}: Defnydd: ~unignore [modiwl]. Modiwlau rydech yn anwybyddu ar hyn o bryd: {modules}", "nl": "{user}: Gebruik: ~unignore [module]. Modules die momenteel worden genegeerd: {modules}.", - "de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ignoriert werden: {modules}." + "de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ignoriert werden: {modules}.", + "fr": "{user}: Utilisation: ~unignore [module]. Modules que vous ignorez actuellement: {modules}." }, "empty_unignore_usage": { "en": "{user}: Usage: ~unignore [module].", @@ -45,7 +50,8 @@ "na'vi": "{user}: Sar: ~unignore ['u].", "cy": "{user}: Defnydd: ~unignore [modiwl].", "nl": "{user}: Gebruik: ~unignore [module].", - "de": "{user}: Benutzung: ~unignore [module]." + "de": "{user}: Benutzung: ~unignore [module].", + "fr": "{user}: Utilisation: ~unignore [module]." }, "invalid_unignore": { "en": "{user}: You're not ignoring that module or it doesn't exist.", @@ -53,7 +59,8 @@ "na'vi":"{user}: Nga terìng mikyun fu fì'ul fìtsengit ke tok.", "cy": "{user}: Nid wyt ti'n anwybyddu'r modiwl yna neu nid yw e'n bodoli", "nl": "{user}: Deze module bestaat niet of wordt niet genegeerd.", - "de": "{user}: Dieses Modul wird entweder nicht ignoriert oder existiert nicht." + "de": "{user}: Dieses Modul wird entweder nicht ignoriert oder existiert nicht.", + "fr": "{user}: Vous n'ignorez pas ce module ou il n'existe pas." }, "unignored": { "en": "{user}: No longer ignoring {module}.", @@ -61,83 +68,96 @@ "na'vi": "{user}: Nga terìng mikyun {module}ne set", "cy": "{user}: Ddim yn anwybyddu {module} bellach", "nl": "{user}: {module} wordt niet langer genegeerd.", - "de": "{user}: {module} wird nicht länger ignoriert." + "de": "{user}: {module} wird nicht länger ignoriert.", + "fr": "{user}: {module} n'est plus ignoré à présent." }, "ban_usage": { "en": "{user}: Usage: ~ban [user] [module/command]. Use * for all modules and commands.", "cy": "{user}: Defnydd: ~ban [defnyddiwr] [modiwl/gorchymyn]. Defnyddio * am pob modiwlau a gorchmynion.", "nl": "{user}: Gebruik: ~ban [gebruiker] [module/commando]. Gebruik * voor alle modules en alle commandos.", - "de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle." + "de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle.", + "fr": "{user}: Utilisation: ~ban [user] [module/command]. Utilisez * pour tous les modules et commandes." }, "already_banned": { "en": "{user}: {banned} is already banned from that module.", "cy": "{user}: {banned} eisoes wedi ei wahardd o'r modiwl.", "nl": "{user}: {banned} is al geband van deze module.", - "de": "{user}: {banned} ist bereits von diesem Modul gebannt." + "de": "{user}: {banned} ist bereits von diesem Modul gebannt.", + "fr": "{user}: {banned} est déjà interdit d'utiliser ce module." }, "banned_success": { "en": "{user}: {banned} is now banned from {module}.", "cy": "{user}: {banned} ei wahardd yn awr am {module}.", "nl": "{user}: {banned} mag {module} nu niet meer gebruiken.", - "de": "{user}: {banned} ist nun von {module} gebannt." + "de": "{user}: {banned} ist nun von {module} gebannt.", + "fr": "{user}: {banned} est maintenant interdit d'utiliser {module}." }, "invalid_ban": { "en": "{user}: That isn't a valid module name.", "cy": "{user}: Nid oedd hwna'n modiwl dilys", "nl": "{user}: Dat is geen geldige modulenaam.", - "de": "{user}: Dies ist nicht der Name eines Moduls." + "de": "{user}: Dies ist nicht der Name eines Moduls.", + "fr": "{user}: Ceci n'est pas un nom de module valide." }, "unban_usage": { "en": "{user}: Usage: ~unban [user] [module].", "cy": "{user}: Defnydd: ~unban [defnyddiwr] [modiwl].", "nl": "{user}: Gebruik: ~unban [gebruiker] [module].", - "de": "{user}: Benutzung: ~unban [Benutzer] [module]." + "de": "{user}: Benutzung: ~unban [Benutzer] [module].", + "fr": "{user}: Utilisation: ~unban [user] [module]." }, "invalid_unban": { "en": "{user}: {banned} is not banned from that module or it doesn't exist.", "cy": "{user}: Nid oedd {banned} wedi ei wahardd o'r modiwl, neu nid yw'n bodoli.", "nl": "{user}: {banned} is niet geband van die module of de module bestaat niet.", - "de": "{user}: {banned} ist von diesem Modul nicht gebannt, oder es existiert nicht." + "de": "{user}: {banned} ist von diesem Modul nicht gebannt, oder es existiert nicht.", + "fr": "{user}: {banned} n'est pas interdit d'utiliser ce module, ou il n'existe pas." }, "unbanned_success": { "en": "{user}: {banned} is no longer banned from {module}.", "cy": "{user}: Nid yw {banned} yn cael ei wahardd mwyach.", "nl": "{user}: {banned} mag {module} weer gebruiken.", - "de": "{user}: {banned} wurde von {module} entbannt." + "de": "{user}: {banned} wurde von {module} entbannt.", + "fr": "{user}: {banned} n'est plus interdit d'utiliser {module}." }, "ignoring_channel": { "en": "Now ignoring {module} in {channel}.", "na'vi": "Oe ke stayawm {module}ur mì {channel}", "cy": "Bellach yn anwybyddu {module} yn {channel}.", "nl": "{module} wordt nu genegeerd in {channel}.", - "de": "{module} in [channel} wird nun ignoriert." + "de": "{module} in {channel} wird nun ignoriert.", + "fr": "{module} dans {channel} maintenant ignoré." }, "already_ignoring_channel": { "en": "Already ignoring {module} in {channel}.", "na'vi": "Oe ke stayawm {module}ur mì {channel} li", "cy": "Eisoes anwybyddu {module} yn {channel}", "nl": "{module} wordt al genegeerd in {channel}.", - "de": "{module} in {channel} wird bereits ignoriert." + "de": "{module} in {channel} wird bereits ignoriert.", + "fr": "{module} dans {channel} déjà ignoré." }, "module_not_exist": { "en": "{module} isn't loaded or doesn't exist.", "na'vi": "Oel ke omum teri {module}it fu {module} ke fkeytok", "cy": "Dydy {module} ddim yn lwythodd, neu ddim yn bodoli.", "nl": "{module} is niet geladen of bestaat niet.", - "de": "{module} ist nicht geladen oder existiert nicht." + "de": "{module} ist nicht geladen oder existiert nicht.", + "fr": "{module} n'est pas chargé ou n'existe pas." }, "unignoring_channel": { "en": "No longer ignoring {module} in {channel}.", "na'vi": "Oel stayawm {module}ur mì {channel} set.", "cy": "Nid anwybyddu {module} yn {channel} mwyach.", "nl": "{module} wordt niet meer genegeerd in {channel}.", - "de": "{module} in {channel} wird nicht länger ignoriert." + "de": "{module} in {channel} wird nicht länger ignoriert.", + "fr": "{module} dans {channel} n'est plus ignoré à présent." }, "not_ignoring_channel": { "en": "{module} wasn't being ignored in {channel}.", "na'vi": "Oel stayawm {module}ur mì {channel} li.", "cy": "Nid yw {module} yn cael ei anwybyddu yn {channel}.", "nl": "{module} werd niet genegeerd in {channel}.", - "de": "{module} wurde in {channel} nicht ignoriert." + "de": "{module} wurde in {channel} nicht ignoriert.", + "fr": "{module} n'était pas ignoré dans {channel}." } } From e29927b478dc8eb1e4ca141ffa1a025594156e7a Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:29:02 +0200 Subject: [PATCH 176/220] French translation --- modules/imgur/strings.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/imgur/strings.json b/modules/imgur/strings.json index 91351f5..cb20fd9 100644 --- a/modules/imgur/strings.json +++ b/modules/imgur/strings.json @@ -4,9 +4,11 @@ "na'vi": "kxawm ke wivìntxu evengur", "cy": "Gallai fod yn anniogel ar gwaith", "nl": "bevat mogelijk gevoelige beelden", - "de": "Könnte 18+ Material enthalten" + "de": "Könnte 18+ Material enthalten", + "fr": "peut être risqué pour le travail (NSFW)" }, "imgurinfo": { - "en": "[{info}]" + "en": "[{info}]", + "fr": "[{info}]" } } From 09dbe7466294a013a9bdad8e9b8f318780c2ed0f Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:46:15 +0200 Subject: [PATCH 177/220] French translation --- modules/kick/strings.json | 51 ++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/modules/kick/strings.json b/modules/kick/strings.json index e81cceb..c7ac7c6 100644 --- a/modules/kick/strings.json +++ b/modules/kick/strings.json @@ -5,16 +5,20 @@ "na'vi": "Tuteol {user}it tsrame'i {kicks} hìmtxan ulte sute tsrame'i {kicked} hìmtxan.", "cy": "Cafwyd {user} ei gicio {kicks} gwaith ac wedi cicio pobl {kicked} gwaith.", "nl": "{user} is {kicks} keer gekickt en heeft anderen {kicked} keer gekickt.", - "de": "{user} wurde {kicks} mal gekickt und hat {kicked} mal andere Benutzer gekickt." + "de": "{user} wurde {kicks} mal gekickt und hat {kicked} mal andere Benutzer gekickt.", + "fr": "{user} a été kické {kicks} fois et a kické des personnes {kicked} fois." }, "quieted": { - "en": "Quieted {quietee}. Remember: don't be a coconut." + "en": "Quieted {quietee}. Remember: don't be a coconut.", + "fr": "{quietee} a été rendu silencieux. Rappelle-toi : ne sois pas têtu." }, "tquieted": { - "en": "Quieted {quietee} for {minutes} minutes. Remember: don't be a coconut." + "en": "Quieted {quietee} for {minutes} minutes. Remember: don't be a coconut.", + "fr": "{quietee} a été rendu silencieux pour {minutes} minutes. Rappelle-toi : ne sois pas têtu." }, "unquieted": { - "en": "Unquieted {quietee}. Remember: don't be a coconut." + "en": "Unquieted {quietee}. Remember: don't be a coconut.", + "fr": "{quietee} peut maintenant parler. Rappelle-toi : ne sois pas têtu." }, "kicked_dbot": { "en": "Thou shalt not kick {botname}", @@ -22,52 +26,65 @@ "na'vi": "Ngal {botname}it ke tsun tsrive'i", "cy": "Ni ddylech cicio {botname}", "nl": "Gij zult {botname} niet kicken", - "de": "Du sollst {botname} nicht kicken" + "de": "Du sollst {botname} nicht kicken", + "fr": "Tu ne kickeras pas {botname}" }, "ckicked": { "en": "Attention: {kicker} has kicked {kickee} from {channel}. The reason given was: \"{reason}.\"", "cy": "Sylw: {kicker} wedi cicio'r {kickee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}.\"", - "de": "Achtung: {kicker} hat {kickee} von {channel} verwiesen. Grund: \"{reason}.\"" + "de": "Achtung: {kicker} hat {kickee} von {channel} verwiesen. Grund: \"{reason}.\"", + "fr": "Attention : {kicker} a kické {kickee} de {channel}. Raison donnée : \"{reason}.\"" }, "cbanned": { "en": "Attention: {banner} has banned {banee} from {channel}. The reason given was \"{reason}.\"", "cy": "Sylw: {banner} wedi gwahardd {banee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}.\"", - "de": "Achtung: {banner} hat {banee} von {channel} gebannt. Grund: \"{reason}.\"" + "de": "Achtung: {banner} hat {banee} von {channel} gebannt. Grund: \"{reason}.\"", + "fr": "Attention : {banner} a banni {banee} de {channel}. Raison donnée : \"{reason}.\"" }, "tbanned": { - "en": "Attention: {banner} has banned {banee} from the {network} network for {hours} hours. The reason given was \"{reason}.\"" + "en": "Attention: {banner} has banned {banee} from the {network} network for {hours} hours. The reason given was \"{reason}.\"", + "fr": "Attention : {banner} a banni {banee} du réseau {network} pour {hours} heures. Raison donnée : \"{reason}.\"" }, "tbanned_notify": { - "en": "You have been banned from the {network} network for {hours} hours by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban." + "en": "You have been banned from the {network} network for {hours} hours by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban.", + "fr": "Vous avez été banni du réseau {network} pour {hours} heures par {banner}. La raison donnée était \"{reason}.\" Vous pouvez rejoindre {admin_channel} pour plus d'information or pour discuter du ban." }, "nbanned": { "en": "Attention: {banner} has banned {banee} from the {network} network. The reason given was \"{reason}.\"", "cy": "Sylw: {banner} wedi gwahardd {banee} ledled y rhwydwaith. Y rheswm a roddwyd oedd: \"{reason}.\"", - "de": "Achtung: {banner} hat {banee} auf dem gesamten Netzwerk gebannt. Grund: \"{reason}.\"" + "de": "Achtung: {banner} hat {banee} auf dem gesamten Netzwerk gebannt. Grund: \"{reason}.\"", + "fr": "Attention : {banner} a banni {banee} du réseau {network}. Raison donnée : \"{reason}.\"" }, "nbanned_notify": { - "en": "You have been banned from the {network} network by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban." + "en": "You have been banned from the {network} network by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban.", + "fr": "Vous avez été banni du réseau {network} par {banner}. La raison donnée était \"{reason}.\" Vous pouvez rejoindre {admin_channel} pour plus d'information or pour discuter du ban." }, "nban_quote": { "en": "{banee} was banned from the network by {banner} on {time}. The reason given was \"{reason}.\"", "cy": "Cafodd {banee} ei wahardd o'r rhwydwaith gan {banner} ar {time}. Y rheswm a roddwyd oedd: \"{reason}.\"", - "de": "{banee} wurde von {banner} auf dem gesamten Netzwerk um {time} gebannt. Grund: \"{reason}.\"" + "de": "{banee} wurde von {banner} auf dem gesamten Netzwerk um {time} gebannt. Grund: \"{reason}.\"", + "fr": "{banee} a été banni du réseau par {banner} à {time}. Raison donnée : \"{reason}.\"" }, "no_user": { - "en": "{user} doesn't seem to be online on this server." + "en": "{user} doesn't seem to be online on this server.", + "fr": "{user} ne semble pas être connecté à ce serveur." }, "nunbanned": { - "en": "Attention: {unbanee} has been unbanned from the {network} network by {unbanner}." + "en": "Attention: {unbanee} has been unbanned from the {network} network by {unbanner}.", + "fr": "Attention : {unbanee} a été débanni du réseau {network} par {unbanner}." }, "nunban_notify": { - "en": "You have been unbanned from the {network} network by {unbanner}." + "en": "You have been unbanned from the {network} network by {unbanner}.", + "fr": "Vous avez été débanni du réseau {network} par {unbanner}." }, "nunban_error": { - "en": "It appears {unbanee} was not banned using the ~nban command." + "en": "It appears {unbanee} was not banned using the ~nban command.", + "fr": "Il semble que {unbanee} n'a pas été banni en utilisant la commande ~nban." }, "quote_recorded": { "en": "This has been recorded in ~ban_{user}.", "cy": "Mae hyn wedi cael ei gofnodi yn ~ban_{user}.", - "de": "Dies wurde in ~ban_{user} aufgenommen." + "de": "Dies wurde in ~ban_{user} aufgenommen.", + "fr": "Cela a été enregistré dans ~ban_{user}." } } From 55c48bf8b006d10336509e91f9de6b83a2eb3d31 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:48:07 +0200 Subject: [PATCH 178/220] French translation --- modules/link/strings.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/link/strings.json b/modules/link/strings.json index 71fb71d..82f31d0 100644 --- a/modules/link/strings.json +++ b/modules/link/strings.json @@ -4,19 +4,23 @@ "na'vi": "Oel ke tsun run 'upxare atxin.", "cy": "Ni chanfuwyd teitl y dudalen", "nl": "Er is geen paginatitel gevonden.", - "de": "Kein Seitenname gefunden." + "de": "Kein Seitenname gefunden.", + "fr": "Aucun titre de page trouvé." }, "xkcd": { - "en": "xkcd {num}: {title} https://xkcd.com/{num}" + "en": "xkcd {num}: {title} https://xkcd.com/{num}", + "fr": "xkcd {num}: {title} https://xkcd.com/{num}" }, "no-hits": { "en": "No hits.", "na'vi": "Oel ke tsun rivum ayuoti.", "cy": "Dim canlyniadau.", "nl": "Geen resultaten.", - "de": "Keine Treffer." + "de": "Keine Treffer.", + "fr": "Aucun résultat." }, "link": { - "en": "{link}" + "en": "{link}", + "fr": "{link}" } } From 86ff430169afa62d1217147ea93cb8bb21c5e382 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:48:52 +0200 Subject: [PATCH 179/220] French translation --- modules/log/strings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/log/strings.json b/modules/log/strings.json index c25d7a8..5915ddd 100644 --- a/modules/log/strings.json +++ b/modules/log/strings.json @@ -1,5 +1,6 @@ { "log_message": { - "en": "[{time}] {user}: {command}" + "en": "[{time}] {user}: {command}", + "fr": "[{time}] {user}: {command}" } } From 02164ab2a74878162f044df646dee9ebb6494474 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:51:01 +0200 Subject: [PATCH 180/220] French translation --- modules/nickserv/strings.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/nickserv/strings.json b/modules/nickserv/strings.json index 90e72c4..8030707 100644 --- a/modules/nickserv/strings.json +++ b/modules/nickserv/strings.json @@ -1,14 +1,18 @@ { "authed": { - "en": "{nick} is authed with nickserv." + "en": "{nick} is authed with nickserv.", + "fr": "{nick} est authentifié avec nickserv." }, "not_authed": { - "en": "{nick} is not authed with nickserv." + "en": "{nick} is not authed with nickserv.", + "fr": "{nick} n'est pas authentifié avec nickserv." }, "hostmask": { - "en": "Hostmask for {nick}: {host}" + "en": "Hostmask for {nick}: {host}", + "fr": "Hostmask pour {nick}: {host}" }, "no_hostmask": { - "en": "No hostmask could be found for {nick}" + "en": "No hostmask could be found for {nick}", + "fr": "Aucun hostmask trouvé pour {nick}" } } From 15113ee2b184b4632d9dad5994689db59fcb675e Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 03:59:30 +0200 Subject: [PATCH 181/220] French translation --- modules/poll/strings.json | 45 ++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/modules/poll/strings.json b/modules/poll/strings.json index 497d48c..4aef150 100644 --- a/modules/poll/strings.json +++ b/modules/poll/strings.json @@ -5,7 +5,8 @@ "na'vi": "Usage: ~newpoll tstxo [sìftxey=tìfxey1,tìfxey2,fìfxey3] tìsla'tsu", "cy": "Defnydd: ~newpoll enw [optiynau=opt1,opt2,op3] disgrifiad", "nl": "Gebruik: ~newpoll name [options=opt1,opt2,opt3] description", - "de": "Benutzung: ~newpoll name [options=opt1,opt2,opt3] Beschreibung" + "de": "Benutzung: ~newpoll name [options=opt1,opt2,opt3] Beschreibung", + "fr": "Utilisation: ~newpoll nom [options=opt1,opt2,opt3] description" }, "poll_exists": { "en": "Poll '{name}' already exists.", @@ -13,17 +14,20 @@ "na'vi": "sìpawm sna'o '{name}' fkeytok srekrr.", "cy": "Mae'r pôl {name} bodoli'n barod", "nl": "Poll '{name}' bestaat al.", - "de": "Umfrage '{name}' existiert bereits." + "de": "Umfrage '{name}' existiert bereits.", + "fr": "Le sondage '{name}' existe déjà." }, "poll_created": { "en": "Poll '{name}' created ({description}). Cast thy votations! - {url}", "es" : "Votación '{name}' creado ({description}). ¡Emited sus votas! - {url}", "na'vi": "sìpawm sna'o '{name}' ngìyop ({description}). Nga tìpe'unit Pe'eiun - {url}", "nl": "Poll '{name}' aangemaakt ({description}). Laat uw stem horen! - {url}", - "de": "Umfrage '{name}' gestartet ({description}). Lasst Antworten ertönen! - {url}" + "de": "Umfrage '{name}' gestartet ({description}). Lasst Antworten ertönen! - {url}", + "fr": "Sondage '{name}' créé ({description}). Tous aux ballots de vote ! - {url}" }, "poll_describe": { - "en": "{name}: {description} - {url}." + "en": "{name}: {description} - {url}.", + "fr": "{name}: {description} - {url}." }, "changed_vote": { "en": "{user} changed their vote in {poll} to '{vote}' ({count}).", @@ -31,7 +35,8 @@ "na'vi": "{user} lìyatem ngeyä tìpe'un {poll}mì, ngeyä tìpe'un amip '{vote}'({count}) lu.", "cy": "Newidiodd {user} eu pleidlais yn {poll} i '{vote}' ({count}).", "nl": "{user} heeft zijn stem voor {poll} veranderd in '{vote}' ({count}).", - "de": "{user} hat seine Antwort in {poll} zu '{vote}' geändert ({count})." + "de": "{user} hat seine Antwort in {poll} zu '{vote}' geändert ({count}).", + "fr": "{user} a changé son vote dans {sondage} pour '{vote}' ({count})." }, "voted": { "en": "{user} voted for '{vote}' in {poll} ({count}).", @@ -39,7 +44,8 @@ "na'vi": "'{vote}'ìri {user} pìye'un {poll}mì ({count}).", "cy": "Pledleisiodd {user} am '{vote}' yn {poll} ({count}).", "nl": "{user} heeft gestemd voor '{vote}' in {poll} ({count}).", - "de": "{user} hat für '{vote}' in {poll} gestimmt ({count})." + "de": "{user} hat für '{vote}' in {poll} gestimmt ({count}).", + "fr":"{user} a voté pour '{vote}' dans {poll} ({count})." }, "invalid_vote": { "en": "Invalid vote: {vote}", @@ -47,7 +53,8 @@ "na'vi": "Ngeyä tìpe'un keyawr lu ({vote}).", "cy": "Pleidlais annilys: {vote}", "nl": "Ongeldige stem: {vote}", - "de": "Ungültige Antwort: {vote}" + "de": "Ungültige Antwort: {vote}", + "fr": "Vote invalide: {vote}" }, "poll_unexistent": { "en": "Poll '{name}' doesn't exist.", @@ -55,7 +62,8 @@ "na'vi": "sìpawm sna'o '{name}' ke fkeytok.", "cy": "Nid yw pôl '{name}' yn bodoli", "nl": "Poll '{name}' bestaat niet.", - "de": "Umfrage '{name}' existiert nicht." + "de": "Umfrage '{name}' existiert nicht.", + "fr": "Le sondage '{name}' n'existe pas." }, "option_added": { "en": "{user}: '{option}' added to '{name}'.", @@ -63,7 +71,8 @@ "na'vi": "'{name}'ur {user}ìl '{option}'it sung.", "cy": "{user}: Ychwanegwyd '{option}' i '{name}'", "nl": "{user}: '{option}' toegevoegd aan '{name}'.", - "de": "{user}: '{option}'in '{name}' hinzugefügt." + "de": "{user}: '{option}'in '{name}' hinzugefügt.", + "fr": "{user}: '{option}' ajouté à '{name}'." }, "option_exists": { "en": "{user}: '{option}' already exists in '{name}'.", @@ -71,7 +80,8 @@ "na'vi": "{user}: '{option}' fkeytok srekrr '{name}'mì.", "cy": "{user}: Mae '{option}' yn bodoli'n barod yn '{name}'.", "nl": "{user}: '{option}' bestaat al in '{name}'.", - "de": "{user}: '{option}' existiert bereits in '{name}'." + "de": "{user}: '{option}' existiert bereits in '{name}'.", + "fr": "{user}: '{option} existe déjà dans '{name}'." }, "not_poll_owner": { "en": "{user}: You don't own the '{name}' poll.", @@ -79,7 +89,8 @@ "na'vi": "{user}: ngaru '{name}' sìpawm sna'o ke lu.", "cy": "{user}: Nid ydech chi'n berchen y pôl '{name}'.", "nl": "{user}: Je bent niet de eigenaar van de poll '{name}'.", - "de": "{user}: Du darfst die Umfrage '{name}' nicht verändern." + "de": "{user}: Du darfst die Umfrage '{name}' nicht verändern.", + "fr": "{user}: Le sondage '{name}' ne t'appartient pas." }, "option_removed": { "en": "{user}: '{option}' removed from '{name}'", @@ -87,7 +98,8 @@ "na'vi": "{user}: '{option}'it 'aku '{name}'ta", "cy": "{user}: '{option}' wedi ei ddileu o '{name}'", "nl": "{user}: '{option}' verwijderd van '{name}'", - "de": "{user}: '{option}' entfernt aus '{name}'" + "de": "{user}: '{option}' entfernt aus '{name}'", + "fr": "{user}: '{option}' enlevé de '{name}'" }, "av_voted": { "en": "{user} voted '{vote}' in {poll}.", @@ -95,7 +107,8 @@ "na'vi": "{user}ìl '{vote}'it pìye'un '{poll}'mì.", "cy": "Pledleisiodd {user} am '{vote}' yn {poll}", "nl": "{user} heeft '{vote}' gestemd in {poll}.", - "de": "{user} hat in {poll} für '{vote}' gestimmt." + "de": "{user} hat in {poll} für '{vote}' gestimmt.", + "fr": "{user} a voté '{vote}' dans {poll}." }, "av_changed_vote": { "en": "{user} changed their vote in {poll} to '{vote}'.", @@ -103,13 +116,15 @@ "na'vi": "{user}ìl lìyatem ngeyä tìpa'unit '{poll}'mì, ngeyä tìpe'un '{vote} lu set.", "cy": "Newidiodd {user} eu pleidlais yn {poll} i '{vote}'", "nl": "{user} heeft zijn stem veranderd naar '{vote}' in {poll}.", - "de": "{user} hat seine Stimme in {poll} auf '{vote}' geändert." + "de": "{user} hat seine Stimme in {poll} auf '{vote}' geändert.", + "fr": "{user} a changé son vote dans {sondage} pour '{vote}'." }, "count": { "en": "The running-order of poll '{poll}' ({description}) is: {places}.", "na'vi": "Sute tsnì pole'un '{poll}'mì ({description}) lu: {places}.", "cy": "Trefn yr pôl '{poll}' ({description}) yw: {places}", "nl": "De volgorde van poll '{poll}' ({description}) is: {places}.", - "de": "Das Ergebnis der Umfrage '{poll}' ({description}) lautet: {places}." + "de": "Das Ergebnis der Umfrage '{poll}' ({description}) lautet: {places}.", + "fr": "L'ordre de passage du sondage '{poll}' ({description}) est : {places}." } } From 97a35bb43be69d6d7419cd00aecb9adafedebf47 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:08:26 +0200 Subject: [PATCH 182/220] French translation --- modules/project/strings.json | 44 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/modules/project/strings.json b/modules/project/strings.json index c5fd9a3..6601db9 100644 --- a/modules/project/strings.json +++ b/modules/project/strings.json @@ -5,7 +5,7 @@ "fr": "{name} parle {lang} ({langen})", "it": "{name} parla {lang} ({langen})", "cy": "{name} yn siarad {lang} ({langen})", - "nl": "{name} spreekt {lang} ({langen})" + "nl": "{name} spreekt {lang} ({langen})", }, "thanks": { "en": "With thanks to:", @@ -36,7 +36,7 @@ }, "fr": { "en": "French", - "fr": "français", + "fr": "Français", "de": "Französisch", "it": "francese", "cy": "Ffrangeg", @@ -44,7 +44,7 @@ }, "de": { "en": "German", - "fr": "allemande", + "fr": "allemand", "de": "Deutsch", "it": "tedesco", "cy": "Almaeneg", @@ -77,7 +77,7 @@ }, "es": { "en": "Spanish", - "fr": "espagnole", + "fr": "espagnol", "de": "Spanisch", "it": "spagnolo", "cy": "Sbaeneg", @@ -91,7 +91,7 @@ }, "revnum": { "en": "{name} is at revision {rev}", - "fr": "{name} est à révision {rev}", + "fr": "{name} est à la révision {rev}", "de": "{name} ist in der Revision {rev}", "it": "{name} il numero di revisione {rev}", "cy": "{name} ar diwygiad {rev}", @@ -115,7 +115,7 @@ }, "debugmode-true": { "en": "Debug mode active", - "fr": "debug actif", + "fr": "Mode de débogage activé", "de": "Debug-Modus aktiviert", "it": "debug attivo", "cy": "Modd dadfygio gweithredol", @@ -123,7 +123,7 @@ }, "debugmode-false": { "en": "Debug off", - "fr": "debug éteint", + "fr": "Mode de débogage arrêté", "de": "Debug-Modus ausgeschaltet", "it": "debug spento", "cy": "Modd dadfygio wedi'i ddiffodd", @@ -131,7 +131,7 @@ }, "milestones": { "en": "Milestones", - "fr": "étapes", + "fr": "Etapes", "cy": "Cerrig milltir", "de": "Zwischenziel" }, @@ -177,27 +177,33 @@ }, "dent-account": { "en": "Submitting dents to @{username}", - "cy": "Cyflwyno 'dents' i'w @{username}" + "cy": "Cyflwyno 'dents' i'w @{username}", + "fr": "Envoi de 'dents' à @{username}" }, "dent-push": { "en": "Pushing quotes to identi.ca", - "cy": "Gwthio dyfyniadau i identi.ca" + "cy": "Gwthio dyfyniadau i identi.ca", + "fr": "Envoi des citations vers identi.ca" }, "quote-rmlimit": { "en": "Quote removal throttle set to {limit}", - "cy": "Trothwy ar dileu dyfyniadau gosod i {limit}" + "cy": "Trothwy ar dileu dyfyniadau gosod i {limit}", + "fr": "Commande d'enlèvement de citations réglée à {limit}" }, "report-notifyvoice": { "en": "Voiced users are being notified of reports", - "cy": "Defnyddwyr leisiwyd yn cael eu hysbysu o adroddiadau" + "cy": "Defnyddwyr leisiwyd yn cael eu hysbysu o adroddiadau", + "fr": "Les utilisateurs ayant la parole sont notifiés des rapports" }, "web-port": { "en": "Web is listening on {port}", - "cy": "We yn gwrando ar {port}" + "cy": "We yn gwrando ar {port}", + "fr": "Le web écoute sur {port} }, "propaganda": { "en": "Contribute to the code on Github!", - "cy": "Cyfrannu at ay cod ar Github!" + "cy": "Cyfrannu at ay cod ar Github!", + "fr": "Contribuez au code sur GitHub!" }, "branch": { "en": "{branch}" @@ -206,7 +212,7 @@ "en": "version control", "de": "Versionsverwaltung", "es": "Control de versiones", - "fr": "Festion de versions", + "fr": "Gestion de versions", "it": "Controllo versione", "cy": "Rheoli fersiwn", "nl": "Versiebeheersysteem" @@ -230,7 +236,7 @@ }, "langhead-progress": { "en": "Translation Progress", - "fr": "Avancement de la Traduction", + "fr": "Avancement de la traduction", "cy": "Cynnydd Cyfieithu", "de": "Übersetzungsfortschritt" }, @@ -241,13 +247,15 @@ }, "outstanding-pullreq": { "en": "There are outstanding pull requests", - "cy": "Mae disgwyl ceisiadau tynnu" + "cy": "Mae disgwyl ceisiadau tynnu", + "fr": "Il a des requêtes pull en attente" }, "oaosidl": { "en": "The Official Aberystwyth Open Source International Development League" }, "link-autotitle": { "en": "Automatically titling links in channels", - "cy": "Teitlo awtomatig cysylltiadau mewn sianelau" + "cy": "Teitlo awtomatig cysylltiadau mewn sianelau", + "fr": "Titre automatiquement les liens dans les channels" } } From f753e6cb83d2d11d4784129d0bc75f58e7e009d4 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:18:49 +0200 Subject: [PATCH 183/220] French translation --- modules/quotes/strings.json | 78 ++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/modules/quotes/strings.json b/modules/quotes/strings.json index 46ecb31..816afef 100644 --- a/modules/quotes/strings.json +++ b/modules/quotes/strings.json @@ -5,7 +5,8 @@ "na'vi": "{category} yawne ke lu kawturu.", "cy": "Does neb yn caru {category}", "nl": "Niemand houdt van {category}", - "de": "Niemand hat {category} gerne" + "de": "Niemand hat {category} gerne", + "fr": "Personne n'aime {category}" }, "large_categories": { "en": "Largest categories: ", @@ -13,7 +14,8 @@ "na'vi": "U atsawl: ", "cy": "Categoriau mwyaf: ", "nl": "Grootste categoriën: ", - "de": "Größte Kategorien: " + "de": "Größte Kategorien: ", + "fr": "Les plus grandes catégories :" }, "empty_category": { "en": "That category has no quotes in. Commence incineration.", @@ -21,7 +23,8 @@ "na'vi": "Tsauru upxare lu. Nga skxawng lu.", "cy": "Nid yw'r categori yna efo dyfyniadau. Cychwyn orfflosgiad", "nl": "Die categorie heeft geen quotes. Bereid het verbrandingsritueel voor.", - "de": "In dieser Kategorie befinden sich keine Zitate. Verbennung einleiten." + "de": "In dieser Kategorie befinden sich keine Zitate. Verbennung einleiten.", + "fr": "Cette catégorie ne contient aucune citation. Commencer l'incinération." }, "no_results": { "en": "No results found.", @@ -29,7 +32,8 @@ "na'vi": "Oel kea humit rìmun", "cy": "Dim canlyniadau ar gael", "nl": "Geen resultaten gevonden.", - "de": "Keine Ergebnisse gefunden." + "de": "Keine Ergebnisse gefunden.", + "fr": "Aucun résultat trouvé." }, "locked_category": { "en": "{category} is locked. Commence incineration.", @@ -37,7 +41,8 @@ "na'vi": "{category} ke fkeytok set. Nga skxawng lu nafì'u", "cy": "Mae {category} wedi cloi. Cychwyn orfflosgiad", "nl": "{category} is op slot. Bereid het verbrandingsritueel voor.", - "de": "{category} ist geschlossen. Verbrennung einleiten." + "de": "{category} ist geschlossen. Verbrennung einleiten.", + "fr": "{category} est verrouillé(e). Commencer l'incinération." }, "no_quotes": { "en": "No quotes exist under {category}", @@ -45,7 +50,8 @@ "na'vi": "Kea upxare fkeytok {category}mì", "cy": "Does dim dyfyniadau gan {category}", "nl": "Er zijn geen quotes in {category}", - "de": "Es existieren keine Ziatate in {category}" + "de": "Es existieren keine Ziatate in {category}", + "fr": "Il n'existe aucune citation dans {category}" }, "last_removed": { "en": "Last quote removed from {category}.", @@ -53,7 +59,8 @@ "na'vi": "Oel 'upxareti aham 'aku {category}ta", "cy": "Dyfyniad olaf wedi ei ddileu o {category}", "nl": "De laatste quote is verwijderd uit {category}.", - "de": "Das letzte Zitat wurde aus {category} entfernt." + "de": "Das letzte Zitat wurde aus {category} entfernt.", + "fr": "Dernière citation enlevée de {category}." }, "no_recent_adds": { "en": "No quotes were added recently.", @@ -61,7 +68,8 @@ "na'vi": "Kea upxareti samung nìfkrr", "cy": "Nid oes unrhyw dyfyniadau wedi ei ychwwanegu'n ddiweddar", "nl": "Er zijn recentelijk geen quotes toegevoegd.", - "de": "Es wurden neulich keine Zitate hinzugefügt." + "de": "Es wurden neulich keine Zitate hinzugefügt.", + "fr": "Aucune citation n'a été ajoutée récemment." }, "rmlast_spam": { "en": "No spamming that shit. Try again in a few minutes...", @@ -69,7 +77,8 @@ "na'vi": "Nga Tsasngelit ke zene fpivere'. Sweylu nga fmivi ye'rìn...", "cy": "Peidiwch a sbamio hwna. Triwch eto mewn ychydyg funudau...", "nl": "Dat spammen kun je ook lekker laten. Probeer het zometeen nog eens...", - "de": "Hör auf zu spammen. Versuche es in einigen Minuten erneut..." + "de": "Hör auf zu spammen. Versuche es in einigen Minuten erneut...", + "fr": "Pas de spam de cette merde. Réessaye dans quelques minutes..." }, "removed_from": { "en": "'{quote}' removed from {category}", @@ -77,7 +86,8 @@ "na'vi": "'{quote}'(it/ti) 'ìyaku {category}", "cy": "'{quote}' wedi ei ddileu o {category}", "nl": "{quote} verwijderd uit {category}", - "de": "'{quote} aus {category} gelöscht" + "de": "'{quote} aus {category} gelöscht", + "fr": "'{quote}' enlevé(e) {category}" }, "q_not_exist_under": { "en": "'{quote}' doesn't exist under '{category}'.", @@ -85,7 +95,8 @@ "na'vi": "'{quote}' ke fkeytok '{category}'ta.", "cy": "Nid yw '{quote}' yn bodoli yn '{category}'", "nl": "{quote} bestaat niet in '{category}'.", - "de": "'{quote} existiert nicht in '{category}'." + "de": "'{quote} existiert nicht in '{category}'.", + "fr": "'{quote}' ne semble pas exister dans '{category}'." }, "total_quotes": { "en": "Total quote count: {count}.", @@ -93,7 +104,8 @@ "na'vi": "'upxareri holpxay: {count}.", "cy": "Cyfanswm dyfyniadau: {count}.", "nl": "Totaal aantal quotes: {count}.", - "de": "Anzahl Zitate insgesamt: {count}." + "de": "Anzahl Zitate insgesamt: {count}.", + "fr": "Nombre total de citations: {count}." }, "quote_exists": { "en": "Quote already in DB. Initiate incineration.", @@ -101,7 +113,8 @@ "na'vi": "'Upxarel säomumit fìtsengit tok srekrr. Nga skxawng lu.", "cy": "Dyfyniad yn y gronfa ddata yn barod. Cychwyn orfflosgiad", "nl": "De quote bestaat al. Bereid het verbrandingsritueel voor.", - "de": "Zitat ist bereits in der Datenbank. Verbennung einleiten." + "de": "Zitat ist bereits in der Datenbank. Verbennung einleiten.", + "fr": "La citation existe déjà dans la base de données. Initier l'incinération." }, "quote_saved": { "en": "Quote saved in '{category}' ({count}).", @@ -109,7 +122,8 @@ "na'vi": "Oe zayerok '{category}'mì ({count}).", "cy": "Dyfyniad wedi ei gadw yn '{category}' ({count}).", "nl": "Quote opgeslagen in '{category}' ({count}).", - "de": "Zitat in '{category}' gespeichert ({count})." + "de": "Zitat in '{category}' gespeichert ({count}).", + "fr": "Citation sauvegardée dans '{category}' ({count})." }, "quote_replace": { "en": "No replacing arrays, you whore.", @@ -117,7 +131,8 @@ "na'vi": "Ngal fìsäomumit ke tsun rivawn. Nga muntxa sayi suteo hrh.", "cy": "Peidiwch a newid rhestrau, y cachgi", "nl": "Geen arrays vervangen, slet.", - "de": "Ersetze keine Arrays, du Schlampe." + "de": "Ersetze keine Arrays, du Schlampe.", + "fr": "On ne remplace pas les arrays, espèce de salope." }, "quote_count": { "en": "{category} has {count} quotes.", @@ -125,7 +140,8 @@ "na'vi": "{count}a upxare {category}ur lu.", "cy": "{count} dyfyniad yn {category}", "nl": "{category} heeft {count} quotes.", - "de": "{count} Zitate befinden sich in {category}." + "de": "{count} Zitate befinden sich in {category}.", + "fr": "{category} contient {count} citations." }, "quote_link": { "en": "Link to {category} - {url}", @@ -133,7 +149,8 @@ "na'vi": "Fya'o {category}ne - {url}", "cy": "Dolen i {category} - {url}", "nl": "Link naar {category} - {url}", - "de": "Link zu {category} - {url}" + "de": "Link zu {category} - {url}", + "fr": "Lien vers {category} - {url}" }, "search_results": { "en": "{category} ({needle}): '{quote}' [{matches} results]", @@ -141,7 +158,8 @@ "na'vi": "{category} ({needle}): '{quote}' [kum a{matches}]", "cy": "{category} ({needle}): '{quote}' [{matches} canlyniad]", "nl": "{category} ({needle}): '{quote}' [{matches} resultaten]", - "de": "{category} ({needle}): '{quote}' [{matches} Ergebnisse]" + "de": "{category} ({needle}): '{quote}' [{matches} Ergebnisse]", + "en": "{category} ({needle}): '{quote}' [{matches} résultats]" }, "quote_cache_auto_remove": { "en": "There are {count} quotes in the removal cache, which will be automatically cleared.", @@ -155,42 +173,50 @@ "na'vi": "{count}a 'upxarel sngelit tok slä oel ke 'ayku sngelit tafral nga zene 'aivku", "cy": "Mae {count} dyfyniadau yn y celc dileu a fydd yn cael ei clirio â llaw.", "nl": "Er staan {count} quotes klaar om verwijderd te worden, wat handmatig zal moeten gebeuren.", - "de": "Es befinden sich {count} im Cache, die manuell entfernt werden müssen." + "de": "Es befinden sich {count} im Cache, die manuell entfernt werden müssen.", + "fr": "Il y a {count} citations dans le cache de suppression, qui va être automatiquement vidé." }, "quote_cache_cleared": { "en": "{count} quotes cleared from the removal cache.", "na'vi": "Oel 'aìmku {count}a 'upxareti ta sngel.", "cy": "{count} dyfyniadau wedi ei clirio o'r celc dileu", "nl": "{count} quotes verwijderd uit de verwijderlijst.", - "de": "{count} Zitate wurden aus dem Cache entfernt." + "de": "{count} Zitate wurden aus dem Cache entfernt.", + "fr": "{count} citation(s) supprimée(s) du cache de suppression." }, "quote_cache_reinstated": { "en": "{count} quotes reinstated from the removal cache.", "na'vi": "{count}a 'upxare tolätxaw ta sngel.", "cy": "{count} dyfyniadau wedi ei adfer o'r celc dileu", "nl": "{count} quotes hersteld van de verwijderlijst.", - "de": "{count} Zitate wurden aus dem Cache gerettet." + "de": "{count} Zitate wurden aus dem Cache gerettet.", + "fr": "{count} citation(s) restaurée(s) du cache de suppression." }, "rm_cache_limit": { "en": "Attention: Too many quotes removed, rmCache must be cleared or reinstated manually with ~rmconfirm or ~rmdeny.", "na'vi": "Oel zerok 'upxareti apxay set, sweylu txo nga 'aivku upxareti ìlä ~rmconfirm fu ~rmdeny.", "cy": "Sylw: Gormod o dyfyniadau wedi ei clirio, rhaid i'r celc dileu yn cael ei glirio neu adfer â llaw gyda ~rmconfirm neu ~rmdeny.", "nl": "Waarschuwing: Er zijn te veel quotes verwijderd. rmCache moet opgeschoond of herinstalleerd worden met ~rmconfirm of ~rmdeny", - "de": "Achtung: Zu viele Zitate gelöscht, rmCache muss geleert werden oder manuell via ~rmconfirm oder ~rmdeny wiedereingesetzt werden." + "de": "Achtung: Zu viele Zitate gelöscht, rmCache muss geleert werden oder manuell via ~rmconfirm oder ~rmdeny wiedereingesetzt werden.", + "fr": "Attention : Trop de citations enlevées, rmCache doit être vidé ou restauré manuellement avec ~rmconfirm ou ~rmdeny." }, "web_not_configured": { "en": "Cannot link to category. Web module is either not loaded or misconfigured.", "cy": "Ni all gysylltu â gategori. Modiwl we yn naill ai nid lwytho neu wedi ei camffurfweddu.", "nl": "De categorie kan niet gelinkt worden. De web module is niet geladen of onjuist geconfigureerd.", - "de": "Diese Kategorie kann nicht gelinkt werden. Das Web-Modul ist entweder nicht geladen oder falsch konfiguriert." + "de": "Diese Kategorie kann nicht gelinkt werden. Das Web-Modul ist entweder nicht geladen oder falsch konfiguriert.", + "fr": "Impossible de donner le lien vers la catégorie. Le module web n'est pas chargé ou est mal configuré." }, "category_renamed": { - "en": "Category ~{oldName} renamed to ~{newName}." + "en": "Category ~{oldName} renamed to ~{newName}.", + "fr": "Catégorie ~{oldName} renommée ~{newName}." }, "newcat_exists": { - "en": "Category ~{newcat} already exists. Delete that first or use ~qmerge." + "en": "Category ~{newcat} already exists. Delete that first or use ~qmerge.", + "fr": "La catégorie ~{newcat} existe déjà. Supprimez-la en premier ou utilisez ~qmerge." }, "categories_merged": { - "en": "Category ~{from} and its quotes merged into ~{into}." + "en": "Category ~{from} and its quotes merged into ~{into}.", + "fr": "La catégorie ~{from} et ses citations ont été fusionnée dans ~{into}." } } From 46d2415c2dd83a24813ad7c7e68407e55ffac4c4 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:23:43 +0200 Subject: [PATCH 184/220] French translation --- modules/rain/strings.json | 42 ++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/modules/rain/strings.json b/modules/rain/strings.json index 53d2316..3c037f7 100644 --- a/modules/rain/strings.json +++ b/modules/rain/strings.json @@ -4,96 +4,110 @@ "na'vi": "tompa ke zup {place}ur.", "cy": "Dyw hi ddim yn bwrw glaw yn {place}.", "nl": "Het regent niet in {place}.", - "de": "Es ist trocken in {place}." + "de": "Es ist trocken in {place}.", + "fr": "Il ne pleut pas à {place}." }, "rain-1": { "en" : "It's raining in {place}.", "na'vi":"tompa zup {place}ur.", "cy": "Mae'n bwrw glaw yn {place}.", "nl": "Het regent in {place}.", - "de": "Es regnet in {place}." + "de": "Es regnet in {place}.", + "fr": "Il pleut à {place}." }, "rain-2": { "en" : "It's raining rather a lot in {place}.", "na'vi":"tompa zup {place}ur nìhawng.", "cy": "Mae'n bwrw glaw cryn dipyn yn {place}.", "nl": "Het regent tamelijk hard in {place}.", - "de": "Es regnet relativ viel in {place}." + "de": "Es regnet relativ viel in {place}.", + "fr": "Il pleut assez fortement à {place}." }, "rain-3": { "en" : "It's raining shitloads.", "na'vi":"tompa zup {place}ur nìhawng.", "cy": "Mae'n bwrw glaw yn uffern o lawer yn {place}.", "nl": "Het regent nu toch wel erg hard.", - "de": "Es regnet stark." + "de": "Es regnet stark.", + "fr": "Il pleut vachement beaucoup." }, "rain-4": { "en" : "It's raining fucktons.", "na'vi": "tompa zup {place}ur nìhawng.", "cy": "Mae'n bwrw glaw yn drwm iawn yn {place}.", "nl": "De regen komt verdorie met bakken uit de lucht.", - "de": "Es regnet extrem stark." + "de": "Es regnet extrem stark.", + "fr": "Il pleut vraiment des putains de tonnes." }, "rain-5": { "en" : "It's raining whales (in {place})!", "na'vi": "payoang zup {place}ur", "cy": "Mae'n bwrw glaw cathod a chŵn yn {place}.", "nl": "Een punker krijgt z'n hanekam niet meer omhoog gehouden.", - "de": "Es regnet unglaublich stark (in {place})!" + "de": "Es regnet unglaublich stark (in {place})!", + "fr": "Il pleut des baleines (à {place}) !" }, "rain-6": { "en" : "IT'S SO FUCKING WET OUT HERE MAN", "na'vi" : "pey lu oeru nìhawng taluna tok fìtengeti", "cy": "MAE'N WIR GWLYB TU ALLAN.", "nl": "Dit is dus een inloopdouche.", - "de": "ES IST SO VERDAMMT NASS HIER MANN." + "de": "ES IST SO VERDAMMT NASS HIER MANN.", + "fr": "C'EST TELLEMENT MOUILLE DEHORS ICI MEC" }, "rain-7": { "en" : "I AM SO MOIST RIGHT NOW", "na'vi":"pey lu oeru nìhawng taluna tok fìtengeti", "cy": "RYDW I'N LLAITH IAWN AR HYN O BRYD", "nl": "IK VOEL ME NU TOCH ANDERS WEL BEHOORLIJK ONDER GEZEKEN.", - "de": "ICH BIN SO EINGENÄSST." + "de": "ICH BIN SO EINGENÄSST.", + "fr": "JE SUIS TELLEMENT HUMIDE LA MAINTENANT" }, "rain-8": { "en" : "You used a #3 pencil instead of #2, didn't you?", "na'vi": "Nga pamrel sami hu pencìl a#3 ulte ke pamrel sami pencìl a#2 kefyak?", "cy": "Rydych yn defnyddio #2 pensil yn hytrach na #3 pensil, ie?", "nl": "PROOST.", - "de": "Jemand muss dich hassen" + "de": "Jemand muss dich hassen", + "fr": "T'as utilisé un crayon #3 au lieu de #2, n'est-ce pas ?" }, "rain-9": { "en" : "WELCOME TO ATLANTIS", "na'vi": "ziva'u nìprrte atlantisftu.", "cy": "CROESO I ATLANTIS!", "nl": "HAD IK GEVRAAGD OM EEN OMMETJE ATLANTIS?!", - "de": "WILLKOMMEN IN ATLANTIS" + "de": "WILLKOMMEN IN ATLANTIS", + "fr": "BIENVENUE A ATLANTIS" }, "rain-10": { "en" : "GET INSIDE", "na'vi": "Sweylu txo nga livatam futa ngal fìtsengeti tok", "nl": "SCHUIL, BITCH! SCHUIL!", - "de": "REIN MIT DIR" + "de": "REIN MIT DIR", + "fr": "RENTRE CHEZ TOI" }, "rain-11": { "en" : "LOL U PROBABLY DIED", "na'vi": "hrh kxawm nga tolerkup.", "cy": "EWCH I MEWN", "nl": "HA, NU BEN JE TOCH ZEKER VERZOPEN?!", - "de": "LOL DU MIST VERMUTLICH TOT" + "de": "LOL DU MIST VERMUTLICH TOT", + "fr": "LOL T'ES PROBABLEMENT MORT" }, "rain-e": { "en" : "Unable to fetch weather data.", "na'vi":"Oel ke tsun rivum sänumeti teriyafkeyk.", "cy": "Nid gallu nôl data tywydd.", "nl": "Geen weerinformatie beschikbaar.", - "de": "Keine Wetterdaten vorhanden." + "de": "Keine Wetterdaten vorhanden.", + "fr": "Impossible de récupérer les données météo." }, "rain-u": { "en": "Location too ambiguous to process.", "na'vi":"tsengeri, yayayr lu oeru.", "cy": "Lleoliad yn rhy amwys i brosesu.", "nl": "Deze locatie is te onduidelijk.", - "de": "Wähle den nächst größeren Ort." + "de": "Wähle den nächst größeren Ort.", + "fr": "Location trop ambiguë à traiter." } } From 0fed8c9923ac30c20d2e8c2b566bedfe98862556 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:27:31 +0200 Subject: [PATCH 185/220] French translation --- modules/reddit/strings.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/reddit/strings.json b/modules/reddit/strings.json index c862277..7400e26 100644 --- a/modules/reddit/strings.json +++ b/modules/reddit/strings.json @@ -2,20 +2,24 @@ "about_subreddit": { "en": "[{display_name} has {subscribers} subscribers ({active} active)]", "cy": "[Mae {display_name} wedi {subscribers} subscribers ({active} active)]", - "de": "[{display_name} hat {subscribers} Abonnenten ({active} active)]" + "de": "[{display_name} hat {subscribers} Abonnenten ({active} active)]", + "fr": "[{display_name} a {subscribers} abonnés ({active} actifs)]" }, "about_post": { "en": "[Post by {poster} in {subreddit} — Comments: {comments}, Score: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)] — {url}", "cy": "[Postio gan {poster} yn {subreddit} - Sylwadau: {comments}, Sgôr: {score} (\u00039]▲{up}\u000f|\u000312{down}▼\u000f)] — {url}", - "de": "[Beitrag von {poster} in {subreddit} — Kommentare: {comments}, Bewertung: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)] — {url}" + "de": "[Beitrag von {poster} in {subreddit} — Kommentare: {comments}, Bewertung: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)] — {url}", + "fr": "[Message de {poster} dans {subreddit} — Commentaires: {comments}, Score: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)] — {url}" }, "about_comment": { "en": "[Comment by {poster} in {subreddit} — Score: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]", "cy": "[Sylw gan {poster} yn {subreddit} - Sgôr: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]", - "de": "[Kommentar von {poster} in {subreddit} — Bewertung: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]" + "de": "[Kommentar von {poster} in {subreddit} — Bewertung: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]", + "fr": "[Commentaire de {poster} dans {subreddit} — Score: {score} (\u00039▲{up}\u000f|\u000312{down}▼\u000f)]" }, "nsfw": { "en": "[NSFW]", - "cy": "[Anniogel Ar Gwaith (AAG)]" + "cy": "[Anniogel Ar Gwaith (AAG)]", + "fr": "[Risqué Pour le Travail (NSFW)]" } } From 878d3b29fb95ad51a165be7102d2dbf9ec5be7c5 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:30:09 +0200 Subject: [PATCH 186/220] French translation --- modules/report/strings.json | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/report/strings.json b/modules/report/strings.json index 469326d..3c4e697 100644 --- a/modules/report/strings.json +++ b/modules/report/strings.json @@ -4,33 +4,38 @@ "na'vi": "{reporter}ìl fpìl futa {reported} fe' lu taluna {reason}.", "cy": "Sylw! {reporter} wedi adrodd {reported} yn {channel}. Y rheswm a rhoddwyd oedd: \"{reason}.\"", "nl": "Waarschuwing: {reporter} heeft {reported} aangegeven in {channel}. De reden die gegeven werd was: \"{reason}.\"", - "de": "Achtung: {reporter} hat {reported} in {channel} gemeldet. Grund: \"{reason}.\"" + "de": "Achtung: {reporter} hat {reported} in {channel} gemeldet. Grund: \"{reason}.\"", + "fr": "Attention : {reporter} a reporté {reported} dans {channel}. Raison donnée : \"{reason}.\"" }, "reported": { "en": "Thank you, {reported} has been reported to the channel administrators.", "na'vi": "Irayo si ngari, fìtsengìri ayeyktan omum teri {reported}it set.", "cy": "Diolch, {reported} wedi cael ei adrodd i'r gweinyddwyr sianel.", "nl": "Bedankt, {reported} is aangegeven bij de administrators.", - "de": "Danke, {reported} wurde bei den Administratoren dieses Kanals gemeldet." + "de": "Danke, {reported} wurde bei den Administratoren dieses Kanals gemeldet.", + "fr": "Merci, {reported} a été reporté aux administrateurs du canal." }, "user_not_found": { "en": "{reported} isn't a known user in {channel}.", "na'vi": "Oel ke omum {reported}it mì {channel}.", "cy": "Nid yw {reported} yn ddefnyddiwr hysbys yn {channel}.", "nl": "{reported} is geen bestaande gebruiker in {channel}.", - "de": "{reported} ist kein bekannter Benutzer in {channel}." + "de": "{reported} ist kein bekannter Benutzer in {channel}.", + "fr": "{reported} n'est pas un utilisateur connu dans {channel}." }, "not_in_channel": { "en": "I am not present in {channel}.", "na'vi": "Oel {channel}it ke tok.", "cy": "Dydw i ddim yn bresennol yn {channel}.", "nl": "Ik ben niet aanwezig in {channel}.", - "de": "Ich bin nicht in {channel} aktiv." + "de": "Ich bin nicht in {channel} aktiv.", + "fr": "Je ne suis pas présent dans {channel}." }, "notify": { "en": "Attention {channel}: {notifier}: {message}" }, "notified": { - "en": "{user}: {channel} staff notified." + "en": "{user}: {channel} staff notified.", + "fr": "{user}: l'équipe de {channel} a été notifiée." } } From 9faee2c71a20491f8bc309a5ce4f9e6c2d1faf24 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:30:58 +0200 Subject: [PATCH 187/220] French translation --- modules/soundcloud/strings.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/soundcloud/strings.json b/modules/soundcloud/strings.json index a3eb6d4..eab2a34 100644 --- a/modules/soundcloud/strings.json +++ b/modules/soundcloud/strings.json @@ -1,8 +1,10 @@ { "sc_track": { - "en": "[{title} by {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]" + "en": "[{title} by {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]", + "en": "[{title} par {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]" }, "sc_notrack": { - "en": "No results found." + "en": "No results found.", + "fr": "Aucun résultat trouvé." } } From 4b3d88ecb06376524193faba453127b20a4fe567 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:32:10 +0200 Subject: [PATCH 188/220] French translation --- modules/spelling/strings.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/spelling/strings.json b/modules/spelling/strings.json index 0c67074..f55d486 100644 --- a/modules/spelling/strings.json +++ b/modules/spelling/strings.json @@ -5,7 +5,8 @@ "na'vi": "Sweylu {correcter} pamrel sivi: {fix}", "cy": "Oedd {correcter} yn feddwl: {fix}", "nl": "{correcter} bedoelde: {fix}", - "de": "{correcter} meinte: {fix}" + "de": "{correcter} meinte: {fix}", + "fr": "{correcter} voulait dire : {fix}" }, "spelling_other": { "en": "{correcter} thinks {candidate} meant: {fix}", @@ -13,6 +14,7 @@ "na'vi": "{correcter} fpìl futa sweylu {candiate} pamrel sivi: {fix}", "cy": "Mae {correcter} yn meddwl bod {candidate} yn feddwl: {fix}", "nl": "{correcter} denkt dat {candidate} bedoelde: {fix}", - "de": "{corrector} denkt, dass {canditate} meinte: {fix}" + "de": "{corrector} denkt, dass {canditate} meinte: {fix}", + "fr": "{correcter} pense que {candidate} voulait dire : {fix}" } } From 9c73342176cf8e3f6b07ee80594188e470797a01 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:34:47 +0200 Subject: [PATCH 189/220] French translation --- modules/spotify/strings.json | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/modules/spotify/strings.json b/modules/spotify/strings.json index 3c90a85..09231af 100644 --- a/modules/spotify/strings.json +++ b/modules/spotify/strings.json @@ -2,28 +2,33 @@ "artist": { "en": "[artist] {artist}", "cy": "[cyfansoddwr] {artist}", - "de": "[Interpret] {artist}" + "de": "[Interpret] {artist}", + "fr": "[artiste] {artist}" }, "album": { "en": "[album] {artist} – {album}", - "cy": "[albwm] {artist} - {album}", - "de": "[Album] {artist} – {album}" + "cy": "[albwm] {artist} – {album}", + "de": "[Album] {artist} – {album}", + "fr": "[album] {artist} – {album}" }, "track": { "en": "[track] {artist} – {track} (from {album})", - "cy": "[trac] {artist} - {track} (o'r albwm: {album})", - "de": "[Track] {artist} – {track} (aus dem Album {album})" + "cy": "[trac] {artist} – {track} (o'r albwm: {album})", + "de": "[Track] {artist} – {track} (aus dem Album {album})", + "fr": "[piste] {artist} – {track} (tiré de {album})" }, "found": { "en": "[{url}] {artist} – {track} (from {album})", - "cy": "[{url}] {artist} - {track} (o'r albwm: {album})", - "de": "[{url}] {artist} – {track} (aus dem Album {album})" + "cy": "[{url}] {artist} – {track} (o'r albwm: {album})", + "de": "[{url}] {artist} – {track} (aus dem Album {album})", + "fr": "[{url}] {artist} – {track} (tiré de {album})" }, "not-found": { "en": "No results.", "na'vi": "Oel ke tsun rivum ayuoti.", "cy": "Dim canlyniadau.", "nl": "Geen resultaten.", - "de": "Kein Ergebnis." + "de": "Kein Ergebnis.", + "fr": "Aucun résultat." } } From 519b7ca7b0c0a4b945c0be9eda61064f0d254ebe Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:38:10 +0200 Subject: [PATCH 190/220] French translation --- modules/users/strings.json | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/modules/users/strings.json b/modules/users/strings.json index 2646e55..7e9f3a9 100644 --- a/modules/users/strings.json +++ b/modules/users/strings.json @@ -4,47 +4,55 @@ "na'vi": "ayfko syaw {user} {alias} nìteng", "cy": "{alias} ydy enw arall o {user}", "nl": "{alias} is een alias van {user}", - "de": "{alias} ist ein Nickname von {user}" + "de": "{alias} ist ein Nickname von {user}", + "fr": "{alias} est un alias de {user}" }, "primary": { "en": "{user} (currently {currentNick}) is a primary user with {count} aliases, ", "na'vi": "{user} ({currentNick}) lu txin ulte {count}a stxo lu poru, ", "nl": "{user} ({currentNick}) is een primaire gebruiker met {count} aliassen, ", "cy": "Mae {user} ({currentNick}) yn ddefnyddiwr gynradd gyda {count} enwau eraill, ", - "de": "{user} ({currentNick}) ist ein Benutzer mit {count} Nicknamen, " + "de": "{user} ({currentNick}) ist ein Benutzer mit {count} Nicknamen, ", + "fr": "{user} (actuellement {currentNick}) est un utilisateur primaire avec {count} alias, " }, "unknown_alias": { "en": "{alias} does not currently exist as an alias or known user.", "na'vi": "{alias} ke fkeytok nìfkrr", "cy": "Nid yw {alias} yn bodoli fel enw arall neu defnyddiwr yn hysbys.", "nl": "{alias} staat momenteel niet bekend als een bestaande gebruiker of alias.", - "de": "{alias} existiert nicht oder ist kein Nickname eines Benutzers." + "de": "{alias} existiert nicht oder ist kein Nickname eines Benutzers.", + "fr": "{alias} n'existe pas actuellement en tant qu'alias ou utilisateur connu." }, "aliasparentset": { "en": "{newParent} is now the parent user, and {newAlias} is an alias.", "na'vi": "{newParent} lu sa'sem set ulte {newAlias} lu stxo set nìteng.", "cy": "Mae {newParent} ydy defnyddiwr rhiant nawr, a {alias} ydy enw arall.", "nl": "{newParent} is nu de bovenliggende gebruiker, en {newAlias} is een alias.", - "de": "{newParent} ist nun der Hauptname und {newAlias} ist ein Nickname." + "de": "{newParent} ist nun der Hauptname und {newAlias} ist ein Nickname.", + "fr": "{newParent} est maintenant le même utilisateur parent, et {newAlias} est un alias." }, "unprimary_error": { "en": "{nick} isn't recorded as a primary user.", "na'vi": "fo sute txin ke lu.", "cy": "Nid yw un o'r defnyddwyr hynny yn cael ei gofnodi ar hyn o bryd fel defnyddiwr gynradd.", "nl": "Een van deze gebruikers is nog niet bekend als een primaire gebruiker.", - "de": "Einer dieser Benutzer ist nicht als Hauptbenutzer gespeichert." + "de": "Einer dieser Benutzer ist nicht als Hauptbenutzer gespeichert.", + "fr": "{nick} n'est pas enregistré en tant qu'utilisateur primaire." }, "merged_users": { "en": "{old_user} and their aliases have been merged into {new_user}.", "na'vi": "{old_user} ulte stxo alahe {new_user} lu set.", "cy": "{old_user} a'u enwau eraill wedi cael eu cyfuno i mewn i {new_user}.", "nl": "{old_user} en zijn aliassen zijn samengevoegd met {new_user}.", - "de": "{old_user} und seine Nicknamen wurden zusammengelegt in {new_user}." + "de": "{old_user} und seine Nicknamen wurden zusammengelegt in {new_user}.", + "fr": "{old_user} et ses alias ont été fusionnés dans {new_user}." }, "alias_exists": { - "en": "Alias {alias} already exists." + "en": "Alias {alias} already exists.", + "fr": "L'alias {alias} existe déjà." }, "alias_added": { - "en": "Alias {alias} added to {user}." + "en": "Alias {alias} added to {user}.", + "fr": "Alias {alias} ajouté à {user}." } } From b93398185990e484c34321257202aa1a65dfcab1 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 04:40:05 +0200 Subject: [PATCH 191/220] French translation --- modules/warning/strings.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/warning/strings.json b/modules/warning/strings.json index c4abcab..295a263 100644 --- a/modules/warning/strings.json +++ b/modules/warning/strings.json @@ -1,11 +1,14 @@ { "no_warnings": { - "en": "No warnings found for {user}." + "en": "No warnings found for {user}.", + "fr": "Aucun avertissement trouvé pour {user}." }, "warning_info": { - "en": "{user} has {num} warnings. More info can be found at {url}" + "en": "{user} has {num} warnings. More info can be found at {url}", + "fr": "{user} a {num} avertissements. Plus d'informations peuvent être trouvées ici : {url}" }, "warn_notify": { - "en": "Attention: {warner} has issued a warning to {warnee} for \"{reason}.\" More info can be found at {url}" + "en": "Attention: {warner} has issued a warning to {warnee} for \"{reason}.\" More info can be found at {url}", + "fr": "Attention : {warner} a donné un avertissement à {warnee} pour \"{reason}.\". Plus d'informations peuvent être trouvées ici : {url}" } } From 3759b7b327deab7a0a886260752e0fb03ec4fe63 Mon Sep 17 00:00:00 2001 From: Luke Slater Date: Thu, 11 Jul 2013 02:46:13 +0000 Subject: [PATCH 192/220] fix admin str err --- modules/admin/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/admin/strings.json b/modules/admin/strings.json index 79f2440..809713c 100644 --- a/modules/admin/strings.json +++ b/modules/admin/strings.json @@ -158,7 +158,7 @@ "en": "Failed to load {module}. See 'status {module}'.", "cy": "Methu i lwytho {module}. Gwelwch 'status {module}'.", "de": "Konnte {module} nicht laden. Siehe 'status {module}'.", - "fr:" "Echec du chargement de {module}. Voir 'status {module}'." + "fr": "Echec du chargement de {module}. Voir 'status {module}'." }, "no_config_key": { "en": "{path} doesn't exist bro", From e1b15b73767d2c21e988f91d57165a24db247b55 Mon Sep 17 00:00:00 2001 From: Luke Slater Date: Thu, 11 Jul 2013 02:49:36 +0000 Subject: [PATCH 193/220] Update strings.json --- modules/project/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/project/strings.json b/modules/project/strings.json index 6601db9..f8c93fb 100644 --- a/modules/project/strings.json +++ b/modules/project/strings.json @@ -198,7 +198,7 @@ "web-port": { "en": "Web is listening on {port}", "cy": "We yn gwrando ar {port}", - "fr": "Le web écoute sur {port} + "fr": "Le web écoute sur {port}" }, "propaganda": { "en": "Contribute to the code on Github!", From da801cc72f183c92f03b17d4d5517b7d66a8f21b Mon Sep 17 00:00:00 2001 From: Luke Slater Date: Thu, 11 Jul 2013 15:11:25 +0000 Subject: [PATCH 194/220] Update strings.json --- modules/project/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/project/strings.json b/modules/project/strings.json index f8c93fb..77d32ee 100644 --- a/modules/project/strings.json +++ b/modules/project/strings.json @@ -5,7 +5,7 @@ "fr": "{name} parle {lang} ({langen})", "it": "{name} parla {lang} ({langen})", "cy": "{name} yn siarad {lang} ({langen})", - "nl": "{name} spreekt {lang} ({langen})", + "nl": "{name} spreekt {lang} ({langen})" }, "thanks": { "en": "With thanks to:", From 9379b73bdf1a8036f132db5bc1f59b7eb7466540 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 11 Jul 2013 15:22:29 +0000 Subject: [PATCH 195/220] thing --- run.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/run.js b/run.js index 27bcc30..a9f202d 100644 --- a/run.js +++ b/run.js @@ -242,8 +242,6 @@ DBot.prototype.reloadModules = function() { if(propertyKey) delete require.cache[propertyKey]; propertyObj = require(moduleDir + property).fetch(this); } catch(err) { - this.status[name] = 'Error loading ' + propertyKey + - ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); console.log('Module error (' + module.name + ') in ' + property + ': ' + err); } @@ -282,7 +280,13 @@ DBot.prototype.reloadModules = function() { var propertyData = {}; try { propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); - } catch(err) {}; + } catch(err) { + this.status[name] = 'Error loading ' + property + + ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); + console.log('Data error (' + module.name + ') in ' + + property + ': ' + err); + + }; _.extend(this[property], propertyData); if(property == 'strings') { _.each(_.keys(propertyData), function(string) { From b677986c683181092c541059fbbb32d9a2ffa1b1 Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 11 Jul 2013 15:24:19 +0000 Subject: [PATCH 196/220] yeah --- modules/github | 1 - 1 file changed, 1 deletion(-) delete mode 160000 modules/github diff --git a/modules/github b/modules/github deleted file mode 160000 index 5f4e3dc..0000000 --- a/modules/github +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5f4e3dc8335000e97af528fee289b880a3c99e81 From a5d02d19ff73d2eb895636edf800d9c2875719ef Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 11 Jul 2013 15:25:45 +0000 Subject: [PATCH 197/220] add github as reg --- modules/github/LICENSE | 18 ++++ modules/github/README.md | 28 +++++ modules/github/config.json | 8 ++ modules/github/github.js | 200 ++++++++++++++++++++++++++++++++++++ modules/github/strings.json | 68 ++++++++++++ 5 files changed, 322 insertions(+) create mode 100644 modules/github/LICENSE create mode 100644 modules/github/README.md create mode 100644 modules/github/config.json create mode 100644 modules/github/github.js create mode 100644 modules/github/strings.json diff --git a/modules/github/LICENSE b/modules/github/LICENSE new file mode 100644 index 0000000..b52fb8d --- /dev/null +++ b/modules/github/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2013 Douglas Gardner + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/modules/github/README.md b/modules/github/README.md new file mode 100644 index 0000000..12d7a9d --- /dev/null +++ b/modules/github/README.md @@ -0,0 +1,28 @@ +## Github + +Grabs interesting data from the GitHub API. + +### Description + +This module for [depressionbot](https://github.com/reality/depressionbot) takes some interesting information about Github and parses it in a pleasing manner. + +### Configuration +#### defaultrepo +When repository information is lacking from the command, this repository will be used. +#### sortorder +Defines the behaviour of ~issue when no arguments are given. Options are ``created``, ``updated``, or ``comments``. +### Commands +#### ~commits +Returns the number of commits in the repository of the current depressionbot instance. +#### ~gstatus +Returns the [current status of Github](https://status.github.com), and a message explaining the current state of affairs. +#### ~issue (user/repo) [id] +Gives information about the isse pecified, from the default repository if one is not explicitly stated. +#### ~milestone [milestone name] +Returns milestone progress for any given milestone, with a link to the milestone in question. +#### ~repo (repo name) +Returns information about the repo given as a parameter. The repo should be specified as ``user/name``; for example, ``twitter/snowflake``. +#### ~repocount [user] +Returns the number of public Github repositories for the specified user. +### Dependencies +* [request](https://github.com/mikeal/request/):``$ npm install request`` diff --git a/modules/github/config.json b/modules/github/config.json new file mode 100644 index 0000000..2721da9 --- /dev/null +++ b/modules/github/config.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ "command" ], + "ignorable": true, + "help": "http://github.com/zuzak/dbot-github/blob/master/README.md", + "defaultrepo": "reality/dbot", + "sortorder": "updated", + "useragent": "reality/depressionbot github module" +} diff --git a/modules/github/github.js b/modules/github/github.js new file mode 100644 index 0000000..2ca7aa3 --- /dev/null +++ b/modules/github/github.js @@ -0,0 +1,200 @@ +/** + * Module Name: Github + * Description: Retrieves interesting Github information + */ +var request = require('request'), + exec = require('child_process').exec; + +var github = function(dbot) { + this.api = { + "githubStatus": function(callback){ + var reqUrl = "https://status.github.com/api/last-message.json"; + request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) { + callback(JSON.parse(body)); + }); + } + }; + + + var commands = { + '~repocount': function(event) { + var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos"; + request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) { + if(response.statusCode == "200") { + var result = JSON.parse(body); + event.reply(dbot.t("repocount",{"user": event.params[1], "count": result.length})); + } else { + event.reply(dbot.t("usernotfound")); + } + }); + }, + '~repo': function(event) { + var repo = event.params[1]; + if (typeof repo == 'undefined') { + repo = this.config.defaultrepo; + } + + var reqUrl = "https://api.github.com/"; + reqUrl += "repos/" + repo; + request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) { + + var data = JSON.parse(body); + if (data["fork"]) { + event.reply(dbot.t("forkedrepo",data)); + } else { + event.reply(dbot.t("unforkedrepo",data)); + } + // TODO: move this shizz into an api call + var longurl = "http://github.com/" + repo; + request({method: 'POST', uri: 'http://git.io', form:{url: longurl}}, function(error, response, body){ + event.reply(dbot.t('location')+" "+response.headers["location"]); + }); + }); + }, + '~gstatus': function(event) { + data = this.api.githubStatus(function(data){ + console.log(data); + event.reply(dbot.t("status"+data["status"])); + event.reply(data["body"]); + }.bind(this)); + }, + '~milestone': function(event) { + var repo = this.config.defaultrepo; + var name = event.params[1]; + if (event.params[2]){ + repo = name; + name = event.params[2]; + } + var reqUrl = "https://api.github.com/repos/"; + reqUrl += repo + "/milestones"; + + request({"url": reqUrl, "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) { + var data = JSON.parse(body); + for (var section in data) { + var milestone = data[section]; + if (milestone["title"] == name){ + var str = "Milestone " + milestone["title"]; + var progress = milestone["closed_issues"] / (milestone["open_issues"] + milestone["closed_issues"]); + progress = Math.round(progress*100); + var bar = "["; + for (var i = 10; i < 100; i += 10) { + if ((progress/i) > 1) { + bar += "█"; + } else { + bar += " "; + } + } + bar += "]"; + str += " is " + bar + progress + "% complete"; + + var longurl = "http://github.com/" + repo + "/issues?milestone=" + milestone["number"]; + request({method: 'POST', uri: 'http://git.io', form:{url: longurl}}, function(error, response, body){ + event.reply(response.headers["location"]); + }); + event.reply(str); + break; + } + } + }); + }, + '~repocount': function(event) { + // TODO: add handling for non existent user + var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos"; + request({"url": reqUrl,"headers": { "User-Agent": this.config.useragent}}, function(error, response, body) { + var result = JSON.parse(body); + event.reply(event.params[1] + " has " + result.length + " public repositories."); + }); + }, + '~grate': function(event) { + request.get({"url":"https://api.github.com/rate_limit", "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) { + var data = JSON.parse(body); + if (data.message){ + event.reply(data.message); + } else { + event.reply(data.rate.remaining + " requests of " + data.rate.limit + " remaining."); + } + }); + }, + '~issue': function(event) { + var repo, issue, randflag; + if (isNaN(event.params[1]) && event.params[1]){ // if ~issue foo/bar + repo = event.params[1]; + issue = event.params[2]; + } else { + repo = this.config.defaultrepo; + issue = event.params[1]; + } + + if (issue == "*" || issue == "random" || issue == "0") { + issue = ""; + randflag = true; + } else if (!issue) { // issue is undefined + issue = ""; + } else { + issue = "/" + issue; // got to be a better way + } + + var reqUrl = "https://api.github.com/repos/" + repo + "/issues" + + issue + "?sort=" + this.config.sortorder; + request.get({"url": reqUrl, headers: { "User-Agent": this.config.useragent}}, function(error,response, body) { + if (response.statusCode == "200") { + var data = JSON.parse(body); + if (!issue){ + if (randflag) { + data = data[Math.floor(Math.random() * data.length)]; + } else { + data = data[0]; + } + } + if (data["pull_request"]["html_url"]){ + console.log(data["pull_request"]["html_url"]); + data["pull_request"] = " with code"; + } else { + data["pull_request"] = ""; + } + if (data["state"]=="open") { + data["state"] = "\u000303" + data["state"]; + } else { + data["state"] = "\u000304" + data["state"]; + } + var labels = ""; + for (var i=0; i < data["labels"].length; i++) { // for-in doesn't like me + var color = "\u0003" + (parseInt(data["labels"][i]["color"],16) % 15); + labels += " " + color + data["labels"][i]["name"]; + } + data["label"] = labels; + event.reply(dbot.t("issue",data)); + event.reply(data["html_url"]); + } else { + event.reply(dbot.t("issuenotfound")); + } + }); + }, + '~commits': function(event) { + exec("git rev-list --all | wc -l", function(error, stdout, stderr) { + stdout = stdout.trim(); + request({"url":"http://numbersapi.com/" + stdout + "?fragment&default=XXX"}, function(error, response, body){ + if (body != "XXX"){ + event.reply(dbot.t("commitcountfun",{"fact": body, "count": stdout})); + } else { + // nothing fun about the number, let's try the year + request({"url":"http://numbersapi.com/" + stdout + "/year?fragment&default=XXX"}, function(error, response, body){ + if (body != "XXX"){ + event.reply(dbot.t("commitcountyear",{"fact": body, "count": stdout})); + } else { + event.reply(dbot.t("commitcountboring",{"count": stdout})); + } + }); + } + }); + }); + } + }; + this.commands = commands; + + this.on = 'PRIVMSG'; +}; + +exports.fetch = function(dbot) { + return new github(dbot); +}; diff --git a/modules/github/strings.json b/modules/github/strings.json new file mode 100644 index 0000000..bd1fec1 --- /dev/null +++ b/modules/github/strings.json @@ -0,0 +1,68 @@ +{ + "repocount": { + "en": "{user} has {count} public repos.", + "cy": "Mae {count} archifdai cyhoeddus gan {user}.", + "de": "{user} hat {count} öffnetliche Repos." + }, + "statusgood": { + "en": "\u000309Shit's fine", + "cy": "\u000309Cachu'n ddirwy", + "de": "\u000309Alles in Ordnung" + }, + "statusminor": { + "en": "\u000308Shit's touchy", + "cy": "\u000308Cachu'n fregus", + "de": "\u000308Kleinere Probleme vorhanden" + }, + "statusmajor": { + "en": "\u000304Shit's fucked:", + "cy": "\u000304Cachu wedi cyrraedd y ffan:", + "de": "\u000304Du bist am Arsch" + }, + "location": { + "en": "You can find that shit at:", + "cy": "Gallwch ddod o hyd y cachu yn:", + "de": "Kann nicht gefunden werden:" + }, + "forkedrepo": { + "en": "{name} is a forked {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]", + "cy": "{name} ydy archif {language} fforchog gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]", + "de": "{name} ist eine geteilte {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]" + }, + "unforkedrepo": { + "en": "{name} is a {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]", + "cy": "{name} ydy archif {language} gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]", + "de": "{name} ist eine {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]" + }, + "usernotfound": { + "en": "User not found.", + "cy": "Defnyddiwr heb ei ganfod.", + "de": "Benutzer nicht gefunden." + }, + "issuenotfound": { + "en": "Unable to find that issue.", + "cy": "Wedi methu dod o hyd mater hwnnw", + "de": "Kann dieses Problem nicht finden." + }, + "issue": { + "en": "Issue \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}", + "cy": "Mater \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} sylwadau]{label}", + "de": "Problem \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}" + }, + "commitcountboring": { + "en": "My code has been committed {count} times.", + "cy": "Mae fy cod wedi cael ei gyflawni ar {count} adegau.", + "de": "Mein Code wurde {count} mal überstellt." + }, + "commitcountfun": { + "en": "My repository has the same number of commits as {fact} ({count}).", + "cy": "Yr un nifer o ymrwymo fel {fact} gan fy archif ({count}).", + "de": "Meine Repository hat die gleiche Anzahl Commits wie {fact} ({count})." + }, + "commitcountyear": { + "en": "My repository's commits number {count}, the year that {fact}.", + "cy": "Nifer o ymrwymo gan fy archif: {count}, y flwyddyn y {fact}.", + "de": "Anzahl der Commits in meinem Repository {count}, des Jahres {fact}" + } +} + From 7401dc0925b538117af0be2ce9eec23edfee7d67 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 17:46:26 +0200 Subject: [PATCH 198/220] French translation --- modules/github/strings.json | 39 ++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/modules/github/strings.json b/modules/github/strings.json index bd1fec1..220943f 100644 --- a/modules/github/strings.json +++ b/modules/github/strings.json @@ -2,67 +2,80 @@ "repocount": { "en": "{user} has {count} public repos.", "cy": "Mae {count} archifdai cyhoeddus gan {user}.", - "de": "{user} hat {count} öffnetliche Repos." + "de": "{user} hat {count} öffnetliche Repos.", + "fr": "{user} a {count} dépôt(s) public(s)." }, "statusgood": { "en": "\u000309Shit's fine", "cy": "\u000309Cachu'n ddirwy", - "de": "\u000309Alles in Ordnung" + "de": "\u000309Alles in Ordnung", + "fr": "\u000309Cette merde tourne bien" }, "statusminor": { "en": "\u000308Shit's touchy", "cy": "\u000308Cachu'n fregus", - "de": "\u000308Kleinere Probleme vorhanden" + "de": "\u000308Kleinere Probleme vorhanden", + "fr": "\u000308Cette merde a un petit problème" }, "statusmajor": { "en": "\u000304Shit's fucked:", "cy": "\u000304Cachu wedi cyrraedd y ffan:", - "de": "\u000304Du bist am Arsch" + "de": "\u000304Du bist am Arsch", + "fr": "\u000304Cette merde est niquée : " }, "location": { "en": "You can find that shit at:", "cy": "Gallwch ddod o hyd y cachu yn:", - "de": "Kann nicht gefunden werden:" + "de": "Kann nicht gefunden werden:", + "fr": "Tu peux trouver cette merde ici : " }, "forkedrepo": { "en": "{name} is a forked {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]", "cy": "{name} ydy archif {language} fforchog gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]", - "de": "{name} ist eine geteilte {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]" + "de": "{name} ist eine geteilte {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]", + "fr": "{name} est un dépôt fourché {language} avec {open_issues} problème(s) non résolu(s) [{forks}F {watchers}W]" }, "unforkedrepo": { "en": "{name} is a {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]", "cy": "{name} ydy archif {language} gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]", - "de": "{name} ist eine {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]" + "de": "{name} ist eine {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]", + "fr": "{name} est un dépôt {language} avec {open_issues} problème(s) non résolu(s) [{forks}F {watchers}W]" }, "usernotfound": { "en": "User not found.", "cy": "Defnyddiwr heb ei ganfod.", - "de": "Benutzer nicht gefunden." + "de": "Benutzer nicht gefunden.", + "fr": "Utilisateur non trouvé." }, "issuenotfound": { "en": "Unable to find that issue.", "cy": "Wedi methu dod o hyd mater hwnnw", - "de": "Kann dieses Problem nicht finden." + "de": "Kann dieses Problem nicht finden.", + "fr": "Impossible de trouver ce problème." }, "issue": { "en": "Issue \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}", "cy": "Mater \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} sylwadau]{label}", - "de": "Problem \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}" + "de": "Problem \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}", + "fr": "Problème \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} commentaires]{label}" }, "commitcountboring": { "en": "My code has been committed {count} times.", "cy": "Mae fy cod wedi cael ei gyflawni ar {count} adegau.", - "de": "Mein Code wurde {count} mal überstellt." + "de": "Mein Code wurde {count} mal überstellt.", + "fr": "Mon code a été modifié {count} fois." }, "commitcountfun": { "en": "My repository has the same number of commits as {fact} ({count}).", "cy": "Yr un nifer o ymrwymo fel {fact} gan fy archif ({count}).", - "de": "Meine Repository hat die gleiche Anzahl Commits wie {fact} ({count})." + "de": "Meine Repository hat die gleiche Anzahl Commits wie {fact} ({count}).", + "fr": "Mon dépôt a le même nombre de modifications que {fact} ({count})." }, "commitcountyear": { "en": "My repository's commits number {count}, the year that {fact}.", "cy": "Nifer o ymrwymo gan fy archif: {count}, y flwyddyn y {fact}.", - "de": "Anzahl der Commits in meinem Repository {count}, des Jahres {fact}" + "de": "Anzahl der Commits in meinem Repository {count}, des Jahres {fact}", + "fr": "Mon dépot compte {count} modifications, l'année où {fact}." } } From 91a121536cec57c962a27dfe11ac7e2a00c11f6e Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 17:48:16 +0200 Subject: [PATCH 199/220] Updated French translation for github module --- modules/github/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/github/strings.json b/modules/github/strings.json index 220943f..4b0fb29 100644 --- a/modules/github/strings.json +++ b/modules/github/strings.json @@ -21,7 +21,7 @@ "en": "\u000304Shit's fucked:", "cy": "\u000304Cachu wedi cyrraedd y ffan:", "de": "\u000304Du bist am Arsch", - "fr": "\u000304Cette merde est niquée : " + "fr": "\u000304Cette merde est foutue : " }, "location": { "en": "You can find that shit at:", From ad76a7b12d6931f999f8aa37e28429ce57d44477 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 17:51:49 +0200 Subject: [PATCH 200/220] Fixed typos in French translation --- modules/admin/strings.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/admin/strings.json b/modules/admin/strings.json index 809713c..d130c0c 100644 --- a/modules/admin/strings.json +++ b/modules/admin/strings.json @@ -96,7 +96,7 @@ "cy": "Categori wedi cloi: {category}", "nl": "Quote categorie vergrendeld: {category}", "de": "Zitat-Kategorie geschlossen: {category}", - "fr": "Catégorie de citations verouillée : {category}" + "fr": "Catégorie de citations verrouillée : {category}" }, "already_in_channel": { "en": "I'm already in {channel}", @@ -140,13 +140,13 @@ "en": "{module} status: Shit looks good", "cy": "{module} statws: Cachu yn edrych yn dda", "de": "Sieht gut aus", - "fr": "Status de {module} : Cette merde tourne bien" + "fr": "Statut de {module} : Cette merde tourne bien" }, "status_bad": { "en": "{module} status: Failed to load: {reason}", "cy": "{module} statws: Methu i lwytho: {reason}", "de": "{module} Status: Konnte nicht geladen werden: {reason}", - "fr": "Status de {module} : échec de chargement : {reason}" + "fr": "Statut de {module} : échec de chargement : {reason}" }, "status_unloaded": { "en": "Either that module wasn't on the roster or shit is totally fucked.", From 3944906de4eb2fcec7c094897ffbc5799383ecc5 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 21:08:43 +0200 Subject: [PATCH 201/220] holla at dem people in Aberystwyth, name of the league translated to French --- modules/project/strings.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/project/strings.json b/modules/project/strings.json index 77d32ee..63f1f57 100644 --- a/modules/project/strings.json +++ b/modules/project/strings.json @@ -206,7 +206,8 @@ "fr": "Contribuez au code sur GitHub!" }, "branch": { - "en": "{branch}" + "en": "{branch}", + "fr": "{branch}" }, "git": { "en": "version control", @@ -251,7 +252,8 @@ "fr": "Il a des requêtes pull en attente" }, "oaosidl": { - "en": "The Official Aberystwyth Open Source International Development League" + "en": "The Official Aberystwyth Open Source International Development League", + "fr": "La Ligue Officielle de Développement International Open Source d'Aberystwyth" }, "link-autotitle": { "en": "Automatically titling links in channels", From d673b9c8ecbcda3ad57facdb7db943fa2cf5fc1c Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 21:12:29 +0200 Subject: [PATCH 202/220] major mess-up fixed; missing translation for a string added --- modules/quotes/strings.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/quotes/strings.json b/modules/quotes/strings.json index 816afef..24baacc 100644 --- a/modules/quotes/strings.json +++ b/modules/quotes/strings.json @@ -159,14 +159,15 @@ "cy": "{category} ({needle}): '{quote}' [{matches} canlyniad]", "nl": "{category} ({needle}): '{quote}' [{matches} resultaten]", "de": "{category} ({needle}): '{quote}' [{matches} Ergebnisse]", - "en": "{category} ({needle}): '{quote}' [{matches} résultats]" + "fr": "{category} ({needle}): '{quote}' [{matches} résultats]" }, "quote_cache_auto_remove": { "en": "There are {count} quotes in the removal cache, which will be automatically cleared.", "na'vi": "{count}a 'upxarel sngelit tok, Oel 'ayku sngelit lukenga.", "cy": "Mae {count} dyfyniadau yn y celc dileu a fydd yn cael ei clirio yn awtomatig.", "nl": "Er staan {count} quotes klaar om verwijderd te worden, wat automatisch zal gebeuren.", - "de": "Es befinden sich {count} im Cache, die automatisch entfernt werden." + "de": "Es befinden sich {count} im Cache, die automatisch entfernt werden.", + "fr": "Il y a {count} citations dans le cache de suppression, qui va être automatiquement vidé." }, "quote_cache_manual_remove": { "en": "There are {count} quotes in the removal cache, which must be manually cleared.", @@ -174,7 +175,7 @@ "cy": "Mae {count} dyfyniadau yn y celc dileu a fydd yn cael ei clirio â llaw.", "nl": "Er staan {count} quotes klaar om verwijderd te worden, wat handmatig zal moeten gebeuren.", "de": "Es befinden sich {count} im Cache, die manuell entfernt werden müssen.", - "fr": "Il y a {count} citations dans le cache de suppression, qui va être automatiquement vidé." + "fr": "Il y a {count} citations dans le cache de suppression, qui doit être manuellement vidé." }, "quote_cache_cleared": { "en": "{count} quotes cleared from the removal cache.", From 0dd7d0385060159ac3e4463dc510d0739f90b041 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 21:19:34 +0200 Subject: [PATCH 203/220] fun French strings are even funnier now --- modules/rain/strings.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/rain/strings.json b/modules/rain/strings.json index 3c037f7..3b7a6d2 100644 --- a/modules/rain/strings.json +++ b/modules/rain/strings.json @@ -29,7 +29,7 @@ "cy": "Mae'n bwrw glaw yn uffern o lawer yn {place}.", "nl": "Het regent nu toch wel erg hard.", "de": "Es regnet stark.", - "fr": "Il pleut vachement beaucoup." + "fr": "Il pleut à mort." }, "rain-4": { "en" : "It's raining fucktons.", @@ -53,7 +53,7 @@ "cy": "MAE'N WIR GWLYB TU ALLAN.", "nl": "Dit is dus een inloopdouche.", "de": "ES IST SO VERDAMMT NASS HIER MANN.", - "fr": "C'EST TELLEMENT MOUILLE DEHORS ICI MEC" + "fr": "C'EST TELLEMENT MOUILLE DEHORS MEC" }, "rain-7": { "en" : "I AM SO MOIST RIGHT NOW", @@ -61,7 +61,7 @@ "cy": "RYDW I'N LLAITH IAWN AR HYN O BRYD", "nl": "IK VOEL ME NU TOCH ANDERS WEL BEHOORLIJK ONDER GEZEKEN.", "de": "ICH BIN SO EINGENÄSST.", - "fr": "JE SUIS TELLEMENT HUMIDE LA MAINTENANT" + "fr": "JE SUIS TELLEMENT MOITE LA" }, "rain-8": { "en" : "You used a #3 pencil instead of #2, didn't you?", @@ -69,7 +69,7 @@ "cy": "Rydych yn defnyddio #2 pensil yn hytrach na #3 pensil, ie?", "nl": "PROOST.", "de": "Jemand muss dich hassen", - "fr": "T'as utilisé un crayon #3 au lieu de #2, n'est-ce pas ?" + "fr": "T'as utilisé un crayon #3 au lieu d'un #2, n'est-ce pas ?" }, "rain-9": { "en" : "WELCOME TO ATLANTIS", From 1f7c247b94666904fb6394b06053a91a307410a2 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 21:21:23 +0200 Subject: [PATCH 204/220] add French translation --- modules/report/strings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/report/strings.json b/modules/report/strings.json index 3c4e697..15068af 100644 --- a/modules/report/strings.json +++ b/modules/report/strings.json @@ -32,7 +32,8 @@ "fr": "Je ne suis pas présent dans {channel}." }, "notify": { - "en": "Attention {channel}: {notifier}: {message}" + "en": "Attention {channel}: {notifier}: {message}", + "fr": "Attention {channel}: {notifier}: {message}" }, "notified": { "en": "{user}: {channel} staff notified.", From b54070d7b3854d68703c6f729a7e5e7acde231ed Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 21:24:30 +0200 Subject: [PATCH 205/220] fixed wrong translation string locale --- modules/soundcloud/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/soundcloud/strings.json b/modules/soundcloud/strings.json index eab2a34..afd8a94 100644 --- a/modules/soundcloud/strings.json +++ b/modules/soundcloud/strings.json @@ -1,7 +1,7 @@ { "sc_track": { "en": "[{title} by {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]", - "en": "[{title} par {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]" + "fr": "[{title} par {artist} — {genre} — \u000312▶\u000f{plays} \u000304♥\u000f{favs}]" }, "sc_notrack": { "en": "No results found.", From 4fbbe39e7983ba6d9c92c8443bfa630e850d4d91 Mon Sep 17 00:00:00 2001 From: iceTwy Date: Thu, 11 Jul 2013 21:40:46 +0200 Subject: [PATCH 206/220] the LAST fr string --- modules/project/strings.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/project/strings.json b/modules/project/strings.json index 63f1f57..d731688 100644 --- a/modules/project/strings.json +++ b/modules/project/strings.json @@ -28,7 +28,7 @@ }, "en": { "en": "English", - "fr": "anglais", + "fr": "Anglais", "de": "Englisch", "it": "inglese", "cy": "saesneg", @@ -44,7 +44,7 @@ }, "de": { "en": "German", - "fr": "allemand", + "fr": "Allemand", "de": "Deutsch", "it": "tedesco", "cy": "Almaeneg", @@ -52,7 +52,7 @@ }, "it": { "en": "Italian", - "fr": "italien", + "fr": "Italien", "de": "Italiener", "it": "italiano", "cy": "Eidaleg", @@ -60,7 +60,7 @@ }, "cy": { "en": "Welsh", - "fr": "gallois", + "fr": "Gallois", "de": "Walisisch", "it": "gallese", "cy": "cymraeg", @@ -77,7 +77,7 @@ }, "es": { "en": "Spanish", - "fr": "espagnol", + "fr": "Espagnol", "de": "Spanisch", "it": "spagnolo", "cy": "Sbaeneg", @@ -87,7 +87,8 @@ "nl": { "en": "Dutch", "cy": "Iseldireg", - "nl": "Nederlands" + "nl": "Nederlands", + "fr": "Néerlandais" }, "revnum": { "en": "{name} is at revision {rev}", From f90a1b97b467ae9fabf5754f9f54791f1c9b595e Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Jul 2013 09:29:22 +0000 Subject: [PATCH 207/220] if user JOIN channel with !currentNick, update [#532] --- modules/users/users.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/users/users.js b/modules/users/users.js index e102f87..73c4ceb 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -95,7 +95,6 @@ var users = function(dbot) { }; this.listener = function(event) { - // TODO: If user joins channel with alias if(event.action == 'JOIN' && event.user != dbot.config.name) { if(!event.rUser) { this.internalAPI.createUser(event.server, event.user, function(user) { @@ -104,6 +103,11 @@ var users = function(dbot) { } else if(!_.include(event.rUser.channels, event.rChannel.id)) { this.internalAPI.addChannelUser(event.rChannel, event.rUser, function() {}); } + + if(event.rUser.currentNick != event.user) { + event.rUser.currentNick = event.user; + this.db.save('users', event.rUser.id, event.rUser, function() {}); + } } else if(event.action == 'NICK') { this.api.isKnownUser(event.server, event.newNick, function(isKnown) { event.rUser.currentNick = event.newNick; From 9abecc623232aef9068d93048c7b196932953fb0 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Jul 2013 09:50:51 +0000 Subject: [PATCH 208/220] derp [#533] --- modules/command/command.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/command/command.js b/modules/command/command.js index ba20716..aee612e 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -49,7 +49,7 @@ var command = function(dbot) { }); } } - if(_.include(commandName, ['reload', 'load', 'unload'])) dbot.api.event.emit('command', [ event ]); + if(!_.include(commandName, ['reload', 'load', 'unload'])) dbot.api.event.emit('command', [ event ]); dbot.save(); } else { if(commandName !== '~') { From 2bdfc55879cb00b4058fd841f81a00238de9275b Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Jul 2013 10:55:08 +0000 Subject: [PATCH 209/220] ffs --- modules/command/command.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/command/command.js b/modules/command/command.js index aee612e..94f3978 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -49,7 +49,7 @@ var command = function(dbot) { }); } } - if(!_.include(commandName, ['reload', 'load', 'unload'])) dbot.api.event.emit('command', [ event ]); + if(!_.include(commandName, ['~reload', '~load', '~unload'])) dbot.api.event.emit('command', [ event ]); dbot.save(); } else { if(commandName !== '~') { From b86987dc487e2b6d84515fdc4d11478e22260717 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Jul 2013 10:58:59 +0000 Subject: [PATCH 210/220] wat --- modules/command/command.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/command/command.js b/modules/command/command.js index 94f3978..13b3654 100644 --- a/modules/command/command.js +++ b/modules/command/command.js @@ -49,7 +49,7 @@ var command = function(dbot) { }); } } - if(!_.include(commandName, ['~reload', '~load', '~unload'])) dbot.api.event.emit('command', [ event ]); + if(!_.include(['~reload', '~load', '~unload'], commandName)) dbot.api.event.emit('command', [ event ]); dbot.save(); } else { if(commandName !== '~') { From 08843950dd3de5820c7d00b7d8a57fcccb61da0b Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Jul 2013 13:25:11 +0000 Subject: [PATCH 211/220] yee [#531] --- modules/users/users.js | 64 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/modules/users/users.js b/modules/users/users.js index 73c4ceb..0e0f53e 100644 --- a/modules/users/users.js +++ b/modules/users/users.js @@ -17,7 +17,7 @@ var users = function(dbot) { 'primaryNick': nick, 'currentNick': nick, 'server': server, - 'channels': [ ], + 'channels': [], 'aliases': [] }, function(err, result) { if(!err) { @@ -33,7 +33,9 @@ var users = function(dbot) { 'id': id, 'server': server, 'name': name, - 'users': [] + 'users': [], + 'op': [], + 'voice': [] }, function(err, result) { if(!err) { dbot.api.event.emit('new_channel', [ result ]); @@ -42,7 +44,7 @@ var users = function(dbot) { }); }.bind(this), - 'addChannelUser': function(channel, user, callback) { + 'addChannelUser': function(channel, user, staff, callback) { if(!_.include(channel.users, user.id)) { channel.users.push(user.id); } @@ -50,13 +52,57 @@ var users = function(dbot) { user.channels.push(channel.id); } + if(!channel.op) channel.op = []; + if(!channel.voice) channel.voice = []; + + if(staff.op) { + channel.op.push(user.id); + } else if(staff.voice) { + channel.voice.push(user.id); + } + this.db.save('users', user.id, user, function(err) { this.db.save('channel_users', channel.id, channel, function(err) { dbot.api.event.emit('new_channel_user', [ user, channel ]); callback(err); }); }.bind(this)); - }.bind(this), + }.bind(this), + + 'modChannelStaff': function(channel, user, staff, callback) { + var needsUpdating = false; + + if(!channel.op) { + channel.op = []; + needsUpdating = true; + } + if(!channel.voice) { + channel.voice = []; + needsUpdating = true; + } + + if(!_.include(channel.op, user.id) && staff.op) { + channel.op.push(user.id); + needsUpdating = true; + } else if(!_.include(channel.voice, user.id) && staff.voice) { + channel.voice.push(user.id); + needsUpdating = true; + } else if(_.include(channel.op, user.id) && !staff.op) { + channel.op = _.without(channel.op, user.id); + needsUpdating = true; + } else if(_.include(channel.voice, user.id) && !staff.voice) { + channel.voice = _.without(channel.voice, user.id); + needsUpdating = true; + } + + if(needsUpdating) { + this.db.save('channel_users', channel.id, channel, function(err) { + callback(err); + }); + } else { + callback(); + } + }.bind(this), 'updateChannelPrimaryUser': function(server, oldUser, newUser) { this.db.search('channel_users', { 'server': server }, function(channel) { @@ -98,10 +144,10 @@ var users = function(dbot) { if(event.action == 'JOIN' && event.user != dbot.config.name) { if(!event.rUser) { this.internalAPI.createUser(event.server, event.user, function(user) { - this.internalAPI.addChannelUser(event.rChannel, user, function() {}); + this.internalAPI.addChannelUser(event.rChannel, user, {}, function() {}); }.bind(this)); } else if(!_.include(event.rUser.channels, event.rChannel.id)) { - this.internalAPI.addChannelUser(event.rChannel, event.rUser, function() {}); + this.internalAPI.addChannelUser(event.rChannel, event.rUser, {}, function() {}); } if(event.rUser.currentNick != event.user) { @@ -150,12 +196,14 @@ var users = function(dbot) { dbot.instance.addListener('366', 'users', function(event) { var checkChannel = function(channel) { async.eachSeries(_.keys(event.channel.nicks), function(nick, next) { + var staff = event.channel.nicks[nick]; + this.api.resolveUser(event.server, nick, function(user) { var checkChannelUser = function(user) { if(!_.include(channel.users, user.id)) { - this.internalAPI.addChannelUser(channel, user, next); + this.internalAPI.addChannelUser(channel, user, staff, next); } else { - next(); + this.internalAPI.modChannelStaff(channel, user, staff, next); } }.bind(this); From 2203f50dea2153ffc8f0138defe753b31ed65b33 Mon Sep 17 00:00:00 2001 From: reality Date: Sun, 14 Jul 2013 14:55:15 +0000 Subject: [PATCH 212/220] testing version of [#530] --- modules/admin/commands.js | 11 +++++++++-- modules/report/report.js | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/modules/admin/commands.js b/modules/admin/commands.js index 252c234..9ca3d0d 100644 --- a/modules/admin/commands.js +++ b/modules/admin/commands.js @@ -185,8 +185,15 @@ var commands = function(dbot) { event.reply(dbot.t("config_array", { "alternate": "pushconfig" })); } } else { - event.reply(dbot.t('new_config_key', { 'key': configPath })); - config = null; + topConfigPath = configPath.split('.')[0]; + if(_.has(dbot.config.modules, topConfigPath)) { + configPath.splice(0, 0, 'modules'); + event.params[1] = configPath.join('.'); + this.commands['~showconfig'](event); + return; + } else { + event.reply(dbot.t('new_config_key', { 'key': configPath })); + } } this.internalAPI.setConfig(configPath, newOption, function(err) { diff --git a/modules/report/report.js b/modules/report/report.js index 52e50c4..b196147 100644 --- a/modules/report/report.js +++ b/modules/report/report.js @@ -1,7 +1,11 @@ var _ = require('underscore')._, - uuid = require('node-uuid'); + uuid = require('node-uuid'), + async = require('async'); var report = function(dbot) { + if(!dbot.db.pending) dbot.db.pending = {}; + this.pending = dbot.db.pending; + this.api = { 'notify': function(server, channel, message) { var channel = dbot.instance.connections[server].channels[channel]; @@ -13,6 +17,25 @@ var report = function(dbot) { } }, this); + dbot.api.users.getChannel(server, channel, function(channel) { + if(channel) { + var perOps = channel.op; + if(this.config.notifyVoice) pOps = _.union(perOps, channel.voice); + + async.eachSeries(ops, function(nick, next) { + dbot.api.users.resolveUser(server, nick, function(user) { + perOps = _.without(perOps, user.id); next(); + }); + }, function() { + offlineUsers = perOps; + _.each(offlineUsers, function(id) { + if(!this.pending[id]) this.pending[id] = []; + this.pending[id].push(message); + }.bind(this)); + }.bind(this)); + } + }.bind(this)); + var i = 0; var notifyChannel = function(ops) { if(i >= ops.length) return; @@ -25,10 +48,20 @@ var report = function(dbot) { } }; + this.listener = function(event) { + if(_.has(this.pending, event.rUser.id)) { + _.each(this.pending[event.rUser.id], function(message) { + dbot.say(event.server, event.rUser.currentNick, message); + }); + delete this.pending[event.rUser.id]; + } + }.bind(this); + this.on = 'JOIN'; + var commands = { '~report': function(event) { var channelName = event.input[1], - nick = event.input[2]; + nick = event.input[2], reason = event.input[3]; dbot.api.users.resolveUser(event.server, nick, function(reportee) { From d9d7d9bff734dddcec5c9a5a7482b5cc445528ff Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 15 Jul 2013 18:51:32 +0000 Subject: [PATCH 213/220] fix the things --- run.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/run.js b/run.js index a9f202d..839bf21 100644 --- a/run.js +++ b/run.js @@ -281,11 +281,8 @@ DBot.prototype.reloadModules = function() { try { propertyData = JSON.parse(fs.readFileSync(moduleDir + property + '.json', 'utf-8')); } catch(err) { - this.status[name] = 'Error loading ' + property + - ': ' + err + ' - ' + err.stack.split('\n')[1].trim(); console.log('Data error (' + module.name + ') in ' + property + ': ' + err); - }; _.extend(this[property], propertyData); if(property == 'strings') { From 9dea85730d2412075437f283989700a05f1b4009 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 15 Jul 2013 18:52:40 +0000 Subject: [PATCH 214/220] youtube link handle thing [#534] --- modules/youtube/config.json | 3 +++ modules/youtube/strings.json | 5 +++++ modules/youtube/youtube.js | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 modules/youtube/config.json create mode 100644 modules/youtube/strings.json create mode 100644 modules/youtube/youtube.js diff --git a/modules/youtube/config.json b/modules/youtube/config.json new file mode 100644 index 0000000..e8e1bae --- /dev/null +++ b/modules/youtube/config.json @@ -0,0 +1,3 @@ +{ + "outputPrefix": "\u000305youtube\u000f" +} diff --git a/modules/youtube/strings.json b/modules/youtube/strings.json new file mode 100644 index 0000000..5afff8d --- /dev/null +++ b/modules/youtube/strings.json @@ -0,0 +1,5 @@ +{ + "yt_video": { + "en": "[{title} by {author} — \u000312▶\u000f{plays} (\u00039▲{likes}\u000f|\u000312{dislikes}▼\u000f)]" + } +} diff --git a/modules/youtube/youtube.js b/modules/youtube/youtube.js new file mode 100644 index 0000000..dbb59a6 --- /dev/null +++ b/modules/youtube/youtube.js @@ -0,0 +1,40 @@ +/** + * Module Name: youtube + * Description: Various Youtube functionality + */ +var _ = require('underscore')._, + request = require('request'); + +var youtube = function(dbot) { + this.ApiRoot = 'https://gdata.youtube.com/feeds/api'; + this.params = { + 'alt': 'json', + 'v': 2 + }; + + this.onLoad = function() { + dbot.api.link.addHandler(this.name, + /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/, + function(event, match, name) { + request.get(this.ApiRoot + '/videos/' + match[2], { + 'qs': this.params, + 'json': true + }, function(error, response, body) { + if(_.isObject(body) && _.has(body, 'entry')) { + var v = body.entry; + event.reply(dbot.t('yt_video', { + 'title': v.title['$t'], + 'plays': v['yt$statistics'].viewCount, + 'author': v.author[0].name['$t'], + 'likes': v['yt$rating'].numLikes, + 'dislikes': v['yt$rating'].numDislikes + })); + } + }); + }.bind(this)); + }.bind(this); +}; + +exports.fetch = function(dbot) { + return new youtube(dbot); +}; From 2c2b501c73fbd5d534ed2d72e8a7646c9b2d88d8 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 15 Jul 2013 19:19:17 +0000 Subject: [PATCH 215/220] thing --- modules/youtube/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/youtube/config.json b/modules/youtube/config.json index e8e1bae..7d3ebcf 100644 --- a/modules/youtube/config.json +++ b/modules/youtube/config.json @@ -1,3 +1,3 @@ { - "outputPrefix": "\u000305youtube\u000f" + "outputPrefix": "\u000407You\u000474Tube\u000f" } From cd93987919750a3afa7c06b534bfc71ec07b76f8 Mon Sep 17 00:00:00 2001 From: reality Date: Mon, 15 Jul 2013 19:30:00 +0000 Subject: [PATCH 216/220] ok this should do it --- modules/youtube/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/youtube/config.json b/modules/youtube/config.json index 7d3ebcf..ce5cb36 100644 --- a/modules/youtube/config.json +++ b/modules/youtube/config.json @@ -1,3 +1,3 @@ { - "outputPrefix": "\u000407You\u000474Tube\u000f" + "outputPrefix": "\u00031,0You\u000315,5Tube\u000f" } From f2d93d2f184ad1c0a9318a9d6b9a6cf23416cf38 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 19 Jul 2013 20:15:50 +0000 Subject: [PATCH 217/220] youtube search --- modules/youtube/strings.json | 3 +++ modules/youtube/youtube.js | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/modules/youtube/strings.json b/modules/youtube/strings.json index 5afff8d..3e5a413 100644 --- a/modules/youtube/strings.json +++ b/modules/youtube/strings.json @@ -1,5 +1,8 @@ { "yt_video": { "en": "[{title} by {author} — \u000312▶\u000f{plays} (\u00039▲{likes}\u000f|\u000312{dislikes}▼\u000f)]" + }, + "yt_noresults": { + "en": "No results found." } } diff --git a/modules/youtube/youtube.js b/modules/youtube/youtube.js index dbb59a6..f0cf892 100644 --- a/modules/youtube/youtube.js +++ b/modules/youtube/youtube.js @@ -12,6 +12,32 @@ var youtube = function(dbot) { 'v': 2 }; + this.commands = { + '~youtube': function(event) { + request.get(this.ApiRoot + '/videos', { + 'qs': _.extend(this.params, { + 'q': encodeURIComponent(event.input[1]), + 'max-results': 1 + }), + 'json': true + }, function(error, response, body) { + if(_.isObject(body) && _.has(body, 'feed') && _.has(body.feed, 'entry')) { + var v = body.feed.entry[0]; + event.reply(dbot.t('yt_video', { + 'title': v.title['$t'], + 'plays': v['yt$statistics'].viewCount, + 'author': v.author[0].name['$t'], + 'likes': v['yt$rating'].numLikes, + 'dislikes': v['yt$rating'].numDislikes + })); + } else { + event.reply(dbot.t('yt_noresults')); + } + }); + } + }; + this.commands['~youtube'].regex = [/^~youtube (.+)$/, 2]; + this.onLoad = function() { dbot.api.link.addHandler(this.name, /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/, From a1a292846d9602917b11e763b1223f0b16f2d306 Mon Sep 17 00:00:00 2001 From: reality Date: Fri, 19 Jul 2013 20:20:59 +0000 Subject: [PATCH 218/220] dumbass --- modules/youtube/youtube.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/youtube/youtube.js b/modules/youtube/youtube.js index f0cf892..868b1d4 100644 --- a/modules/youtube/youtube.js +++ b/modules/youtube/youtube.js @@ -21,7 +21,8 @@ var youtube = function(dbot) { }), 'json': true }, function(error, response, body) { - if(_.isObject(body) && _.has(body, 'feed') && _.has(body.feed, 'entry')) { + if(_.isObject(body) && _.has(body, 'feed') && _.has(body.feed, + 'entry') && _.has(body.feed.entry[0], 'yt$statistics')) { var v = body.feed.entry[0]; event.reply(dbot.t('yt_video', { 'title': v.title['$t'], From 879bbf63b582b6081f168c94601b1b09160d019f Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 24 Jul 2013 18:02:06 +0000 Subject: [PATCH 219/220] fix youtube --- modules/youtube/youtube.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/youtube/youtube.js b/modules/youtube/youtube.js index 868b1d4..9c24705 100644 --- a/modules/youtube/youtube.js +++ b/modules/youtube/youtube.js @@ -48,6 +48,12 @@ var youtube = function(dbot) { 'json': true }, function(error, response, body) { if(_.isObject(body) && _.has(body, 'entry')) { + if(!_.has(v, 'yt$rating')) { + v['yt$rating'] = { + 'numLikes': 0, + 'numDislikes': 0 + }; + } var v = body.entry; event.reply(dbot.t('yt_video', { 'title': v.title['$t'], From 79eaf8c56e51f370620f3b4b62ddfd6a67fcd0d7 Mon Sep 17 00:00:00 2001 From: reality Date: Wed, 24 Jul 2013 18:06:39 +0000 Subject: [PATCH 220/220] fix youtube again --- modules/youtube/youtube.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/youtube/youtube.js b/modules/youtube/youtube.js index 9c24705..30bc33f 100644 --- a/modules/youtube/youtube.js +++ b/modules/youtube/youtube.js @@ -24,6 +24,12 @@ var youtube = function(dbot) { if(_.isObject(body) && _.has(body, 'feed') && _.has(body.feed, 'entry') && _.has(body.feed.entry[0], 'yt$statistics')) { var v = body.feed.entry[0]; + if(!_.has(v, 'yt$rating')) { + v['yt$rating'] = { + 'numLikes': 0, + 'numDislikes': 0 + }; + } event.reply(dbot.t('yt_video', { 'title': v.title['$t'], 'plays': v['yt$statistics'].viewCount, @@ -48,13 +54,13 @@ var youtube = function(dbot) { 'json': true }, function(error, response, body) { if(_.isObject(body) && _.has(body, 'entry')) { + var v = body.entry; if(!_.has(v, 'yt$rating')) { v['yt$rating'] = { 'numLikes': 0, 'numDislikes': 0 }; } - var v = body.entry; event.reply(dbot.t('yt_video', { 'title': v.title['$t'], 'plays': v['yt$statistics'].viewCount,