Software / code / prosody-modules
Comparison
mod_http_muc_log/mod_http_muc_log.lua @ 1654:1a6d6221c5f6
mod_http_muc_log: Cleanup [luacheck]
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Tue, 07 Apr 2015 18:12:40 +0200 |
| parent | 1625:c427de617ada |
| child | 1671:c813b69ae279 |
comparison
equal
deleted
inserted
replaced
| 1653:1fe899527ee5 | 1654:1a6d6221c5f6 |
|---|---|
| 70 return value; | 70 return value; |
| 71 end | 71 end |
| 72 end)); | 72 end)); |
| 73 end | 73 end |
| 74 | 74 |
| 75 local template = "Could not load template" | 75 local template; |
| 76 do | 76 do |
| 77 local template_file = module:get_option_string(module.name .. "_template", module.name .. ".html"); | 77 local template_file = module:get_option_string(module.name .. "_template", module.name .. ".html"); |
| 78 template_file = assert(module:load_resource(template_file)); | 78 template_file = assert(module:load_resource(template_file)); |
| 79 template = template_file:read("*a"); | 79 template = template_file:read("*a"); |
| 80 template_file:close(); | 80 template_file:close(); |
| 81 end | 81 end |
| 82 | 82 |
| 83 local base_url = module:http_url() .. '/'; | 83 -- local base_url = module:http_url() .. '/'; -- TODO: Generate links in a smart way |
| 84 local get_link do | 84 local get_link do |
| 85 local link, path = { path = '/' }, { "", "", is_directory = true }; | 85 local link, path = { path = '/' }, { "", "", is_directory = true }; |
| 86 function get_link(room, date) | 86 function get_link(room, date) |
| 87 path[1], path[2] = room, date; | 87 path[1], path[2] = room, date; |
| 88 path.is_directory = not date; | 88 path.is_directory = not date; |
| 107 local t_diff = os_time(os_date("*t")) - os_time(os_date("!*t")); | 107 local t_diff = os_time(os_date("*t")) - os_time(os_date("!*t")); |
| 108 local function time(t) | 108 local function time(t) |
| 109 return os_time(t) + t_diff; | 109 return os_time(t) + t_diff; |
| 110 end | 110 end |
| 111 | 111 |
| 112 local function find_once(room, query, retval) | |
| 113 if query then query.limit = 1; else query = { limit = 1 }; end | |
| 114 local iter, err = archive:find(room, query); | |
| 115 if not iter then return iter, err; end | |
| 116 if retval then | |
| 117 return select(retval, iter()); | |
| 118 end | |
| 119 return iter(); | |
| 120 end | |
| 121 | |
| 112 local function years_page(event, path) | 122 local function years_page(event, path) |
| 113 local request, response = event.request, event.response; | 123 local response = event.response; |
| 114 | 124 |
| 115 local room = nodeprep(path:match("^(.*)/$")); | 125 local room = nodeprep(path:match("^(.*)/$")); |
| 116 if not room or not public_room(room) then return end | 126 if not room or not public_room(room) then return end |
| 117 | 127 |
| 118 local dates = mt.new(); | 128 local dates = mt.new(); |
| 119 module:log("debug", "Find all dates with messages"); | 129 module:log("debug", "Find all dates with messages"); |
| 120 local next_day, t; | 130 local next_day; |
| 121 repeat | 131 repeat |
| 122 local iter = archive:find(room, { | 132 local when = find_once(room, { start = next_day; with = "message<groupchat"; }, 3); |
| 123 start = next_day; | 133 if not when then break; end |
| 124 limit = 1; | 134 local t = os_date("!*t", when); |
| 125 with = "message<groupchat"; | 135 dates:set(t.year, t.month, t.day, when ); |
| 126 }) | 136 next_day = when + (86400 - (when % 86400)); |
| 127 if not iter then break end | |
| 128 next_day = nil; | |
| 129 for key, message, when in iter do | |
| 130 t = os_date("!*t", when); | |
| 131 dates:set(t.year, t.month, t.day, when ); | |
| 132 next_day = when + (86400 - (when % 86400)); | |
| 133 break; | |
| 134 end | |
| 135 until not next_day; | 137 until not next_day; |
| 136 | 138 |
| 137 local year, years; | 139 local years = {}; |
| 138 local month, months; | 140 |
| 139 local week, weeks; | 141 for current_year, months_t in pairs(dates.data) do |
| 140 local days; | 142 local t = { year = current_year, month = 1, day = 1 }; |
| 141 local tmp, n; | 143 local months = { }; |
| 142 | 144 local year = { year = current_year, months = months }; |
| 143 years = {}; | |
| 144 | |
| 145 for Y, m in pairs(dates.data) do | |
| 146 t = { year = Y, month = 1, day = 1 }; | |
| 147 months = { }; | |
| 148 year = { year = Y, months = months }; | |
| 149 years[#years+1] = year; | 145 years[#years+1] = year; |
| 150 for m, d in pairs(m) do | 146 for current_month, days_t in pairs(months_t) do |
| 151 t.day = 1; | 147 t.day = 1; |
| 152 t.month = m; | 148 t.month = current_month; |
| 153 tmp = os_date("!*t", time(t)); | 149 local tmp = os_date("!*t", time(t)); |
| 154 days = {}; | 150 local days = {}; |
| 155 week = { days = days } | 151 local week = { days = days } |
| 156 weeks = { week }; | 152 local weeks = { week }; |
| 157 month = { year = year.year, month = os_date("!%B", time(t)), n = m, weeks = weeks }; | 153 local month = { year = year.year, month = os_date("!%B", time(t)), n = current_month, weeks = weeks }; |
| 158 months[#months+1] = month; | 154 months[#months+1] = month; |
| 159 n = 1; | 155 local current_day = 1; |
| 160 for i=1, (tmp.wday+5)%7 do | 156 for _=1, (tmp.wday+5)%7 do |
| 161 days[n], n = {}, n+1; | 157 days[current_day], current_day = {}, current_day+1; |
| 162 end | 158 end |
| 163 for i = 1, 31 do | 159 for i = 1, 31 do |
| 164 t.day = i; | 160 t.day = i; |
| 165 tmp = os_date("!*t", time(t)); | 161 tmp = os_date("!*t", time(t)); |
| 166 if tmp.month ~= m then break end | 162 if tmp.month ~= current_month then break end |
| 167 if i > 1 and tmp.wday == 2 then | 163 if i > 1 and tmp.wday == 2 then |
| 168 days = {}; | 164 days = {}; |
| 169 weeks[#weeks+1] = { days = days }; | 165 weeks[#weeks+1] = { days = days }; |
| 170 n = 1; | 166 current_day = 1; |
| 171 end | 167 end |
| 172 days[n], n = { wday = tmp.wday, day = i, href = d[i] and datetime.date(d[i]) }, n+1; | 168 days[current_day], current_day = { wday = tmp.wday, day = i, href = days_t[i] and datetime.date(days_t[i]) }, current_day+1; |
| 173 end | 169 end |
| 174 end | 170 end |
| 175 table.sort(year, sort_m); | 171 table.sort(year, sort_m); |
| 176 end | 172 end |
| 177 table.sort(years, sort_Y); | 173 table.sort(years, sort_Y); |
| 186 }; | 182 }; |
| 187 }); | 183 }); |
| 188 end | 184 end |
| 189 | 185 |
| 190 local function logs_page(event, path) | 186 local function logs_page(event, path) |
| 191 local request, response = event.request, event.response; | 187 local response = event.response; |
| 192 | 188 |
| 193 local room, date = path:match("^(.-)/(%d%d%d%d%-%d%d%-%d%d)$"); | 189 local room, date = path:match("^(.-)/(%d%d%d%d%-%d%d%-%d%d)$"); |
| 194 room = nodeprep(room); | 190 room = nodeprep(room); |
| 195 if not room then | 191 if not room then |
| 196 return years_page(event, path); | 192 return years_page(event, path); |
| 201 local iter, err = archive:find(room, { | 197 local iter, err = archive:find(room, { |
| 202 ["start"] = datetime.parse(date.."T00:00:00Z"); | 198 ["start"] = datetime.parse(date.."T00:00:00Z"); |
| 203 ["end"] = datetime.parse(date.."T23:59:59Z"); | 199 ["end"] = datetime.parse(date.."T23:59:59Z"); |
| 204 -- with = "message<groupchat"; | 200 -- with = "message<groupchat"; |
| 205 }); | 201 }); |
| 206 if not iter then return 500; end | 202 if not iter then |
| 203 module:log("warn", "Could not search archive: %s", err or "no error"); | |
| 204 return 500; | |
| 205 end | |
| 207 | 206 |
| 208 local first, last; | 207 local first, last; |
| 209 local verb, subject, body; | 208 local verb, subject, body; |
| 210 for key, item, when in iter do | 209 for key, item, when in iter do |
| 211 body = item:get_child_text("body"); | 210 body = item:get_child_text("body"); |
| 233 first = first or key; | 232 first = first or key; |
| 234 last = key; | 233 last = key; |
| 235 end | 234 end |
| 236 if i == 1 then return end -- No items | 235 if i == 1 then return end -- No items |
| 237 | 236 |
| 238 local next_when = ""; | |
| 239 local prev_when = ""; | |
| 240 | |
| 241 module:log("debug", "Find next date with messages"); | 237 module:log("debug", "Find next date with messages"); |
| 242 for key, message, when in archive:find(room, { | 238 local next_when = find_once(room, { after = last }, 3); |
| 243 after = last; | 239 if next_when then |
| 244 limit = 1; | 240 next_when = datetime.date(next_when); |
| 245 }) do | 241 module:log("debug", "Next message: %s", datetime.datetime(next_when)); |
| 246 next_when = datetime.date(when); | 242 else |
| 247 module:log("debug", "Next message: %s", datetime.datetime(when)); | 243 next_when = ""; |
| 248 end | 244 end |
| 249 | 245 |
| 250 module:log("debug", "Find prev date with messages"); | 246 module:log("debug", "Find prev date with messages"); |
| 251 for key, message, when in archive:find(room, { | 247 local prev_when = find_once(room, { before = first, reverse = true }, 3); |
| 252 before = first; | 248 if prev_when then |
| 253 limit = 1; | 249 prev_when = datetime.date(prev_when); |
| 254 reverse = true; | 250 module:log("debug", "Previous message: %s", datetime.datetime(prev_when)); |
| 255 }) do | 251 else |
| 256 prev_when = datetime.date(when); | 252 prev_when = ""; |
| 257 module:log("debug", "Previous message: %s", datetime.datetime(when)); | |
| 258 end | 253 end |
| 259 | 254 |
| 260 response.headers.content_type = "text/html; charset=utf-8"; | 255 response.headers.content_type = "text/html; charset=utf-8"; |
| 261 return render(template, { | 256 return render(template, { |
| 262 title = ("%s - %s"):format(get_room(room):get_name(), date); | 257 title = ("%s - %s"):format(get_room(room):get_name(), date); |
| 269 }; | 264 }; |
| 270 }); | 265 }); |
| 271 end | 266 end |
| 272 | 267 |
| 273 local function list_rooms(event) | 268 local function list_rooms(event) |
| 274 local request, response = event.request, event.response; | 269 local response = event.response; |
| 275 local room_list, i = {}, 1; | 270 local room_list, i = {}, 1; |
| 276 for room in each_room() do | 271 for room in each_room() do |
| 277 if public_room(room) then | 272 if public_room(room) then |
| 278 room_list[i], i = { | 273 room_list[i], i = { |
| 279 href = get_link(jid_split(room.jid), nil); | 274 href = get_link(jid_split(room.jid), nil); |
| 311 response.headers.content_type = "text/html; charset=utf-8"; | 306 response.headers.content_type = "text/html; charset=utf-8"; |
| 312 return cached[1]; | 307 return cached[1]; |
| 313 end | 308 end |
| 314 | 309 |
| 315 local start = gettime(); | 310 local start = gettime(); |
| 316 local render = f(event, path); | 311 local rendered = f(event, path); |
| 317 module:log("debug", "Rendering took %dms", math.floor( (gettime() - start) * 1000 + 0.5)); | 312 module:log("debug", "Rendering took %dms", math.floor( (gettime() - start) * 1000 + 0.5)); |
| 318 | 313 |
| 319 if type(render) == "string" then | 314 if type(rendered) == "string" then |
| 320 local etag = uuid(); | 315 local etag = uuid(); |
| 321 cached = { render, etag = etag, date = datetime.date() }; | 316 cached = { rendered, etag = etag, date = datetime.date() }; |
| 322 response.headers.etag = etag; | 317 response.headers.etag = etag; |
| 323 cache[ckey] = cached; | 318 cache[ckey] = cached; |
| 324 end | 319 end |
| 325 | 320 |
| 326 response.headers.content_type = "text/html; charset=utf-8"; | 321 response.headers.content_type = "text/html; charset=utf-8"; |
| 327 return render; | 322 return rendered; |
| 328 end | 323 end |
| 329 end | 324 end |
| 330 | 325 |
| 331 -- How is cache invalidation a hard problem? ;) | 326 -- How is cache invalidation a hard problem? ;) |
| 332 module:hook("muc-broadcast-message", function (event) | 327 module:hook("muc-broadcast-message", function (event) |