some bug fixes

This commit is contained in:
ppwwyyxx
2014-12-20 15:47:55 +08:00
parent 4ad694e6bc
commit acbd81e5fa
7 changed files with 72 additions and 55 deletions
+15 -13
View File
@@ -10,18 +10,20 @@
+ python-csscompressor(optional)
#### Get Necessary Data:
+ Get /data/data/com.tencent.mm/MicroMsg/long-long-name/EnMicroMsg.db from root filesystem.
+ Get WeChat user resource directory from user filesystem, for example: storage/tencent/MicroMsg/long-long-name.
+ Get Wechat uin:
+ login to [web-based wechat](https://wx.qq.com); get wxuin=1234567 from `document.cookie`
+ Or get ``default_uin`` from /data/data/com.tencent.mm/shared_prefs/system_config_prefs.xml.
+ Get phone IMEI:
+ Get /data/data/com.tencent.mm/MicroMsg/long-long-name/EnMicroMsg.db from root filesystem, possible ways are:
+ `adb root`, `adb pull /xxx/xxx.db`
+ Use your rooted file system manager app
+ Get WeChat user resource directory from user filesystem, for example: sdcard:/tencent/MicroMsg/long-long-name. (could be different)
+ Get Wechat uin, possible ways are:
+ Login to [web-based wechat](https://wx.qq.com); get wxuin=1234567 from `document.cookie`
+ Get ``default_uin`` from /data/data/com.tencent.mm/shared_prefs/system_config_prefs.xml.
+ Get phone IMEI, possible ways are:
+ Call `*#06#` on your phone
+ Or find IMEI in system settings
+ Or use `adb shell dumpsys iphonesubinfo | grep 'Device ID' | grep -o '[0-9]*'`
+ Find IMEI in system settings
+ `adb shell dumpsys iphonesubinfo | grep 'Device ID' | grep -o '[0-9]*'`
#### Run:
+ Decrypt database and get decrypted_db.db (for now, Linux x64 only):
+ Decrypt database, will produce decrypted_db.db (for now, Linux x64 only):
```
./decrypt_db.sh <path to EnMicroMsg.db> <imei> <uin>
```
@@ -29,12 +31,12 @@
```
./dump_msg.py decrypted_db.db output_dir
```
+ Dump messages of one contact to single-file html, containing voice messages and image thumbnail:
+ Dump messages of one contact to single-file html, containing voice messages and images:
```
./dump_html.py decrypted_db.db <resource directory> <contact name> output.html
```
### TODO
+ parse links, custom emoji, and other message types
+ show name of unicode emoji in txt
+ given uid/username..
+ Parse custom emoji, and other message types
+ Show name of emoji in text
+ Search by uid/username..
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
# File: emoji.py
# Date: Tue Dec 16 23:52:13 2014 +0800
# Date: Sat Dec 20 15:08:45 2014 +0800
# Author: Yuxin Wu <[email protected]>
import os
+17 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
# File: msg.py
# Date: Sun Nov 23 20:44:33 2014 +0800
# Date: Sat Dec 20 15:12:34 2014 +0800
# Author: Yuxin Wu <[email protected]>
from datetime import datetime
@@ -11,10 +11,11 @@ from .utils import ensure_bin_str, ensure_unicode
TYPE_MSG = 1
TYPE_IMG = 3
TYPE_SPEAK = 34
TYPE_NAMECARD = 42
TYPE_VIDEO = 43
TYPE_EMOJI = 47
TYPE_LOCATION = 48
TYPE_LINK = 49 # link share or file from web
TYPE_LINK = 49 # link share OR file from web
TYPE_VOIP = 50
TYPE_SYSTEM = 10000
@@ -36,6 +37,8 @@ class WeChatMsg(object):
self.talker_name = None
if self.content:
self.content = ensure_unicode(self.content)
else:
self.content = u""
def msg_str(self):
# TODO: fix more types
@@ -58,11 +61,22 @@ class WeChatMsg(object):
url = soup.find('url').text
if not url:
title = soup.find('title').text
assert title, "No title or url found in TYPE_LINK"
if not title:
print self.content
from IPython import embed; embed()
assert title, \
u"No title or url found in TYPE_LINK: {}".format(self.content)
return u"FILE:{}".format(title)
return u"URL:{}".format(url)
elif self.type == TYPE_VIDEO:
return "VIDEO"
elif self.type == TYPE_NAMECARD:
soup = BeautifulSoup(self.content)
msg = soup.find('msg').attrs
name = msg.get('nickname', '')
if not name:
name = msg.get('alias', '')
return u"NAMECARD: {}".format(name)
else:
return self.content
+4 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
# File: parser.py
# Date: Fri Dec 12 22:35:56 2014 +0800
# Date: Wed Dec 17 23:04:54 2014 +0800
# Author: Yuxin Wu <[email protected]>
import sqlite3
@@ -43,7 +43,7 @@ SELECT username,conRemark,nickname FROM rcontact
else:
self.contacts[username] = ensure_unicode(nickname)
logger.info("Got {} contacts.".format(len(self.contacts)))
logger.info("Found {} contacts.".format(len(self.contacts)))
def _parse_msg(self):
msgs_tot_cnt = 0
@@ -62,7 +62,7 @@ SELECT {} FROM message
for msg in v:
msg.talker_name = ensure_unicode(k)
msgs_tot_cnt += len(v)
logger.info("Got {} messages in total.".format(msgs_tot_cnt))
logger.info("Found {} message records.".format(msgs_tot_cnt))
def _parse_userinfo(self):
userinfo_q = self.cc.execute(""" SELECT id, value FROM userinfo """)
@@ -74,7 +74,7 @@ SELECT {} FROM message
imginfo_q = self.cc.execute("""SELECT msgSvrId, bigImgPath FROM ImgInfo2""")
self.imginfo = dict([(k, v) for (k, v) in imginfo_q
if not v.startswith('SERVERID://')])
logger.info("Got {} big images.".format(len(self.imginfo)))
logger.info("Found {} big images records.".format(len(self.imginfo)))
def _find_msg_by_type(self, msgs=None):
ret = []
+27 -27
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
# File: render.py
# Date: Wed Dec 17 00:04:02 2014 +0800
# Date: Sat Dec 20 15:40:19 2014 +0800
# Author: Yuxin Wu <[email protected]>
import os
@@ -41,7 +41,7 @@ class HTMLRender(object):
csss = glob.glob(os.path.join(LIB_PATH, 'static/*.css'))
css_string = []
for css in csss:
logger.info("Load {}".format(os.path.basename(css)))
logger.info("Loading {}.".format(os.path.basename(css)))
css = ensure_unicode(css_compress(open(css).read()))
css = u'<style type="text/css">{}</style>'.format(css)
css_string.append(css)
@@ -50,7 +50,7 @@ class HTMLRender(object):
jss = glob.glob(os.path.join(LIB_PATH, 'static/*.js'))
js_string = []
for js in jss:
logger.info("Load {}".format(os.path.basename(js)))
logger.info("Loading {}".format(os.path.basename(js)))
js = ensure_unicode(open(js).read())
# TODO: add js compress
js = u'<script type="text/javascript">{}</script>'.format(js)
@@ -68,39 +68,39 @@ class HTMLRender(object):
def render_msg(self, msg):
""" render a message, return the html block"""
sender = 'you' if not msg.isSend else 'me'
# TODO
try:
if msg.type == TYPE_VIDEO:
# send a video file
raise
template = ensure_unicode(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)
elif msg.type == TYPE_IMG:
# imgPath was original THUMBNAIL_DIRPATH://th_xxxxxxxxx
imgpath = msg.imgPath.split('_')[-1]
bigimgpath = self.parser.imginfo.get(msg.msgSvrId)
bigimg, smallimg = self.res.get_img([imgpath, bigimgpath])
return template.format(sender_label=sender,
small_img=smallimg,
big_img=bigimg)
else:
raise
except:
def fallback():
template = ensure_unicode(TEMPLATES[1])
content = msg.msg_str()
content = self.emoji.replace_emojicode(content)
return template.format(sender_label=sender,
content=content)
if msg.type not in TEMPLATES:
return fallback()
template = ensure_unicode(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)
elif msg.type == TYPE_IMG:
# imgPath was original THUMBNAIL_DIRPATH://th_xxxxxxxxx
imgpath = msg.imgPath.split('_')[-1]
bigimgpath = self.parser.imginfo.get(msg.msgSvrId)
fnames = [k for k in [imgpath, bigimgpath] if k is not None]
bigimg, smallimg = self.res.get_img(fnames)
assert smallimg
# TODO do not show fancybox when no bigimg found
return template.format(sender_label=sender,
small_img=smallimg,
big_img=bigimg)
return fallback()
def render_msgs(self, msgs):
""" render msgs of the same friend"""
talker_name = msgs[0].talker
logger.info(u"Rendering messages of {}".format(talker_name))
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]
+7 -5
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
# File: res.py
# Date: Wed Dec 17 00:02:13 2014 +0800
# Date: Sat Dec 20 15:40:33 2014 +0800
# Author: Yuxin Wu <[email protected]>
import glob
@@ -110,17 +110,19 @@ class Resource(object):
else:
logger.warn("Found big image but not thumbnail: {}".format(fname))
return (name, "")
big, small = cands[-1], cands[0]
if not name_is_thumbnail(small[0]):
big = cands[-1]
ths = filter(name_is_thumbnail, [k[0] for k in cands])
if not ths:
return (big[0], "")
return (big[0], small[0])
return (big[0], ths[0])
def get_img(self, fnames):
""" return two base64 jpg string"""
big_file, small_file = self.get_img_file(fnames)
def get_jpg_b64(img_file):
if not big_file:
if not img_file:
return None
if not img_file.endswith('jpg'):
# possibly not jpg
+1 -2
View File
@@ -1361,8 +1361,7 @@ a.btnSecondary:active {
background-color: #EFF3F7;
}
.chatPanel .chatContent {
padding: 10px;
width: 100%;
padding-left: 10px;
overflow: hidden;
position: relative;
}