plugins/disco.lua

changeset 380
0891b4e27766
parent 267
d30897e4f5c2
child 392
cdea6a28369e
equal deleted inserted replaced
379:d80d27234e38 380:0891b4e27766
1 -- Verse XMPP Library 1 -- Verse XMPP Library
2 -- Copyright (C) 2010 Hubert Chathi <hubert@uhoreg.ca> 2 -- Copyright (C) 2010 Hubert Chathi <hubert@uhoreg.ca>
3 -- Copyright (C) 2010 Matthew Wild <mwild1@gmail.com> 3 -- Copyright (C) 2010 Matthew Wild <mwild1@gmail.com>
4 -- 4 --
5 -- This project is MIT/X11 licensed. Please see the 5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information. 6 -- COPYING file in the source package for more information.
7 -- 7 --
8 8
9 local verse = require "verse"; 9 local verse = require "verse";
116 node = stream.caps.node, 116 node = stream.caps.node,
117 ver = hash 117 ver = hash
118 }) 118 })
119 end 119 end
120 }) 120 })
121 121
122 function stream:set_identity(identity, node) 122 function stream:set_identity(identity, node)
123 self.disco.info[node or false].identities = { identity }; 123 self.disco.info[node or false].identities = { identity };
124 stream:resend_presence(); 124 stream:resend_presence();
125 end 125 end
126 126
133 function stream:add_disco_feature(feature, node) 133 function stream:add_disco_feature(feature, node)
134 local feature = feature.var or feature; 134 local feature = feature.var or feature;
135 self.disco.info[node or false].features[feature] = true; 135 self.disco.info[node or false].features[feature] = true;
136 stream:resend_presence(); 136 stream:resend_presence();
137 end 137 end
138 138
139 function stream:remove_disco_feature(feature, node) 139 function stream:remove_disco_feature(feature, node)
140 local feature = feature.var or feature; 140 local feature = feature.var or feature;
141 self.disco.info[node or false].features[feature] = nil; 141 self.disco.info[node or false].features[feature] = nil;
142 stream:resend_presence(); 142 stream:resend_presence();
143 end 143 end
179 if not cached_disco or not cached_disco.features then 179 if not cached_disco or not cached_disco.features then
180 return nil, "no-cache"; 180 return nil, "no-cache";
181 end 181 end
182 return cached_disco.features[feature] or false; 182 return cached_disco.features[feature] or false;
183 end 183 end
184 184
185 function stream:get_local_services(category, type) 185 function stream:get_local_services(category, type)
186 local host_disco = self.disco.cache[self.host]; 186 local host_disco = self.disco.cache[self.host];
187 if not(host_disco) or not(host_disco.items) then 187 if not(host_disco) or not(host_disco.items) then
188 return nil, "no-cache"; 188 return nil, "no-cache";
189 end 189 end
190 190
191 local results = {}; 191 local results = {};
192 for _, service in ipairs(host_disco.items) do 192 for _, service in ipairs(host_disco.items) do
193 if self:jid_has_identity(service.jid, category, type) then 193 if self:jid_has_identity(service.jid, category, type) then
194 table.insert(results, service.jid); 194 table.insert(results, service.jid);
195 end 195 end
196 end 196 end
197 return results; 197 return results;
198 end 198 end
199 199
200 function stream:disco_local_services(callback) 200 function stream:disco_local_services(callback)
201 self:disco_items(self.host, nil, function (items) 201 self:disco_items(self.host, nil, function (items)
202 if not items then 202 if not items then
203 return callback({}); 203 return callback({});
204 end 204 end
207 n_items = n_items - 1; 207 n_items = n_items - 1;
208 if n_items == 0 then 208 if n_items == 0 then
209 return callback(items); 209 return callback(items);
210 end 210 end
211 end 211 end
212 212
213 for _, item in ipairs(items) do 213 for _, item in ipairs(items) do
214 if item.jid then 214 if item.jid then
215 n_items = n_items + 1; 215 n_items = n_items + 1;
216 self:disco_info(item.jid, nil, item_callback); 216 self:disco_info(item.jid, nil, item_callback);
217 end 217 end
219 if n_items == 0 then 219 if n_items == 0 then
220 return callback(items); 220 return callback(items);
221 end 221 end
222 end); 222 end);
223 end 223 end
224 224
225 function stream:disco_info(jid, node, callback) 225 function stream:disco_info(jid, node, callback)
226 local disco_request = verse.iq({ to = jid, type = "get" }) 226 local disco_request = verse.iq({ to = jid, type = "get" })
227 :tag("query", { xmlns = xmlns_disco_info, node = node }); 227 :tag("query", { xmlns = xmlns_disco_info, node = node });
228 self:send_iq(disco_request, function (result) 228 self:send_iq(disco_request, function (result)
229 if result.attr.type == "error" then 229 if result.attr.type == "error" then
230 return callback(nil, result:get_error()); 230 return callback(nil, result:get_error());
231 end 231 end
232 232
233 local identities, features = {}, {}; 233 local identities, features = {}, {};
234 234
235 for tag in result:get_child("query", xmlns_disco_info):childtags() do 235 for tag in result:get_child("query", xmlns_disco_info):childtags() do
236 if tag.name == "identity" then 236 if tag.name == "identity" then
237 identities[tag.attr.category.."/"..tag.attr.type] = tag.attr.name or true; 237 identities[tag.attr.category.."/"..tag.attr.type] = tag.attr.name or true;
238 elseif tag.name == "feature" then 238 elseif tag.name == "feature" then
239 features[tag.attr.var] = true; 239 features[tag.attr.var] = true;
240 end 240 end
241 end 241 end
242 242
243 243
244 if not self.disco.cache[jid] then 244 if not self.disco.cache[jid] then
245 self.disco.cache[jid] = { nodes = {} }; 245 self.disco.cache[jid] = { nodes = {} };
246 end 246 end
247 247
256 self.disco.cache[jid].features = features; 256 self.disco.cache[jid].features = features;
257 end 257 end
258 return callback(self.disco.cache[jid]); 258 return callback(self.disco.cache[jid]);
259 end); 259 end);
260 end 260 end
261 261
262 function stream:disco_items(jid, node, callback) 262 function stream:disco_items(jid, node, callback)
263 local disco_request = verse.iq({ to = jid, type = "get" }) 263 local disco_request = verse.iq({ to = jid, type = "get" })
264 :tag("query", { xmlns = xmlns_disco_items, node = node }); 264 :tag("query", { xmlns = xmlns_disco_items, node = node });
265 self:send_iq(disco_request, function (result) 265 self:send_iq(disco_request, function (result)
266 if result.attr.type == "error" then 266 if result.attr.type == "error" then
274 jid = tag.attr.jid; 274 jid = tag.attr.jid;
275 node = tag.attr.node; 275 node = tag.attr.node;
276 }); 276 });
277 end 277 end
278 end 278 end
279 279
280 if not self.disco.cache[jid] then 280 if not self.disco.cache[jid] then
281 self.disco.cache[jid] = { nodes = {} }; 281 self.disco.cache[jid] = { nodes = {} };
282 end 282 end
283 283
284 if node then 284 if node then
285 if not self.disco.cache[jid].nodes[node] then 285 if not self.disco.cache[jid].nodes[node] then
286 self.disco.cache[jid].nodes[node] = { nodes = {} }; 286 self.disco.cache[jid].nodes[node] = { nodes = {} };
287 end 287 end
288 self.disco.cache[jid].nodes[node].items = disco_items; 288 self.disco.cache[jid].nodes[node].items = disco_items;
290 self.disco.cache[jid].items = disco_items; 290 self.disco.cache[jid].items = disco_items;
291 end 291 end
292 return callback(disco_items); 292 return callback(disco_items);
293 end); 293 end);
294 end 294 end
295 295
296 stream:hook("iq/"..xmlns_disco_info, function (stanza) 296 stream:hook("iq/"..xmlns_disco_info, function (stanza)
297 local query = stanza.tags[1]; 297 local query = stanza.tags[1];
298 if stanza.attr.type == 'get' and query.name == "query" then 298 if stanza.attr.type == 'get' and query.name == "query" then
299 local query_node = query.attr.node; 299 local query_node = query.attr.node;
300 local node = stream.disco.info[query_node or false]; 300 local node = stream.disco.info[query_node or false];
335 end 335 end
336 stream:send(result); 336 stream:send(result);
337 return true 337 return true
338 end 338 end
339 end); 339 end);
340 340
341 local initial_disco_started; 341 local initial_disco_started;
342 stream:hook("ready", function () 342 stream:hook("ready", function ()
343 if initial_disco_started then return; end 343 if initial_disco_started then return; end
344 initial_disco_started = true; 344 initial_disco_started = true;
345 stream:disco_local_services(function (services) 345 stream:disco_local_services(function (services)
356 end 356 end
357 stream:event("ready"); 357 stream:event("ready");
358 end); 358 end);
359 return true; 359 return true;
360 end, 50); 360 end, 50);
361 361
362 stream:hook("presence-out", function (presence) 362 stream:hook("presence-out", function (presence)
363 if not presence:get_child("c", xmlns_caps) then 363 if not presence:get_child("c", xmlns_caps) then
364 presence:reset():add_child(stream:caps()):reset(); 364 presence:reset():add_child(stream:caps()):reset();
365 end 365 end
366 end, 10); 366 end, 10);

mercurial