mod_http_muc_log/mod_http_muc_log.lua
changeset 1555 2e51f70cd7ea
parent 1554 8059b7cdaf17
child 1556 0b80a02c2e3d
equal deleted inserted replaced
1554:8059b7cdaf17 1555:2e51f70cd7ea
    27 end
    27 end
    28 
    28 
    29 module:depends"http";
    29 module:depends"http";
    30 
    30 
    31 local function template(data)
    31 local function template(data)
    32 	local _doc = [[
    32 	--[[ DOC
    33 	Like util.template, but deals with plain text
    33 	Like util.template, but deals with plain text
    34 	Returns a closure that is called with a table of values
    34 	Returns a closure that is called with a table of values
    35 	{name} is substituted for values["name"] and is XML escaped
    35 	{name} is substituted for values["name"] and is XML escaped
    36 	{name!} is substituted without XML escaping
    36 	{name!} is substituted without XML escaping
    37 	{name?} is optional and is replaced with an empty string if no value exists
    37 	{name?} is optional and is replaced with an empty string if no value exists
    49 			end
    49 			end
    50 		end));
    50 		end));
    51 	end
    51 	end
    52 end
    52 end
    53 
    53 
    54 local base = template[[
    54 -- TODO Move templates into files
       
    55 local base = template(template[[
    55 <!DOCTYPE html>
    56 <!DOCTYPE html>
       
    57 <html>
       
    58 <head>
    56 <meta charset="utf-8">
    59 <meta charset="utf-8">
    57 <title>{title}</title>
    60 <title>{title}</title>
    58 <style>
    61 <style>
    59 body { margin: 1ex 1em; }
    62 body{background-color:#eeeeec;margin:1ex 0;padding-bottom:3em;font-family:Arial,Helvetica,sans-serif;}
    60 ul { padding: 0; }
    63 header,footer{margin:1ex 1em;font-size:smaller;color:#babdb6;}
    61 li.action dt, li.action dd { display: inline-block; margin-left: 0;}
    64 .content{background-color:white;padding:1em;list-style-position:inside;}
    62 li.action dd { margin-left: 1ex;}
    65 nav{font-size:x-large;margin:1ex 2em;}
    63 li { list-style: none; }
    66 nav a{text-decoration:none;}
    64 li:hover { background: #eee; }
    67 nav a.up{font-size:smaller;}
    65 li time { float: right; font-size: small; opacity: 0.2; }
    68 nav a.next{float:right;}
    66 li:hover time { opacity: 1; }
    69 a:link,a:visited{color:#2e3436;text-decoration:none;}
    67 li.join , li.leave { color: green; }
    70 a:link:hover,a:visited:hover{color:#3465a4;}
    68 li.join dt, li.leave dt { color: green; }
    71 ul,ol{padding:0;}
    69 nav { font-size: x-large; margin: 1ex 2em; }
    72 li{list-style:none;}
    70 nav a { text-decoration: none; }
    73 hr{display:none;}
       
    74 li time{float:right;font-size:small;opacity:0.2;}
       
    75 li:hover time{opacity:1;}
       
    76 .room-list .name{font-size:larger;}
       
    77 q.body::before,q.body::after{content:"";}
       
    78 .presence .verb{font-style:normal;color:#30c030;}
       
    79 .presence.unavailable .verb{color:#c03030;}
    71 </style>
    80 </style>
       
    81 </head>
       
    82 <body>
    72 <h1>{title}</h1>
    83 <h1>{title}</h1>
       
    84 <header>
       
    85 {header!}
       
    86 </header>
       
    87 <hr>
       
    88 <div class="content">
    73 {body!}
    89 {body!}
    74 ]]
    90 </div>
       
    91 <hr>
       
    92 <footer>
       
    93 {footer!}
       
    94 <div class="powered-by">Prosody {prosody_version?}</div>
       
    95 </footer>
       
    96 </head>
       
    97 </html>
       
    98 ]] { prosody_version = prosody.version });
    75 
    99 
    76 local dates_template = template(base{
   100 local dates_template = template(base{
    77 	title = "Logs for room {room}";
   101 	title = "Logs for room {room}";
       
   102 	header = [[
       
   103 <nav>
       
   104 <a href=".." class="up">Back to room list</a>
       
   105 </nav>
       
   106 ]];
    78 	body = [[
   107 	body = [[
    79 <base href="{room}/">
       
    80 <nav>
   108 <nav>
    81 <a href="..">↑</a>
   109 <ul class="dates">
       
   110 {lines!}</ul>
    82 </nav>
   111 </nav>
    83 <ul>
   112 ]];
    84 {lines!}</ul>
   113 	footer = "";
    85 ]];
       
    86 })
   114 })
    87 
   115 
    88 local date_line_template = template[[
   116 local date_line_template = template[[
    89 <li><a href="{date}">{date}</a></li>
   117 <li><a href="{date}">{date}</a></li>
    90 ]];
   118 ]];
    91 
   119 
    92 local page_template = template(base{
   120 local page_template = template(base{
    93 	title = "Logs for room {room} on {date}";
   121 	title = "Logs for room {room} on {date}";
       
   122 	header = [[
       
   123 <nav>
       
   124 <a class="up" href=".">Back to date list</a>
       
   125 <br>
       
   126 <a class="prev" href="{prev}">← {prev}</a>
       
   127 <a class="next" href="{next}">{next} →</a>
       
   128 </nav>
       
   129 ]];
    94 	body = [[
   130 	body = [[
       
   131 <ol class="chat-logs">
       
   132 {logs!}</ol>
       
   133 ]];
       
   134 	footer = [[
    95 <nav>
   135 <nav>
    96 <a class="prev" href="{prev}">←</a>
   136 <div>
    97 <a class="up" href=".">↑</a>
   137 <a class="prev" href="{prev}">← {prev}</a>
    98 <a class="next" href="{next}">→</a>
   138 <a class="next" href="{next}">{next} →</a>
       
   139 </div>
    99 </nav>
   140 </nav>
   100 <ul>
   141 <script>
   101 {logs!}
   142 (function () {
   102 </ul>
   143 	var timeTags = document.getElementsByTagName("time");
       
   144 	var i = 0;
       
   145 	var date;
       
   146 	while(timeTags[i]) {
       
   147 		date = new Date(timeTags[i].getAttribute("datetime"));
       
   148 		timeTags[i].textContent = date.toLocaleTimeString();
       
   149 		timeTags[i].setAttribute("title", date.toString());
       
   150 		i++;
       
   151 	}
       
   152 })();
       
   153 </script>
   103 ]];
   154 ]];
   104 });
   155 });
   105 
   156 
   106 local line_templates = {
   157 local line_template = template[[
   107 	["message<groupchat"] = template[[
   158 <li class="{st_name} {st_type?}" id="{key}">
   108 <li id="{key}" class="{st_name}"><a href="#{key}"><time>{time}</time></a><dl><dt>{nick}</dt><dd>{body}</dd></dl></li>
   159 	<span class="time">
   109 ]];
   160 		<a href="#{key}"><time datetime="{datetime}">{time}</time></a>
   110 	["message<groupchat<subject"] = template[[
   161 	</span>
   111 <li id="{key}" class="{st_name} action subject"><a href="#{key}"><time>{time}</time></a><dl><dt>{nick}</dt><dd>changed subject to {subject}</dd></dl></li>
   162 	<b class="nick">{nick}</b>
   112 ]];
   163 	<em class="verb">{verb?}</em>
   113 	["presence"] = template[[
   164 	<q class="body">{body?}</q>
   114 <li id="{key}" class="action join"><a href="#{key}"><time>{time}</time></a><dl><dt>{nick}</dt><dd>joined</dd></dl></li>
   165 </li>
   115 ]];
   166 ]];
   116 	["presence<unavailable"] = template[[
       
   117 <li id="{key}" class="action leave"><a href="#{key}"><time>{time}</time></a><dl><dt>{nick}</dt><dd>left</dd></dl></li>
       
   118 ]];
       
   119 };
       
   120 
   167 
   121 local room_list_template = template(base{
   168 local room_list_template = template(base{
   122 	title = "Rooms on {host}";
   169 	title = "Rooms on {host}";
       
   170 	header = "";
   123 	body = [[
   171 	body = [[
   124 <dl>
   172 <dl class="room-list">
   125 {rooms!}
   173 {rooms!}
   126 </dl>
   174 </dl>
   127 ]];
   175 ]];
       
   176 	footer = "";
   128 });
   177 });
   129 
   178 
   130 local room_item_template = template[[
   179 local room_item_template = template[[
   131 <dt><a href="{room}/">{name}</a></dt>
   180 <dt class="name"><a href="{room}/">{name}</a></dt>
   132 <dd>{description?}</dd>
   181 <dd class="description">{description?}</dd>
   133 ]];
   182 ]];
   134 
   183 
   135 local function public_room(room)
   184 local function public_room(room)
   136 	if type(room) == "string" then
   185 	if type(room) == "string" then
   137 		room = get_room(room);
   186 		room = get_room(room);
   190 		limit = math.huge;
   239 		limit = math.huge;
   191 		-- with = "message<groupchat";
   240 		-- with = "message<groupchat";
   192 	});
   241 	});
   193 	if not iter then return 500; end
   242 	if not iter then return 500; end
   194 
   243 
   195 	local templ, typ;
   244 	local verb, subject, body;
   196 	for key, message, when in iter do
   245 	for key, item, when in iter do
   197 		templ = message.name;
   246 		body = item:get_child_text("body");
   198 		local typ = message.attr.type;
   247 		subject = item:get_child_text("subject");
   199 		if typ then templ = templ .. '<' .. typ; end
   248 		verb = nil;
   200 		local subject = message:get_child_text("subject");
   249 		if subject then
   201 		if subject then templ = templ .. '<subject'; end
   250 			verb = "set the topic to";
   202 		templ = line_templates[templ];
   251 		elseif body and body:sub(1,4) == "/me " then
   203 		if templ then
   252 			verb, body = body:sub(5), nil;
   204 			logs[i], i = templ { 
   253 		elseif item.name == "presence" then
   205 				key = key;
   254 			verb = item.attr.type == "unavailable" and "has left" or "has joined";
   206 				time = datetime.time(when);
   255 		end
   207 				nick = select(3, jid_split(message.attr.from));
   256 		logs[i], i = line_template { 
   208 				body = message:get_child_text("body");
   257 			key = key;
   209 				subject = subject;
   258 			datetime = datetime.datetime(when);
   210 				st_name = message.name;
   259 			time = datetime.time(when);
   211 				st_type = message.attr.type;
   260 			verb = verb;
   212 			}, i + 1;
   261 			body = subject or body;
   213 		else
   262 			nick = select(3, jid_split(item.attr.from));
   214 			module:log("debug", "No template for %s", tostring(message));
   263 			st_name = item.name;
   215 		end
   264 			st_type = item.attr.type;
       
   265 		}, i + 1;
   216 	end
   266 	end
   217 
   267 
   218 	local next_when = datetime.parse(date.."T12:00:00Z") + 86400;
   268 	local next_when = datetime.parse(date.."T12:00:00Z") + 86400;
   219 	local prev_when = datetime.parse(date.."T12:00:00Z") - 86400;
   269 	local prev_when = datetime.parse(date.."T12:00:00Z") - 86400;
   220 
   270