view mod_muc_eventsource/mod_muc_eventsource.lua @ 4210:a0937b5cfdcb

mod_invites_page: Remove preauth URI button This button is incompatible with the majority of XMPP clients around, yet based on feedback from users, many are drawn to click it when they have any XMPP client installed already. In the case where the user already has software installed, we would prefer them to select it from the software list so they can follow the setup process suited to their specific client (we already track which software supports preauth URIs). If their client is not listed, they can still use the manual registration link instead.
author Matthew Wild <mwild1@gmail.com>
date Fri, 16 Oct 2020 11:03:38 +0100
parents 39485b9bbdd6
children
line wrap: on
line source

module:depends("http");
local nodeprep = require "util.encodings".stringprep.nodeprep;

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)
	local response = event.response;

	node = nodeprep(node);
	if node == nil then
		return 400;
	end

	module:log("debug", "Client subscribed to: %s", node);

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