Mon, 17 Sep 2018 14:46:47 +0100
Dockerfile: Switch to alpine for final image
--[[ pubsub2room relays pubsub broadcasts to rooms example conf: pubsub2room = { ["pubsub.prosody.im#commits"] = { room = "prosody@conference.prosody.im"; template = "${author.name} committed: ${title}"; }; }; --]] local verse = require "verse"; local st = require "util.stanza"; local json = require "util.json"; -- FIXME Should this really be here? local extractor_mt = { __index = function (t, k) local n; if k:match("^data%.") then k = k:gsub("^data.", ""); n = t.data; else n = t.stanza; end for x in k:gmatch("[^.]+") do local m, a = x:match("^([^@]*)@(.*)$"); if m and a then m = n:get_child(m); return m and m.attr[a] or nil; end n = n:get_child(x); if not n then return end end return n[1]; end }; local json_extractor_mt = { __index = function (t, k) if not k:find"%." then return nil; end for x in k:gmatch("[^.]+") do t = rawget(t, x) or rawget(t, tonumber(x)); if t == nil then return end end if type(t) == "table" then return json.encode(t); end return tostring(t); end }; local function new_extractor(stanza, data) if not stanza then return nil end if stanza.attr.xmlns == "urn:xmpp:json:0" then local payload = json.decode(stanza:get_text()); if type(payload) == "table" then return setmetatable(payload, json_extractor_mt); end end return setmetatable({ stanza = stanza, data = data }, extractor_mt); end local last_message_time = 0; function riddim.plugins.pubsub2room(bot) local bare_jid = require "util.jid".bare; bot.stream:add_plugin("pubsub"); local config = bot.config.pubsub2room; bot.stream:hook("pubsub/event", function(event) local conf = config[event.from .. "#" .. event.node]; if not conf then return end local room = bot.rooms[conf.room]; local data = st.stanza("data"):tag("id"):text(event.item.attr.id); local entry = event.item and new_extractor(event.item.tags[1], data) if not conf or not entry or not room then return end local message = conf.template:gsub("%${([^}]+)}", entry); -- Throttle to 1 message/second so we don't flood the room if os.time() - last_message_time > 0 then room:send_message(message); last_message_time = os.time(); else last_message_time = last_message_time + 1; verse.add_task(last_message_time - os.time(), function () room:send_message(message); end); end end); -- FIXME When to unsubscribe? bot:hook("started", function() local jid = bare_jid(bot.stream.jid); for hostnode in pairs(config) do local host, node = hostnode:match("^([^#]+)#(.*)"); bot.stream.pubsub(host, node):subscribe(jid); end end); end