clix/archive.lua

1
local jid_split = require"prosody.util.jid".split;
2
local bare_jid = require"prosody.util.jid".bare;
3
local datetime = require"prosody.util.datetime";
4
return function (opts, arg)
5
	if opts.short_help then
6
		print("Fetch archived messages");
7
		return;
8
	end
9
 
10
	local function parse_datetime(s)
11
		if s:match("^%d%d:") then
12
			s = datetime.date().."T"..s;
13
		end
14
		if #s < 20 then
15
			s = s .. ("0000-01-01T00:00:00Z"):sub(#s+1)
16
		end
17
		return datetime.parse(s)
18
	end
19
	local reverse = opts.before;
20
	if opts.start then
21
		opts.start = parse_datetime(opts.start);
22
	end
23
	if opts["end"] then
24
		opts["end"] = parse_datetime(opts["end"]);
25
	end
26
	local selfjid;
27
	local function print_message(i)
28
		-- TODO Roster lookup
29
		local m = i.message;
30
		if not m:get_child("body") then return end
31
		local a = m.attr;
32
		if i.stamp then
33
			print(os.date("%Y-%m-%d %H:%M:%S", i.stamp));
34
		end
35
		if a.to and bare_jid(a.to) ~= selfjid then
36
			print("To ".. bare_jid(a.to));
37
		end
38
		if a.from and bare_jid(a.from) ~= selfjid then
39
			print("From ".. bare_jid(a.from));
40
		end
41
		print(m:get_child_text"body");
42
		print"";
43
	end
44
	if opts.format == "raw" then
45
		local st = require"prosody.util.stanza";
46
		local datetime = require"prosody.util.datetime".datetime;
47
		function print_message(i)
48
		print(st.stanza("forwarded",{xmlns="urn:xmpp:forward:0"})
49
			:tag("delay", {xmlns="urn:xmpp:delay", stamp=datetime(i.stamp)}):up()
50
			:add_child(i.message));
51
		end
52
	elseif opts.format == "irc" then
53
		local date;
54
		local os_date = os.date;
55
		function print_message(i)
56
			local m = i.message;
57
			local body = m:get_child_text("body");
58
			local a = m.attr;
59
			local _, _, nick = jid_split(a.from);
60
 
61
			local curdate = os_date("%F", i.stamp);
62
			if date ~= curdate then
63
				print("-!- "..curdate);
64
				date = curdate;
65
			end
66
			if nick and body then
67
				print(("%s <%s> %s"):format(os_date("%T", i.stamp), nick, body));
68
			end
69
		end
70
	end
71
 
72
	local function on_connect(conn)
73
		if opts.debug then
74
			conn:hook("stanza-out", print);
75
			conn:hook("stanza", print);
76
		end
77
		selfjid = bare_jid(conn.jid);
78
		local function handle_results(result, err)
79
			if not result then
80
				conn:close();
81
				return;
82
			end
83
			for i=1,#result do
84
				print_message(result[i]);
85
			end
86
			if result[reverse and "first" or "last"] then
87
				local fetch_next = opts.everything;
88
				if opts.interactive and not fetch_next then
89
					io.stderr:write "--More--"
90
					fetch_next = io.read"*l" or print();
91
				end
92
				if fetch_next then
93
					if reverse then
94
						opts.before = result.first and result.first[1];
95
					else
96
						opts.after = result.last;
97
					end
98
					conn:query_archive(opts.to, opts, handle_results);
99
					return
100
				else
101
					local whatnext, nextpage = reverse and "before" or "after";
102
					if reverse then
103
						nextpage = result.first and result.first[1];
104
					else
105
						nextpage = result.last;
106
					end
107
					conn:info("Next page: --%s=%s", whatnext, nextpage);
108
				end
109
			end
110
			if result.count then
111
				conn:info("Total: %d items", result.count);
112
			end
113
			conn:close();
114
		end
115
		conn:add_plugin"archive";
116
		-- TODO conn:add_plugin"roster";
117
		-- c.roster:fetch(function()
118
		conn:query_archive(opts.to, opts, handle_results);
119
	end
120
	clix_connect(opts, on_connect);
121
end