| 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 |