diff options
Diffstat (limited to 'atom-bot')
-rw-r--r-- | atom-bot/index.js | 217 |
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(); |