Roster updates
[prosody.git] / core / rostermanager.lua
1
2 local mainlog = log;
3 local function log(type, message)
4         mainlog(type, "rostermanager", message);
5 end
6
7 local setmetatable = setmetatable;
8 local format = string.format;
9 local loadfile, setfenv, pcall = loadfile, setfenv, pcall;
10 local pairs, ipairs = pairs, ipairs;
11
12 local hosts = hosts;
13
14 require "util.datamanager"
15
16 local datamanager = datamanager;
17 local st = require "util.stanza";
18
19 module "rostermanager"
20
21 function add_to_roster(session, jid, item)
22         if session.roster then
23                 local old_item = session.roster[jid];
24                 session.roster[jid] = item;
25                 if save_roster(session.username, session.host) then
26                         return true;
27                 else
28                         session.roster[jid] = old_item;
29                         return nil, "wait", "internal-server-error", "Unable to save roster";
30                 end
31         else
32                 return nil, "auth", "not-authorized", "Session's roster not loaded";
33         end
34 end
35
36 function remove_from_roster(session, jid)
37         if session.roster then
38                 local old_item = session.roster[jid];
39                 session.roster[jid] = nil;
40                 if save_roster(session.username, session.host) then
41                         return true;
42                 else
43                         session.roster[jid] = old_item;
44                         return nil, "wait", "internal-server-error", "Unable to save roster";
45                 end
46         else
47                 return nil, "auth", "not-authorized", "Session's roster not loaded";
48         end
49 end
50
51 function roster_push(username, host, jid)
52         if hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster then
53                 local item = hosts[host].sessions[username].roster[jid];
54                 local stanza = st.iq({type="set"});
55                 stanza:tag("query", {xmlns = "jabber:iq:roster"});
56                 if item then
57                         stanza:tag("item", {jid = jid, subscription = item.subscription, name = item.name, ask = item.ask});
58                         for group in pairs(item.groups) do
59                                 stanza:tag("group"):text(group):up();
60                         end
61                 else
62                         stanza:tag("item", {jid = jid, subscription = "remove"});
63                 end
64                 stanza:up();
65                 stanza:up();
66                 -- stanza ready
67                 for _, session in pairs(hosts[host].sessions[username].sessions) do
68                         if session.interested then
69                                 -- FIXME do we need to set stanza.attr.to?
70                                 session.send(stanza);
71                         end
72                 end
73         end
74 end
75
76 function load_roster(username, host)
77         if hosts[host] and hosts[host].sessions[username] then
78                 local roster = hosts[host].sessions[username].roster;
79                 if not roster then
80                         roster = datamanager.load(username, host, "roster") or {};
81                         hosts[host].sessions[username].roster = roster;
82                 end
83                 return roster;
84         end
85         -- Attempt to load roster for non-loaded user
86         -- TODO also support loading for offline user
87 end
88
89 function save_roster(username, host)
90         if hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster then
91                 return datamanager.store(username, host, "roster", hosts[host].sessions[username].roster);
92         end
93         return nil;
94 end
95
96 return _M;