comparison mod_http_muc_log/mod_http_muc_log.lua @ 3750:9002c8a2165f

mod_http_muc_log: Refactor calendarization of date list into a template filter BC This breaks any custom templates using the calendar data structure.
author Kim Alvefur <zash@zash.se>
date Sun, 17 Nov 2019 15:16:23 +0100
parents cb61f0e06de3
children 971417eedfee
comparison
equal deleted inserted replaced
3749:cb61f0e06de3 3750: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 = {