mod_message: mod_message now handles all cases
[prosody.git] / plugins / mod_message.lua
1
2 local full_sessions = full_sessions;
3 local bare_sessions = bare_sessions;
4
5 local jid_bare = require "util.jid".bare;
6 local user_exists = require "core.usermanager".user_exists;
7 local offlinemanager = require "core.offlinemanager";
8
9 local function select_top_resources(user)
10         local priority = 0;
11         local recipients = {};
12         for _, session in pairs(user.sessions) do -- find resource with greatest priority
13                 if session.presence then
14                         local p = session.priority;
15                         if p > priority then
16                                 priority = p;
17                                 recipients = {session};
18                         elseif p == priority then
19                                 t_insert(recipients, session);
20                         end
21                 end
22         end
23         return recipients;
24 end
25
26 local function process_to_bare(bare, origin, stanza)
27         local user = bare_sessions[bare];
28         
29         local t = stanza.attr.type;
30         if t == "error" then return true; end
31         if t == "groupchat" then
32                 origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
33                 return true;
34         end
35         if t == "headline" then
36                 if user then
37                         for _, session in pairs(user.sessions) do
38                                 if session.presence and session.priority >= 0 then
39                                         session.send(stanza);
40                                 end
41                         end
42                 end  -- current policy is to discard headlines if no recipient is available
43                 return true;
44         end
45         -- chat or normal message
46         if user then -- some resources are connected
47                 local recipients = select_top_resources(user);
48                 if #recipients > 0 then
49                         for i=1,#recipients do
50                                 recipients[i].send(stanza);
51                         end
52                         return true;
53                 end
54         end
55         -- no resources are online
56         local node, host = jid_split(bare);
57         if user_exists(node, host) then
58                 -- TODO apply the default privacy list
59                 offlinemanager.store(node, host, stanza);
60         else
61                 origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
62         end
63         return true;
64 end
65
66 module:hook("message/full", function(data)
67         -- message to full JID recieved
68         local origin, stanza = data.origin, data.stanza;
69         
70         local session = full_sessions[stanza.attr.to];
71         if session then
72                 -- TODO fire post processing event
73                 session.send(stanza);
74                 return true;
75         else -- resource not online
76                 return process_to_bare(jid_bare(stanza.attr.to), origin, stanza);
77         end
78 end);
79
80 module:hook("message/bare", function(data)
81         -- message to bare JID recieved
82         local origin, stanza = data.origin, data.stanza;
83
84         return process_to_bare(stanza.attr.to or (origin.username..'@'..origin.host), origin, stanza);
85 end);