comparison mod_muc_log_http/muc_log_http/mod_muc_log_http.lua @ 972:61b63affd402

mod_muc_log_http: more proper 0.9 port.
author Marco Cirillo <maranda@lightwitch.org>
date Sun, 07 Apr 2013 12:54:33 +0200
parents adcb751f22f3
children 1db6d5028b3d
comparison
equal deleted inserted replaced
971:53e158e44a44 972:61b63affd402
1 -- Copyright (C) 2009 Thilo Cestonaro
2 --
3 -- This project is MIT/X11 licensed. Please see the
4 -- COPYING file in the source package for more information.
5 --
6
7 module:set_global();
8
9 module:depends("http"); 1 module:depends("http");
10 2
11 local prosody = prosody; 3 local prosody = prosody;
4 local my_host = module:get_host();
12 local tabSort = table.sort; 5 local tabSort = table.sort;
13 local tonumber = _G.tonumber; 6 local tonumber = _G.tonumber;
14 local tostring = _G.tostring; 7 local tostring = _G.tostring;
15 local strchar = string.char; 8 local strchar = string.char;
16 local strformat = string.format; 9 local strformat = string.format;
17 local splitJid = require "util.jid".split; 10 local splitJid = require "util.jid".split;
18 local config_get = require "core.configmanager".get; 11 local config_get = require "core.configmanager".get;
19 local httpserver = require "net.httpserver";
20 local urlencode = require "net.http".urlencode; 12 local urlencode = require "net.http".urlencode;
21 local urldecode = require "net.http".urldecode; 13 local urldecode = require "net.http".urldecode;
22 local datamanager = require "util.datamanager"; 14 local http_event = require "net.http.server".fire_server_event;
23 local data_load, data_getpath = datamanager.load, datamanager.getpath; 15 local data_load, data_getpath = datamanager.load, datamanager.getpath;
24 local datastore = "muc_log"; 16 local datastore = "muc_log";
17 local urlBase = "muc_log";
25 local config = nil; 18 local config = nil;
26 local tostring = _G.tostring; 19 local tostring = _G.tostring;
27 local tonumber = _G.tonumber; 20 local tonumber = _G.tonumber;
28 local os_date, os_time = os.date, os.time; 21 local os_date, os_time = os.date, os.time;
29 local str_format = string.format; 22 local str_format = string.format;
30 local io_open = io.open; 23 local io_open = io.open;
31 local themesParent = (module.path and module.path:gsub("[/\\][^/\\]*$", "") or (prosody.paths.plugins or "./plugins") .. "/muc_log_http") .. "/themes"; 24 local themesParent = (module.path and module.path:gsub("[/\\][^/\\]*$", "") or (prosody.paths.plugins or "./plugins") .. "/muc_log_http") .. "/themes";
32 25
33 local lom = require "lxp.lom"; 26 local lom = require "lxp.lom";
34
35 --[[ LuaFileSystem
36 * URL: http://www.keplerproject.org/luafilesystem/index.html
37 * Install: luarocks install luafilesystem
38 * ]]
39 local lfs = require "lfs"; 27 local lfs = require "lfs";
40
41
42 --[[
43 * Default templates for the html output.
44 ]]--
45 local html = {}; 28 local html = {};
46 local theme; 29 local theme;
47 30
48 local function checkDatastorePathExists(node, host, today, create) 31 local function checkDatastorePathExists(node, host, today, create)
49 create = create or false; 32 create = create or false;
85 end 68 end
86 return t; 69 return t;
87 end 70 end
88 71
89 function createDoc(body, title) 72 function createDoc(body, title)
90 if not body then 73 if not body then return "" end
91 return 404;
92 end
93 body = body:gsub("%%", "%%%%"); 74 body = body:gsub("%%", "%%%%");
94 return html.doc:gsub("###BODY_STUFF###", body) 75 return html.doc:gsub("###BODY_STUFF###", body)
95 :gsub("<title>muc_log</title>", "<title>"..(title and htmlEscape(title) or "Chatroom logs").."</title>"); 76 :gsub("<title>muc_log</title>", "<title>"..(title and htmlEscape(title) or "Chatroom logs").."</title>");
96 end 77 end
97 78
98 function urlunescape (escapedUrl) 79 function urlunescape (escapedUrl)
99 escapedUrl = escapedUrl:gsub("+", " ") 80 escapedUrl = escapedUrl:gsub("+", " ")
100 escapedUrl = escapedUrl:gsub("%%(%x%x)", function(h) return strchar(tonumber(h,16)) end) 81 escapedUrl = escapedUrl:gsub("%%(%x%x)", function(h) return strchar(tonumber(h,16)) end)
101 escapedUrl = escapedUrl:gsub("\r\n", "\n") 82 escapedUrl = escapedUrl:gsub("\r\n", "\n")
102 return escapedUrl 83 return escapedUrl
103 end
104
105 local function generateComponentListSiteContent()
106 local components = "";
107 for component,host in pairs(hosts) do
108 if host.modules.muc and host.modules.muc_log then
109 components = components .. html.components.bit:gsub("###COMPONENT###", component);
110 end
111 end
112 return (html.components.body:gsub("###COMPONENTS_STUFF###", components));
113 end 84 end
114 85
115 local function generateRoomListSiteContent(component) 86 local function generateRoomListSiteContent(component)
116 local rooms = ""; 87 local rooms = "";
117 if prosody.hosts[component] and prosody.hosts[component].muc ~= nil then 88 if prosody.hosts[component] and prosody.hosts[component].muc ~= nil then
293 end 264 end
294 end 265 end
295 266
296 room = prosody.hosts[host].muc.rooms[bareRoomJid]; 267 room = prosody.hosts[host].muc.rooms[bareRoomJid];
297 if room._data.hidden then 268 if room._data.hidden then
298 room = nil 269 room = nil;
299 end 270 end
300 end 271 end
301 if attributes ~= nil and room ~= nil then 272 if attributes ~= nil and room ~= nil then
302 local alreadyDoneYears = {}; 273 local alreadyDoneYears = {};
303 topic = room._data.subject or "(no subject)" 274 topic = room._data.subject or "(no subject)"
642 return tmp, "Chatroom logs for "..bareRoomJid.." ("..tostring(os_date("%A, %B %d, %Y", os_time(temptime)))..")"; 613 return tmp, "Chatroom logs for "..bareRoomJid.." ("..tostring(os_date("%A, %B %d, %Y", os_time(temptime)))..")";
643 end 614 end
644 end 615 end
645 end 616 end
646 617
647 function handle_request(event, path) 618 local function handle_error(code, err) return http_event("http-error", { code = code, message = err }); end
648 local request, response = event.request, event.response; 619 function handle_request(event)
649 local host, node, day, more = path:match("^([^/]*)/?([^/]*)/?([^/]*)/?(.*)$"); 620 local response = event.response;
650 if more ~= "" then return 404; end 621 local request = event.request;
651 if host == "" then host = nil; end 622 local room;
623
624 local node, day, more = request.url.path:match("^/"..urlBase.."/+([^/]*)/*([^/]*)/*(.*)$");
625 if more ~= "" then
626 response.status_code = 404;
627 return response:send(handle_error(response.status_code, "Unknown URL."));
628 end
652 if node == "" then node = nil; end 629 if node == "" then node = nil; end
653 if day == "" then day = nil; end 630 if day == "" then day = nil; end
654 631
655 node = urldecode(node); 632 node = urldecode(node);
656 633
657 if not html.doc then 634 if not html.doc then
658 response.status_code = 500; 635 response.status_code = 500;
659 return "MUC hosts or theme not loaded"; 636 return response:send(handle_error(response.status_code, "Muc Theme is not loaded."));
660 end 637 end
661 638
662 if host and not(hosts[host] and hosts[host].modules.muc and hosts[host].modules.muc_log) then 639
640 if node then room = hosts[my_host].modules.muc.rooms[node.."@"..my_host]; end
641 if node and not room then
663 response.status_code = 404; 642 response.status_code = 404;
664 return "No such MUC component"; 643 return response:send(handle_error(response.status_code, "Room doesn't exist."));
665 end 644 end
666 if host and node and not(hosts[host].modules.muc.rooms[node.."@"..host]) then 645 if room and room._data.hidden then
667 response.status_code = 404; 646 response.status_code = 404;
668 return "No such MUC room"; 647 return response:send(handle_error(response.status_code, "There're no logs for this room."));
669 end 648 end
670 649
671 if not host then -- main component list 650
672 return createDoc(generateComponentListSiteContent()); 651 if not node then -- room list for component
673 elseif not node then -- room list for component 652 return response:send(createDoc(generateRoomListSiteContent(my_host)));
674 return createDoc(generateRoomListSiteContent(host));
675 elseif not day then -- room's listing 653 elseif not day then -- room's listing
676 return createDoc(generateDayListSiteContentByRoom(node.."@"..host)); 654 return response:send(createDoc(generateDayListSiteContentByRoom(node.."@"..my_host)));
677 else 655 else
678 if not day:match("^20(%d%d)-(%d%d)-(%d%d)$") then 656 if not day:match("^20(%d%d)-(%d%d)-(%d%d)$") then
679 local y,m,d = day:match("^(%d%d)(%d%d)(%d%d)$"); 657 local y,m,d = day:match("^(%d%d)(%d%d)(%d%d)$");
680 if not y then 658 if not y then
681 return 404; 659 response.status_code = 404;
682 end 660 return response:send(handle_error(response.status_code, "No entries for that year."));
683 response.headers.location = request.path .. "../20"..y.."-"..m.."-"..d.."/"; 661 end
684 return 301; 662 response.status_code = 301;
685 end 663 response.headers = { ["Location"] = request.url.path:match("^/"..urlBase.."/+[^/]*").."/20"..y.."-"..m.."-"..d.."/" };
686 local room = hosts[host].modules.muc.rooms[node.."@"..host]; 664 return response:send();
687 return createDoc(parseDay(node.."@"..host, room._data.subject or "", day)); 665 end
666
667 local body = createDoc(parseDay(node.."@"..my_host, room._data.subject or "", day));
668 if body == "" then
669 response.status_code = 404;
670 return response:send(handle_error(response.status_code, "Day entry doesn't exist."));
671 end
672 return response:send(body);
688 end 673 end
689 end 674 end
690 675
691 local function readFile(filepath) 676 local function readFile(filepath)
692 local f,err = io_open(filepath, "r"); 677 local f,err = io_open(filepath, "r");
713 end 698 end
714 end 699 end
715 return true; 700 return true;
716 end 701 end
717 702
718 function module.add_host(module) 703 function module.load()
719 config = config_get("*", "core", "muc_log_http") or {}; 704 config = module:get_option_table("muc_log_http_config", {});
720 if config.showStatus == nil then 705 if config.showStatus == nil then config.showStatus = true; end
721 config.showStatus = true; 706 if config.showJoin == nil then config.showJoin = true; end
722 end 707 if config.urlBase ~= nil and type(config.urlBase) then urlBase = config.urlBase; end
723 if config.showJoin == nil then
724 config.showJoin = true;
725 end
726 708
727 theme = config.theme or "prosody"; 709 theme = config.theme or "prosody";
728 local themePath = themesParent .. "/" .. tostring(theme); 710 local themePath = themesParent .. "/" .. tostring(theme);
729 local attributes, err = lfs.attributes(themePath); 711 local attributes, err = lfs.attributes(themePath);
730 if attributes == nil or attributes.mode ~= "directory" then 712 if attributes == nil or attributes.mode ~= "directory" then
737 module:log("error", "Theme \"%s\" is missing something: %s", tostring(theme), err); 719 module:log("error", "Theme \"%s\" is missing something: %s", tostring(theme), err);
738 return false; 720 return false;
739 end 721 end
740 722
741 module:provides("http", { 723 module:provides("http", {
742 name = "muc_log"; 724 default_path = urlBase,
743 route = { 725 route = {
744 ["GET"] = function(event) 726 ["GET /*"] = handle_request;
745 event.response.headers.location = event.request.path .. "/"; 727 }
746 return 301;
747 end;
748 ["GET /*"] = handle_request;
749 }
750 }); 728 });
751 end 729 end