Comparison

mod_pubsub_feed/mod_pubsub_feed.lua @ 278:653c1826739e

mod_pubsub_feed: Fetches Atom feeds and publishes to PubSub
author Kim Alvefur <zash@zash.se>
date Sat, 27 Nov 2010 04:14:53 +0100
child 279:aa0df3db4901
comparison
equal deleted inserted replaced
277:07c1c3eaf0c4 278:653c1826739e
1 -- Fetches Atom feeds and publishes to PubSub nodes
2 --
3 -- Config:
4 -- Component "pubsub.example.com" "pubsub"
5 -- modules_enabled = {
6 -- "pubsub_feed";
7 -- }
8 -- feeds = { -- node -> url
9 -- telecomix = "https://status.telecomix.org/api/statuses/public_timeline.atom";
10 -- }
11 -- feed_pull_interval = 20 -- minutes
12
13 local modules = hosts[module.host].modules;
14 if not modules.pubsub then
15 module:log("warn", "Pubsub needs to be loaded on this host");
16 end
17 local add_task = require "util.timer".add_task;
18 local date, time = os.date, os.time;
19 local dt_parse = require "util.datetime".parse;
20 local http = require "net.http";
21 local parse_feed = require "feeds".feed_from_string;
22
23 local config = module:get_option("feeds") or {
24 planet_jabber = "http://planet.jabber.org/atom.xml";
25 prosody_blog = "http://blog.prosody.im/feed/atom.xml";
26 };
27 local refresh_interval = (module:get_option("feed_pull_interval") or 15) * 60;
28 local feed_list = { }
29 for node, url in pairs(config) do
30 feed_list[node] = { url = url };
31 end
32
33 local function update(item, callback)
34 local headers = { };
35 if item.data and item.last_update then
36 headers["If-Modified-Since"] = date("!%a, %d %b %Y %T %Z", item.last_update);
37 end
38 http.request(item.url, {headers = headers}, function(data, code, req)
39 if code == 200 then
40 item.data = data;
41 callback(item)
42 item.last_update = time();
43 end
44 if code == 304 then
45 item.last_update = time();
46 end
47 end);
48 end
49
50 local actor = module.host.."/"..module.name;
51
52 local function refresh_feeds()
53 for node, item in pairs(feed_list) do
54 update(item, function(item)
55 local feed = parse_feed(item.data);
56 module:log("debug", "node: %s", node);
57 for _, entry in ipairs(feed) do
58 entry.attr.xmlns = "http://www.w3.org/2005/Atom";
59
60 local e_published = entry:get_child("published");
61 e_published = e_published and e_published[1];
62 e_published = e_published and dt_parse(e_published);
63 local e_updated = entry:get_child("updated");
64 e_updated = e_updated and e_updated[1];
65 e_updated = e_updated and dt_parse(e_updated);
66
67 local timestamp = e_published or e_updated or nil;
68 module:log("debug", "timestamp is %s, item.last_update is %s", tostring(timestamp), tostring(item.last_update));
69 if not timestamp or not item.last_update or timestamp > item.last_update then
70 local id = entry:get_child("id");
71 id = id[1] or item.url.."#"..timestamp;
72 module:log("debug", "publishing to %s, id %s", node, id);
73 modules.pubsub.service:publish(node, actor, id, entry)
74 end
75 end
76 end);
77 end
78 return refresh_interval;
79 end
80
81 function init()
82 add_task(0, refresh_feeds);
83 end
84
85 if prosody.start_time then -- already started
86 init();
87 else
88 prosody.events.add_handler("server-started", init);
89 end
90