comparison mod_muc_log/mod_muc_log.lua @ 59:50e3d5b87119

mod_muc_log: better presence and message parsing; react on subject changes
author Thilo Cestonaro <thilo@cestona.ro>
date Tue, 20 Oct 2009 23:25:21 +0200
parents cddcea7c091a
children 5cca708c9f11
comparison
equal deleted inserted replaced
58:b07193056935 59:50e3d5b87119
63 html.day = {}; 63 html.day = {};
64 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 64 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
65 html.day.presence = {}; 65 html.day.presence = {};
66 html.day.presence.join = [[###TIME_STUFF###<font class="muc_join"> *** ###NICK### joins the room</font><br />]]; 66 html.day.presence.join = [[###TIME_STUFF###<font class="muc_join"> *** ###NICK### joins the room</font><br />]];
67 html.day.presence.leave = [[###TIME_STUFF###<font class="muc_leave"> *** ###NICK### leaves the room</font><br />]]; 67 html.day.presence.leave = [[###TIME_STUFF###<font class="muc_leave"> *** ###NICK### leaves the room</font><br />]];
68 html.day.presence.statusChange = [[###TIME_STUFF###<font class="muc_statusChange"> *** ###NICK### changed his/her status to: ###STATUS###</font><br />]]; 68 html.day.presence.statusText = [[ and his status message is "###STATUS###"]];
69 html.day.presence.statusChange = [[###TIME_STUFF###<font class="muc_statusChange"> *** ###NICK### shows now as "###SHOW###"###STATUS_STUFF###</font><br />]];
69 html.day.message = [[###TIME_STUFF###<font class="muc_name">&lt;###NICK###&gt;</font> ###MSG###<br />]]; 70 html.day.message = [[###TIME_STUFF###<font class="muc_name">&lt;###NICK###&gt;</font> ###MSG###<br />]];
70 html.day.titleChange = [[###TIME_STUFF###<font class="muc_titlenick"> *** ###NICK### change title to:</font> <font class="muc_title">###MSG###</font><br />]]; 71 html.day.titleChange = [[###TIME_STUFF###<font class="muc_titlenick"> *** ###NICK### changed the title to</font> <font class="muc_title">"###TITLE###"</font><br />]];
71 html.day.kick = [[###TIME_STUFF###<font class="muc_titlenick"> *** ###NICK### kicked ###VICTIM###</font><br />]]; 72 html.day.kick = [[###TIME_STUFF###<font class="muc_titlenick"> *** ###NICK### kicked ###VICTIM###</font><br />]];
72 html.day.bann = [[###TIME_STUFF###<font class="muc_titlenick"> *** ###NICK### banned ###VICTIM###</font><br />]]; 73 html.day.bann = [[###TIME_STUFF###<font class="muc_titlenick"> *** ###NICK### banned ###VICTIM###</font><br />]];
73 html.day.body = [[<h2>room ###JID### logging of 20###YEAR###/###MONTH###/###DAY###</h2><hr /><p> 74 html.day.body = [[<h2>room ###JID### logging of 20###YEAR###/###MONTH###/###DAY###</h2><hr /><p>
74 ###DAY_STUFF### 75 ###DAY_STUFF###
75 </p><hr />]]; 76 </p><hr />]];
166 return t; 167 return t;
167 end 168 end
168 169
169 function splitQuery(query) 170 function splitQuery(query)
170 local ret = {}; 171 local ret = {};
172 local name, value = nil, nil;
171 if query == nil then return ret; end 173 if query == nil then return ret; end
172 local last = 1; 174 local last = 1;
173 local idx = query:find("&", last); 175 local idx = query:find("&", last);
174 while idx ~= nil do 176 while idx ~= nil do
175 ret[#ret + 1] = query:sub(last, idx - 1); 177 name, value = query:sub(last, idx - 1):match("^(%a+)=(%d+)$");
178 ret[name] = value;
176 last = idx + 1; 179 last = idx + 1;
177 idx = query:find("&", last); 180 idx = query:find("&", last);
178 end 181 end
179 ret[#ret + 1] = query:sub(last); 182 name, value = query:sub(last):match("^(%a+)=(%d+)$");
183 ret[name] = value;
180 return ret; 184 return ret;
181 end 185 end
182 186
183 function grepRoomJid(url) 187 function grepRoomJid(url)
184 local tmp = url:sub(string.len("/muc_log/") + 1); 188 local tmp = url:sub(string.len("/muc_log/") + 1);
222 if year ~= nil and month ~= nil and day ~= nil and 226 if year ~= nil and month ~= nil and day ~= nil and
223 year ~= "" and month ~= "" and day ~= "" 227 year ~= "" and month ~= "" and day ~= ""
224 then 228 then
225 tmp = html.days.bit; 229 tmp = html.days.bit;
226 tmp = tmp:gsub("###JID###", bareRoomJid); 230 tmp = tmp:gsub("###JID###", bareRoomJid);
227 tmp = tmp:gsub("###YEAR###", year); 231 tmp = tmp:gsub("###YEAR###", year):gsub("###MONTH###", month):gsub("###DAY###", day);
228 tmp = tmp:gsub("###MONTH###", month);
229 tmp = tmp:gsub("###DAY###", day);
230 days = tmp .. days; 232 days = tmp .. days;
231 end 233 end
232 end 234 end
233 if days ~= "" then 235 if days ~= "" then
234 tmp = html.days.body:gsub("###DAYS_STUFF###", days); 236 tmp = html.days.body:gsub("###DAYS_STUFF###", days);
235 return tmp:gsub("###JID###", bareRoomJid); 237 return tmp:gsub("###JID###", bareRoomJid);
236 else 238 else
237 return generateRoomListSiteContent(); -- fallback 239 return generateRoomListSiteContent(); -- fallback
238 end 240 end
241 end
242
243 local function parsePresenceStanza(stanza, timeStuff, nick)
244 local ret = "";
245 -- module:log("debug", serialize(stanza));
246 if stanza[1].attr.type == nil then
247 local show, status = nil, "";
248 for _, tag in ipairs(stanza[1]) do
249 module:log("debug", serialize(tag));
250 if tag.tag == "show" then
251 show = tag[1];
252 elseif tag.tag == "status" then
253 status = tag[1];
254 end
255 end
256 if show ~= nil then
257 ret = html.day.presence.statusChange:gsub("###TIME_STUFF###", timeStuff);
258 if status ~= "" then
259 status = html.day.presence.statusText:gsub("###STATUS###", status);
260 end
261 ret = ret:gsub("###SHOW###", show):gsub("###NICK###", nick):gsub("###STATUS_STUFF###", status);
262 else
263 ret = html.day.presence.join:gsub("###TIME_STUFF###", timeStuff):gsub("###NICK###", nick);
264 end
265 elseif stanza[1].attr.type ~= nil and stanza[1].attr.type == "unavailable" then
266 ret = html.day.presence.leave:gsub("###TIME_STUFF###", timeStuff):gsub("###NICK###", nick);
267 end
268 return ret;
269 end
270
271 local function parseMessageStanza(stanza, timeStuff, nick)
272 local body, title, ret = nil, nil, "";
273
274 for _,tag in ipairs(stanza[1]) do
275 if tag.tag == "body" then
276 body = tag[1];
277 if nick ~= nil then
278 break;
279 end
280 elseif tag.tag == "nick" and nick == nil then
281 nick = tag[1];
282 if body ~= nil or title ~= nil then
283 break;
284 end
285 elseif tag.tag == "subject" then
286 title = tag[1];
287 if nick ~= nil then
288 break;
289 end
290 end
291 end
292 if nick ~= nil and body ~= nil then
293 body = htmlEscape(body);
294 ret = html.day.message:gsub("###TIME_STUFF###", timeStuff):gsub("###NICK###", nick):gsub("###MSG###", body);
295 elseif nick ~= nil and title ~= nil then
296 title = htmlEscape(title);
297 ret = html.day.titleChange:gsub("###TIME_STUFF###", timeStuff):gsub("###NICK###", nick):gsub("###TITLE###", title);
298 end
299 return ret;
239 end 300 end
240 301
241 local function parseDay(bareRoomJid, query) 302 local function parseDay(bareRoomJid, query)
242 local ret = ""; 303 local ret = "";
243 local year; 304 local year;
244 local month; 305 local month;
245 local day; 306 local day;
246 local tmp; 307 local tmp;
247 308
248 for _,str in ipairs(query) do 309 if query.year ~= nil and query.month ~= nil and query.day ~= nil then
249 local name, value; 310 local file = config.folder .. "/" .. query.year .. query.month .. query.day .. "_" .. bareRoomJid .. ".log";
250 name, value = str:match("^(%a+)=(%d+)$");
251 if name == "year" then
252 year = value;
253 elseif name == "month" then
254 month = value;
255 elseif name == "day" then
256 day = value;
257 else
258 log("warn", "unknown query value");
259 end
260 end
261
262 if year ~= nil and month ~= nil and day ~= nil then
263 local file = config.folder .. "/" .. year .. month .. day .. "_" .. bareRoomJid .. ".log";
264 local f, err = io.open(file, "r"); 311 local f, err = io.open(file, "r");
265 if f ~= nil then 312 if f ~= nil then
266 local content = f:read("*a"); 313 local content = f:read("*a");
267 local parsed = lom.parse("<xml>" .. content .. "</xml>"); 314 local parsed = lom.parse("<xml>" .. content .. "</xml>");
315 f:close();
268 if parsed ~= nil then 316 if parsed ~= nil then
269 for _,stanza in ipairs(parsed) do 317 for _,stanza in ipairs(parsed) do
270 if stanza.attr ~= nil and stanza.attr.time ~= nil then 318 if stanza.attr ~= nil and stanza.attr.time ~= nil then
271 local timeStuff = html.day.time:gsub("###TIME###", stanza.attr.time); 319 local timeStuff = html.day.time:gsub("###TIME###", stanza.attr.time);
272 if stanza[1] ~= nil then 320 if stanza[1] ~= nil then
276 if stanza[1].attr.from ~= nil then 324 if stanza[1].attr.from ~= nil then
277 nick = stanza[1].attr.from:match("/(.+)$"); 325 nick = stanza[1].attr.from:match("/(.+)$");
278 end 326 end
279 327
280 if stanza[1].tag == "presence" and nick ~= nil then 328 if stanza[1].tag == "presence" and nick ~= nil then
281 329 ret = ret .. parsePresenceStanza(stanza, timeStuff, nick);
282 if stanza[1].attr.type == nil then
283 tmp = html.day.presence.join:gsub("###TIME_STUFF###", timeStuff);
284 ret = ret .. tmp:gsub("###NICK###", nick);
285 elseif stanza[1].attr.type ~= nil and stanza[1].attr.type == "unavailable" then
286 tmp = html.day.presence.leave:gsub("###TIME_STUFF###", timeStuff);
287 ret = ret .. tmp:gsub("###NICK###", nick);
288 else
289 tmp = html.day.presence.leave:gsub("###TIME_STUFF###", timeStuff);
290 tmp = tmp:gsub("###STATUS###", stanza[1].attr.type);
291 ret = ret .. tmp:gsub("###NICK###", nick);
292 end
293 elseif stanza[1].tag == "message" then 330 elseif stanza[1].tag == "message" then
294 local body; 331 ret = ret .. parseMessageStanza(stanza, timeStuff, nick);
295 for _,tag in ipairs(stanza[1]) do
296 if tag.tag == "body" then
297 body = htmlEscape(tag[1]);
298 if nick ~= nil then
299 break;
300 end
301 elseif tag.tag == "nick" and nick == nil then
302 nick = tag[1];
303 if body ~= nil then
304 break;
305 end
306 end
307 end
308 if nick ~= nil and body ~= nil then
309 tmp = html.day.message:gsub("###TIME_STUFF###", timeStuff);
310 tmp = tmp:gsub("###NICK###", nick);
311 ret = ret .. tmp:gsub("###MSG###", body);
312 end
313 else 332 else
314 module:log("info", "unknown stanza subtag in log found. room: %s; day: %s", bareRoomJid, year .. "/" .. month .. "/" .. day); 333 module:log("info", "unknown stanza subtag in log found. room: %s; day: %s", bareRoomJid, query.year .. "/" .. query.month .. "/" .. query.day);
315 end 334 end
316 end 335 end
317 end 336 end
318 end 337 end
319 else 338 else
320 module:log("warn", "could not parse room log. room: %s; day: %s", bareRoomJid, year .. "/" .. month .. "/" .. day); 339 module:log("warn", "could not parse room log. room: %s; day: %s", bareRoomJid, query.year .. "/" .. query.month .. "/" .. query.day);
321 end 340 end
322 f:close();
323 else 341 else
324 ret = err; 342 ret = err;
325 end 343 end
326 tmp = html.day.body:gsub("###DAY_STUFF###", ret); 344 tmp = html.day.body:gsub("###DAY_STUFF###", ret):gsub("###JID###", bareRoomJid);
327 tmp = tmp:gsub("###JID###", bareRoomJid); 345 tmp = tmp:gsub("###YEAR###", query.year):gsub("###MONTH###", query.month):gsub("###DAY###", query.day);
328 tmp = tmp:gsub("###YEAR###", year);
329 tmp = tmp:gsub("###MONTH###", month);
330 tmp = tmp:gsub("###DAY###", day);
331 return tmp; 346 return tmp;
332 else 347 else
333 return generateDayListSiteContentByRoom(bareRoomJid); -- fallback 348 return generateDayListSiteContentByRoom(bareRoomJid); -- fallback
334 end 349 end
335 end 350 end