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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 130 <input type="checkbox" onclick="showHide('joinLeave')" ###JOIN_CHECKED###/>show/hide joins and Leaves</button>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
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">&nbsp;</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