summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2012-06-01 19:29:08 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2012-06-01 19:29:08 +0200
commita105b34ab53963ab651810f33caa2ee51869b1c7 (patch)
treebe49b089e1d4a81d6b327c6370afcc14c60ac865 /lib
downloaddynobot-irc-a105b34ab53963ab651810f33caa2ee51869b1c7.tar.gz
dynobot-irc-a105b34ab53963ab651810f33caa2ee51869b1c7.tar.bz2
dynobot-irc-a105b34ab53963ab651810f33caa2ee51869b1c7.tar.xz
dynobot-irc-a105b34ab53963ab651810f33caa2ee51869b1c7.zip
o Initial import.
Diffstat (limited to 'lib')
-rw-r--r--lib/arktekk-bot.js165
-rw-r--r--lib/irc.js12
2 files changed, 177 insertions, 0 deletions
diff --git a/lib/arktekk-bot.js b/lib/arktekk-bot.js
new file mode 100644
index 0000000..3a00c7f
--- /dev/null
+++ b/lib/arktekk-bot.js
@@ -0,0 +1,165 @@
+/*
+ * Possible strategies for updating the topic:
+ *
+ * o Set the topic unconditionally when the feed changes. This makes
+ * it possible for users to change the topic and it won't be
+ * overridden until the feed changes.
+ *
+ * o Set the topic on any topic change (making the feed control the
+ * entire topic)
+ *
+ * o Support a delimiter so it can control only a part of the topic,
+ * like "<>". Example
+ *
+ * Next meeting, sat 1900 <> DATA FROM FEED.
+ *
+ * A regexp selecting the are to be updated might conver it.
+ *
+ * o If the bot changed the topic the last time, it's probably safe to
+ * just update it.
+ */
+
+var node_irc = require('../node_modules/node-irc/IRC.js')
+ , cron = require('cron').CronJob
+ , parser = require('blindparser')
+ , events = require('events')
+ , _ = require('underscore');
+
+var parserOptions = {};
+
+var config;
+var cronJobs = [];
+
+var state = {
+ channelTopic: undefined,
+ irc: undefined,
+ updatingFeed: false,
+ feeds: [],
+ newest: {
+ timestamp: 0,
+ text: undefined
+ }
+};
+module.exports.state = state;
+
+var eventEmitter = new events.EventEmitter;
+
+function startIrc() {
+ irc = new node_irc.IRC(config.host, config.port);
+ irc.on('raw', function(data) { console.log(data) });
+ irc.on('connected', function(server) {
+ console.log('Connected to ' + server);
+ irc.join(config.channel, function(error) {
+ irc.notice(config.channel, 'well hello yall');
+ });
+ });
+ irc.topic = function(channel, topic) {
+ irc._socket.write('topic ' + channel + ' :' + topic + '\r\n');
+ };
+
+ irc.on('topic', function(channel, topic) {
+ console.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).
+ topic = t;
+ */
+
+ state.channelTopic = topic;
+ });
+}
+
+function updateFeed(feedState) {
+ console.log("Fetching " + feedState.url);
+ if(feedState.updatingFeed)
+ console.log("Already working");
+ feedState.updatingFeed = true;
+
+ parser.parseURL(feedState.url, parserOptions, function(err, feed) {
+// console.log("Fetched " + feedState.url + ", status=" + (err ? "failure" : "success"));
+ if(err) {
+ console.log(err);
+ return;
+ }
+ var newest = processFeed(feed);
+ if(typeof newest == "object") {
+ eventEmitter.emit("feedChanged", feedState.url, newest);
+ }
+ feedState.updatingFeed = false;
+ });
+}
+
+function processFeed(feed) {
+ // Extracts the username from the 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);
+ return undefined;
+ }
+ var match = /^http:\/\/twitter.com\/([a-zA-Z0-9_]+)\/.*$/.exec(feed.items[0].link)
+ if(match.length != 2) {
+ return undefined;
+ }
+ return {
+ text: feed.items[0].title,
+ author: match[1],
+ timestamp: feed.items[0].date
+ };
+}
+module.exports.processFeed = processFeed;
+
+eventEmitter.on("feedChanged", function(url, newest) {
+ state.feeds[url] = newest;
+
+ if(state.newest.timestamp >= newest.timestamp) {
+// console.log("oold: " + newest.text);
+ return;
+ }
+
+ var text = newest.author + ": " + newest.text;
+ console.log("New topic", newest.timestamp, url, text);
+ state.newest = newest;
+ if(config.connect && state.topic != text) {
+ irc.topic(config.channel, text);
+ }
+});
+
+eventEmitter.on("configUpdated", function(c) {
+ setup();
+});
+
+function setup() {
+ console.log("Stopping " + cronJobs.length + " cron jobs");
+ _.each(cronJobs, function(job) { job.stop(); });
+ cronJobs = [];
+ _.each(config.feeds, function(feed) {
+ var state = {
+ url: feed,
+ updatingFeed: false,
+ last: undefined
+ };
+ var job = new cron("*/10 * * * *", function() {
+ updateFeed(state);
+ }, function() {}, true);
+ cronJobs.push(job);
+ });
+}
+
+function start(c) {
+ config = c;
+ startIrc();
+ setup();
+ if(config.connect) {
+ console.log('Connecting to ' + config.host + ':' + config.port);
+ irc.connect(config.nick);
+ } else {
+ console.log('Not connecting to IRC');
+ }
+}
+
+module.exports.start = start;
+
+module.exports.emit = function(config) {
+ eventEmitter.emit("configUpdated", config);
+}
diff --git a/lib/irc.js b/lib/irc.js
new file mode 100644
index 0000000..935d2b3
--- /dev/null
+++ b/lib/irc.js
@@ -0,0 +1,12 @@
+module.exports.nickGenerator = function(nick) {
+ var nickCount = 0;
+ var nickAdditions = [ '', '^', '-', '_', '\\', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
+
+ return function() {
+ if (nickCount == nickAdditions.length) {
+ nickCount = 0;
+ }
+
+ return nick + nickAdditions[nickCount++];
+ }
+}