view mod_throttle_presence/mod_throttle_presence.lua @ 5608:1893ae742f66

mod_http_oauth2: Show errors on device flow user code entry page If the user enters the code incorrectly, having to click back to try again is no fun. Instead, show the error and the code entry form again.
author Kim Alvefur <zash@zash.se>
date Wed, 19 Jul 2023 13:05:47 +0200
parents 552faee596b7
children
line wrap: on
line source

local filters = require "util.filters";
local st = require "util.stanza";

module:depends("csi");

local function presence_filter(stanza, session)
	if getmetatable(stanza) ~= st.stanza_mt then
		return stanza; -- Things we don't want to touch
	end
	if stanza._flush then
		stanza._flush = nil;
		return stanza;
	end
	local buffer = session.presence_buffer;
	local from = stanza.attr.from;
	if stanza.name == "presence" and (stanza.attr.type == nil or stanza.attr.type == "unavailable") then
		module:log("debug", "Buffering presence stanza from %s to %s", stanza.attr.from, session.full_jid);
		buffer[stanza.attr.from] = st.clone(stanza);
		return nil; -- Drop this stanza (we've stored it for later)
	else
		local cached_presence = buffer[stanza.attr.from];
		if cached_presence then
			module:log("debug", "Important stanza for %s from %s, flushing presence", session.full_jid, from);
			stanza._flush = true;
			cached_presence._flush = true;
			session.send(cached_presence);
			buffer[stanza.attr.from] = nil;
		end
	end
	return stanza;
end

local function throttle_session(event)
	local session = event.origin;
	if session.presence_buffer then return; end
	module:log("debug", "Suppressing presence updates to %s", session.full_jid);
	session.presence_buffer = {};
	filters.add_filter(session, "stanzas/out", presence_filter);
end

local function restore_session(event)
	local session = event.origin;
	if not session.presence_buffer then return; end
	filters.remove_filter(session, "stanzas/out", presence_filter);
	module:log("debug", "Flushing buffer for %s", session.full_jid);
	for jid, presence in pairs(session.presence_buffer) do
		session.send(presence);
	end
	session.presence_buffer = nil;
end

module:hook("csi-client-inactive", throttle_session);
module:hook("csi-client-active", restore_session);