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 }); |