/* * 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. */ require('tinycolor'); var cron = require('cron').CronJob , parser = require('blindparser') , events = require('events') , _ = 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 channel = new Channel(); return new Proxy(IrcClient.prototype, 'irc', 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 state = { channelTopic: undefined, topic: undefined, updatingFeed: false, feeds: [], newest: { timestamp: 0, text: undefined } }; var eventEmitter = new events.EventEmitter; function updateFeed(feedState) { log("Fetching " + feedState.url); if(feedState.updatingFeed) log("Already working"); feedState.updatingFeed = true; parser.parseURL(feedState.url, parserOptions, function(err, feed) { log("Fetched " + feedState.url + ", status=" + (err ? "failure" : "success")); if(err) { 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") { 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) if(match.length != 2) { return undefined; } return { text: feed.items[0].title, author: match[1], timestamp: feed.items[0].date }; } eventEmitter.on("feedChanged", function(url, newest) { state.feeds[url] = newest; if(state.newest.timestamp >= newest.timestamp) { log("oold: " + newest.text); return; } /* */ var text = newest.author + ": " + newest.text; log("New topic: " + newest.timestamp + ", url=" + url + ", text=" + text); state.newest = newest; /* if(state.channelTopic != text) { irc.topic(channel, text); } */ irc.notice(channel, text); }); 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); }); } 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 * the topic after the bot has set it and it will persist (until * next update from the feed). topic = t; */ state.channelTopic = topic; }); setup();