Software / code / verse
Comparison
plugins/roster.lua @ 192:d20feb8034f5
plugins.roster: Add roster push handling, roster item parsing, delete_contact()
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Wed, 09 Mar 2011 18:38:24 +0100 |
| parent | 82:f306c2f8bb88 |
| child | 209:48a404e083c4 |
comparison
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 |