IMPORTANT: due to a drive failure, as of 13-Mar-2021, the Mercurial repository had to be re-mirrored, which changed every commit SHA. The old SHAs and trees are backed up in the vault branches. Please migrate to the new branches as soon as you can.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
prosody/plugins/muc/occupant.lib.lua

85 lines
2.2 KiB

local pairs = pairs;
local setmetatable = setmetatable;
local st = require "prosody.util.stanza";
local util = module:require "muc/util";
local function get_filtered_presence(stanza)
return util.filter_muc_x(st.clone(stanza));
end
local occupant_mt = {};
occupant_mt.__index = occupant_mt;
local function new_occupant(bare_real_jid, nick)
return setmetatable({
bare_jid = bare_real_jid;
nick = nick; -- in-room jid
sessions = {}; -- hash from real_jid to presence stanzas. stanzas should not be modified
role = nil;
jid = nil; -- Primary session
}, occupant_mt);
end
-- Deep copy an occupant
local function copy_occupant(occupant)
local sessions = {};
for full_jid, presence_stanza in pairs(occupant.sessions) do
-- 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;
end
end
return setmetatable({
bare_jid = occupant.bare_jid;
nick = occupant.nick;
sessions = sessions;
role = occupant.role;
jid = occupant.jid;
}, occupant_mt);
end
-- finds another session to be the primary (there might not be one)
function occupant_mt:choose_new_primary()
for jid, pr in self:each_session() do
if pr.attr.type == nil then
return jid;
end
end
return nil;
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;
if replace_primary then
self.jid = real_jid;
elseif self.jid == nil or (pr.attr.type == "unavailable" and self.jid == real_jid) then
-- Only leave an unavailable presence as primary when there are no other options
self.jid = self:choose_new_primary() or real_jid;
end
end
function occupant_mt:remove_session(real_jid)
-- Delete original session
self.sessions[real_jid] = nil;
if self.jid == real_jid then
self.jid = self:choose_new_primary();
end
end
function occupant_mt:each_session()
return pairs(self.sessions)
end
function occupant_mt:get_presence(real_jid)
return self.sessions[real_jid or self.jid]
end
return {
new = new_occupant;
copy = copy_occupant;
mt = occupant_mt;
}