plugins.disco: Fix to use util.caps instead of broken hacky implementation

Wed, 27 Jun 2018 19:19:11 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Wed, 27 Jun 2018 19:19:11 +0100
changeset 423
e98cef597393
parent 422
ff59e4a1a600
child 424
eaaaf4495e06

plugins.disco: Fix to use util.caps instead of broken hacky implementation

plugins/disco.lua file | annotate | diff | comparison | revisions
--- a/plugins/disco.lua	Wed Jun 27 19:18:06 2018 +0100
+++ b/plugins/disco.lua	Wed Jun 27 19:19:11 2018 +0100
@@ -9,6 +9,7 @@
 local verse = require "verse";
 local b64 = require("mime").b64;
 local sha1 = require("util.hashes").sha1;
+local calculate_hash = require "util.caps".calculate_hash;
 
 local xmlns_caps = "http://jabber.org/protocol/caps";
 local xmlns_disco = "http://jabber.org/protocol/disco";
@@ -54,60 +55,32 @@
 	stream.caps = {}
 	stream.caps.node = 'http://code.matthewwild.co.uk/verse/'
 
-	local function cmp_identity(item1, item2)
-		if item1.category < item2.category then
-			return true;
-		elseif item2.category < item1.category then
-			return false;
-		end
-		if item1.type < item2.type then
-			return true;
-		elseif item2.type < item1.type then
-			return false;
+	local function build_self_disco_info_stanza(query_node)
+		local node = stream.disco.info[query_node or false];
+		if query_node and query_node == stream.caps.node .. "#" .. stream.caps.hash then
+			node = stream.disco.info[false];
 		end
-		if (not item1['xml:lang'] and item2['xml:lang']) or
-			 (item2['xml:lang'] and item1['xml:lang'] < item2['xml:lang']) then
-			return true
-		end
-		return false
-	end
-
-	local function cmp_feature(item1, item2)
-		return item1.var < item2.var
-	end
+		local identities, features = node.identities, node.features
 
-	local function calculate_hash(node)
-		local identities = stream.disco.info[node or false].identities;
-		table.sort(identities, cmp_identity)
-		local features = {};
-		for var in pairs(stream.disco.info[node or false].features) do
-			features[#features+1] = { var = var };
+		-- construct the response
+		local result = verse.stanza("query", {
+			xmlns = xmlns_disco_info,
+			node = query_node,
+		});
+		for _,identity in pairs(identities) do
+			result:tag('identity', identity):up()
 		end
-		table.sort(features, cmp_feature)
-		local S = {};
-		for key,identity in pairs(identities) do
-			S[#S+1] = table.concat({
-				identity.category, identity.type or '',
-				identity['xml:lang'] or '', identity.name or ''
-			}, '/');
+		for feature in pairs(features) do
+			result:tag('feature', { var = feature }):up()
 		end
-		for key,feature in pairs(features) do
-			S[#S+1] = feature.var
-		end
-		S[#S+1] = '';
-		S = table.concat(S,'<');
-		-- FIXME: make sure S is utf8-encoded
-		--stream:debug("Computed hash string: "..S);
-		--stream:debug("Computed hash string (sha1): "..sha1(S, true));
-		--stream:debug("Computed hash string (sha1+b64): "..b64(sha1(S)));
-		return (b64(sha1(S)))
+		return result;
 	end
 
 	setmetatable(stream.caps, {
 		__call = function (...) -- vararg: allow calling as function or member
 			-- retrieve the c stanza to insert into the
 			-- presence stanza
-			local hash = calculate_hash()
+			local hash = calculate_hash(build_self_disco_info_stanza())
 			stream.caps.hash = hash;
 			-- TODO proper caching.... some day
 			return verse.stanza('c', {
@@ -296,24 +269,8 @@
 	stream:hook("iq/"..xmlns_disco_info, function (stanza)
 		local query = stanza.tags[1];
 		if stanza.attr.type == 'get' and query.name == "query" then
-			local query_node = query.attr.node;
-			local node = stream.disco.info[query_node or false];
-			if query_node and query_node == stream.caps.node .. "#" .. stream.caps.hash then
-				node = stream.disco.info[false];
-			end
-			local identities, features = node.identities, node.features
-
-			-- construct the response
-			local result = verse.reply(stanza):tag("query", {
-				xmlns = xmlns_disco_info,
-				node = query_node,
-			});
-			for _,identity in pairs(identities) do
-				result:tag('identity', identity):up()
-			end
-			for feature in pairs(features) do
-				result:tag('feature', { var = feature }):up()
-			end
+			local query_tag = build_self_disco_info_stanza(query.attr.node);
+			local result = verse.reply(stanza):add_child(query_tag);
 			stream:send(result);
 			return true
 		end
@@ -342,17 +299,28 @@
 	stream:hook("ready", function ()
 		if initial_disco_started then return; end
 		initial_disco_started = true;
+
+		-- Using the disco cache, fires events for each identity of a given JID
+		local function scan_identities_for_service(service_jid)
+			local service_disco_info = stream.disco.cache[service_jid];
+			if service_disco_info then
+				for identity in pairs(service_disco_info.identities) do
+					local category, type = identity:match("^(.*)/(.*)$");
+					print(service_jid, category, type)
+					stream:event("disco/service-discovered/"..category, {
+						type = type, jid = service_jid;
+					});
+				end
+			end
+		end
+
+		stream:disco_info(stream.host, nil, function ()
+			scan_identities_for_service(stream.host);
+		end);
+
 		stream:disco_local_services(function (services)
 			for _, service in ipairs(services) do
-				local service_disco_info = stream.disco.cache[service.jid];
-				if service_disco_info then
-					for identity in pairs(service_disco_info.identities) do
-						local category, type = identity:match("^(.*)/(.*)$");
-						stream:event("disco/service-discovered/"..category, {
-							type = type, jid = service.jid;
-						});
-					end
-				end
+				scan_identities_for_service(service.jid);
 			end
 			stream:event("ready");
 		end);

mercurial