2011-08-16 18:41:29 +02:00
|
|
|
var fs = require('fs');
|
2011-09-04 16:39:03 +02:00
|
|
|
var timers = require('./timer');
|
2011-08-18 19:03:00 +02:00
|
|
|
var jsbot = require('./jsbot');
|
2011-09-04 16:39:03 +02:00
|
|
|
require('./snippets');
|
2011-08-23 01:04:40 +02:00
|
|
|
|
2012-02-11 17:02:16 +01:00
|
|
|
var DBot = function(timers) {
|
2012-02-13 20:56:04 +01:00
|
|
|
// Load external files
|
2011-11-09 22:54:16 +01:00
|
|
|
this.config = JSON.parse(fs.readFileSync('config.json', 'utf-8'));
|
2012-03-07 00:54:52 +01:00
|
|
|
try {
|
|
|
|
this.db = JSON.parse(fs.readFileSync('db.json', 'utf-8'));
|
|
|
|
} catch (e) {
|
|
|
|
this.db = {};
|
|
|
|
} finally { /* fill any missing parts of the db; if this is a new DB, that's all of them */
|
|
|
|
if(!this.db.hasOwnProperty("bans")) {
|
|
|
|
this.db.bans = {};
|
|
|
|
}
|
|
|
|
if(!this.db.bans.hasOwnProperty("*")) {
|
|
|
|
this.db.bans["*"] = [];
|
|
|
|
}
|
|
|
|
if(!this.db.hasOwnProperty("quoteArrs")) {
|
|
|
|
this.db.quoteArrs = {};
|
|
|
|
}
|
2012-03-07 05:25:07 +01:00
|
|
|
if(!this.db.quoteArrs.hasOwnProperty("realityonce")) {
|
|
|
|
this.db.quoteArrs.realityonce = [];
|
|
|
|
}
|
2012-03-07 00:54:52 +01:00
|
|
|
if(!this.db.hasOwnProperty("kicks")) {
|
|
|
|
this.db.kicks = {};
|
|
|
|
}
|
|
|
|
if(!this.db.hasOwnProperty("kickers")) {
|
|
|
|
this.db.kickers = {};
|
|
|
|
}
|
|
|
|
if(!this.db.hasOwnProperty("modehate")) {
|
|
|
|
this.db.modehate = [];
|
|
|
|
}
|
|
|
|
if(!this.db.hasOwnProperty("locks")) {
|
|
|
|
this.db.locks = [];
|
|
|
|
}
|
|
|
|
}
|
2011-08-24 02:57:52 +02:00
|
|
|
|
2012-02-13 20:56:04 +01:00
|
|
|
// Populate bot properties with config data
|
2011-11-27 13:52:04 +01:00
|
|
|
this.name = this.config.name || 'dbox';
|
2011-11-09 22:54:16 +01:00
|
|
|
this.admin = this.config.admin || 'reality';
|
2011-11-24 14:19:18 +01:00
|
|
|
this.password = this.config.password || 'lolturtles';
|
2011-11-27 13:52:04 +01:00
|
|
|
this.nickserv = this.config.nickserv || 'zippy';
|
2011-11-27 19:25:54 +01:00
|
|
|
this.server = this.config.server || 'elara.ivixor.net';
|
|
|
|
this.port = this.config.port || 6667;
|
2012-02-11 17:27:30 +01:00
|
|
|
this.moduleNames = this.config.modules || [ 'js', 'admin', 'kick', 'modehate', 'quotes', 'puns', 'spelling', 'web', 'youare' ];
|
2011-11-09 22:54:16 +01:00
|
|
|
|
|
|
|
this.timers = timers.create();
|
2011-10-31 18:07:14 +01:00
|
|
|
|
2011-11-27 19:25:54 +01:00
|
|
|
this.instance = jsbot.createJSBot(this.name, this.server, this.port, this, function() {
|
2011-11-24 14:19:18 +01:00
|
|
|
if(this.config.hasOwnProperty('channels')) {
|
|
|
|
this.config.channels.each(function(channel) {
|
|
|
|
this.instance.join(channel);
|
|
|
|
}.bind(this));
|
2011-11-09 22:54:16 +01:00
|
|
|
}
|
2011-11-27 13:52:04 +01:00
|
|
|
}.bind(this), this.nickserv, this.password);
|
2011-08-24 02:57:52 +02:00
|
|
|
|
2012-02-13 20:56:04 +01:00
|
|
|
// Load the modules and connect to the server
|
2011-08-24 02:57:52 +02:00
|
|
|
this.reloadModules();
|
|
|
|
this.instance.connect();
|
|
|
|
};
|
|
|
|
|
2012-03-07 23:13:31 +01:00
|
|
|
// Retrieve a random quote from a given category, interpolating any quote references (~~QUOTE CATEGORY~~) within it
|
|
|
|
DBot.prototype.interpolatedQuote = function(key) {
|
|
|
|
var quoteString = this.db.quoteArrs[key].random();
|
|
|
|
var quoteRefs = quoteString.match(/~~([\d\w\s-]*)~~/);
|
|
|
|
if (quoteRefs) {
|
|
|
|
quoteRefs = quoteRefs.slice(1);
|
|
|
|
for(var i=0;i<quoteRefs.length;i++) {
|
|
|
|
var cleanRef = this.cleanNick(quoteRefs[i].trim());
|
|
|
|
if (this.db.quoteArrs.hasOwnProperty(cleanRef)) {
|
|
|
|
quoteString = quoteString.replace("~~"+cleanRef+"~~", this.db.quoteArrs[cleanRef].random());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return quoteString;
|
|
|
|
};
|
|
|
|
|
2012-02-13 20:56:04 +01:00
|
|
|
// Say something in a channel
|
2011-08-24 02:57:52 +02:00
|
|
|
DBot.prototype.say = function(channel, data) {
|
|
|
|
this.instance.say(channel, data);
|
|
|
|
};
|
|
|
|
|
2012-02-27 17:43:47 +01:00
|
|
|
DBot.prototype.act = function(channel, data) {
|
2012-03-09 22:44:05 +01:00
|
|
|
this.instance.send('PRIVMSG', channel, ':\001ACTION ' + data + '\001');
|
2012-02-27 17:43:47 +01:00
|
|
|
}
|
|
|
|
|
2012-02-13 20:56:04 +01:00
|
|
|
// Save the database file
|
2011-08-24 02:57:52 +02:00
|
|
|
DBot.prototype.save = function() {
|
2011-10-12 16:12:06 +02:00
|
|
|
fs.writeFile('db.json', JSON.stringify(this.db, null, ' '));
|
2011-08-24 02:57:52 +02:00
|
|
|
};
|
|
|
|
|
2012-02-13 20:56:04 +01:00
|
|
|
// Hot-reload module files.
|
2011-08-24 02:57:52 +02:00
|
|
|
DBot.prototype.reloadModules = function() {
|
2012-02-13 20:56:04 +01:00
|
|
|
if(this.modules) { // Run 'onDestroy' code for each module if it exists.
|
2011-09-14 18:31:26 +02:00
|
|
|
this.modules.each(function(module) {
|
|
|
|
if(module.onDestroy) {
|
|
|
|
module.onDestroy();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2011-09-14 18:30:39 +02:00
|
|
|
|
2011-08-24 02:57:52 +02:00
|
|
|
this.rawModules = [];
|
|
|
|
this.modules = [];
|
2011-08-28 16:00:22 +02:00
|
|
|
this.commands = {};
|
2011-09-04 16:39:03 +02:00
|
|
|
this.timers.clearTimers();
|
2011-10-12 15:52:58 +02:00
|
|
|
this.save();
|
|
|
|
|
2012-02-13 20:56:04 +01:00
|
|
|
// Reload Javascript snippets
|
2011-08-25 18:54:59 +02:00
|
|
|
var path = require.resolve('./snippets');
|
2012-02-08 19:42:38 +01:00
|
|
|
delete require.cache[path];
|
2011-08-25 18:54:59 +02:00
|
|
|
require('./snippets');
|
|
|
|
|
2011-08-24 02:57:52 +02:00
|
|
|
this.moduleNames.each(function(name) {
|
2011-08-24 17:15:42 +02:00
|
|
|
var cacheKey = require.resolve('./modules/' + name);
|
2012-02-08 19:42:38 +01:00
|
|
|
delete require.cache[cacheKey];
|
2011-08-24 19:23:00 +02:00
|
|
|
try {
|
|
|
|
this.rawModules.push(require('./modules/' + name));
|
|
|
|
} catch(err) {
|
|
|
|
console.log('Failed to load module: ' + name);
|
|
|
|
}
|
2011-08-24 02:57:52 +02:00
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
this.instance.removeListeners();
|
|
|
|
|
|
|
|
this.modules = this.rawModules.collect(function(rawModule) {
|
|
|
|
var module = rawModule.fetch(this);
|
2011-08-28 16:00:22 +02:00
|
|
|
|
|
|
|
if(module.listener) {
|
|
|
|
this.instance.addListener(module.on, module.listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(module.onLoad) {
|
|
|
|
var newCommands = module.onLoad();
|
|
|
|
for(key in newCommands) {
|
|
|
|
if(newCommands.hasOwnProperty(key) && Object.prototype.isFunction(newCommands[key])) {
|
|
|
|
this.commands[key] = newCommands[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-24 02:57:52 +02:00
|
|
|
return module;
|
|
|
|
}.bind(this));
|
2011-08-28 16:00:22 +02:00
|
|
|
|
|
|
|
this.instance.addListener('PRIVMSG', function(data) {
|
|
|
|
params = data.message.split(' ');
|
|
|
|
if(data.channel == this.name) data.channel = data.user;
|
|
|
|
|
|
|
|
if(this.commands.hasOwnProperty(params[0])) {
|
2011-11-27 19:25:54 +01:00
|
|
|
if((this.db.bans.hasOwnProperty(params[0]) &&
|
|
|
|
this.db.bans[params[0]].include(data.user)) || this.db.bans['*'].include(data.user))
|
|
|
|
this.say(data.channel, data.user +
|
|
|
|
' is banned from using this command. Commence incineration.');
|
2011-10-10 14:41:50 +02:00
|
|
|
else {
|
2011-10-09 17:06:28 +02:00
|
|
|
this.commands[params[0]](data, params);
|
2011-10-12 16:12:06 +02:00
|
|
|
this.save();
|
2011-10-09 17:06:28 +02:00
|
|
|
}
|
2011-08-28 16:00:22 +02:00
|
|
|
} else {
|
2012-02-15 21:39:11 +01:00
|
|
|
var q = data.message.valMatch(/^~([\d\w\s-]*)/, 2);
|
|
|
|
if(q) {
|
2012-03-06 15:44:38 +01:00
|
|
|
if(this.db.bans['*'].include(data.user)) {
|
|
|
|
this.say(data.channel, data.user +
|
|
|
|
' is banned from using this command. Commence incineration.');
|
|
|
|
} else {
|
|
|
|
q[1] = q[1].trim();
|
|
|
|
key = this.cleanNick(q[1])
|
|
|
|
if(this.db.quoteArrs.hasOwnProperty(key)) {
|
2012-03-07 23:13:31 +01:00
|
|
|
this.say(data.channel, q[1] + ': ' + this.interpolatedQuote(key));
|
2011-12-09 02:35:39 +01:00
|
|
|
} else {
|
2012-03-06 15:44:38 +01:00
|
|
|
// See if it's similar to anything
|
|
|
|
var winnerDistance = Infinity;
|
|
|
|
var winner = false;
|
|
|
|
for(var commandName in this.commands) {
|
|
|
|
var distance = String.prototype.distance(params[0], commandName);
|
|
|
|
if(distance < winnerDistance) {
|
|
|
|
winner = commandName;
|
|
|
|
winnerDistance = distance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(winnerDistance < 3) {
|
|
|
|
this.say(data.channel, 'Did you mean ' + winner + '? Learn to type, hippie!');
|
2012-02-15 21:29:37 +01:00
|
|
|
}
|
2011-12-09 02:35:39 +01:00
|
|
|
}
|
2011-08-28 18:16:28 +02:00
|
|
|
}
|
2011-08-28 16:00:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}.bind(this));
|
2011-08-24 02:57:52 +02:00
|
|
|
};
|
|
|
|
|
2011-11-10 20:36:01 +01:00
|
|
|
DBot.prototype.cleanNick = function(key) {
|
|
|
|
key = key.toLowerCase();
|
|
|
|
while(key.endsWith("_")) {
|
|
|
|
if(this.db.quoteArrs.hasOwnProperty(key)) {
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
key = key.substring(0, key.length-1);
|
|
|
|
}
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
2012-02-11 17:26:29 +01:00
|
|
|
new DBot(timers);
|