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/mod_message.lua

87 lines
2.4 KiB

local full_sessions = full_sessions;
local bare_sessions = bare_sessions;
local st = require "util.stanza";
local jid_bare = require "util.jid".bare;
local jid_split = require "util.jid".split;
local user_exists = require "core.usermanager".user_exists;
local offlinemanager = require "core.offlinemanager";
local t_insert = table.insert;
local function select_top_resources(user)
local priority = 0;
local recipients = {};
for _, session in pairs(user.sessions) do -- find resource with greatest priority
if session.presence then
-- TODO check active privacy list for session
local p = session.priority;
if p > priority then
priority = p;
recipients = {session};
elseif p == priority then
t_insert(recipients, session);
end
end
end
return recipients;
end
local function process_to_bare(bare, origin, stanza)
local user = bare_sessions[bare];
local t = stanza.attr.type;
if t == "error" then
-- discard
elseif t == "groupchat" then
origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
elseif t == "headline" then
if user then
for _, session in pairs(user.sessions) do
if session.presence and session.priority >= 0 then
session.send(stanza);
end
end
end -- current policy is to discard headlines if no recipient is available
else -- chat or normal message
if user then -- some resources are connected
local recipients = select_top_resources(user);
if #recipients > 0 then
for i=1,#recipients do
recipients[i].send(stanza);
end
return true;
end
end
-- no resources are online
local node, host = jid_split(bare);
if user_exists(node, host) then
-- TODO apply the default privacy list
offlinemanager.store(node, host, stanza);
else
origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
end
end
return true;
end
module:hook("message/full", function(data)
-- message to full JID recieved
local origin, stanza = data.origin, data.stanza;
local session = full_sessions[stanza.attr.to];
if session then
-- TODO fire post processing event
session.send(stanza);
return true;
else -- resource not online
return process_to_bare(jid_bare(stanza.attr.to), origin, stanza);
end
end);
module:hook("message/bare", function(data)
-- message to bare JID recieved
local origin, stanza = data.origin, data.stanza;
return process_to_bare(stanza.attr.to or (origin.username..'@'..origin.host), origin, stanza);
end);