plugins/trac.lua

1
--local bugs = {};
2
local s_match = string.match;
3
local t_insert = table.insert;
4
local to_json = require "json".encode;
5
 
6
function riddim.plugins.trac(bot)
7
	local trac = bot.config.trac;
8
	if not trac then return end
9
 
10
	local http = require("prosody.net.http");
11
 
12
	bot:hook("commands/ticket", function(command)
13
		if not command.param then return end
14
		local bug_id = s_match(command.param, "%d+");
15
		if not bug_id then return end
16
		local format = s_match(command.param, "%w+$");
17
		local url = trac .. '/ticket/' .. bug_id;
18
		http.request(url .. '?format=csv', nil, function (data, code)
19
			if code ~= 200 then return end
20
			if data:sub(1,3) ~= "id," then return end
21
			local ticket = map_table(parse_csv(data));
22
			command:reply(
23
			format == "raw" and to_json(ticket) or 
24
			ticket[format] or
25
			(   ticket.component .. " / "
26
			..  ticket.summary   .. ": "
27
			.. (ticket.status == "closed"
28
			and ticket.resolution
29
			or  ticket.status == "assigned" and ""
30
			or  ticket.status)   .. " "
31
			..  ticket.priority  .. " "
32
			..  ticket.type      ..
33
			(   ticket.status == "assigned"
34
			and " assigned till "..  ticket.owner or "")
35
			..  " - <" ..  url .. ">"
36
			));
37
		end);
38
	end);
39
end
40
 
41
function parse_csv(s)
42
	s = s        -- ending comma
43
	local t, l = {{}}, 1        -- table to collect fields
44
	local fieldstart = 1
45
	repeat
46
		-- next field is quoted? (start with `"'?)
47
		if string.find(s, '^"', fieldstart) then
48
			local a, c
49
			local i  = fieldstart
50
			repeat
51
				-- find closing quote
52
				a, i, c = string.find(s, '"("?)', i+1)
53
			until c ~= '"'    -- quote not followed by quote?
54
			if not i then error('unmatched "') end
55
			local f = string.sub(s, fieldstart+1, i-1)
56
			if not t[l] then t[l] = {} end
57
			table.insert(t[l], (string.gsub(f, '""', '"')))
58
			fieldstart = string.find(s, ',', i) + 1
59
		else                -- unquoted; find next comma
60
			local nexti = math.min(string.find(s, ',', fieldstart) or #s,	string.find(s, "\r\n", fieldstart) or #s)
61
			if not t[l] then t[l] = {} end
62
			table.insert(t[l], string.sub(s, fieldstart, nexti-1))
63
			if string.sub(s, nexti, nexti +1) == "\r\n" then l = l + 1; nexti = nexti +1 end
64
			fieldstart = nexti + 1
65
		end
66
	until fieldstart > string.len(s)
67
	return t
68
end
69
 
70
function map_table(t)
71
	local ret = {};
72
	if not t[1] then return nil end
73
	if not t[2] then return nil end
74
 
75
	for i,v in ipairs(t[1]) do
76
		ret[t[1][i]] = t[2][i] or "";
77
	end
78
	return ret
79
end