summaryrefslogtreecommitdiff
path: root/atom-bot/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'atom-bot/index.js')
-rw-r--r--atom-bot/index.js217
1 files changed, 173 insertions, 44 deletions
diff --git a/atom-bot/index.js b/atom-bot/index.js
index 7de99bc..18eaf14 100644
--- a/atom-bot/index.js
+++ b/atom-bot/index.js
@@ -21,57 +21,55 @@
require('tinycolor');
var cron = require('cron').CronJob
- , parser = require('blindparser')
, events = require('events')
+ , fs = require('fs')
+ , parser = require('blindparser')
+ , url = require('url')
, _ = require('underscore');
-var irc = function() {
- var Proxy = require('../node_modules/dynobot/proxy');
- var Channel = require('../node_modules/dynobot/channel');
- var IrcClient = require('../irc-client.js').IrcClient;
+var Proxy = require('../node_modules/dynobot/proxy');
+var Channel = require('../node_modules/dynobot/channel');
- var channel = new Channel();
- return new Proxy(IrcClient.prototype, 'irc', channel);
-}();
+var irc = new Proxy(require('../irc-client.js').IrcClient.prototype, 'irc', new Channel());
function log(message) {
console.log(('log ' + message).green);
}
-var parserOptions = {};
-
-// Config
-var channel = '#dynobot';
-var feeds = [
-// "http://search.twitter.com/search.atom?q=from:AgileBorat",
-// "http://search.twitter.com/search.atom?q=from:KongenDin",
-// "http://search.twitter.com/search.atom?q=from:NestenSivJensen",
- "http://search.twitter.com/search.atom?q=ndc2012"
-// "http://search.twitter.com/search.atom?q=awesome",
-// "http://search.twitter.com/search.atom?q=eurovision",
-];
-var cronJobs = [];
+var config;
var state = {
channelTopic: undefined,
topic: undefined,
- updatingFeed: false,
- feeds: [],
newest: {
timestamp: 0,
text: undefined
}
};
+var feeds = {};
+
+function FeedState(url) {
+ this.url = url;
+ this.updatingFeed = false;
+ this.last = undefined;
+ this.job = undefined;
+}
+
var eventEmitter = new events.EventEmitter;
+function parseFeed(url, cb) {
+ var parserOptions = {};
+ parser.parseURL(url, parserOptions, cb);
+}
+
function updateFeed(feedState) {
log("Fetching " + feedState.url);
if(feedState.updatingFeed)
log("Already working");
feedState.updatingFeed = true;
- parser.parseURL(feedState.url, parserOptions, function(err, feed) {
+ parseFeed(feedState.url, function(err, feed) {
log("Fetched " + feedState.url + ", status=" + (err ? "failure" : "success"));
if(err) {
log(err);
@@ -106,7 +104,7 @@ function processFeed(feed) {
}
eventEmitter.on("feedChanged", function(url, newest) {
- state.feeds[url] = newest;
+ feeds[url].newest = newest;
if(state.newest.timestamp >= newest.timestamp) {
log("oold: " + newest.text);
@@ -120,33 +118,55 @@ eventEmitter.on("feedChanged", function(url, newest) {
state.newest = newest;
/*
if(state.channelTopic != text) {
- irc.topic(channel, text);
+ irc.topic(config.channel, text);
}
*/
- irc.notice(channel, text);
+ log(config.channel);
+ irc.notice(config.channel, text);
});
+function appendFeed(feedUrl) {
+ var feedState = new FeedState(feedUrl);
+ log("Job starting for " + feedUrl);
+ feedState.job = new cron("*/10 * * * *", function() {
+ updateFeed(feedState);
+ }, function() {
+ log("Job stopping for " + feedUrl);
+ }, true);
+ feeds[feedUrl] = feedState;
+ log("appendFeed: keys=" + _.keys(feeds));
+}
+
+function removeFeed(feedUrl) {
+ log("removeFeed: feedUrl=" + feedUrl);
+ log("removeFeed: keys=" + _.keys(feeds));
+ var feedState = feeds[feedUrl];
+ log("removeFeed: feedState=" + typeof feedState);
+ if(_.isObject(feedState)) {
+ log("removeFeed: keys feedState=" + _.keys(feedState));
+ feedState.job.stop();
+ }
+ else {
+ log("removeFeed: feed not found");
+ }
+ delete feeds[feedUrl];
+ log("removeFeed: keys=" + _.keys(feeds));
+}
+
function setup() {
- log("Stopping " + cronJobs.length + " cron jobs");
- _.each(cronJobs, function(job) { job.stop(); });
- cronJobs = [];
- _.each(feeds, function(feed) {
- var state = {
- url: feed,
- updatingFeed: false,
- last: undefined
- };
- var job = new cron("*/10 * * * *", function() {
- updateFeed(state);
- }, function() {}, true);
- cronJobs.push(job);
+ log('Starting..');
+
+ loadConfig(function(err, config) {
+ log('config: ' + JSON.stringify(config));
+ irc.join(config.channel, function(c) {
+ irc.notice(config.channel, 'Atom plugin online. Monitoring ' + config.feeds.length + ' feeds.');
+ });
+ _.each(config.feeds, function(feed) {
+ appendFeed(feed);
+ });
});
}
-irc.join(channel, function(c) {
- irc.notice(channel, 'well hello yall: ' + c);
-});
-
irc.on('topic', function(channel, topic) {
log("new topic: " + topic);
/* If we're not storing this, it is possible for people to set
@@ -158,4 +178,113 @@ irc.on('topic', function(channel, topic) {
state.channelTopic = topic;
});
+irc.on('privmsg', function(nick, channel, message) {
+ irc.whoami(function(whoami) {
+ // Hm, what happens if a nick contain funny characters like '.
+ var reg = new RegExp('^' + whoami + ': atom ');
+ if(!reg.test(message)) {
+ return;
+ }
+ var args = message.substring(whoami.length + 7).split(' ');
+
+ if(args.length < 1) {
+ usage(channel);
+ return;
+ }
+ var rest = _.rest(args);
+ switch(args[0]) {
+ case 'list-feeds': onListFeeds(channel); break;
+ case 'add-feed': onAddFeed(channel, rest); break;
+ case 'remove-feed': onRemoveFeed(channel, rest); break;
+ case 'load-config': onLoadConfig(channel); break;
+ }
+ });
+});
+
+function usage(channel) {
+}
+
+function onListFeeds(channel) {
+ _.each(config.feeds, function(feed, i) {
+ irc.notice(channel, 'feed #' + i + ': ' + feed);
+ });
+}
+
+function onAddFeed(channel, urls) {
+ if(urls.length != 1) {
+ return;
+ }
+ var u = urls[0];
+ log('Adding feed: ' + u);
+ url.parse(u); // TODO: Add error handling
+ parseFeed(u, function(err, feed) {
+ if(err) {
+ log('Unable to fetch feed');
+ log(util.format(err));
+ return;
+ }
+ config.feeds.push(u);
+ appendFeed(u);
+ saveConfig(function(err) {
+ if(err) throw err;
+ irc.notice(channel, 'Feed added');
+ });
+ });
+}
+
+function onRemoveFeed(channel, args) {
+ if(args.length != 1) {
+ return;
+ }
+ log("onRemoveFeed: args[0]=" + args[0]);
+ var i = parseInt(args[0]);
+ log("onRemoveFeed: i=" + i);
+ var feedUrl = config.feeds[i];
+ log("onRemoveFeed: config=" + JSON.stringify(config));
+ config.feeds.splice(i, 1);
+ log("onRemoveFeed: config=" + JSON.stringify(config));
+ log("onRemoveFeed: feedUrl=" + feedUrl);
+ removeFeed(feedUrl);
+ saveConfig(function(err) {
+ if(err) {
+ log(err);
+ irc.notice(channel, 'Error removing feed');
+ return;
+ }
+ irc.notice(channel, 'Feed removed');
+ });
+}
+
+function onLoadConfig(channel) {
+ loadConfig(function(err, config) {
+ if(err) {
+ irc.notice(channel, 'Unable to load config');
+ }
+ else {
+ irc.notice(channel, 'Loaded configuration, has ' + config.feeds.length + ' feeds.');
+ }
+ });
+}
+
+function loadConfig(cb) {
+ fs.readFile('config.json', function(err, data) {
+ if(err) return cb(err, undefined);
+
+ try {
+ config = JSON.parse(data);
+ } catch(e) {
+ log('Unable to parse config.json, using defaults.');
+ }
+
+ config.channel = _.isString(config.channel) ? config.channel : '#dynobot';
+ config.feeds = _.isArray(config.feeds) ? config.feeds : [];
+ cb(undefined, config);
+ });
+}
+
+function saveConfig(cb) {
+ log('Saving config: ' + JSON.stringify(config));
+ fs.writeFile('config.json', JSON.stringify(config), cb);
+}
+
setup();