view mod_presence_dedup/mod_presence_dedup.lua @ 4876:0f5f2d4475b9

mod_http_xep227: Add support for import via APIs rather than direct store manipulation In particular this transitions PEP nodes and data to be imported via mod_pep's APIs, fixing issues with importing at runtime while PEP data may already be live in RAM. Next obvious candidate for this approach is rosters, so clients get immediate roster pushes and other special handling (such as emitting subscribes to reach the desired subscription state).
author Matthew Wild <mwild1@gmail.com>
date Tue, 18 Jan 2022 17:01:18 +0000
parents 19924a2c4a48
children
line wrap: on
line source

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

local cache_size = module:get_option_number("presence_dedup_cache_size", 100);

-- stanza equality tests
local function attr_eq(a, b)
	if a == b then return true; end -- unlikely but not impossible
	for k,v in pairs(a) do if b[k] ~= v then return false; end end
	for k,v in pairs(b) do if a[k] ~= v then return false; end end
	return true;
end

local function st_eq(a, b)
	if a == b then return true; end
	if type(b) ~= "table" then return false; end
	if getmetatable(b) ~= st.stanza_mt then return false; end
	if a.name ~= b.name then return false; end
	if #a ~= #b then return false; end
	if not attr_eq(a.attr, b.attr) then return false; end
	for i = 1, #a do if not st_eq(a[i], b[i]) then return false; end end
	return true;
end

local function dedup_presence(stanza, session)
	if session.presence_cache and session.presence
	and getmetatable(stanza) == st.stanza_mt and stanza.name == "presence"
	and stanza.attr.xmlns == nil and stanza.attr.from then
		local cached = session.presence_cache:get(stanza.attr.from);
		if st_eq(stanza, cached) then
			return nil;
		else
			session.presence_cache:set(stanza.attr.from, st.clone(stanza));
		end
	end
	return stanza;
end

module:hook("presence/initial",	function (event)
	local session = event.origin;
	session.presence_cache = cache.new(cache_size);
	add_filter(session, "stanzas/out", dedup_presence, 90);
end);