plugins/xeps.lua

1
local parse_xeps, xeps_updated_at;
2
local xeps, xeps_short = {}, {};
3
 
4
function riddim.plugins.xeps(bot)
5
	bot:hook("commands/xep", function(command)
6
		-- Cache XEP list for an hour
7
		if os.difftime(os.time(), xeps_updated_at) > (60 * 60) then -- Not refreshed within 1 hour
8
			bot:http_request('https://xmpp.org/extensions/xeplist.xml', nil, function (data, code)
9
				if code ~= 200 then
10
					if code > 0 then
11
						command:reply("Received HTTP "..code.." error trying to fetch the XEP list");
12
					else
13
						command:reply("Unable to fetch the XEP list from xmpp.org: "..data:gsub("%-", " "));
14
					end
15
					return;
16
				end
17
				xeps_updated_at = os.time();
18
				parse_xeps(data);
19
				command:reply(handle_xep_command(command));
20
			end);
21
		else
22
			return handle_xep_command(command);
23
		end
24
	end);
25
end
26
 
27
function handle_xep_command(command)
28
	local xepnum = command.param;
29
	if not xepnum then return "Please supply an XEP number or a search string :)"; end
30
	if xeps_short[xepnum:lower()] then
31
		xepnum = xeps_short[xepnum:lower()];
32
	elseif not tonumber(xepnum) then -- Search for an XEP
33
		if xepnum:match("^(%d+) ex%S* (%d+)$") then
34
			local num, example = xepnum:match("^(%d+) ex%S* (%d+)$");
35
			return "https://xmpp.org/extensions/xep-"..string.rep("0", 4-num:len())..num..".html#example-"..tostring(example);
36
		end
37
		local results = {};
38
		for x, xep in pairs(xeps) do
39
			name = " "..xep.name:lower().." ";
40
			if name:match(xepnum:lower():gsub("%-", "%%-")) then
41
				table.insert(results, x);
42
				--return commands.xep(msg, x);
43
			end
44
		end
45
		if #results == 0 then
46
			return "Sorry, I couldn't find a match";
47
		elseif #results == 1 then
48
			command.param = results[1];
49
			return handle_xep_command(command);
50
		else
51
			-- We have more than one match
52
			local ret = "Multiple matches:";
53
			for _, x in ipairs(results) do
54
				local xepnum = tostring(tonumber(x));
55
				xepnum = string.rep("0", 4-x:len())..x;
56
				local xep = xeps[tostring(x)];
57
				ret = string.format("%s XEP-%s: %s%s", ret, xep.number, xep.name, ((_ < #results) and ",") or "");
58
				if _ > 5 then ret = ret .. " " .. (#results - 5) .. " more"; break; end
59
			end
60
			return ret;
61
		end
62
	end
63
	-- Check that xepnum is a valid number
64
	xepnum = tostring(tonumber(xepnum));
65
	if not xepnum then return "What XEP? or enter a search string."; end
66
	-- Expand to full 4 char number
67
	xepnum = string.rep("0", 4-xepnum:len())..xepnum;
68
	xep = xeps[tostring(xepnum)];
69
	if not xep then return "Sorry, I don't think there is a XEP-"..xepnum; end
70
	return "XEP-"..xep.number..": "..xep.name.." is "..xep.type.." ("..xep.status..", "..xep.updated..") See: https://xmpp.org/extensions/xep-"..xep.number..".html";
71
end
72
 
73
function parse_xeps(t)
74
	if not t then return nil; end
75
	local currxep = {};
76
	for b in string.gmatch(t,"<xep>(.-)</xep>") do
77
		for k,v in string.gmatch(b,"<(%w+)>(.-)</%1>") do
78
			currxep[k] = v;
79
		end
80
		if xeps_short[currxep.shortname] == nil then
81
			xeps_short[currxep.shortname] = currxep.number;
82
		elseif xeps_short[currxep.shortname] then
83
			xeps_short[currxep.shortname] = false; -- kill dupes
84
		end
85
		xeps[currxep.number] = { };
86
		for k, v in pairs(currxep) do
87
			xeps[currxep.number][k] = v;
88
		end
89
	end
90
	xeps["0028"] = { number = "0028", name = "XSF Plans for World Domination", type="Top Secret", status = "Hidden", updated = "Work ongoing" };
91
	return true;
92
end