comparison mod_http_muc_log/mod_http_muc_log.lua @ 1555:2e51f70cd7ea

mod_http_muc_log: Make pretty
author Kim Alvefur <zash@zash.se>
date Sun, 09 Nov 2014 08:38:57 +0100
parents 8059b7cdaf17
children 0b80a02c2e3d
comparison
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