Software /
code /
prosody-modules
Comparison
mod_muc_log/mod_muc_log.lua @ 55:d9749ed44f6e
mod_muc_log: make it recognize s2s messages/presences
author | Thilo Cestonaro <thilo@cestona.ro> |
---|---|
date | Mon, 19 Oct 2009 16:06:48 +0200 |
parent | 54:f15108153710 |
child | 56:e9de45beaf5e |
comparison
equal
deleted
inserted
replaced
54:f15108153710 | 55:d9749ed44f6e |
---|---|
18 local lfs = require "lfs"; | 18 local lfs = require "lfs"; |
19 | 19 |
20 local lom = require "lxp.lom"; | 20 local lom = require "lxp.lom"; |
21 | 21 |
22 function validateLogFolder() | 22 function validateLogFolder() |
23 module:log("debug", "validateLogFolder; Folder: %s", tostring(config.folder)); | |
24 if config.folder == nil then | 23 if config.folder == nil then |
25 module:log("warn", "muc_log folder isn't configured. configure it please!"); | 24 module:log("warn", "muc_log folder isn't configured. configure it please!"); |
26 return false; | 25 return false; |
27 end | 26 end |
28 | 27 |
34 elseif attributes.mode ~= "directory" then | 33 elseif attributes.mode ~= "directory" then |
35 module:log("warn", "muc_log folder isn't a folder, it's a %s. change this please!", attributes.mode); | 34 module:log("warn", "muc_log folder isn't a folder, it's a %s. change this please!", attributes.mode); |
36 return false; | 35 return false; |
37 end --TODO: check for write rights! | 36 end --TODO: check for write rights! |
38 | 37 |
39 module:log("debug", "Folder is validated and correct.") | |
40 return true; | 38 return true; |
41 end | 39 end |
42 | 40 |
43 function logIfNeeded(e) | 41 function logIfNeeded(e) |
44 local stanza, origin = e.stanza, e.origin; | 42 local stanza, origin = e.stanza, e.origin; |
45 if validateLogFolder() == false then | 43 if validateLogFolder() == false then |
46 return; | 44 return; |
47 end | 45 end |
48 | 46 |
49 if (stanza.name == "presence") or | 47 if (stanza.name == "presence") or |
50 (stanza.name == "message" and tostring(stanza.attr.type) == "groupchat") | 48 (stanza.name == "message" and tostring(stanza.attr.type) == "groupchat") |
51 then | 49 then |
52 local node, host, resource = splitJid(stanza.attr.to); | 50 local node, host, resource = splitJid(stanza.attr.to); |
53 if node ~= nil and host ~= nil then | 51 if node ~= nil and host ~= nil then |
54 local bare = node .. "@" .. host; | 52 local bare = node .. "@" .. host; |
55 if prosody.hosts[host] ~= nil and prosody.hosts[host].muc ~= nil and prosody.hosts[host].muc.rooms[bare] ~= nil then | 53 if prosody.hosts[host] ~= nil and prosody.hosts[host].muc ~= nil and prosody.hosts[host].muc.rooms[bare] ~= nil then |
56 local room = prosody.hosts[host].muc.rooms[bare] | 54 local room = prosody.hosts[host].muc.rooms[bare] |
57 local logging = config_get(host, "core", "logging"); | 55 local today = os.date("%y%m%d"); |
58 if logging == true then | 56 local now = os.date("%X") |
59 local today = os.date("%y%m%d"); | 57 local fn = config.folder .. "/" .. today .. "_" .. bare .. ".log"; |
60 local now = os.date("%X") | 58 local mucFrom = nil; |
61 local fn = config.folder .. "/" .. today .. "_" .. bare .. ".log"; | 59 |
62 local mucFrom = nil; | 60 if stanza.name == "presence" and stanza.attr.type == nil then |
63 | 61 mucFrom = stanza.attr.to; |
64 if stanza.name == "presence" and stanza.attr.type == nil then | 62 else |
65 mucFrom = stanza.attr.to; | 63 for jid, nick in pairs(room._jid_nick) do |
66 else | 64 if jid == stanza.attr.from then |
67 for jid, nick in pairs(room._jid_nick) do | 65 mucFrom = nick; |
68 if jid == stanza.attr.from then | |
69 mucFrom = nick; | |
70 end | |
71 end | 66 end |
72 end | 67 end |
73 | 68 end |
74 if mucFrom ~= nil then | 69 |
75 module:log("debug", "try to open room log: %s", fn); | 70 if mucFrom ~= nil then |
76 local f = assert(io.open(fn, "a")); | 71 module:log("debug", "try to open room log: %s", fn); |
77 local realFrom = stanza.attr.from; | 72 local f = assert(io.open(fn, "a")); |
78 local realTo = stanza.attr.to; | 73 local realFrom = stanza.attr.from; |
79 stanza.attr.from = mucFrom; | 74 local realTo = stanza.attr.to; |
80 stanza.attr.to = nil; | 75 stanza.attr.from = mucFrom; |
81 f:write("<stanza time=\"".. now .. "\">" .. tostring(stanza) .. "</stanza>\n"); | 76 stanza.attr.to = nil; |
82 stanza.attr.from = realFrom; | 77 f:write("<stanza time=\"".. now .. "\">" .. tostring(stanza) .. "</stanza>\n"); |
83 stanza.attr.to = realTo; | 78 stanza.attr.from = realFrom; |
84 f:close() | 79 stanza.attr.to = realTo; |
85 end | 80 f:close() |
86 end | 81 end |
87 end | 82 end |
88 end | 83 end |
89 end | 84 end |
90 return; | 85 return; |
147 | 142 |
148 local function generateRoomListSiteContent() | 143 local function generateRoomListSiteContent() |
149 local ret = "<h2>Rooms hosted on this server:</h2><hr /><p>"; | 144 local ret = "<h2>Rooms hosted on this server:</h2><hr /><p>"; |
150 for host, config in pairs(prosody.hosts) do | 145 for host, config in pairs(prosody.hosts) do |
151 if prosody.hosts[host].muc ~= nil then | 146 if prosody.hosts[host].muc ~= nil then |
152 local logging = config_get(host, "core", "logging"); | 147 for jid, room in pairs(prosody.hosts[host].muc.rooms) do |
153 if logging then | 148 ret = ret .. "<a href=\"/muc_log/" .. jid .. "/\">" .. jid .."</a><br />\n"; |
154 for jid, room in pairs(prosody.hosts[host].muc.rooms) do | |
155 ret = ret .. "<a href=\"/muc_log/" .. jid .. "/\">" .. jid .."</a><br />\n"; | |
156 end | |
157 else | |
158 module:log("debug", "logging not enabled for muc component: %s", tostring(host)); | |
159 end | 149 end |
160 end | 150 end |
161 end | 151 end |
162 return ret .. "</p><hr />"; | 152 return ret .. "</p><hr />"; |
163 end | 153 end |
165 local function generateDayListSiteContentByRoom(bareRoomJid) | 155 local function generateDayListSiteContentByRoom(bareRoomJid) |
166 local ret = ""; | 156 local ret = ""; |
167 | 157 |
168 for file in lfs.dir(config.folder) do | 158 for file in lfs.dir(config.folder) do |
169 local year, month, day = file:match("^(%d%d)(%d%d)(%d%d)_" .. bareRoomJid .. ".log"); | 159 local year, month, day = file:match("^(%d%d)(%d%d)(%d%d)_" .. bareRoomJid .. ".log"); |
170 module:log("debug", "year: %s, month: %s, day: %s", year, month, day); | |
171 if year ~= nil and month ~= nil and day ~= nil and | 160 if year ~= nil and month ~= nil and day ~= nil and |
172 year ~= "" and month ~= "" and day ~= "" | 161 year ~= "" and month ~= "" and day ~= "" |
173 then | 162 then |
174 ret = "<a href=\"/muc_log/" .. bareRoomJid .. "/?year=" .. year .. "&month=" .. month .. "&day=" .. day .. "\">20" .. year .. "/" .. month .. "/" .. day .. "</a><br />\n" .. ret; | 163 ret = "<a href=\"/muc_log/" .. bareRoomJid .. "/?year=" .. year .. "&month=" .. month .. "&day=" .. day .. "\">20" .. year .. "/" .. month .. "/" .. day .. "</a><br />\n" .. ret; |
175 end | 164 end |
207 if f ~= nil then | 196 if f ~= nil then |
208 local content = f:read("*a"); | 197 local content = f:read("*a"); |
209 local parsed = lom.parse("<xml>" .. content .. "</xml>"); | 198 local parsed = lom.parse("<xml>" .. content .. "</xml>"); |
210 if parsed ~= nil then | 199 if parsed ~= nil then |
211 for _,stanza in ipairs(parsed) do | 200 for _,stanza in ipairs(parsed) do |
212 -- module:log("debug", "dump of stanza: \n%s", dump(stanza)) | |
213 if stanza.attr ~= nil and stanza.attr.time ~= nil then | 201 if stanza.attr ~= nil and stanza.attr.time ~= nil then |
214 ret = ret .. "<a name=\"" .. stanza.attr.time .. "\" href=\"#" .. stanza.attr.time .. "\" class=\"timestuff\">[" .. stanza.attr.time .. "]</a> "; | 202 local tmp = "<a name=\"" .. stanza.attr.time .. "\" href=\"#" .. stanza.attr.time .. "\" class=\"timestuff\">[" .. stanza.attr.time .. "]</a> "; |
215 if stanza[1] ~= nil then | 203 if stanza[1] ~= nil then |
216 local nick; | 204 local nick; |
217 if stanza[1].attr.from ~= nil then | 205 if stanza[1].attr.from ~= nil then |
218 nick = stanza[1].attr.from:match("/(.+)$"); | 206 nick = stanza[1].attr.from:match("/(.+)$"); |
219 end | 207 end |
220 if stanza[1].tag == "presence" and nick ~= nil then | 208 if stanza[1].tag == "presence" and nick ~= nil then |
221 if stanza[1].attr.type == nil then | 209 if stanza[1].attr.type == nil then |
222 ret = ret .. "<font class=\"muc_join\"> *** " .. nick .. " joins the room</font><br />\n"; | 210 ret = ret .. tmp .. "<font class=\"muc_join\"> *** " .. nick .. " joins the room</font><br />\n"; |
223 elseif stanza[1].attr.type ~= nil and stanza[1].attr.type == "unavailable" then | 211 elseif stanza[1].attr.type ~= nil and stanza[1].attr.type == "unavailable" then |
224 ret = ret .. "<font class=\"muc_leave\"> *** " .. nick .. " leaves the room</font><br />\n"; | 212 ret = ret .. tmp .. "<font class=\"muc_leave\"> *** " .. nick .. " leaves the room</font><br />\n"; |
225 else | 213 else |
226 ret = ret .. "<font class=\"muc_leave\"> *** " .. nick .. " changed his/her status to: " .. stanza[1].attr.type .. "</font><br />\n"; | 214 ret = ret .. tmp .. "<font class=\"muc_leave\"> *** " .. nick .. " changed his/her status to: " .. stanza[1].attr.type .. "</font><br />\n"; |
227 end | 215 end |
228 elseif stanza[1].tag == "message" then | 216 elseif stanza[1].tag == "message" then |
229 local body; | 217 local body; |
230 for _,tag in ipairs(stanza[1]) do | 218 for _,tag in ipairs(stanza[1]) do |
231 if tag.tag == "body" then | 219 if tag.tag == "body" then |
239 break; | 227 break; |
240 end | 228 end |
241 end | 229 end |
242 end | 230 end |
243 if nick ~= nil and body ~= nil then | 231 if nick ~= nil and body ~= nil then |
244 ret = ret .. "<font class=\"muc_name\"><" .. nick .. "></font> " .. body .. "<br />\n"; | 232 ret = ret .. tmp .. "<font class=\"muc_name\"><" .. nick .. "></font> " .. body .. "<br />\n"; |
245 end | 233 end |
246 else | 234 else |
247 module:log("info", "unknown stanza subtag in log found. room: %s; day: %s", bareRoomJid, year .. "/" .. month .. "/" .. day); | 235 module:log("info", "unknown stanza subtag in log found. room: %s; day: %s", bareRoomJid, year .. "/" .. month .. "/" .. day); |
248 end | 236 end |
249 end | 237 end |
261 return generateDayListSiteContentByRoom(bareRoomJid); -- fallback | 249 return generateDayListSiteContentByRoom(bareRoomJid); -- fallback |
262 end | 250 end |
263 end | 251 end |
264 | 252 |
265 function handle_request(method, body, request) | 253 function handle_request(method, body, request) |
266 module:log("debug", "method: %s, body: %s, request: %s", tostring(method), tostring(body), tostring(request)); | |
267 -- module:log("debug", "dump of request:\n%s\n", dump(request)); | |
268 local query = splitQuery(request.url.query); | 254 local query = splitQuery(request.url.query); |
269 local node, host = grepRoomJid(request.url.path); | 255 local node, host = grepRoomJid(request.url.path); |
270 | 256 |
271 if validateLogFolder() == false then | 257 if validateLogFolder() == false then |
272 return createDoc([[ | 258 return createDoc([[ |
281 end | 267 end |
282 if node ~= nil and host ~= nil then | 268 if node ~= nil and host ~= nil then |
283 local bare = node .. "@" .. host; | 269 local bare = node .. "@" .. host; |
284 if prosody.hosts[host] ~= nil and prosody.hosts[host].muc ~= nil and prosody.hosts[host].muc.rooms[bare] ~= nil then | 270 if prosody.hosts[host] ~= nil and prosody.hosts[host].muc ~= nil and prosody.hosts[host].muc.rooms[bare] ~= nil then |
285 local room = prosody.hosts[host].muc.rooms[bare]; | 271 local room = prosody.hosts[host].muc.rooms[bare]; |
286 local logging = config_get(host, "core", "logging"); | 272 if request.url.query == nil then |
287 if logging == true then | 273 return createDoc(generateDayListSiteContentByRoom(bare)); |
288 if request.url.query == nil then | |
289 return createDoc(generateDayListSiteContentByRoom(bare)); | |
290 else | |
291 return createDoc(parseDay(bare, query)); | |
292 end | |
293 else | 274 else |
294 module:log("debug", "logging not enabled for this room: %s", bare); | 275 return createDoc(parseDay(bare, query)); |
295 end | 276 end |
296 else | 277 else |
297 module:log("debug", "room instance not found. bare room jid: %s", tostring(bare)); | 278 module:log("warn", "room instance not found. bare room jid: %s", tostring(bare)); |
298 end | 279 end |
299 else | 280 else |
300 return createDoc(generateRoomListSiteContent()); | 281 return createDoc(generateRoomListSiteContent()); |
301 end | 282 end |
302 return; | 283 return; |
303 end | 284 end |
304 | 285 |
305 function module.load() | 286 config = config_get(module:get_host(), "core", "muc_log"); |
306 config = config_get("*", "core", "muc_log"); | 287 |
307 -- module:log("debug", "muc_log config: \n%s", dump(config)); | 288 httpserver.new_from_config({ config.http_port or true }, handle_request, { base = "muc_log" }); |
308 | 289 |
309 httpserver.new_from_config({ config.http_port or true }, handle_request, { base = "muc_log" }); | 290 module:hook("message/bare", logIfNeeded, 500); |
310 return validateLogFolder(); | |
311 end | |
312 | |
313 module:hook("pre-message/bare", logIfNeeded, 500); | 291 module:hook("pre-message/bare", logIfNeeded, 500); |
292 module:hook("presence/full", logIfNeeded, 500); | |
314 module:hook("pre-presence/full", logIfNeeded, 500); | 293 module:hook("pre-presence/full", logIfNeeded, 500); |