Mercurial > prosody-hg
comparison plugins/muc/occupant.lib.lua @ 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 | 74b9e05af71e |
| children |
comparison
equal
deleted
inserted
replaced
| 13902:7e6deed12e03 | 13903:4af7d00a2966 |
|---|---|
| 21 end | 21 end |
| 22 | 22 |
| 23 -- Deep copy an occupant | 23 -- Deep copy an occupant |
| 24 local function copy_occupant(occupant) | 24 local function copy_occupant(occupant) |
| 25 local sessions = {}; | 25 local sessions = {}; |
| 26 for full_jid, presence_stanza in pairs(occupant.sessions) do | 26 for full_jid, session in pairs(occupant.sessions) do |
| 27 local presence_stanza = session.presence; | |
| 27 -- Don't keep unavailable presences, as they'll accumulate; unless they're the primary session | 28 -- Don't keep unavailable presences, as they'll accumulate; unless they're the primary session |
| 28 if presence_stanza.attr.type ~= "unavailable" or full_jid == occupant.jid then | 29 if presence_stanza.attr.type ~= "unavailable" or full_jid == occupant.jid then |
| 29 sessions[full_jid] = presence_stanza; | 30 sessions[full_jid] = session; |
| 30 end | 31 end |
| 31 end | 32 end |
| 32 return setmetatable({ | 33 return setmetatable({ |
| 33 bare_jid = occupant.bare_jid; | 34 bare_jid = occupant.bare_jid; |
| 34 nick = occupant.nick; | 35 nick = occupant.nick; |
| 46 end | 47 end |
| 47 end | 48 end |
| 48 return nil; | 49 return nil; |
| 49 end | 50 end |
| 50 | 51 |
| 52 function occupant_mt:get_session(real_jid) | |
| 53 return self.sessions[real_jid]; | |
| 54 end | |
| 55 | |
| 51 function occupant_mt:set_session(real_jid, presence_stanza, replace_primary) | 56 function occupant_mt:set_session(real_jid, presence_stanza, replace_primary) |
| 52 local pr = get_filtered_presence(presence_stanza); | 57 local pr = get_filtered_presence(presence_stanza); |
| 53 pr.attr.from = self.nick; | 58 pr.attr.from = self.nick; |
| 54 pr.attr.to = real_jid; | 59 pr.attr.to = real_jid; |
| 55 | 60 |
| 56 self.sessions[real_jid] = pr; | 61 self.sessions[real_jid] = { presence = pr }; |
| 57 if replace_primary then | 62 if replace_primary then |
| 58 self.jid = real_jid; | 63 self.jid = real_jid; |
| 59 elseif self.jid == nil or (pr.attr.type == "unavailable" and self.jid == real_jid) then | 64 elseif self.jid == nil or (pr.attr.type == "unavailable" and self.jid == real_jid) then |
| 60 -- Only leave an unavailable presence as primary when there are no other options | 65 -- Only leave an unavailable presence as primary when there are no other options |
| 61 self.jid = self:choose_new_primary() or real_jid; | 66 self.jid = self:choose_new_primary() or real_jid; |
| 68 if self.jid == real_jid then | 73 if self.jid == real_jid then |
| 69 self.jid = self:choose_new_primary(); | 74 self.jid = self:choose_new_primary(); |
| 70 end | 75 end |
| 71 end | 76 end |
| 72 | 77 |
| 78 -- An iterator over self.sessions that returns (jid, presence, session) | |
| 79 local function _session_iter(s, var) | |
| 80 local k = next(s, var); | |
| 81 if k then | |
| 82 local v = s[k]; | |
| 83 return k, v.presence, v; | |
| 84 end | |
| 85 end | |
| 86 | |
| 73 function occupant_mt:each_session() | 87 function occupant_mt:each_session() |
| 74 return pairs(self.sessions) | 88 return _session_iter, self.sessions; |
| 75 end | 89 end |
| 76 | 90 |
| 77 function occupant_mt:get_presence(real_jid) | 91 function occupant_mt:get_presence(real_jid) |
| 78 return self.sessions[real_jid or self.jid] | 92 local session = self.sessions[real_jid or self.jid]; |
| 93 if not session then return; end | |
| 94 return session.presence; | |
| 79 end | 95 end |
| 80 | 96 |
| 81 return { | 97 return { |
| 82 new = new_occupant; | 98 new = new_occupant; |
| 83 copy = copy_occupant; | 99 copy = copy_occupant; |
