plugins/roster.lua

changeset 192
d20feb8034f5
parent 82
f306c2f8bb88
child 209
48a404e083c4
equal deleted inserted replaced
191:e0664081654c 192:d20feb8034f5
1 local xmlns_roster = "jabber:iq:roster"; 1 local xmlns_roster = "jabber:iq:roster";
2 local bare_jid = require "util.jid".bare;
3 local t_insert = table.insert;
2 4
3 function verse.plugins.roster(stream) 5 function verse.plugins.roster(stream)
4 function stream:roster_add(jid, callback) 6 local roster = {
5 self:send_iq(verse.iq({ type = "set" }) 7 items = {};
8 -- TODO:
9 -- groups = {};
10 -- ver = nil;
11 };
12 stream.roster = roster;
13
14 local function item_lua2xml(item_table)
15 local xml_item = verse.stanza("item", { xmlns = xmlns_roster });
16 for k, v in pairs(item_table) do
17 if k ~= "groups" then
18 xml_item.attr[k] = v;
19 else
20 for i = 1,#v do
21 xml_item:tag("group"):text(v[i]):up();
22 end
23 end
24 end
25 return xml_item;
26 end
27
28 local function item_xml2lua(xml_item)
29 local item_table = { };
30 local groups = {};
31 item_table.groups = groups;
32 local jid = xml_item.attr.jid;
33
34 for k, v in pairs(xml_item.attr) do
35 if k ~= "xmlns" then
36 item_table[k] = v
37 end
38 end
39
40 for group in xml_item:childtags("group") do
41 t_insert(groups, group:get_text())
42 end
43 return item_table;
44 end
45
46 -- should this be add_contact(item, callback) instead?
47 function roster:add_contact(jid, nick, groups, callback)
48 local item = { jid = jid, name = nick, groups = groups };
49 local stanza = verse.iq({ type = "set" })
6 :tag("query", { xmlns = xmlns_roster }) 50 :tag("query", { xmlns = xmlns_roster })
7 :tag("item", { jid = jid }), function () 51 :add_child(item_lua2xml(item));
8 callback(); 52 stream:send_iq(stanza, function (reply)
9 end); 53 if not callback then return end
54 if reply.attr.type == "result" then
55 callback(true);
56 else
57 type, condition, text = reply:get_error();
58 callback(nil, { type, condition, text });
59 end
60 end);
10 end 61 end
11 62 -- What about subscriptions?
12 function stream:roster_fetch(callback) 63
13 self:send_iq(verse.iq({type="get"}):tag("query", { xmlns = xmlns_roster }), 64 function roster:delete_contact(jid, callback)
14 function (result) 65 jid = (type(jid) == "table" and jid.jid) or jid;
15 --TODO: Pass parsed roster to callback 66 local item = { jid = jid, subscription = "remove" }
16 callback(result); 67 if not roster.items[jid] then return false, "item-not-found"; end
68 stream:send_iq(verse.iq({ type = "set" })
69 :tag("query", { xmlns = xmlns_roster })
70 :add_child(item_lua2xml(item)),
71 function (reply)
72 if not callback then return end
73 if result.attr.type == "result" then
74 callback(true);
75 else
76 type, condition, text = reply:get_error();
77 callback(nil, { type, condition, text });
78 end
17 end); 79 end);
18 end 80 end
81
82 local function add_item(item) -- Takes one roster <item/>
83 local roster_item = item_xml2lua(item);
84 roster.items[roster_item.jid] = roster_item;
85 end
86
87 -- Private low level
88 local function delete_item(jid)
89 local deleted_item = roster.items[jid];
90 roster.items[jid] = nil;
91 return deleted_item;
92 end
93
94 function roster:fetch(callback)
95 stream:send_iq(verse.iq({type="get"}):tag("query", { xmlns = xmlns_roster }),
96 function (result)
97 if result.attr.type == "result" then
98 local query = result:get_child("query", xmlns_roster);
99 for item in query:childtags("item") do
100 add_item(item)
101 end
102 callback(roster);
103 else
104 type, condition, text = stanza:get_error();
105 callback(nil, { type, condition, text }); --FIXME
106 end
107 end);
108 end
109
110 stream:hook("iq/"..xmlns_roster, function(stanza)
111 local type, from = stanza.attr.type, stanza.attr.from;
112 if type == "set" and (not from or from == bare_jid(stream.jid)) then
113 local query = stanza:get_child("query", xmlns_roster);
114 local item = query and query:get_child("item");
115 if item then
116 local event, target;
117 local jid = item.attr.jid;
118 if item.attr.subscription == "remove" then
119 event = "removed"
120 target = delete_item(jid);
121 else
122 event = roster.items[jid] and "changed" or "added";
123 add_item(item)
124 target = roster.items[jid];
125 end
126 stream:event("roster/item-"..event, target);
127 -- TODO else return error? Events?
128 end
129 stream:send(verse.reply(stanza))
130 return true;
131 end
132 end);
19 end 133 end

mercurial