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);