# HG changeset patch # User Matthew Wild # Date 1731329221 0 # Node ID 4af7d00a2966eb742463fc6bdb007c99d776498b # Parent 7e6deed12e0314b1a1c48ca0e911c0295eb6b7ad 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). diff -r 7e6deed12e03 -r 4af7d00a2966 plugins/muc/occupant.lib.lua --- 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 {