summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2012-06-16 14:24:33 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2012-06-16 14:24:33 +0200
commit2870c4da1aedf41926972dd60227c3d62cdaa123 (patch)
treebab887acdac4969c8a4cc3fcaf827ebb81726f6c
parente971ae61c99c8a602a1d60c95e9f8f908d4cf053 (diff)
downloaddynobot-irc-2870c4da1aedf41926972dd60227c3d62cdaa123.tar.gz
dynobot-irc-2870c4da1aedf41926972dd60227c3d62cdaa123.tar.bz2
dynobot-irc-2870c4da1aedf41926972dd60227c3d62cdaa123.tar.xz
dynobot-irc-2870c4da1aedf41926972dd60227c3d62cdaa123.zip
o Polishing the dynobot a bit.
-rw-r--r--FakeSocket.js44
-rw-r--r--Repl.js82
-rw-r--r--atom-bot/index.js25
-rw-r--r--dynobot-irc.js183
-rw-r--r--echo-bot/index.js2
-rw-r--r--irc-client.js20
-rw-r--r--ngircd.conf5
7 files changed, 214 insertions, 147 deletions
diff --git a/FakeSocket.js b/FakeSocket.js
new file mode 100644
index 0000000..af3d74c
--- /dev/null
+++ b/FakeSocket.js
@@ -0,0 +1,44 @@
+function FakeSocket(stdin, stdout, msgHandler) {
+ this.stdin = stdin;
+ this.stdout = stdout;
+ this.msgHandler = msgHandler;
+ this.connectHandler = undefined;
+ this.errorHandler = undefined;
+}
+
+FakeSocket.prototype.setEncoding = function(encoding) {
+ this.stdin.setEncoding(encoding);
+}
+
+FakeSocket.prototype.on = function(event, cb) {
+ switch(event) {
+ case 'data':
+ this.stdin.on('data', function(chunk) {
+ cb(chunk.trim() + '\r\n');
+ });
+ break;
+ case 'connect':
+ this.connectHandler = cb;
+ break;
+ case 'close':
+ this.stdin.on('exit', cb);
+ break;
+ case 'end':
+ case 'error':
+ break;
+ default:
+ process.exit(1);
+ break;
+ }
+}
+
+FakeSocket.prototype.connect = function(server, port) {
+ this.connectHandler();
+}
+
+FakeSocket.prototype.write = function(chunk) {
+ this.stdout.write(chunk.red);
+ this.msgHandler && this.msgHandler(chunk);
+}
+
+module.exports = FakeSocket;
diff --git a/Repl.js b/Repl.js
new file mode 100644
index 0000000..cce93d0
--- /dev/null
+++ b/Repl.js
@@ -0,0 +1,82 @@
+var rl = require('readline');
+
+function quit() {
+ i.close();
+ process.stdin.destroy();
+ process.exit(0);
+}
+
+var i;
+
+module.exports.init = function() {
+ process.stdin.resume();
+ i = rl.createInterface(process.stdin, process.stdout, null);
+}
+
+module.exports.setupRepl = function() {
+}
+
+module.exports.setupSimulatorRepl = function(config) {
+ var from = 'alice!~alice@example.com';
+ var channel = config.channel;
+
+ function updatePrompt() {
+ var prefix = 'from=' + from;
+ prefix += channel ? ', channel=' + channel : '';
+ prefix += '> ';
+ i.setPrompt(prefix, prefix.length);
+ i.prompt();
+ }
+
+ i.on('line', function (cmd) {
+ cmd = cmd.trim();
+ if(cmd.length == 0) {
+ i.prompt();
+ return;
+ }
+ var parts = cmd.split(' ');
+ switch(parts[0]) {
+ case '/quit':
+ case '/q':
+ quit();
+ break;
+ case '/raw':
+ case '/r':
+ parts.shift();
+ stdinPipe.send(parts.join(' '));
+ updatePrompt();
+ break;
+ case '/join':
+ case '/j':
+ channel = parts[1];
+ updatePrompt();
+ break;
+ case '/from':
+ case '/f':
+ from = parts[1];
+ updatePrompt();
+ break;
+ case '/notice':
+ case '/n':
+ if(channel) {
+ parts.shift();
+ stdinPipe.send(':' + from + ' NOTICE ' + channel + ' :' + parts.join(' '));
+ }
+ else {
+ info('You have to /j a channel first');
+ }
+ break;
+ default:
+ stdinPipe.send(':' + from + ' PRIVMSG ' + channel + ' :' + parts.join(' '));
+ updatePrompt();
+ break;
+ }
+ }).on('close', function() {
+ quit();
+ });
+ updatePrompt();
+
+ setTimeout(function() {
+ stdinPipe.send(':irc.foo.bar 001 this :Welcome to Some Internet Relay Chat Network this');
+ }, 1000);
+}
diff --git a/atom-bot/index.js b/atom-bot/index.js
index 470786c..7de99bc 100644
--- a/atom-bot/index.js
+++ b/atom-bot/index.js
@@ -34,10 +34,14 @@ var irc = function() {
return new Proxy(IrcClient.prototype, 'irc', channel);
}();
+function log(message) {
+ console.log(('log ' + message).green);
+}
+
var parserOptions = {};
// Config
-var channel = '#bitraf2';
+var channel = '#dynobot';
var feeds = [
// "http://search.twitter.com/search.atom?q=from:AgileBorat",
// "http://search.twitter.com/search.atom?q=from:KongenDin",
@@ -62,15 +66,15 @@ var state = {
var eventEmitter = new events.EventEmitter;
function updateFeed(feedState) {
- console.log("Fetching " + feedState.url);
+ log("Fetching " + feedState.url);
if(feedState.updatingFeed)
- console.log("Already working");
+ log("Already working");
feedState.updatingFeed = true;
parser.parseURL(feedState.url, parserOptions, function(err, feed) {
- console.log("Fetched " + feedState.url + ", status=" + (err ? "failure" : "success"));
+ log("Fetched " + feedState.url + ", status=" + (err ? "failure" : "success"));
if(err) {
- console.log(err);
+ log(err);
return;
}
var newest = processFeed(feed);
@@ -86,7 +90,8 @@ function processFeed(feed) {
// TODO: Use something better than blindparser to parse atom so that
// each entry has an author too to get the full name.
if(typeof feed.items[0] == "undefined") {
- console.log("feed does not contain any items", feed);
+ log("feed does not contain any items");
+ log(feed);
return undefined;
}
var match = /^http:\/\/twitter.com\/([a-zA-Z0-9_]+)\/.*$/.exec(feed.items[0].link)
@@ -104,14 +109,14 @@ eventEmitter.on("feedChanged", function(url, newest) {
state.feeds[url] = newest;
if(state.newest.timestamp >= newest.timestamp) {
- console.log("oold: " + newest.text);
+ log("oold: " + newest.text);
return;
}
/*
*/
var text = newest.author + ": " + newest.text;
- console.log("New topic", newest.timestamp, url, text);
+ log("New topic: " + newest.timestamp + ", url=" + url + ", text=" + text);
state.newest = newest;
/*
if(state.channelTopic != text) {
@@ -122,7 +127,7 @@ eventEmitter.on("feedChanged", function(url, newest) {
});
function setup() {
- console.log("Stopping " + cronJobs.length + " cron jobs");
+ log("Stopping " + cronJobs.length + " cron jobs");
_.each(cronJobs, function(job) { job.stop(); });
cronJobs = [];
_.each(feeds, function(feed) {
@@ -143,7 +148,7 @@ irc.join(channel, function(c) {
});
irc.on('topic', function(channel, topic) {
- console.log("new topic: " + topic);
+ log("new topic: " + topic);
/* If we're not storing this, it is possible for people to set
* the topic after the bot has set it and it will persist (until
* next update from the feed).
diff --git a/dynobot-irc.js b/dynobot-irc.js
index 8258930..9cae258 100644
--- a/dynobot-irc.js
+++ b/dynobot-irc.js
@@ -1,60 +1,46 @@
require('tinycolor');
-var EventEmitter = require('events').EventEmitter;
-var util = require('util');
+var Channel = require('dynobot/channel.js');
+var cmdopt = require('cmdopt')
var cp = require('child_process');
+var EventEmitter = require('events').EventEmitter;
+var FakeSocket = require('./FakeSocket.js');
var IrcClient = require('./irc-client').IrcClient;
-var Service = require('dynobot/service.js');
-var Channel = require('dynobot/channel.js');
+var os = require('os')
var _ = require('underscore');
-var rl = require('readline');
-
-/************************************************************/
-
-function FakeSocket(stdin, stdout, msgHandler) {
- this.stdin = stdin;
- this.stdout = stdout;
- this.msgHandler = msgHandler;
- this.connectHandler = undefined;
- this.errorHandler = undefined;
-}
-
-FakeSocket.prototype.setEncoding = function(encoding) {
- this.stdin.setEncoding(encoding);
-}
+var Service = require('dynobot/service.js');
+var util = require('util');
-FakeSocket.prototype.on = function(event, cb) {
- switch(event) {
- case 'data':
- this.stdin.on('data', function(chunk) {
- cb(chunk.trim() + '\r\n');
- });
- break;
- case 'connect':
- this.connectHandler = cb;
- break;
- case 'close':
- this.stdin.on('exit', cb);
- break;
- case 'end':
- case 'error':
- break;
- default:
- process.exit(1);
- break;
+var parser = new cmdopt.Parser();
+parser.option("-h, --help", "Show this help");
+parser.option("-s, --server=HOST", "Server to join");
+parser.option("-p, --port=PORT", "Port to use");
+parser.option("-n, --nick=NICK", "Nickname of the bot");
+parser.option("-c, --channel=CHANNEL", "IRC channel to join");
+
+var args = process.argv.slice(2);
+var defaults = {
+ server: "irc.freenode.org",
+ port: "6667",
+ nick: os.hostname(),
+ channel: "#dynobot"
+};
+
+try {
+ var config = parser.parse(args);
+ if (config.help) {
+ console.log(parser.help());
+ return;
}
+ config = _.defaults(config, defaults);
+ console.log("config", config);
+} catch (ex) {
+ if (ex instanceof cmdopt.ParseError) {
+ process.stderr.write(ex.message + "\n");
+ process.exit(1);
+ }
+ throw ex;
}
-FakeSocket.prototype.connect = function(server, port) {
- this.connectHandler();
-}
-
-FakeSocket.prototype.write = function(chunk) {
- this.stdout.write(chunk.red);
- this.msgHandler && this.msgHandler(chunk);
-}
-
-/************************************************************/
-
var StdinPipe = function() {
EventEmitter.call(this);
}
@@ -66,11 +52,8 @@ StdinPipe.prototype.send = function(msg) {
stdinPipe.emit('data', msg + '\r\n');
}
-/************************************************************/
-
var stdinPipe = new StdinPipe();
var irc;
-var nick = 'dynobot';
var realName = 'bots\'r\'us';
var ident = 'ident';
@@ -80,9 +63,7 @@ function info(a, b, c) {
var reallyConnect = true;
if(reallyConnect) {
- var host = 'localhost';
- // host = 'irc.freenode.net';
- irc = new IrcClient(nick, realName, ident, host, 6667);
+ irc = new IrcClient(config.nick, realName, ident, config.server, config.port);
}
else {
var msgHandler = function(line) {
@@ -94,8 +75,7 @@ else {
stdinPipe.send(prefix + ' JOIN ' + parts[1]);
}
}
- irc = new IrcClient(nick, realName, ident,new FakeSocket(stdinPipe, process.stdout, msgHandler));
- process.stdin.resume();
+ irc = new IrcClient(nick, realName, ident, new FakeSocket(stdinPipe, process.stdout, msgHandler));
}
var ircService = new Service('irc', irc);
@@ -109,8 +89,8 @@ function Plugin(name, script) {
}
var plugins = [
- new Plugin('echo', './echo-bot/index.js')
-// new Plugin('atom', './atom-bot/index.js')
+// new Plugin('echo', './echo-bot/index.js')
+ new Plugin('atom', './atom-bot/index.js')
];
_.each(plugins, function(plugin) {
@@ -133,85 +113,18 @@ _.each(plugins, function(plugin) {
// piping to process.stdout
});
-process.stdin.resume();
-var i = rl.createInterface(process.stdin, process.stdout, null);
-
-function quit() {
- i.close();
- process.stdin.destroy();
- process.exit(0);
-}
-
-function setupRepl() {
- var from = 'alice!~alice@example.com';
- var channel = '#bitraf2';
-
- function updatePrompt() {
- var prefix = 'from=' + from;
- prefix += channel ? ', channel=' + channel : '';
- prefix += '> ';
- i.setPrompt(prefix, prefix.length);
- i.prompt();
- }
-
- i.on('line', function (cmd) {
- cmd = cmd.trim();
- if(cmd.length == 0) {
- i.prompt();
- return;
- }
- var parts = cmd.split(' ');
- switch(parts[0]) {
- case '/quit':
- case '/q':
- quit();
- break;
- case '/raw':
- case '/r':
- parts.shift();
- stdinPipe.send(parts.join(' '));
- updatePrompt();
- break;
- case '/join':
- case '/j':
- channel = parts[1];
- updatePrompt();
- break;
- case '/from':
- case '/f':
- from = parts[1];
- updatePrompt();
- break;
- case '/notice':
- case '/n':
- if(channel) {
- parts.shift();
- stdinPipe.send(':' + from + ' NOTICE ' + channel + ' :' + parts.join(' '));
- }
- else {
- info('You have to /j a channel first');
- }
- break;
- default:
- stdinPipe.send(':' + from + ' PRIVMSG ' + channel + ' :' + parts.join(' '));
- updatePrompt();
- break;
- }
- }).on('close', function() {
- quit();
- });
- updatePrompt();
-}
-
-irc.join('#bitraf2', function(name) {
+irc.join(config.channel, function(name) {
info('joined ' + name + ' from dynobot.');
});
info('colors: ' + 'from bot'.red + ', ' + 'to bot'.blue);
irc.connect();
-setupRepl(i);
-
-setTimeout(function() {
- stdinPipe.send(':irc.foo.bar 001 this :Welcome to Some Internet Relay Chat Network this');
-}, 1000);
+var repl = require('./Repl.js');
+repl.init();
+if(reallyConnect) {
+ repl.setupRepl();
+}
+else {
+ repl.setupSimulatorRepl();
+}
diff --git a/echo-bot/index.js b/echo-bot/index.js
index 234e450..43240d4 100644
--- a/echo-bot/index.js
+++ b/echo-bot/index.js
@@ -22,7 +22,7 @@ irc.on('join', function(nick, channel) {
notice(channel, 'on join: hello ' + nick + '!');
});
-irc.join('#bitraf2', function(channel) {
+irc.join('#dynobot', function(channel) {
notice(channel, 'join(): channel=' + channel);
});
diff --git a/irc-client.js b/irc-client.js
index 275ee72..1be71bf 100644
--- a/irc-client.js
+++ b/irc-client.js
@@ -1,4 +1,4 @@
-var IRC = require('./node_modules/node-irc/irc').IRC;
+var IRC = require('irc.js');
var util = require('util');
var events = require('events');
var _ = require('underscore');
@@ -35,6 +35,10 @@ function IrcClient(nick, realName, ident, server, port, password) {
this.connected = false;
this.debugLevel = undefined;
this.irc = undefined;
+
+ this.nickCount = 0;
+ this.nickAdditions = [ '', '^', '-', '_', '\\', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
+ console.log("server: " + server);
}
util.inherits(IrcClient, events.EventEmitter);
@@ -68,6 +72,13 @@ IrcClient.prototype.init = function(irc) {
info('JOINed ' + channelName);
client.getChannel(channelName).fire(channelName);
});
+ irc.on('errorcode', function(code) {
+ if (code == 'ERR_NICKNAMEINUSE') {
+ var nick = client.findNick();
+ info("nick: " + nick);
+ irc.nick(nick);
+ }
+ });
_.each(['privmsg', 'topic', 'join'], function(e) {
irc.on(e, function() {
var args = [e];
@@ -110,6 +121,13 @@ IrcClient.prototype.join = function(name, cb) {
}
}
+IrcClient.prototype.findNick = function() {
+ if (this.nickCount == this.nickAdditions.length) {
+ this.nickCount = 0;
+ }
+ return this.nick + this.nickAdditions[this.nickCount++];
+}
+
// TODO: fix
function dispatch(name) {
this.irc[name].apply(this.irc, arguments);
diff --git a/ngircd.conf b/ngircd.conf
new file mode 100644
index 0000000..dae83b7
--- /dev/null
+++ b/ngircd.conf
@@ -0,0 +1,5 @@
+[Global]
+ MaxNickLength = 20
+ Name = irc.example.net
+ Info = Server Info Text
+ MotdPhrase = "Hello world!"