annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
1 local pairs = pairs;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
2 local setmetatable = setmetatable;
12977
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 7086
diff changeset
3 local st = require "prosody.util.stanza";
6271
006b0e0f0de2 plugins/muc: Move 'x' filtering from occupant to util
daurnimator <quae@daurnimator.com>
parents: 6251
diff changeset
4 local util = module:require "muc/util";
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
5
6271
006b0e0f0de2 plugins/muc: Move 'x' filtering from occupant to util
daurnimator <quae@daurnimator.com>
parents: 6251
diff changeset
6 local function get_filtered_presence(stanza)
006b0e0f0de2 plugins/muc: Move 'x' filtering from occupant to util
daurnimator <quae@daurnimator.com>
parents: 6251
diff changeset
7 return util.filter_muc_x(st.clone(stanza));
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
8 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
9
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
10 local occupant_mt = {};
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
11 occupant_mt.__index = occupant_mt;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
12
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
13 local function new_occupant(bare_real_jid, nick)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
14 return setmetatable({
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
15 bare_jid = bare_real_jid;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
16 nick = nick; -- in-room jid
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
17 sessions = {}; -- hash from real_jid to presence stanzas. stanzas should not be modified
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
18 role = nil;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
19 jid = nil; -- Primary session
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
20 }, occupant_mt);
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
21 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
22
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
23 -- Deep copy an occupant
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
24 local function copy_occupant(occupant)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
25 local sessions = {};
13903
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
26 for full_jid, session in pairs(occupant.sessions) do
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
27 local presence_stanza = session.presence;
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
28 -- Don't keep unavailable presences, as they'll accumulate; unless they're the primary session
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
29 if presence_stanza.attr.type ~= "unavailable" or full_jid == occupant.jid then
13903
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
30 sessions[full_jid] = session;
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
31 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
32 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
33 return setmetatable({
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
34 bare_jid = occupant.bare_jid;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
35 nick = occupant.nick;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
36 sessions = sessions;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
37 role = occupant.role;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
38 jid = occupant.jid;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
39 }, occupant_mt);
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
40 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
41
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
42 -- finds another session to be the primary (there might not be one)
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
43 function occupant_mt:choose_new_primary()
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
44 for jid, pr in self:each_session() do
6251
41a5e5205fd9 plugins/muc/occupant: Check for type == nil rather than type ~= unavailable
daurnimator <quae@daurnimator.com>
parents: 6210
diff changeset
45 if pr.attr.type == nil then
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
46 return jid;
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
47 end
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
48 end
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
49 return nil;
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
50 end
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
51
13903
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
52 function occupant_mt:get_session(real_jid)
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
53 return self.sessions[real_jid];
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
54 end
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
55
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
56 function occupant_mt:set_session(real_jid, presence_stanza, replace_primary)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
57 local pr = get_filtered_presence(presence_stanza);
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
58 pr.attr.from = self.nick;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
59 pr.attr.to = real_jid;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
60
13903
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
61 self.sessions[real_jid] = { presence = pr };
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
62 if replace_primary then
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
63 self.jid = real_jid;
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
64 elseif self.jid == nil or (pr.attr.type == "unavailable" and self.jid == real_jid) then
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
65 -- Only leave an unavailable presence as primary when there are no other options
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
66 self.jid = self:choose_new_primary() or real_jid;
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
67 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
68 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
69
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
70 function occupant_mt:remove_session(real_jid)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
71 -- Delete original session
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
72 self.sessions[real_jid] = nil;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
73 if self.jid == real_jid then
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
74 self.jid = self:choose_new_primary();
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
75 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
76 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
77
13903
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
78 -- An iterator over self.sessions that returns (jid, presence, session)
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
79 local function _session_iter(s, var)
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
80 local k = next(s, var);
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
81 if k then
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
82 local v = s[k];
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
83 return k, v.presence, v;
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
84 end
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
85 end
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
86
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
87 function occupant_mt:each_session()
13903
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
88 return _session_iter, self.sessions;
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
89 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
90
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
91 function occupant_mt:get_presence(real_jid)
13903
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
92 local session = self.sessions[real_jid or self.jid];
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
93 if not session then return; end
4af7d00a2966 MUC: occupant: refactor to allow storing more than just presence for a session
Matthew Wild <mwild1@gmail.com>
parents: 12977
diff changeset
94 return session.presence;
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
95 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
96
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
97 return {
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
98 new = new_occupant;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
99 copy = copy_occupant;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
100 mt = occupant_mt;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
101 }