mod_http_muc_log/mod_http_muc_log.lua
changeset 3754 9002c8a2165f
parent 3753 cb61f0e06de3
child 3761 971417eedfee
equal deleted inserted replaced
3753:cb61f0e06de3 3754:9002c8a2165f
     4 local nodeprep = require"util.encodings".stringprep.nodeprep;
     4 local nodeprep = require"util.encodings".stringprep.nodeprep;
     5 local it = require"util.iterators";
     5 local it = require"util.iterators";
     6 local url = require"socket.url";
     6 local url = require"socket.url";
     7 local os_time, os_date = os.time, os.date;
     7 local os_time, os_date = os.time, os.date;
     8 local httplib = require "util.http";
     8 local httplib = require "util.http";
     9 local render = require"util.interpolation".new("%b{}", require"util.stanza".xml_escape);
     9 local render_funcs = {};
       
    10 local render = require"util.interpolation".new("%b{}", require"util.stanza".xml_escape, render_funcs);
    10 
    11 
    11 local archive = module:open_store("muc_log", "archive");
    12 local archive = module:open_store("muc_log", "archive");
    12 
    13 
    13 -- Support both old and new MUC code
    14 -- Support both old and new MUC code
    14 local mod_muc = module:depends"muc";
    15 local mod_muc = module:depends"muc";
   145 		end
   146 		end
   146 	end
   147 	end
   147 	return false;
   148 	return false;
   148 end
   149 end
   149 
   150 
   150 -- Produce the calendar view
   151 local function get_dates(room) --> { integer, ... }
   151 local function years_page(event, path)
       
   152 	local request, response = event.request, event.response;
       
   153 
       
   154 	local room = nodeprep(path:match("^(.*)/$"));
       
   155 	local is_open = open_room(room);
       
   156 	if is_open == nil then
       
   157 		return -- implicit 404
       
   158 	elseif is_open == false then
       
   159 		return 403;
       
   160 	end
       
   161 
       
   162 	-- Collect each date that has messages
       
   163 	-- convert it to a year / month / day tree
       
   164 	local date_list = archive.dates and archive:dates(room);
   152 	local date_list = archive.dates and archive:dates(room);
   165 	local dates = mt.new();
       
   166 	if date_list then
   153 	if date_list then
   167 		for _, date in ipairs(date_list) do
   154 		for i = 1, #date_list do
   168 			local when = datetime.parse(date.."T00:00:00Z");
   155 			date_list[i] = datetime.parse(date_list[i].."T00:00:00Z");
   169 			local t = os_date("!*t", when);
   156 		end
   170 			dates:set(t.year, t.month, t.day, when);
   157 		return date_list;
   171 		end
   158 	end
   172 	elseif lazy then
   159 
       
   160 	if lazy then
   173 		-- Lazy with many false positives
   161 		-- Lazy with many false positives
       
   162 		date_list = {};
   174 		local first_day = find_once(room, nil, 3);
   163 		local first_day = find_once(room, nil, 3);
   175 		local last_day = find_once(room, { reverse = true }, 3);
   164 		local last_day = find_once(room, { reverse = true }, 3);
   176 		if first_day and last_day then
   165 		if first_day and last_day then
   177 			first_day = date_floor(first_day);
   166 			first_day = date_floor(first_day);
   178 			last_day = date_floor(last_day);
   167 			last_day = date_floor(last_day);
   179 			for when = first_day, last_day, 86400 do
   168 			for when = first_day, last_day, 86400 do
   180 				local t = os_date("!*t", when);
   169 				table.insert(date_list, when);
   181 				dates:set(t.year, t.month, t.day, when);
       
   182 			end
   170 			end
   183 		else
   171 		else
   184 			return; -- 404
   172 			return; -- 404
   185 		end
   173 		end
   186 	else
   174 		return date_list;
   187 		-- Collect date the hard way
   175 	end
   188 		module:log("debug", "Find all dates with messages");
   176 
   189 		local next_day;
   177 	-- Collect date the hard way
   190 		repeat
   178 	module:log("debug", "Find all dates with messages");
   191 			local when = find_once(room, { start = next_day; }, 3);
   179 	date_list = {};
   192 			if not when then break; end
   180 	local next_day;
   193 			local t = os_date("!*t", when);
   181 	repeat
   194 			dates:set(t.year, t.month, t.day, when );
   182 		local when = find_once(room, { start = next_day; }, 3);
   195 			next_day = date_floor(when) + 86400;
   183 		if not when then break; end
   196 		until not next_day;
   184 		table.insert(date_list, when);
   197 	end
   185 		next_day = date_floor(when) + 86400;
   198 
   186 	until not next_day;
       
   187 	return date_list;
       
   188 end
       
   189 
       
   190 function render_funcs.calendarize(date_list)
       
   191 	-- convert array of timestamps to a year / month / day tree
       
   192 	local dates = mt.new();
       
   193 	for _, when in ipairs(date_list) do
       
   194 		local t = os_date("!*t", when);
       
   195 		dates:set(t.year, t.month, t.day, when);
       
   196 	end
       
   197 	-- Wrangle Y/m/d tree into year / month / week / day tree for calendar view
   199 	local years = {};
   198 	local years = {};
   200 
       
   201 	-- Wrangle Y/m/d tree into year / month / week / day tree for calendar view
       
   202 	for current_year, months_t in pairs(dates.data) do
   199 	for current_year, months_t in pairs(dates.data) do
   203 		local t = { year = current_year, month = 1, day = 1 };
   200 		local t = { year = current_year, month = 1, day = 1 };
   204 		local months = { };
   201 		local months = { };
   205 		local year = { year = current_year, months = months };
   202 		local year = { year = current_year, months = months };
   206 		years[#years+1] = year;
   203 		years[#years+1] = year;
   233 			end
   230 			end
   234 		end
   231 		end
   235 		table.sort(months, sort_m);
   232 		table.sort(months, sort_m);
   236 	end
   233 	end
   237 	table.sort(years, sort_Y);
   234 	table.sort(years, sort_Y);
       
   235 	return years;
       
   236 end
       
   237 
       
   238 -- Produce the calendar view
       
   239 local function years_page(event, path)
       
   240 	local request, response = event.request, event.response;
       
   241 
       
   242 	local room = nodeprep(path:match("^(.*)/$"));
       
   243 	local is_open = open_room(room);
       
   244 	if is_open == nil then
       
   245 		return -- implicit 404
       
   246 	elseif is_open == false then
       
   247 		return 403;
       
   248 	end
       
   249 
       
   250 	local date_list = get_dates(room);
       
   251 	if not date_list then
       
   252 		return; -- 404
       
   253 	end
   238 
   254 
   239 	-- Phew, all wrangled, all that's left is rendering it with the template
   255 	-- Phew, all wrangled, all that's left is rendering it with the template
   240 
   256 
   241 	response.headers.content_type = "text/html; charset=utf-8";
   257 	response.headers.content_type = "text/html; charset=utf-8";
   242 	return render(template, {
   258 	return render(template, {
   243 		room = get_room(room)._data;
   259 		room = get_room(room)._data;
   244 		jid = get_room(room).jid;
   260 		jid = get_room(room).jid;
   245 		jid_node = jid_split(get_room(room).jid);
   261 		jid_node = jid_split(get_room(room).jid);
   246 		hide_presence = hide_presence(request);
   262 		hide_presence = hide_presence(request);
   247 		presence_available = presence_logged;
   263 		presence_available = presence_logged;
   248 		years = years;
   264 		dates = date_list;
   249 		links = {
   265 		links = {
   250 			{ href = "../", rel = "up", text = "Room list" },
   266 			{ href = "../", rel = "up", text = "Room list" },
   251 			{ href = "latest", rel = "last", text = "Latest" },
   267 			{ href = "latest", rel = "last", text = "Latest" },
   252 		};
   268 		};
   253 	});
   269 	});
   383 		hide_presence = hide_presence(request);
   399 		hide_presence = hide_presence(request);
   384 		presence_available = presence_logged;
   400 		presence_available = presence_logged;
   385 		lang = get_room(room).get_language and get_room(room):get_language();
   401 		lang = get_room(room).get_language and get_room(room):get_language();
   386 		lines = logs;
   402 		lines = logs;
   387 		links = links;
   403 		links = links;
       
   404 		dates = {}; -- COMPAT util.interpolation {nil|func#...} bug
   388 	});
   405 	});
   389 end
   406 end
   390 
   407 
   391 local function list_rooms(event)
   408 local function list_rooms(event)
   392 	local request, response = event.request, event.response;
   409 	local request, response = event.request, event.response;
   412 		title = module:get_option_string("name", "Prosody Chatrooms");
   429 		title = module:get_option_string("name", "Prosody Chatrooms");
   413 		jid = module.host;
   430 		jid = module.host;
   414 		hide_presence = hide_presence(request);
   431 		hide_presence = hide_presence(request);
   415 		presence_available = presence_logged;
   432 		presence_available = presence_logged;
   416 		rooms = room_list;
   433 		rooms = room_list;
       
   434 		dates = {}; -- COMPAT util.interpolation {nil|func#...} bug
   417 	});
   435 	});
   418 end
   436 end
   419 
   437 
   420 module:provides("http", {
   438 module:provides("http", {
   421 	route = {
   439 	route = {