Software /
code /
prosody-modules
File
mod_pubsub_feed/mod_pubsub_feed.lua @ 320:8d4f3cd41f82
mod_post_msg: Better initialization
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 27 Jan 2011 17:30:48 +0100 |
parent | 300:b81e4f86a231 |
child | 322:637dc0a04052 |
line wrap: on
line source
-- Fetches Atom feeds and publishes to PubSub nodes -- -- Config: -- Component "pubsub.example.com" "pubsub" -- modules_enabled = { -- "pubsub_feed"; -- } -- feeds = { -- node -> url -- prosody_blog = "http://blog.prosody.im/feed/atom.xml"; -- } -- feed_pull_interval = 20 -- minutes local modules = hosts[module.host].modules; if not modules.pubsub then module:log("warn", "Pubsub needs to be loaded on this host"); end local add_task = require "util.timer".add_task; local date, time = os.date, os.time; local dt_parse, dt_datetime = require "util.datetime".parse, require "util.datetime".datetime; local http = require "net.http"; local parse_feed = require "feeds".feed_from_string; local st = require "util.stanza"; local config = module:get_option("feeds") or { planet_jabber = "http://planet.jabber.org/atom.xml"; prosody_blog = "http://blog.prosody.im/feed/atom.xml"; }; local refresh_interval = (module:get_option("feed_pull_interval") or 15) * 60; local feed_list = { } for node, url in pairs(config) do feed_list[node] = { url = url }; end local function update(item, callback) local headers = { }; if item.data and item.last_update then headers["If-Modified-Since"] = date("!%a, %d %b %Y %T %Z", item.last_update); end http.request(item.url, {headers = headers}, function(data, code, req) if code == 200 then item.data = data; callback(item) item.last_update = time(); end if code == 304 then item.last_update = time(); end end); end local actor = module.host.."/"..module.name; local function refresh_feeds() for node, item in pairs(feed_list) do update(item, function(item) local feed = parse_feed(item.data); module:log("debug", "node: %s", node); for _, entry in ipairs(feed) do entry.attr.xmlns = "http://www.w3.org/2005/Atom"; local e_published = entry:get_child("published"); e_published = e_published and e_published[1]; e_published = e_published and dt_parse(e_published); local e_updated = entry:get_child("updated"); e_updated = e_updated and e_updated[1]; e_updated = e_updated and dt_parse(e_updated); local timestamp = e_updated or e_published or nil; module:log("debug", "timestamp is %s, item.last_update is %s", tostring(timestamp), tostring(item.last_update)); if not timestamp or not item.last_update or timestamp > item.last_update then local id = entry:get_child("id"); id = id[1] or item.url.."#"..dt_datetime(timestamp); -- Missing id, so make one up local item = st.stanza("item", { id = id }):add_child(entry); module:log("debug", "publishing to %s, id %s", node, id); local ok, err = modules.pubsub.service:publish(node, actor, id, item); if not ok then if err == "item-not-found" then -- try again module:log("debug", "got item-not-found, creating %s and trying again", node); local ok, err = modules.pubsub.service:create(node, actor); if not ok then module:log("error", "could not create node: %s", err); return; end local ok, err = modules.pubsub.service:publish(node, actor, id, item); if not ok then module:log("error", "still could not create node: %s", err); return end else module:log("error", "publish failed: %s", err); end end end end end); end return refresh_interval; end function init() add_task(0, refresh_feeds); end if prosody.start_time then -- already started init(); else prosody.events.add_handler("server-started", init); end