changeset 13903:4af7d00a2966

MUC: occupant: refactor to allow storing more than just presence for a session Previously a "session" (i.e. a full JID joined to a MUC) was stored as simply a mapping of full JIDs->presence, contained within occupant objects (an occupant object groups all sessions behind a certain nick in the MUC). To enable developing GC3 and other features, it would be helpful if we can store additional metadata when a client joins a room, for example, whether it has opted out of receiving presence stanzas (a GC3 feature). This changes the internal data structure, which shouldn't be used outside this module, it adds a new :get_session() method, and modifies the :each_session() iterator to return the session as an additional result (which should be backwards compatible with code that just consumes the existing two results).
author Matthew Wild <mwild1@gmail.com>
date Mon, 11 Nov 2024 12:47:01 +0000
parents 7e6deed12e03
children f8779be95156
files plugins/muc/occupant.lib.lua
diffstat 1 files changed, 21 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/muc/occupant.lib.lua	Thu Jun 26 13:04:40 2025 +0100
+++ b/plugins/muc/occupant.lib.lua	Mon Nov 11 12:47:01 2024 +0000
@@ -23,10 +23,11 @@
 -- Deep copy an occupant
 local function copy_occupant(occupant)
 	local sessions = {};
-	for full_jid, presence_stanza in pairs(occupant.sessions) do
+	for full_jid, session in pairs(occupant.sessions) do
+		local presence_stanza = session.presence;
 		-- Don't keep unavailable presences, as they'll accumulate; unless they're the primary session
 		if presence_stanza.attr.type ~= "unavailable" or full_jid == occupant.jid then
-			sessions[full_jid] = presence_stanza;
+			sessions[full_jid] = session;
 		end
 	end
 	return setmetatable({
@@ -48,12 +49,16 @@
 	return nil;
 end
 
+function occupant_mt:get_session(real_jid)
+	return self.sessions[real_jid];
+end
+
 function occupant_mt:set_session(real_jid, presence_stanza, replace_primary)
 	local pr = get_filtered_presence(presence_stanza);
 	pr.attr.from = self.nick;
 	pr.attr.to = real_jid;
 
-	self.sessions[real_jid] = pr;
+	self.sessions[real_jid] = { presence = pr };
 	if replace_primary then
 		self.jid = real_jid;
 	elseif self.jid == nil or (pr.attr.type == "unavailable" and self.jid == real_jid) then
@@ -70,12 +75,23 @@
 	end
 end
 
+-- An iterator over self.sessions that returns (jid, presence, session)
+local function _session_iter(s, var)
+	local k = next(s, var);
+	if k then
+		local v = s[k];
+		return k, v.presence, v;
+	end
+end
+
 function occupant_mt:each_session()
-	return pairs(self.sessions)
+	return _session_iter, self.sessions;
 end
 
 function occupant_mt:get_presence(real_jid)
-	return self.sessions[real_jid or self.jid]
+	local session = self.sessions[real_jid or self.jid];
+	if not session then return; end
+	return session.presence;
 end
 
 return {