Mercurial > prosody-modules
comparison mod_muc_log_http/mod_muc_log_http.lua @ 101:e3c09996cf7b
mod_muc_log_http: display available days in a calendar view
author | Thilo Cestonaro <thilo@cestona.ro> |
---|---|
date | Wed, 02 Dec 2009 20:38:31 +0100 |
parents | 941fd7d8b9b2 |
children | a10ab09096e2 |
comparison
equal
deleted
inserted
replaced
100:999a4b3e699b | 101:e3c09996cf7b |
---|---|
14 local datamanager = require "util.datamanager"; | 14 local datamanager = require "util.datamanager"; |
15 local data_load, data_getpath = datamanager.load, datamanager.getpath; | 15 local data_load, data_getpath = datamanager.load, datamanager.getpath; |
16 local datastore = "muc_log"; | 16 local datastore = "muc_log"; |
17 local muc_hosts = {}; | 17 local muc_hosts = {}; |
18 local config = nil; | 18 local config = nil; |
19 local tostring = _G.tostring; | |
20 local tonumber = _G.tonumber; | |
21 local os_date, os_time = os.date, os.time; | |
22 local str_format = string.format; | |
19 | 23 |
20 local lom = require "lxp.lom"; | 24 local lom = require "lxp.lom"; |
21 | 25 |
22 --[[ LuaFileSystem | 26 --[[ LuaFileSystem |
23 * URL: http://www.keplerproject.org/luafilesystem/index.html | 27 * URL: http://www.keplerproject.org/luafilesystem/index.html |
39 function showHide(name) { | 43 function showHide(name) { |
40 var eles = document.getElementsByName(name); | 44 var eles = document.getElementsByName(name); |
41 for (var i = 0; i < eles.length; i++) { | 45 for (var i = 0; i < eles.length; i++) { |
42 eles[i].style.display = eles[i].style.display != "none" ? "none" : ""; | 46 eles[i].style.display = eles[i].style.display != "none" ? "none" : ""; |
43 } | 47 } |
44 | |
45 } | 48 } |
46 --></script> | 49 --></script> |
47 <style type="text/css"> | 50 <style type="text/css"> |
48 <!-- | 51 <!-- |
52 .day { font: 12px Verdana; height: 17px; } | |
53 .weekday { font: 10px Verdana; height: 17px; color: #FFFFFF; background-color: #000000; } | |
49 .timestuff {color: #AAAAAA; text-decoration: none;} | 54 .timestuff {color: #AAAAAA; text-decoration: none;} |
50 .muc_join {color: #009900; font-style: italic;} | 55 .muc_join {color: #009900; font-style: italic;} |
51 .muc_leave {color: #009900; font-style: italic;} | 56 .muc_leave {color: #009900; font-style: italic;} |
52 .muc_statusChange {color: #009900; font-style: italic;} | 57 .muc_statusChange {color: #009900; font-style: italic;} |
53 .muc_title {color: #BBBBBB; font-size: 32px;} | 58 .muc_title {color: #BBBBBB; font-size: 32px;} |
60 //--> | 65 //--> |
61 </style> | 66 </style> |
62 <body> | 67 <body> |
63 ###BODY_STUFF### | 68 ###BODY_STUFF### |
64 </body> | 69 </body> |
70 <script><!-- | |
71 window.captureEvents(Event.RESIZE | Event.LOAD); | |
72 window.onresize = resize; | |
73 window.onload = load; | |
74 function load(e) { | |
75 resize(e); | |
76 } | |
77 | |
78 function resize(e) { | |
79 var ele = document.getElementById("main"); | |
80 ele.style.height = window.innerHeight - ele.offsetTop - 25; | |
81 | |
82 var yearDivs = document.getElemetsByName("yearDiv"); | |
83 if(yearDivs) { | |
84 for each (var year in yearDivs) { | |
85 year.style.width = window.innerWidth - year.style.padding; | |
86 } | |
87 } | |
88 } | |
89 | |
90 --></script> | |
65 </html>]]; | 91 </html>]]; |
66 | 92 |
67 html.components = {}; | 93 html.components = {}; |
68 html.components.bit = [[<a href="###COMPONENT###/">###COMPONENT###</a><br />]] | 94 html.components.bit = [[<a href="###COMPONENT###/">###COMPONENT###</a><br />]] |
69 html.components.body = [[<h2>MUC hosts available on this server:</h2><hr /><p> | 95 html.components.body = [[<h2>MUC hosts available on this server:</h2><hr /><p> |
75 html.rooms.body = [[<h2>Rooms hosted on MUC host: ###COMPONENT###</h2><hr /><p> | 101 html.rooms.body = [[<h2>Rooms hosted on MUC host: ###COMPONENT###</h2><hr /><p> |
76 ###ROOMS_STUFF### | 102 ###ROOMS_STUFF### |
77 </p><hr />]]; | 103 </p><hr />]]; |
78 | 104 |
79 html.days = {}; | 105 html.days = {}; |
80 html.days.bit = [[<a href="###BARE_DAY###/">20###YEAR###/###MONTH###/###DAY###</a><br />]]; | 106 html.days.bit = [[<a href="###BARE_DAY###/">###DAY###</a><br />]]; |
81 html.days.body = [[<h2>available logged days of room: ###JID###</h2><hr /><p> | 107 html.days.body = [[<h2>available logged days of room: ###JID###</h2><hr /><div id="main" style="overflow: auto;"> |
82 ###DAYS_STUFF### | 108 ###DAYS_STUFF### |
83 </p><hr />]]; | 109 </div><hr />]]; |
84 | 110 |
85 html.day = {}; | 111 html.day = {}; |
86 html.day.title = [[Subject: <font class="muc_title">###TITLE###</font>]]; | 112 html.day.title = [[Subject: <font class="muc_title">###TITLE###</font>]]; |
87 html.day.time = [[<a name="###TIME###" href="####TIME###" class="timestuff">[###TIME###]</a> ]]; -- the one ####TIME### need to stay! it will evaluate to e.g. #09:10:56 which is an anker then | 113 html.day.time = [[<a name="###TIME###" href="####TIME###" class="timestuff">[###TIME###]</a> ]]; -- the one ####TIME### need to stay! it will evaluate to e.g. #09:10:56 which is an anker then |
88 html.day.presence = {}; | 114 html.day.presence = {}; |
104 <input type="checkbox" onclick="showHide('joinLeave')" ###JOIN_CHECKED###/>show/hide joins and Leaves</button> | 130 <input type="checkbox" onclick="showHide('joinLeave')" ###JOIN_CHECKED###/>show/hide joins and Leaves</button> |
105 <input type="checkbox" onclick="showHide('status')" ###STATUS_CHECKED###/>show/hide status changes</button> | 131 <input type="checkbox" onclick="showHide('status')" ###STATUS_CHECKED###/>show/hide status changes</button> |
106 <hr /><div id="main" style="overflow: auto;"> | 132 <hr /><div id="main" style="overflow: auto;"> |
107 ###DAY_STUFF### | 133 ###DAY_STUFF### |
108 </div><hr /> | 134 </div><hr /> |
109 <script><!-- | 135 ]]; |
110 window.captureEvents(Event.RESIZE | Event.LOAD); | 136 |
111 window.onresize = resize; | 137 -- Calendar stuff |
112 window.onload = resize; | 138 html.year = {}; |
113 function resize(e) { | 139 html.year.title = [[<center><font style="font: bold 16px Verdana;"><a name="###YEAR###">###YEAR###</a></font></center>]]; |
114 var ele = document.getElementById("main"); | 140 |
115 ele.style.height = window.innerHeight - ele.offsetTop - 25; | 141 html.month = {}; |
116 } | 142 html.month.header = [[<table rules="groups" cellpadding="5"> |
117 | 143 <thead><tr><td colspan="7"><center><H2><font size="2" face="Verdana">###TITLE###</font></H2></center></td></tr></thead> |
118 --></script>]]; | 144 <tbody style="border: solid black 1px;"> |
145 <tr> | |
146 ###WEEKDAYS###</tr> | |
147 ]]; | |
148 html.month.weekDay = [[ <th class="weekday" valign="middle" align="center">###DAY###</th>]]; | |
149 html.month.emptyDay = [[ <td class="day"> </td>]]; | |
150 html.month.day = [[ <td class="day" valign="middle" align="center">###DAY###</td>]]; | |
151 html.month.footer = [[</tbody></table>]]; | |
152 | |
119 | 153 |
120 local function checkDatastorePathExists(node, host, today, create) | 154 local function checkDatastorePathExists(node, host, today, create) |
121 create = create or false; | 155 create = create or false; |
122 local path = data_getpath(node, host, datastore, "dat", true); | 156 local path = data_getpath(node, host, datastore, "dat", true); |
123 path = path:gsub("/[^/]*$", ""); | 157 path = path:gsub("/[^/]*$", ""); |
211 return html.rooms.body:gsub("###ROOMS_STUFF###", rooms):gsub("###COMPONENT###", component); | 245 return html.rooms.body:gsub("###ROOMS_STUFF###", rooms):gsub("###COMPONENT###", component); |
212 end | 246 end |
213 end | 247 end |
214 end | 248 end |
215 | 249 |
250 -- Calendar stuff | |
251 local function getDaysForMonth(month, year) | |
252 local daysCount = 30; | |
253 local leapyear = false; | |
254 | |
255 if year%4 == 0 and year%100 == 0 then | |
256 if year%400 == 0 then | |
257 leapyear = true; | |
258 else | |
259 leapyear = false; -- turn of the century but not a leapyear | |
260 end | |
261 elseif year%4 == 0 then | |
262 leapyear = true; | |
263 end | |
264 | |
265 if month == 2 and leapyear then | |
266 daysCount = 29; | |
267 elseif month == 2 and not leapyear then | |
268 daysCount = 28; | |
269 elseif month < 8 and month%2 == 1 or | |
270 month >= 8 and month%2 == 0 | |
271 then | |
272 daysCount = 31; | |
273 end | |
274 return daysCount; | |
275 end | |
276 | |
277 local function createMonth(month, year, dayCallback) | |
278 local htmlStr = html.month.header; | |
279 local days = getDaysForMonth(month, year); | |
280 local time = os_time{year=year, month=month, day=1}; | |
281 local dow = tostring(os_date("%a", time)) | |
282 local title = tostring(os_date("%B", time)); | |
283 local weekDays = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; | |
284 local weekDay = 0; | |
285 local weeks = 1; | |
286 | |
287 local weekDaysHtml = ""; | |
288 for _, tmp in ipairs(weekDays) do | |
289 weekDaysHtml = weekDaysHtml .. html.month.weekDay:gsub("###DAY###", tmp) .. "\n"; | |
290 end | |
291 | |
292 htmlStr = htmlStr:gsub("###TITLE###", title):gsub("###WEEKDAYS###", weekDaysHtml); | |
293 | |
294 for i = 1, 31 do | |
295 weekDay = weekDay + 1; | |
296 if weekDay == 1 then htmlStr = htmlStr .. "<tr>\n"; end | |
297 if i == 1 then | |
298 for _, tmp in ipairs(weekDays) do | |
299 if dow ~= tmp then | |
300 htmlStr = htmlStr .. html.month.emptyDay .. "\n"; | |
301 weekDay = weekDay + 1; | |
302 else | |
303 break; | |
304 end | |
305 end | |
306 end | |
307 if i < days + 1 then | |
308 tmp = tostring(i); | |
309 if dayCallback ~= nil and dayCallback.callback ~= nil then | |
310 tmp = dayCallback.callback(dayCallback.path, i, month, year); | |
311 end | |
312 htmlStr = htmlStr .. html.month.day:gsub("###DAY###", tmp) .. "\n"; | |
313 end | |
314 | |
315 if i >= days then | |
316 break; | |
317 end | |
318 | |
319 if weekDay == 7 then | |
320 weekDay = 0; | |
321 weeks = weeks + 1; | |
322 htmlStr = htmlStr .. "</tr>\n"; | |
323 end | |
324 end | |
325 | |
326 if weekDay + 1 < 8 or weeks < 6 then | |
327 weekDay = weekDay + 1; | |
328 if weekDay > 7 then | |
329 weekDay = 1; | |
330 end | |
331 if weekDay == 1 then | |
332 weeks = weeks + 1; | |
333 end | |
334 for y = weeks, 6 do | |
335 if weekDay == 1 then | |
336 htmlStr = htmlStr .. "<tr>\n"; | |
337 end | |
338 for i = weekDay, 7 do | |
339 htmlStr = htmlStr .. html.month.emptyDay .. "\n"; | |
340 end | |
341 weekDay = 1 | |
342 htmlStr = htmlStr .. "</tr>\n"; | |
343 end | |
344 end | |
345 htmlStr = htmlStr .. html.month.footer; | |
346 return htmlStr; | |
347 end | |
348 | |
349 local function createYear(year, dayCallback) | |
350 local year = year; | |
351 if tonumber(year) <= 99 then | |
352 year = year + 2000; | |
353 end | |
354 local htmlStr = "<div name='yearDiv' style='padding: 40px; text-align: center;'>" .. html.year.title:gsub("###YEAR###", tostring(year)); | |
355 for i=1, 12 do | |
356 htmlStr = htmlStr .. "<div style='float: left; padding: 5px;'>\n" .. createMonth(i, year, dayCallback) .. "</div>\n"; | |
357 end | |
358 return htmlStr .. "</div><div style='clear:left;'/> \n"; | |
359 end | |
360 | |
361 local function perDayCallback(path, day, month, year) | |
362 local year = year; | |
363 if year > 2000 then | |
364 year = year - 2000; | |
365 end | |
366 local bareDay = str_format("%.02d%.02d%.02d", year, month, day); | |
367 local attributes, err = lfs.attributes(path.."/"..bareDay) | |
368 if attributes ~= nil and attributes.mode == "directory" then | |
369 local s = html.days.bit; | |
370 s = s:gsub("###BARE_DAY###", bareDay); | |
371 s = s:gsub("###DAY###", day); | |
372 return s; | |
373 else | |
374 return tostring("<font color='#DDDDDD'>"..day.."</font>"); | |
375 end | |
376 end | |
377 | |
216 local function generateDayListSiteContentByRoom(bareRoomJid) | 378 local function generateDayListSiteContentByRoom(bareRoomJid) |
217 local days = ""; | 379 local days = ""; |
218 local arrDays = {}; | 380 local arrDays = {}; |
219 local tmp; | 381 local tmp; |
220 local node, host, resource = splitJid(bareRoomJid); | 382 local node, host, resource = splitJid(bareRoomJid); |
229 if room._data.hidden then | 391 if room._data.hidden then |
230 room = nil | 392 room = nil |
231 end | 393 end |
232 end | 394 end |
233 if attributes ~= nil and room ~= nil then | 395 if attributes ~= nil and room ~= nil then |
396 local alreadyDoneYears = {}; | |
234 for file in lfs.dir(path) do | 397 for file in lfs.dir(path) do |
235 local year, month, day = file:match("^(%d%d)(%d%d)(%d%d)"); | 398 local year, month, day = file:match("^(%d%d)(%d%d)(%d%d)"); |
236 if year ~= nil and month ~= nil and day ~= nil and | 399 if year ~= nil and alreadyDoneYears[year] == nil then |
237 year ~= "" and month ~= "" and day ~= "" | 400 days = days .. createYear(year, {callback=perDayCallback, path=path}); |
238 then | 401 alreadyDoneYears[year] = true; |
239 arrDays[#arrDays + 1] = {bare=file, year=year, month=month, day=day}; | 402 end |
240 end | |
241 end | |
242 tabSort(arrDays, function(a,b) | |
243 return a.bare < b.bare; | |
244 end); | |
245 for _, date in pairs(arrDays) do | |
246 tmp = html.days.bit; | |
247 tmp = tmp:gsub("###ROOM###", node):gsub("###COMPONENT###", host); | |
248 tmp = tmp:gsub("###BARE_DAY###", date.bare); | |
249 tmp = tmp:gsub("###YEAR###", date.year):gsub("###MONTH###", date.month):gsub("###DAY###", date.day); | |
250 days = tmp .. days; | |
251 end | 403 end |
252 end | 404 end |
253 | 405 |
254 if days ~= "" then | 406 if days ~= "" then |
255 tmp = html.days.body:gsub("###DAYS_STUFF###", days); | 407 tmp = html.days.body:gsub("###DAYS_STUFF###", days); |
563 end | 715 end |
564 return; | 716 return; |
565 end | 717 end |
566 | 718 |
567 function module.load() | 719 function module.load() |
720 module:log("debug", "loading mod_muc_log_http"); | |
568 config = config_get("*", "core", "muc_log_http") or {}; | 721 config = config_get("*", "core", "muc_log_http") or {}; |
569 if config.showStatus == nil then | 722 if config.showStatus == nil then |
570 config.showStatus = true; | 723 config.showStatus = true; |
571 end | 724 end |
572 if config.showJoin == nil then | 725 if config.showJoin == nil then |
573 config.showJoin = true; | 726 config.showJoin = true; |
574 end | 727 end |
575 httpserver.new_from_config({ config.http_port or true }, handle_request, { base = "muc_log" }); | 728 module:log("debug", "opening httpserver port: " .. tostring(config.port)); |
729 httpserver.new_from_config({ config.port or true }, handle_request, { base = "muc_log", ssl = false, port = 5290 }); | |
576 | 730 |
577 for jid, host in pairs(prosody.hosts) do | 731 for jid, host in pairs(prosody.hosts) do |
578 if host.muc then | 732 if host.muc then |
579 local enabledModules = config_get(jid, "core", "modules_enabled"); | 733 local enabledModules = config_get(jid, "core", "modules_enabled"); |
580 if enabledModules then | 734 if enabledModules then |
586 end | 740 end |
587 end | 741 end |
588 end | 742 end |
589 end | 743 end |
590 end | 744 end |
745 module:log("debug", "loaded mod_muc_log_http"); | |
591 end | 746 end |
592 | 747 |
593 function module.unload() | 748 function module.unload() |
749 module:log("debug", "unloading mod_muc_log_http"); | |
594 muc_hosts = nil; | 750 muc_hosts = nil; |
751 module:log("debug", "unloaded mod_muc_log_http"); | |
595 end | 752 end |
596 | 753 |
597 module:add_event_hook("component-activated", function(component, config) | 754 module:add_event_hook("component-activated", function(component, config) |
598 if config.core and config.core.modules_enabled then | 755 if config.core and config.core.modules_enabled then |
599 for _,mod in ipairs(config.core.modules_enabled) do | 756 for _,mod in ipairs(config.core.modules_enabled) do |