Software /
code /
prosody-modules
Diff
mod_muc_eventsource/mod_muc_eventsource.lua @ 2883:7c16afc70d11
mod_muc_eventsource: New module forked from mod_pubsub_eventsource, exposes room message stream over SSE
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 19 Feb 2018 22:17:38 +0000 |
child | 2897:39485b9bbdd6 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_muc_eventsource/mod_muc_eventsource.lua Mon Feb 19 22:17:38 2018 +0000 @@ -0,0 +1,75 @@ +module:depends("http"); + +local jid_split = require "util.jid".split; +local json = require "util.json"; + +local streams = {}; + +function client_closed(response) + local node = response._eventsource_node; + module:log("debug", "Destroying client for %q", node); + streams[node][response] = nil; + if next(streams[node]) == nil then + streams[node] = nil; + end +end + +function serve_stream(event, node) + module:log("debug", "Client subscribed to: %s", node); + + local response = event.response; + response.on_destroy = client_closed; + response._eventsource_node = node; + + response.conn:write(table.concat({ + "HTTP/1.1 200 OK"; + "Content-Type: text/event-stream"; + "Access-Control-Allow-Origin: *"; + "Access-Control-Allow-Methods: GET"; + "Access-Control-Max-Age: 7200"; + ""; + ""; + }, "\r\n")); + + local clientlist = streams[node]; + if not clientlist then + clientlist = {}; + streams[node] = clientlist; + end + clientlist[response] = response.conn; + + return true; +end + +function handle_message(event) + local room, stanza = event.room, event.stanza; + local node = (jid_split(event.room.jid)); + local clientlist = streams[node]; + if not clientlist then module:log("debug", "No clients for %q", node); return; end + + -- Extract body from message + local body = event.stanza:get_child_text("body"); + if not body then + return; + end + local nick = select(3, jid_split(stanza.attr.from)); + -- Encode body and broadcast to eventsource subscribers + local json_data = json.encode({ + nick = nick; + body = body; + }); + local data = "data: "..json_data:gsub("\n", "\ndata: \n").."\n\n"; + for response, conn in pairs(clientlist) do + conn:write(data); + end +end + +module:provides("http", { + name = "eventsource"; + route = { + ["GET /*"] = serve_stream; + }; +}); + + +module:hook("muc-broadcast-message", handle_message);