Mercurial > prosody-modules
comparison mod_http_muc_log/mod_http_muc_log.lua @ 1606:2c8b985ebde5
mod_http_muc_log: Switch to a calendar view for selecting dates
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Tue, 10 Feb 2015 15:00:10 +0100 |
| parents | c8a51d1bc96d |
| children | c427de617ada |
comparison
equal
deleted
inserted
replaced
| 1605:c8a51d1bc96d | 1606:2c8b985ebde5 |
|---|---|
| 1 local st = require "util.stanza"; | 1 local st = require "util.stanza"; |
| 2 local mt = require"util.multitable"; | |
| 2 local datetime = require"util.datetime"; | 3 local datetime = require"util.datetime"; |
| 3 local jid_split = require"util.jid".split; | 4 local jid_split = require"util.jid".split; |
| 4 local nodeprep = require"util.encodings".stringprep.nodeprep; | 5 local nodeprep = require"util.encodings".stringprep.nodeprep; |
| 5 local uuid = require"util.uuid".generate; | 6 local uuid = require"util.uuid".generate; |
| 6 local it = require"util.iterators"; | 7 local it = require"util.iterators"; |
| 7 local gettime = require"socket".gettime; | 8 local gettime = require"socket".gettime; |
| 8 local url = require"socket.url"; | 9 local url = require"socket.url"; |
| 9 local xml_escape = st.xml_escape; | 10 local xml_escape = st.xml_escape; |
| 10 local t_concat = table.concat; | 11 local t_concat = table.concat; |
| 12 local os_time, os_date = os.time, os.date; | |
| 11 | 13 |
| 12 local archive = module:open_store("muc_log", "archive"); | 14 local archive = module:open_store("muc_log", "archive"); |
| 13 | 15 |
| 14 -- Support both old and new MUC code | 16 -- Support both old and new MUC code |
| 15 local mod_muc = module:depends"muc"; | 17 local mod_muc = module:depends"muc"; |
| 90 and not (room.get_hidden or room.is_hidden)(room) | 92 and not (room.get_hidden or room.is_hidden)(room) |
| 91 and not (room.get_members_only or room.is_members_only)(room) | 93 and not (room.get_members_only or room.is_members_only)(room) |
| 92 and room._data.logging == true); | 94 and room._data.logging == true); |
| 93 end | 95 end |
| 94 | 96 |
| 95 -- FIXME Invent some more efficient API for this | 97 local function sort_Y(a,b) return a.year > b.year end |
| 96 local function dates_page(event, path) | 98 local function sort_m(a,b) return a.n > b.n end |
| 99 | |
| 100 local t_diff = os_time(os_date("*t")) - os_time(os_date("!*t")); | |
| 101 local function time(t) | |
| 102 return os_time(t) + t_diff; | |
| 103 end | |
| 104 | |
| 105 local function years_page(event, path) | |
| 97 local request, response = event.request, event.response; | 106 local request, response = event.request, event.response; |
| 98 | 107 |
| 99 local room = nodeprep(path:match("^(.*)/$")); | 108 local room = nodeprep(path:match("^(.*)/$")); |
| 100 if not room or not public_room(room) then return end | 109 if not room or not public_room(room) then return end |
| 101 | 110 |
| 102 local dates, i = {}, 1; | 111 local dates = mt.new(); |
| 103 module:log("debug", "Find all dates with messages"); | 112 module:log("debug", "Find all dates with messages"); |
| 104 local prev_day; | 113 local next_day, t; |
| 105 repeat | 114 repeat |
| 106 local iter = archive:find(room, { | 115 local iter = archive:find(room, { |
| 107 ["end"] = prev_day; | 116 start = next_day; |
| 108 limit = 1; | 117 limit = 1; |
| 109 with = "message<groupchat"; | 118 with = "message<groupchat"; |
| 110 reverse = true; | |
| 111 }) | 119 }) |
| 112 if not iter then break end | 120 if not iter then break end |
| 113 prev_day = nil; | 121 next_day = nil; |
| 114 for key, message, when in iter do | 122 for key, message, when in iter do |
| 115 prev_day = datetime.date(when); | 123 t = os_date("!*t", when); |
| 116 dates[i], i = { | 124 dates:set(t.year, t.month, t.day, when ); |
| 117 date = prev_day; | 125 next_day = when + (86400 - (when % 86400)); |
| 118 }, i + 1; | |
| 119 prev_day = datetime.parse(prev_day .. "T00:00:00Z") - 1; | |
| 120 break; | 126 break; |
| 121 end | 127 end |
| 122 until not prev_day; | 128 until not next_day; |
| 129 | |
| 130 local year, years; | |
| 131 local month, months; | |
| 132 local week, weeks; | |
| 133 local days; | |
| 134 local tmp, n; | |
| 135 | |
| 136 years = {}; | |
| 137 | |
| 138 for Y, m in pairs(dates.data) do | |
| 139 t = { year = Y, month = 1, day = 1 }; | |
| 140 months = { }; | |
| 141 year = { year = Y, months = months }; | |
| 142 years[#years+1] = year; | |
| 143 for m, d in pairs(m) do | |
| 144 t.day = 1; | |
| 145 t.month = m; | |
| 146 tmp = os_date("!*t", time(t)); | |
| 147 days = {}; | |
| 148 week = { days = days } | |
| 149 weeks = { week }; | |
| 150 month = { year = year.year, month = os_date("!%B", time(t)), n = m, weeks = weeks }; | |
| 151 months[#months+1] = month; | |
| 152 n = 1; | |
| 153 for i=1, (tmp.wday+5)%7 do | |
| 154 days[n], n = {}, n+1; | |
| 155 end | |
| 156 for i = 1, 31 do | |
| 157 t.day = i; | |
| 158 tmp = os_date("!*t", time(t)); | |
| 159 if tmp.month ~= m then break end | |
| 160 if i > 1 and tmp.wday == 2 then | |
| 161 days = {}; | |
| 162 weeks[#weeks+1] = { days = days }; | |
| 163 n = 1; | |
| 164 end | |
| 165 if d[i] then | |
| 166 days[n], n = { wday = tmp.wday, links = {{ href = datetime.date(d[i]), day = i }} }, n+1; | |
| 167 else | |
| 168 days[n], n = { wday = tmp.wday, plain = i }, n+1; | |
| 169 end | |
| 170 end | |
| 171 end | |
| 172 table.sort(year, sort_m); | |
| 173 end | |
| 174 table.sort(years, sort_Y); | |
| 123 | 175 |
| 124 response.headers.content_type = "text/html; charset=utf-8"; | 176 response.headers.content_type = "text/html; charset=utf-8"; |
| 125 return render(template, { | 177 return render(template, { |
| 126 title = get_room(room):get_name(); | 178 title = get_room(room):get_name(); |
| 127 jid = get_room(room).jid; | 179 jid = get_room(room).jid; |
| 128 dates = dates; | 180 years = years; |
| 129 links = { | 181 links = { |
| 130 { href = "../", rel = "up", text = "Back to room list" }, | 182 { href = "../", rel = "up", text = "Back to room list" }, |
| 131 }; | 183 }; |
| 132 }); | 184 }); |
| 133 end | 185 end |
| 136 local request, response = event.request, event.response; | 188 local request, response = event.request, event.response; |
| 137 | 189 |
| 138 local room, date = path:match("^(.-)/(%d%d%d%d%-%d%d%-%d%d)$"); | 190 local room, date = path:match("^(.-)/(%d%d%d%d%-%d%d%-%d%d)$"); |
| 139 room = nodeprep(room); | 191 room = nodeprep(room); |
| 140 if not room then | 192 if not room then |
| 141 return dates_page(event, path); | 193 return years_page(event, path); |
| 142 end | 194 end |
| 143 if not public_room(room) then return end | 195 if not public_room(room) then return end |
| 144 | 196 |
| 145 local logs, i = {}, 1; | 197 local logs, i = {}, 1; |
| 146 local iter, err = archive:find(room, { | 198 local iter, err = archive:find(room, { |
| 206 return render(template, { | 258 return render(template, { |
| 207 title = ("%s - %s"):format(get_room(room):get_name(), date); | 259 title = ("%s - %s"):format(get_room(room):get_name(), date); |
| 208 jid = get_room(room).jid; | 260 jid = get_room(room).jid; |
| 209 lines = logs; | 261 lines = logs; |
| 210 links = { | 262 links = { |
| 211 { href = "./", rel = "up", text = "Back to date list" }, | 263 { href = "./", rel = "up", text = "Back to calendar" }, |
| 212 { href = prev_when, rel = "prev", text = prev_when}, | 264 { href = prev_when, rel = "prev", text = prev_when}, |
| 213 { href = next_when, rel = "next", text = next_when}, | 265 { href = next_when, rel = "next", text = next_when}, |
| 214 }; | 266 }; |
| 215 }); | 267 }); |
| 216 end | 268 end |
