1local pairs = pairs; 2local setmetatable = setmetatable; 3local st = require "util.stanza"; 4local util = module:require "muc/util"; 5 6local function get_filtered_presence(stanza) 7 return util.filter_muc_x(st.clone(stanza)); 8end 9 10local occupant_mt = {}; 11occupant_mt.__index = occupant_mt; 12 13local function new_occupant(bare_real_jid, nick) 14 return setmetatable({ 15 bare_jid = bare_real_jid; 16 nick = nick; -- in-room jid 17 sessions = {}; -- hash from real_jid to presence stanzas. stanzas should not be modified 18 role = nil; 19 jid = nil; -- Primary session 20 }, occupant_mt); 21end 22 23-- Deep copy an occupant 24local function copy_occupant(occupant) 25 local sessions = {}; 26 for full_jid, presence_stanza in pairs(occupant.sessions) do 27 -- 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 sessions[full_jid] = presence_stanza; 30 end 31 end 32 return setmetatable({ 33 bare_jid = occupant.bare_jid; 34 nick = occupant.nick; 35 sessions = sessions; 36 role = occupant.role; 37 jid = occupant.jid; 38 }, occupant_mt); 39end 40 41-- finds another session to be the primary (there might not be one) 42function occupant_mt:choose_new_primary() 43 for jid, pr in self:each_session() do 44 if pr.attr.type == nil then 45 return jid; 46 end 47 end 48 return nil; 49end 50 51function occupant_mt:set_session(real_jid, presence_stanza, replace_primary) 52 local pr = get_filtered_presence(presence_stanza); 53 pr.attr.from = self.nick; 54 pr.attr.to = real_jid; 55 56 self.sessions[real_jid] = pr; 57 if replace_primary then 58 self.jid = real_jid; 59 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 61 self.jid = self:choose_new_primary() or real_jid; 62 end 63end 64 65function occupant_mt:remove_session(real_jid) 66 -- Delete original session 67 self.sessions[real_jid] = nil; 68 if self.jid == real_jid then 69 self.jid = self:choose_new_primary(); 70 end 71end 72 73function occupant_mt:each_session() 74 return pairs(self.sessions) 75end 76 77function occupant_mt:get_presence(real_jid) 78 return self.sessions[real_jid or self.jid] 79end 80 81return { 82 new = new_occupant; 83 copy = copy_occupant; 84 mt = occupant_mt; 85} 86