diff --git a/lib/msgslice.py b/lib/msgslice.py new file mode 100644 index 0000000..1b78d81 --- /dev/null +++ b/lib/msgslice.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python2 +# -*- coding: UTF-8 -*- +# File: msgslice.py +# Date: Mon Dec 22 22:24:32 2014 +0800 +# Author: Yuxin Wu + +class MessageSlicer(object): + """ Separate messages into slices by time. + A new day always begins a new slice. + """ + def __init__(self, diff_thres=5 * 60): + self.diff_thres = diff_thres + + def slice(self, msgs): + ret = [] + now = [] + for m in msgs: + if len(now) == 0: + now.append(m) + continue + nowtime, lasttime = m.createTime, now[-1].createTime + if nowtime.date() == lasttime.date() and \ + (nowtime - lasttime).seconds < self.diff_thres: + now.append(m) + continue + + ret.append(now) + now = [] + return ret + + diff --git a/lib/parser.py b/lib/parser.py index df40330..4a0641c 100644 --- a/lib/parser.py +++ b/lib/parser.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # -*- coding: UTF-8 -*- # File: parser.py -# Date: Mon Dec 22 21:59:26 2014 +0800 +# Date: Mon Dec 22 22:14:18 2014 +0800 # Author: Yuxin Wu import sqlite3 @@ -76,7 +76,7 @@ SELECT {} FROM message imginfo_q = self.cc.execute("""SELECT msgSvrId, bigImgPath FROM ImgInfo2""") self.imginfo = {k: v for (k, v) in imginfo_q if not v.startswith('SERVERID://')} - logger.info("Found {} big images records.".format(len(self.imginfo))) + logger.info("Found {} hd image records.".format(len(self.imginfo))) def _find_msg_by_type(self, msgs=None): ret = [] @@ -103,7 +103,6 @@ SELECT {} FROM message if catalog not in NEEDED_EMOJI_CATALOG: continue self.internal_emojis[md5] = name - print self.internal_emojis def parse(self): diff --git a/lib/render.py b/lib/render.py index 7305117..a86fa24 100644 --- a/lib/render.py +++ b/lib/render.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 # -*- coding: UTF-8 -*- # File: render.py -# Date: Mon Dec 22 16:52:48 2014 +0800 +# Date: Mon Dec 22 22:48:32 2014 +0800 # Author: Yuxin Wu import os @@ -11,7 +11,8 @@ import logging logger = logging.getLogger(__name__) LIB_PATH = os.path.dirname(os.path.abspath(__file__)) -HTML_FILE = os.path.join(LIB_PATH, 'static/template.html') +HTML_FILE = os.path.join(LIB_PATH, 'static', 'template.html') +TIME_HTML_FILE = os.path.join(LIB_PATH, 'static', 'TP_TIME.html') try: from csscompressor import compress as css_compress @@ -20,7 +21,8 @@ except: from .msg import * from .utils import ensure_unicode -from smiley import SmileyProvider +from .smiley import SmileyProvider +from .msgslice import MessageSlicer TEMPLATES_FILES = {TYPE_MSG: "TP_MSG", TYPE_IMG: "TP_IMG", @@ -33,11 +35,13 @@ TEMPLATES = {k: ensure_unicode(open(os.path.join(LIB_PATH, 'static/{}.html'.form class HTMLRender(object): def __init__(self, parser, res=None): self.html = ensure_unicode(open(HTML_FILE).read()) + self.time_html = open(TIME_HTML_FILE).read() self.parser = parser self.res = res if self.res is None: logger.warn("Resource Directory not given. Images / Voice Message won't be displayed.") self.smiley = SmileyProvider() + self.slicer = MessageSlicer() csss = glob.glob(os.path.join(LIB_PATH, 'static/*.css')) css_string = [] @@ -69,21 +73,23 @@ class HTMLRender(object): def render_msg(self, msg): """ render a message, return the html block""" sender = 'you' if not msg.isSend else 'me' + format_dict = {'sender_label': sender, + 'time': msg.createTime } def fallback(): template = TEMPLATES[TYPE_MSG] content = msg.msg_str() - content = self.smiley.replace_smileycode(content) - return template.format(sender_label=sender, - content=content) + format_dict['content'] = self.smiley.replace_smileycode(content) + return template.format(**format_dict) + if msg.type not in TEMPLATES: return fallback() template = TEMPLATES[msg.type] if msg.type == TYPE_SPEAK: audio_str, duration = self.res.get_voice_mp3(msg.imgPath) - return template.format(sender_label=sender, - voice_duration=duration, - voice_str=audio_str) + format_dict['voice_duration'] = duration + format_dict['voice_str'] = audio_str + return template.format(**format_dict) elif msg.type == TYPE_IMG: # imgPath was original THUMBNAIL_DIRPATH://th_xxxxxxxxx imgpath = msg.imgPath.split('_')[-1] @@ -94,9 +100,9 @@ class HTMLRender(object): logger.warn("No image thumbnail found for {}".format(imgpath)) return fallback() # TODO do not show fancybox when no bigimg found - return template.format(sender_label=sender, - small_img=smallimg, - big_img=bigimg) + format_dict['small_img'] = smallimg + format_dict['big_img'] = bigimg + return template.format(**format_dict) elif msg.type == TYPE_EMOJI: imgpath = msg.imgPath if imgpath in self.parser.internal_emojis: @@ -107,33 +113,42 @@ class HTMLRender(object): else: group = None emoji_img, format = self.res.get_emoji(imgpath, group) - #assert emoji_img - return template.format(sender_label=sender, - emoji_format=format, - emoji_img=emoji_img) + format_dict['emoji_format'] = format + format_dict['emoji_img'] = emoji_img + return template.format(**format_dict) elif msg.type == TYPE_LINK: content = msg.msg_str() if content.startswith(u'URL:'): url = content[4:] content = u'URL:{0}'.format(url) - return template.format(sender_label=sender, - content=content) + format_dict['content'] = content + return template.format(**format_dict) return fallback() def render_msgs(self, msgs): - """ render msgs of the same friend""" + """ render msgs of one friend""" talker_name = msgs[0].talker logger.info(u"Rendering {} messages of {}({})".format( len(msgs), self.parser.contacts[talker_name], talker_name)) avatars = self.get_avatar_pair(talker_name) - blocks = [self.render_msg(m) for m in msgs] + slices = self.slicer.slice(msgs) + + blocks = [] + for idx, slice in enumerate(slices): + nowtime = slice[0].createTime + if idx == 0 or \ + slices[idx - 1][0].createTime.date() != nowtime.date(): + timestr = nowtime + else: + timestr = nowtime.strftime("%H:%M:%S") + blocks.append(self.time_html.format(time=timestr)) + blocks.extend([self.render_msg(m) for m in slice]) return self.html.format(extra_css=self.css_string, extra_js=self.js_string, talker=msgs[0].talker_name, messages=u''.join(blocks), - avatar_me=avatars[0], - avatar_you=avatars[1]) + avatars=avatars) if __name__ == '__main__': r = HTMLRender() diff --git a/lib/static/TP_EMOJI.html b/lib/static/TP_EMOJI.html index ad8d095..cc6c5dd 100644 --- a/lib/static/TP_EMOJI.html +++ b/lib/static/TP_EMOJI.html @@ -1,8 +1,8 @@
- +
-
+
diff --git a/lib/static/TP_IMG.html b/lib/static/TP_IMG.html index ca80302..1373e5c 100644 --- a/lib/static/TP_IMG.html +++ b/lib/static/TP_IMG.html @@ -1,8 +1,8 @@
- +
-
+
diff --git a/lib/static/TP_MSG.html b/lib/static/TP_MSG.html index a9ebc8e..603cea7 100644 --- a/lib/static/TP_MSG.html +++ b/lib/static/TP_MSG.html @@ -1,8 +1,8 @@
- +
-
+
{content}
diff --git a/lib/static/TP_SPEAK.html b/lib/static/TP_SPEAK.html index cb9cbb4..2ec9dba 100644 --- a/lib/static/TP_SPEAK.html +++ b/lib/static/TP_SPEAK.html @@ -1,8 +1,8 @@
- +
-
+
{voice_duration}"
diff --git a/lib/static/TP_TIME.html b/lib/static/TP_TIME.html new file mode 100644 index 0000000..d3212fb --- /dev/null +++ b/lib/static/TP_TIME.html @@ -0,0 +1,5 @@ +
+ + {time} + +
diff --git a/lib/static/template.html b/lib/static/template.html index 9118bad..e08533a 100644 --- a/lib/static/template.html +++ b/lib/static/template.html @@ -2,16 +2,15 @@ - WeChat - + Chat with {talker} {extra_css} @@ -33,8 +32,7 @@
- +