emoji works
This commit is contained in:
@@ -37,6 +37,8 @@
|
||||
```
|
||||
|
||||
### TODO
|
||||
+ Parse custom emoji, and other message types
|
||||
+ Parse uncommon message types
|
||||
+ Show name of emoji in text
|
||||
+ Search by uid/username..
|
||||
+ Fix emoji sizes..
|
||||
+ Sometimes beautiful soup failed on links..
|
||||
|
||||
+12
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: UTF-8 -*-
|
||||
# File: msg.py
|
||||
# Date: Sat Dec 20 15:12:34 2014 +0800
|
||||
# Date: Sat Dec 20 18:38:59 2014 +0800
|
||||
# Author: Yuxin Wu <[email protected]>
|
||||
|
||||
from datetime import datetime
|
||||
@@ -77,6 +77,9 @@ class WeChatMsg(object):
|
||||
if not name:
|
||||
name = msg.get('alias', '')
|
||||
return u"NAMECARD: {}".format(name)
|
||||
elif self.type == TYPE_EMOJI:
|
||||
# TODO add emoji name
|
||||
return self.content
|
||||
else:
|
||||
return self.content
|
||||
|
||||
@@ -95,3 +98,11 @@ class WeChatMsg(object):
|
||||
|
||||
def __lt__(self, r):
|
||||
return self.createTime < r.createTime
|
||||
|
||||
def get_emoji_product_id(self):
|
||||
assert self.type == TYPE_EMOJI, "Wrong call to get_emoji_product_id()!"
|
||||
soup = BeautifulSoup(self.content)
|
||||
emoji = soup.find('emoji')
|
||||
if emoji is None:
|
||||
return None
|
||||
return emoji.get('productid', None)
|
||||
|
||||
+11
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: UTF-8 -*-
|
||||
# File: parser.py
|
||||
# Date: Sat Dec 20 15:58:16 2014 +0800
|
||||
# Date: Sat Dec 20 19:40:31 2014 +0800
|
||||
# Author: Yuxin Wu <[email protected]>
|
||||
|
||||
import sqlite3
|
||||
@@ -30,6 +30,7 @@ class WeChatDBParser(object):
|
||||
self.cc = self.db_conn.cursor()
|
||||
self.contacts = {}
|
||||
self.msgs_by_talker = defaultdict(list)
|
||||
self.emojis = {}
|
||||
self.parse()
|
||||
|
||||
def _parse_contact(self):
|
||||
@@ -86,8 +87,17 @@ SELECT {} FROM message
|
||||
ret.append(msg)
|
||||
return sorted(ret)
|
||||
|
||||
def _parse_emoji(self):
|
||||
# wechat provided emojis
|
||||
emojiinfo_q = self.cc.execute(
|
||||
""" SELECT md5, desc, groupid FROM EmojiInfoDesc """)
|
||||
for row in emojiinfo_q:
|
||||
md5, desc, group = row
|
||||
self.emojis[md5] = (group, desc)
|
||||
|
||||
def parse(self):
|
||||
self._parse_userinfo()
|
||||
self._parse_contact()
|
||||
self._parse_msg()
|
||||
self._parse_imginfo()
|
||||
self._parse_emoji()
|
||||
|
||||
+11
-5
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: UTF-8 -*-
|
||||
# File: render.py
|
||||
# Date: Sat Dec 20 17:48:48 2014 +0800
|
||||
# Date: Sat Dec 20 20:15:47 2014 +0800
|
||||
# Author: Yuxin Wu <[email protected]>
|
||||
|
||||
import os
|
||||
@@ -24,7 +24,8 @@ from smiley import SmileyProvider
|
||||
|
||||
TEMPLATES_FILES = {TYPE_MSG: "TP_MSG",
|
||||
TYPE_IMG: "TP_IMG",
|
||||
TYPE_SPEAK: "TP_SPEAK"}
|
||||
TYPE_SPEAK: "TP_SPEAK",
|
||||
TYPE_EMOJI: "TP_EMOJI"}
|
||||
TEMPLATES = dict([(k, open(os.path.join(
|
||||
LIB_PATH, 'static/{}.html'.format(v))).read())
|
||||
for k, v in TEMPLATES_FILES.iteritems()])
|
||||
@@ -96,10 +97,15 @@ class HTMLRender(object):
|
||||
big_img=bigimg)
|
||||
elif msg.type == TYPE_EMOJI:
|
||||
imgpath = msg.imgPath
|
||||
print imgpath
|
||||
return fallback()
|
||||
# custom emoji
|
||||
|
||||
if imgpath in self.parser.emojis:
|
||||
group, _ = self.parser.emojis[imgpath]
|
||||
else:
|
||||
group = None
|
||||
emoji_img, format = self.res.get_emoji(imgpath, group)
|
||||
return template.format(sender_label=sender,
|
||||
emoji_format=format,
|
||||
emoji_img=emoji_img)
|
||||
return fallback()
|
||||
|
||||
def render_msgs(self, msgs):
|
||||
|
||||
+25
-6
@@ -1,22 +1,26 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: UTF-8 -*-
|
||||
# File: res.py
|
||||
# Date: Sat Dec 20 16:26:51 2014 +0800
|
||||
# Date: Sat Dec 20 20:14:40 2014 +0800
|
||||
# Author: Yuxin Wu <[email protected]>
|
||||
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import Image
|
||||
import cStringIO
|
||||
import base64
|
||||
import logging
|
||||
import eyed3
|
||||
import imghdr
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
import eyed3
|
||||
|
||||
from lib.avatar import AvatarReader
|
||||
|
||||
VOICE_DIRNAME = 'voice2'
|
||||
IMG_DIRNAME = 'image2'
|
||||
EMOJI_DIRNAME = 'emoji'
|
||||
JPEG_QUALITY = 50
|
||||
|
||||
class Resource(object):
|
||||
@@ -25,6 +29,7 @@ class Resource(object):
|
||||
assert os.path.isdir(res_dir), "No such directory: {}".format(res_dir)
|
||||
self.res_dir = res_dir
|
||||
self.img_dir = os.path.join(res_dir, IMG_DIRNAME)
|
||||
self.emoji_dir = os.path.join(res_dir, EMOJI_DIRNAME)
|
||||
assert os.path.isdir(self.img_dir), \
|
||||
"No such directory: {}".format(self.img_dir)
|
||||
self.avt_reader = AvatarReader(self.res_dir)
|
||||
@@ -78,7 +83,7 @@ class Resource(object):
|
||||
jpeg_str = buf.getvalue()
|
||||
return base64.b64encode(jpeg_str)
|
||||
|
||||
def get_img_file(self, fnames):
|
||||
def _get_img_file(self, fnames):
|
||||
""" fnames: a list of filename to search for
|
||||
return (filename, filename) of (big, small) image.
|
||||
could be empty string.
|
||||
@@ -120,13 +125,13 @@ class Resource(object):
|
||||
|
||||
def get_img(self, fnames):
|
||||
""" return two base64 jpg string"""
|
||||
big_file, small_file = self.get_img_file(fnames)
|
||||
big_file, small_file = self._get_img_file(fnames)
|
||||
|
||||
def get_jpg_b64(img_file):
|
||||
if not img_file:
|
||||
return None
|
||||
if not img_file.endswith('jpg'):
|
||||
# possibly not jpg
|
||||
if not img_file.endswith('jpg') and \
|
||||
imghdr.what(img_file) != 'jpeg':
|
||||
im = Image.open(open(img_file, 'rb'))
|
||||
buf = cStringIO.StringIO()
|
||||
im.save(buf, 'JPEG', quality=JPEG_QUALITY)
|
||||
@@ -140,3 +145,17 @@ class Resource(object):
|
||||
pass
|
||||
return (big_file, small_file)
|
||||
|
||||
def get_emoji(self, md5, pack_id):
|
||||
path = self.emoji_dir
|
||||
if pack_id:
|
||||
path = os.path.join(path, pack_id)
|
||||
candidates = glob.glob(os.path.join(path, '{}*'.format(md5)))
|
||||
candidates = [k for k in candidates if \
|
||||
not k.endswith('_thumb') and not k.endswith('_cover')]
|
||||
if len(candidates) > 1:
|
||||
# annimation
|
||||
candidates = [k for k in candidates if not re.match('.*_[0-9]+$', k)]
|
||||
assert len(candidates) == 1
|
||||
fname = candidates[0]
|
||||
return Resource.get_file_b64(fname), imghdr.what(fname)
|
||||
|
||||
|
||||
@@ -5242,7 +5242,6 @@ a.btnBlue:active .btnBluePanel {
|
||||
}
|
||||
.cloudImg .cloudContent {
|
||||
min-height: 30px;
|
||||
max-height: 200px;
|
||||
}
|
||||
.cloudImg .cloudContent img {
|
||||
min-width: 50px;
|
||||
@@ -5447,8 +5446,6 @@ a.btnBlue:active .btnBluePanel {
|
||||
}
|
||||
.you .cloudImg .img_wrap{
|
||||
display: block;
|
||||
max-width: 280px;
|
||||
max-height: 150px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.you .cloudImg .cloudArrow {
|
||||
|
||||
Reference in New Issue
Block a user