From dd9908a83cec6f63f3c12ba959e291b35006ff02 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 01:44:15 +0800 Subject: [PATCH 01/14] fix startfile() issue. Changes to be committed: modified: weixin.py --- weixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weixin.py b/weixin.py index ea1172c..0cf69c3 100755 --- a/weixin.py +++ b/weixin.py @@ -101,7 +101,7 @@ class WebWeixin(object): return False def genQRCode(self): - if sys.platform.find('win') >= 0: + if sys.platform.startswith('win'): self._showQRCodeImg() else: self._str2qr('https://login.weixin.qq.com/l/' + self.uuid) From 13ea12f7854acf68e001cc2c0c79a90c7788b13c Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 03:20:36 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=AD=E9=9F=B3?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E6=B6=88=E6=81=AF=E4=B8=8B=E8=BD=BD=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=9F=AD=E8=A7=86=E9=A2=91=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to be committed: modified: weixin.py --- weixin.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/weixin.py b/weixin.py index 0cf69c3..add64fb 100755 --- a/weixin.py +++ b/weixin.py @@ -414,7 +414,9 @@ class WebWeixin(object): print '= 来自: %s' % self._searchContent('appname', content, 'xml') print '=========================' elif msgType == 62: + video = self.webwxgetvideo(msgid) print name+' 给你发了一个小视频,请在手机上查看' + self._safe_open(video) elif msgType == 10002: print name+' 撤回消息' else: @@ -552,8 +554,10 @@ class WebWeixin(object): result = data.decode('utf-8') return result - def _get(self, url): + def _get(self, url, api=None): request = urllib2.Request(url = url) + if api == 'webwxgetvoice': request.add_header('Range', 'bytes=0-') + if api == 'webwxgetvideo': request.add_header('Range', 'bytes=0-') response = urllib2.urlopen(request) data = response.read() return data From ae2e4805299bb30bb08251594e30931941dec729 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 08:36:58 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20logging=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to be committed: modified: weixin.py --- weixin.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/weixin.py b/weixin.py index add64fb..f784d63 100755 --- a/weixin.py +++ b/weixin.py @@ -9,6 +9,7 @@ import json import time, re, sys, os, random import multiprocessing import platform +import logging from collections import defaultdict def catchKeyboardInterrupt(fn): @@ -17,6 +18,7 @@ def catchKeyboardInterrupt(fn): return fn(*args) except KeyboardInterrupt: print '\n[*] 强制退出程序' + logging.debug('[*] 强制退出程序') return wrapper def _decode_list(data): @@ -268,6 +270,7 @@ class WebWeixin(object): dic = self._post(url, params) if self.DEBUG: print json.dumps(dic, indent=4) + logging.debug(json.dumps(dic, indent=4)) if dic['BaseResponse']['Ret'] == 0: self.SyncKey = dic['SyncKey'] @@ -318,7 +321,7 @@ class WebWeixin(object): # Not work now for weixin haven't support this API def webwxgetvideo(self, msgid): url = self.base_uri + '/webwxgetvideo?msgid=%s&skey=%s' % (msgid, self.skey) - data = self._get(url) + data = self._get(url, api='webwxgetvideo') fn = 'video_'+msgid+'.mp4' with open(fn, 'wb') as f: f.write(data) return fn @@ -347,11 +350,13 @@ class WebWeixin(object): def handleMsg(self, r): for msg in r['AddMsgList']: print '[*] 你有新的消息,请注意查收' + logging.debug('[*] 你有新的消息,请注意查收') if self.DEBUG: fn = 'msg' + str(int(random.random() * 1000)) + '.json' with open(fn, 'w') as f: f.write(json.dumps(msg)) print '[*] 该消息已储存到文件: ' + fn + logging.debug('[*] 该消息已储存到文件: %s' % (fn)) msgType = msg['MsgType'] name = self.getUserRemarkName(msg['FromUserName']) @@ -359,36 +364,45 @@ class WebWeixin(object): msgid = msg['MsgId'] if msgType == 51: print '[*] 成功截获微信初始化消息' + logging.debug('[*] 成功截获微信初始化消息') elif msgType == 1: if content.find('http://weixin.qq.com/cgi-bin/redirectforward?args=') != -1: # 地理位置消息 data = self._get(content).decode('gbk').encode('utf-8') pos = self._searchContent('title', data, 'xml') print '%s 给你发送了一个位置消息 [我在%s]' % (name, pos) + logging.info('%s 给你发送了一个位置消息 [我在%s]' % (name, pos)) elif msg['ToUserName'] == 'filehelper': print '%s -> 文件传输助手: %s' % (name, content.replace('
','\n')) + logging.info('%s -> 文件传输助手: %s' % (name, content.replace('
','\n'))) elif msg['FromUserName'] == self.User['UserName']: pass elif msg['FromUserName'][:2] == '@@': [people, content] = content.split(':
') group = self.getUserRemarkName(msg['FromUserName']) name = self.getUserRemarkName(people) - print '|%s| %s: %s' % (group, name, content.replace('
','\n')) + print '|%s| %s: %s' % (group.strip(), name.strip(), content.replace('
','\n')) + logging.info('|%s| %s: %s' % (group.strip(), name.strip(), content.replace('
','\n'))) else: print name+': '+content + logging.info(name+': '+content) if self.autoReplyMode: ans = self._xiaodoubi(content)+'\n[微信机器人自动回复]' if self.webwxsendmsg(ans, msg['FromUserName']): print '自动回复: '+ans + logging.info('自动回复: '+ans) else: print '自动回复失败' + logging.info('自动回复失败') elif msgType == 3: image = self.webwxgetmsgimg(msgid) print '%s 给你发送了一张图片: %s' % (name, image) + logging.info('%s 给你发送了一张图片: %s' % (name, image)) self._safe_open(image) elif msgType == 34: voice = self.webwxgetvoice(msgid) print '%s 给你发了一段语音: %s' % (name, voice) + logging.info('%s 给你发送了一张图片: %s' % (name, image)) self._safe_open(voice) elif msgType == 42: info = msg['RecommendInfo'] @@ -399,9 +413,11 @@ class WebWeixin(object): print '= 地区: %s %s' % (info['Province'], info['City']) print '= 性别: %s' % ['未知', '男', '女'][info['Sex']] print '=========================' + logging.info('%s 给你发送了一张名片: %s' % (name.strip(), json.dumps(info))) elif msgType == 47: url = self._searchContent('cdnurl', content) print '%s 给你发了一个动画表情,点击下面链接查看:\n%s' % (name, url) + logging.info('%s 给你发了一个动画表情,点击下面链接查看:\n%s' % (name, url)) self._safe_open(url) elif msgType == 49: appMsgType = defaultdict(lambda : "") @@ -413,25 +429,32 @@ class WebWeixin(object): print '= 链接: %s' % msg['Url'] print '= 来自: %s' % self._searchContent('appname', content, 'xml') print '=========================' + string = "%s 给你分享了一个%s:" % (name, appMsgType[msg['AppMsgType']]) elif msgType == 62: - video = self.webwxgetvideo(msgid) print name+' 给你发了一个小视频,请在手机上查看' + logging.info(name+' 给你发了一个小视频,请在手机上查看') + video = self.webwxgetvideo(msgid) self._safe_open(video) elif msgType == 10002: print name+' 撤回消息' + logging.info(name+' 撤回消息') else: print '[*] 该消息类型为: %d,可能是表情,图片或链接' % msg['MsgType'] print msg + logging.debug('[*] 该消息类型为: %d,可能是表情,图片或链接: ' % (msg['MsgType'], json.dumps(msg))) def listenMsgMode(self): print '[*] 进入消息监听模式 ... 成功' + logging.debug('[*] 进入消息监听模式 ... 成功') self._run('[*] 进行同步线路测试 ... ', self.testsynccheck) playWeChat = 0 while True: [retcode, selector] = self.synccheck() if self.DEBUG: print 'retcode: %s, selector: %s' % (retcode, selector) + logging.debug('retcode: %s, selector: %s' % (retcode, selector)) if retcode == '1100': print '[*] 你在手机上登出了微信,债见' + logging.debug('[*] 你在手机上登出了微信,债见') break elif retcode == '0': if selector == '2': @@ -440,6 +463,7 @@ class WebWeixin(object): elif selector == '7': playWeChat += 1 print '[*] 你在手机上玩微信被我发现了 %d 次' % playWeChat + logging.debug('[*] 你在手机上玩微信被我发现了 %d 次' % playWeChat) r = self.webwxsync() elif selector == '0': time.sleep(1) @@ -460,10 +484,13 @@ class WebWeixin(object): else: if self.webwxsendmsg(word, id): print '[*] 消息发送成功' + logging.debug('[*] 消息发送成功') else: print '[*] 消息发送失败' + logging.debug('[*] 消息发送失败') else: print '[*] 此用户不存在' + logging.debug('[*] 此用户不存在') def sendMsgToAll(self, word): for contact in self.ContactList: @@ -478,23 +505,26 @@ class WebWeixin(object): @catchKeyboardInterrupt def start(self): - print '[*] 微信网页版 ... 开动' + self._echo('[*] 微信网页版 ... 开动'); print; logging.debug('[*] 微信网页版 ... 开动') self._run('[*] 正在获取 uuid ... ', self.getUUID) - print '[*] 正在获取二维码 ... 成功'; self.genQRCode() + self._echo('[*] 正在获取二维码 ... 成功'); print; logging.debug('[*] 微信网页版 ... 开动'); self.genQRCode() self._run('[*] 请使用微信扫描二维码以登录 ... ', self.waitForLogin) self._run('[*] 请在手机上点击确认以登录 ... ', self.waitForLogin, 0) self._run('[*] 正在登录 ... ', self.login) self._run('[*] 微信初始化 ... ', self.webwxinit) self._run('[*] 开启状态通知 ... ', self.webwxstatusnotify) self._run('[*] 获取联系人 ... ', self.webwxgetcontact) - print '[*] 共有 %d 位联系人' % len(self.ContactList) + self._echo('[*] 共有 %d 位联系人' % len(self.ContactList)); print; logging.debug('[*] 微信网页版 ... 开动') if self.DEBUG: print self + logging.debug(self) if raw_input('[*] 是否开启自动回复模式(y/n): ') == 'y': self.autoReplyMode = True print '[*] 自动回复模式 ... 开启' + logging.debug('[*] 自动回复模式 ... 开启') else: print '[*] 自动回复模式 ... 关闭' + logging.debug('[*] 自动回复模式 ... 关闭') listenProcess = multiprocessing.Process(target=self.listenMsgMode) listenProcess.start() @@ -504,6 +534,7 @@ class WebWeixin(object): if text == 'quit': listenProcess.terminate() print('[*] 退出微信') + logging.debug('[*] 退出微信') exit() elif text[:2] == '->': [name, word] = text[2:].split(':') @@ -514,8 +545,10 @@ class WebWeixin(object): self.sendMsg(name, file, True) elif text[:3] == 'f->': print '发送文件' + logging.debug('发送文件') elif text[:3] == 'i->': print '发送图片' + logging.debug('发送图片') def _safe_open(self, path): if platform.system() == "Linux": @@ -525,8 +558,8 @@ class WebWeixin(object): def _run(self, str, func, *args): self._echo(str) - if func(*args): print '成功' - else: print('失败\n[*] 退出程序');exit() + if func(*args): print '成功'; logging.debug('%s... 开启' % (str)) + else: print('失败\n[*] 退出程序'); logging.debug('%s... 失败' % (str)); logging.debug('[*] 退出程序'); exit() def _echo(self, str): sys.stdout.write(str) @@ -560,6 +593,7 @@ class WebWeixin(object): if api == 'webwxgetvideo': request.add_header('Range', 'bytes=0-') response = urllib2.urlopen(request) data = response.read() + logging.debug(url) return data def _post(self, url, params, jsonfmt = True): @@ -619,5 +653,10 @@ if sys.stdout.encoding == 'cp936': if __name__ == '__main__': + + logger = logging.getLogger(__name__) + import coloredlogs + coloredlogs.install(level='DEBUG') + webwx = WebWeixin() webwx.start() From e4c8f2a31461e68eccf30a0b00d493cc78c7bbb5 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 08:43:51 +0800 Subject: [PATCH 04/14] fix logging bug --- weixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weixin.py b/weixin.py index f784d63..cbc3ece 100755 --- a/weixin.py +++ b/weixin.py @@ -441,7 +441,7 @@ class WebWeixin(object): else: print '[*] 该消息类型为: %d,可能是表情,图片或链接' % msg['MsgType'] print msg - logging.debug('[*] 该消息类型为: %d,可能是表情,图片或链接: ' % (msg['MsgType'], json.dumps(msg))) + logging.debug('[*] 该消息类型为: %d,可能是表情,图片或链接: %s' % (msg['MsgType'], json.dumps(msg))) def listenMsgMode(self): print '[*] 进入消息监听模式 ... 成功' From 455719526077a991c77100ee0ff3b4fc668b95f5 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 08:50:53 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20User-Agent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to be committed: modified: weixin.py --- weixin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/weixin.py b/weixin.py index cbc3ece..79b032b 100755 --- a/weixin.py +++ b/weixin.py @@ -81,8 +81,10 @@ class WebWeixin(object): self.GroupList = [] self.autoReplyMode = False self.syncHost = '' + self.user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36' opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar())) + opener.addheaders = [('User-agent', self.user_agent)] urllib2.install_opener(opener) def getUUID(self): From 06c2fd8053d3bdcc6ea4f94fa2dcde2cf5e4570a Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 09:12:24 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=E7=BC=BA=E7=9C=81=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=9B=9E=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to be committed: modified: weixin.py --- weixin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/weixin.py b/weixin.py index 79b032b..a8781c4 100755 --- a/weixin.py +++ b/weixin.py @@ -82,6 +82,7 @@ class WebWeixin(object): self.autoReplyMode = False self.syncHost = '' self.user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36' + self.interactive = False opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar())) opener.addheaders = [('User-agent', self.user_agent)] @@ -520,7 +521,7 @@ class WebWeixin(object): if self.DEBUG: print self logging.debug(self) - if raw_input('[*] 是否开启自动回复模式(y/n): ') == 'y': + if self.interactive and raw_input('[*] 是否开启自动回复模式(y/n): ') == 'y': self.autoReplyMode = True print '[*] 自动回复模式 ... 开启' logging.debug('[*] 自动回复模式 ... 开启') From 6f16d192e0384c6a55626246346c84bf3c195114 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 09:13:18 +0800 Subject: [PATCH 07/14] =?UTF-8?q?=E4=BB=8E=E9=85=8D=E7=BD=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=8A=A0=E8=BD=BD=E5=88=9D=E5=A7=8B=E5=8C=96=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E5=8A=9F=E8=83=BD=20Changes=20to=20be=20committed:=20?= =?UTF-8?q?=09modified:=20=20=20weixin.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/weixin.py b/weixin.py index a8781c4..4910b93 100755 --- a/weixin.py +++ b/weixin.py @@ -88,6 +88,12 @@ class WebWeixin(object): opener.addheaders = [('User-agent', self.user_agent)] urllib2.install_opener(opener) + def loadConfig(self, config): + if config['DEBUG']: self.DEBUG = config['DEBUG'] + if config['autoReplyMode']: self.autoReplyMode = config['autoReplyMode'] + if config['user_agent']: self.user_agent = config['user_agent'] + if config['interactive']: self.interactive = config['interactive'] + def getUUID(self): url = 'https://login.weixin.qq.com/jslogin' params = { From d5376c0a6ccff002ed0ffbf8775d8ff30616155d Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 09:14:45 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=E4=BD=BF=E5=BE=97=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E5=BA=93=E4=BD=BF=E7=94=A8=20Changes=20to=20?= =?UTF-8?q?be=20committed:=20=09new=20file:=20=20=20=5F=5Finit=5F=5F.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __init__.py | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 __init__.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..394a0a0 --- /dev/null +++ b/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python +# coding: utf-8 From 36385702d657c7557d8721fb106d0f3f4f7660b8 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 10:34:28 +0800 Subject: [PATCH 09/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E9=99=84=E4=BB=B6=E4=BF=9D=E5=AD=98=E7=9B=AE=E5=BD=95=E7=9A=84?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to be committed: modified: weixin.py --- weixin.py | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/weixin.py b/weixin.py index 4910b93..9884547 100755 --- a/weixin.py +++ b/weixin.py @@ -83,6 +83,10 @@ class WebWeixin(object): self.syncHost = '' self.user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36' self.interactive = False + self.autoOpen = False + self.appid = 'wx782c26e4c19acffb' + self.lang = 'zh_CN' + opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar())) opener.addheaders = [('User-agent', self.user_agent)] @@ -93,6 +97,7 @@ class WebWeixin(object): if config['autoReplyMode']: self.autoReplyMode = config['autoReplyMode'] if config['user_agent']: self.user_agent = config['user_agent'] if config['interactive']: self.interactive = config['interactive'] + if config['autoOpen']: self.autoOpen = config['autoOpen'] def getUUID(self): url = 'https://login.weixin.qq.com/jslogin' @@ -306,41 +311,47 @@ class WebWeixin(object): dic = r.json() return dic['BaseResponse']['Ret'] == 0 + def _saveFile(self, filename, data, api=None): + fn = filename + if self.saveSubFolders[api]: + dirName = os.path.join(self.saveFolder, self.saveSubFolders[api]) + if not os.path.exists(dirName): + os.makedirs(dirName) + fn = os.path.join(dirName, filename) + logging.debug('Saved file: %s' % fn) + with open(fn, 'wb') as f: f.write(data); f.close() + return fn + def webwxgeticon(self, id): url = self.base_uri + '/webwxgeticon?username=%s&skey=%s' % (id, self.skey) data = self._get(url) fn = 'img_'+id+'.jpg' - with open(fn, 'wb') as f: f.write(data) - return fn + return self._saveFile(fn, data, 'webwxgeticon') def webwxgetheadimg(self, id): url = self.base_uri + '/webwxgetheadimg?username=%s&skey=%s' % (id, self.skey) data = self._get(url) fn = 'img_'+id+'.jpg' - with open(fn, 'wb') as f: f.write(data) - return fn + return self._saveFile(fn, data, 'webwxgetheadimg') def webwxgetmsgimg(self, msgid): url = self.base_uri + '/webwxgetmsgimg?MsgID=%s&skey=%s' % (msgid, self.skey) data = self._get(url) fn = 'img_'+msgid+'.jpg' - with open(fn, 'wb') as f: f.write(data) - return fn + return self._saveFile(fn, data, 'webwxgetmsgimg') # Not work now for weixin haven't support this API def webwxgetvideo(self, msgid): url = self.base_uri + '/webwxgetvideo?msgid=%s&skey=%s' % (msgid, self.skey) data = self._get(url, api='webwxgetvideo') fn = 'video_'+msgid+'.mp4' - with open(fn, 'wb') as f: f.write(data) - return fn + return self._saveFile(fn, data, 'webwxgetvideo') def webwxgetvoice(self, msgid): url = self.base_uri + '/webwxgetvoice?msgid=%s&skey=%s' % (msgid, self.skey) data = self._get(url) fn = 'voice_'+msgid+'.mp3' - with open(fn, 'wb') as f: f.write(data) - return fn + return self._saveFile(fn, data, 'webwxgetvoice') def getUserRemarkName(self, id): name = '未知群' if id[:2] == '@@' else '陌生人' @@ -560,10 +571,11 @@ class WebWeixin(object): logging.debug('发送图片') def _safe_open(self, path): - if platform.system() == "Linux": - os.system("xdg-open %s &" % path) - else: - os.system('open %s &' % path) + if self.autoOpen: + if platform.system() == "Linux": + os.system("xdg-open %s &" % path) + else: + os.system('open %s &' % path) def _run(self, str, func, *args): self._echo(str) From 819936acde52426b17a2f11b821f19de8be8c164 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 10:35:23 +0800 Subject: [PATCH 10/14] =?UTF-8?q?=E4=BD=BF=20appid=20=E5=92=8C=20lang=20?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=8F=AF=E4=BB=A5=E4=BB=8E=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=AD=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit modified: weixin.py --- weixin.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/weixin.py b/weixin.py index 9884547..0ea26e0 100755 --- a/weixin.py +++ b/weixin.py @@ -84,6 +84,8 @@ class WebWeixin(object): self.user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36' self.interactive = False self.autoOpen = False + self.saveFolder = os.path.join(os.getcwd(), 'saved') + self.saveSubFolders = {'webwxgeticon': 'icons', 'webwxgetheadimg': 'headimgs', 'webwxgetmsgimg': 'msgimgs', 'webwxgetvideo': 'videos', 'webwxgetvoice': 'voices'} self.appid = 'wx782c26e4c19acffb' self.lang = 'zh_CN' @@ -102,9 +104,9 @@ class WebWeixin(object): def getUUID(self): url = 'https://login.weixin.qq.com/jslogin' params = { - 'appid': 'wx782c26e4c19acffb', + 'appid': self.appid, 'fun': 'new', - 'lang': 'zh_CN', + 'lang': self.lang, '_': int(time.time()), } data = self._post(url, params, False) From 4d0befb610258d702667562ef9cd488ba081d7f7 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 10:42:03 +0800 Subject: [PATCH 11/14] =?UTF-8?q?=E7=BB=9F=E4=B8=80=20qrcode=20=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E6=96=87=E4=BB=B6=E7=9A=84=E4=BF=9D=E5=AD=98=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to be committed: modified: weixin.py --- weixin.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/weixin.py b/weixin.py index 0ea26e0..45b4ab0 100755 --- a/weixin.py +++ b/weixin.py @@ -85,7 +85,7 @@ class WebWeixin(object): self.interactive = False self.autoOpen = False self.saveFolder = os.path.join(os.getcwd(), 'saved') - self.saveSubFolders = {'webwxgeticon': 'icons', 'webwxgetheadimg': 'headimgs', 'webwxgetmsgimg': 'msgimgs', 'webwxgetvideo': 'videos', 'webwxgetvoice': 'voices'} + self.saveSubFolders = {'webwxgeticon': 'icons', 'webwxgetheadimg': 'headimgs', 'webwxgetmsgimg': 'msgimgs', 'webwxgetvideo': 'videos', 'webwxgetvoice': 'voices', '_showQRCodeImg': 'qrcodes'} self.appid = 'wx782c26e4c19acffb' self.lang = 'zh_CN' @@ -125,17 +125,14 @@ class WebWeixin(object): self._str2qr('https://login.weixin.qq.com/l/' + self.uuid) def _showQRCodeImg(self): - QRCODE_PATH = os.path.join(os.getcwd(),'qrcode.jpg') url = 'https://login.weixin.qq.com/qrcode/' + self.uuid params = { 't' : 'webwx', '_' : int(time.time()) } - data = self._post(url,params,False) - with open(QRCODE_PATH, 'wb') as f: - f.write(data) - + data = self._post(url, params, False) + QRCODE_PATH = self._saveFile('qrcode.jpg', data, '_showQRCodeImg') os.startfile(QRCODE_PATH) def waitForLogin(self, tip = 1): From 99c500bd519029e95e239f9de2d08c5cc8c4dadc Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 10:45:36 +0800 Subject: [PATCH 12/14] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=AD=E9=9F=B3?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=8A=A5=E9=94=99=E9=94=99=E8=AF=AF=20bug=20?= =?UTF-8?q?Changes=20to=20be=20committed:=20=09modified:=20=20=20weixin.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weixin.py b/weixin.py index 45b4ab0..2648288 100755 --- a/weixin.py +++ b/weixin.py @@ -421,7 +421,7 @@ class WebWeixin(object): elif msgType == 34: voice = self.webwxgetvoice(msgid) print '%s 给你发了一段语音: %s' % (name, voice) - logging.info('%s 给你发送了一张图片: %s' % (name, image)) + logging.info('%s 给你发了一段语音: %s' % (name, voice)) self._safe_open(voice) elif msgType == 42: info = msg['RecommendInfo'] From c8be4aeccacfff106793ad28e127e4dfa02e9900 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 13:10:24 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20Referer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to be committed: modified: weixin.py --- weixin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/weixin.py b/weixin.py index 2648288..2e416ec 100755 --- a/weixin.py +++ b/weixin.py @@ -609,6 +609,7 @@ class WebWeixin(object): def _get(self, url, api=None): request = urllib2.Request(url = url) + request.add_header('Referer', 'https://wx.qq.com/') if api == 'webwxgetvoice': request.add_header('Range', 'bytes=0-') if api == 'webwxgetvideo': request.add_header('Range', 'bytes=0-') response = urllib2.urlopen(request) From f4c2b24ba833e0f7815f557eb852e846e1e362d9 Mon Sep 17 00:00:00 2001 From: sbilly Date: Mon, 22 Feb 2016 19:15:39 +0800 Subject: [PATCH 14/14] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=20Changes=20to=20be=20committed:=20=09modifi?= =?UTF-8?q?ed:=20=20=20weixin.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin.py | 124 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 82 insertions(+), 42 deletions(-) diff --git a/weixin.py b/weixin.py index 2e416ec..7741522 100755 --- a/weixin.py +++ b/weixin.py @@ -11,6 +11,8 @@ import multiprocessing import platform import logging from collections import defaultdict +from urlparse import urlparse +from lxml import html def catchKeyboardInterrupt(fn): def wrapper(*args): @@ -366,6 +368,59 @@ class WebWeixin(object): return member['UserName'] return None + def _showMsg(self, message): + + srcName = None + dstName = None + groupName = None + content = None + + msg = message + logging.debug(msg) + + if msg['raw_msg']: + srcName = self.getUserRemarkName(msg['raw_msg']['FromUserName']) + dstName = self.getUserRemarkName(msg['raw_msg']['ToUserName']) + content = msg['raw_msg']['Content'].replace('<','<').replace('>','>') + message_id = msg['raw_msg']['MsgId'] + + if content.find('http://weixin.qq.com/cgi-bin/redirectforward?args=') != -1: + # 地理位置消息 + data = self._get(content).decode('gbk').encode('utf-8') + pos = self._searchContent('title', data, 'xml') + tree = html.fromstring(self._get(content)) + url = tree.xpath('//html/body/div/img')[0].attrib['src'] + + for item in urlparse(url).query.split('&'): + if item.split('=')[0] == 'center': loc = item.split('=')[-1:] + + content = '%s 发送了一个 位置消息 - 我在 [%s](%s) @ %s]' % (srcName, pos, url, loc) + + if msg['raw_msg']['ToUserName'] == 'filehelper': + # 文件传输助手 + dstName = '文件传输助手' + + if msg['raw_msg']['FromUserName'][:2] == '@@': + # 接收到来自群的消息 + [people, content] = content.split(':
') + groupName = srcName + srcName = self.getUserRemarkName(people) + dstName = 'GROUP' + elif msg['raw_msg']['ToUserName'][:2] == '@@': + # 自己发给群的消息 + groupName = dstName + dstName = 'GROUP' + + # 指定了消息内容 + if 'message' in msg.keys(): content = msg['message'] + + if groupName != None: + print '%s |%s| %s -> %s: %s' % (message_id, groupName.strip(), srcName.strip(), dstName.strip(), content.replace('
','\n')) + logging.info('%s |%s| %s -> %s: %s' % (message_id, groupName.strip(), srcName.strip(), dstName.strip(), content.replace('
','\n'))) + else: + print '%s %s -> %s: %s' % (message_id, srcName.strip(), dstName.strip(), content.replace('
','\n')) + logging.info('%s %s -> %s: %s' % (message_id, srcName.strip(), dstName.strip(), content.replace('
','\n'))) + def handleMsg(self, r): for msg in r['AddMsgList']: print '[*] 你有新的消息,请注意查收' @@ -385,81 +440,62 @@ class WebWeixin(object): print '[*] 成功截获微信初始化消息' logging.debug('[*] 成功截获微信初始化消息') elif msgType == 1: - if content.find('http://weixin.qq.com/cgi-bin/redirectforward?args=') != -1: - # 地理位置消息 - data = self._get(content).decode('gbk').encode('utf-8') - pos = self._searchContent('title', data, 'xml') - print '%s 给你发送了一个位置消息 [我在%s]' % (name, pos) - logging.info('%s 给你发送了一个位置消息 [我在%s]' % (name, pos)) - elif msg['ToUserName'] == 'filehelper': - print '%s -> 文件传输助手: %s' % (name, content.replace('
','\n')) - logging.info('%s -> 文件传输助手: %s' % (name, content.replace('
','\n'))) - elif msg['FromUserName'] == self.User['UserName']: - pass - elif msg['FromUserName'][:2] == '@@': - [people, content] = content.split(':
') - group = self.getUserRemarkName(msg['FromUserName']) - name = self.getUserRemarkName(people) - print '|%s| %s: %s' % (group.strip(), name.strip(), content.replace('
','\n')) - logging.info('|%s| %s: %s' % (group.strip(), name.strip(), content.replace('
','\n'))) - else: - print name+': '+content - logging.info(name+': '+content) - if self.autoReplyMode: - ans = self._xiaodoubi(content)+'\n[微信机器人自动回复]' - if self.webwxsendmsg(ans, msg['FromUserName']): - print '自动回复: '+ans - logging.info('自动回复: '+ans) - else: - print '自动回复失败' - logging.info('自动回复失败') + raw_msg = { 'raw_msg': msg } + self._showMsg(raw_msg) + if self.autoReplyMode: + ans = self._xiaodoubi(content)+'\n[微信机器人自动回复]' + if self.webwxsendmsg(ans, msg['FromUserName']): + print '自动回复: '+ans + logging.info('自动回复: '+ans) + else: + print '自动回复失败' + logging.info('自动回复失败') elif msgType == 3: image = self.webwxgetmsgimg(msgid) - print '%s 给你发送了一张图片: %s' % (name, image) - logging.info('%s 给你发送了一张图片: %s' % (name, image)) + raw_msg = { 'raw_msg': msg, 'message': '%s 发送了一张图片: %s' % (name, image) } + self._showMsg(raw_msg) self._safe_open(image) elif msgType == 34: voice = self.webwxgetvoice(msgid) - print '%s 给你发了一段语音: %s' % (name, voice) - logging.info('%s 给你发了一段语音: %s' % (name, voice)) + raw_msg = { 'raw_msg': msg, 'message': '%s 发了一段语音: %s' % (name, voice) } + self._showMsg(raw_msg) self._safe_open(voice) elif msgType == 42: info = msg['RecommendInfo'] - print '%s 给你发送了一张名片:' % name + print '%s 发送了一张名片:' % name print '=========================' print '= 昵称: %s' % info['NickName'] print '= 微信号: %s' % info['Alias'] print '= 地区: %s %s' % (info['Province'], info['City']) print '= 性别: %s' % ['未知', '男', '女'][info['Sex']] print '=========================' - logging.info('%s 给你发送了一张名片: %s' % (name.strip(), json.dumps(info))) + logging.info('%s 发送了一张名片: %s' % (name.strip(), json.dumps(info))) elif msgType == 47: url = self._searchContent('cdnurl', content) - print '%s 给你发了一个动画表情,点击下面链接查看:\n%s' % (name, url) - logging.info('%s 给你发了一个动画表情,点击下面链接查看:\n%s' % (name, url)) + raw_msg = { 'raw_msg': msg, 'message': '%s 发了一个动画表情,点击下面链接查看: %s' % (name, url) } + self._showMsg(raw_msg) self._safe_open(url) elif msgType == 49: appMsgType = defaultdict(lambda : "") appMsgType.update({5:'链接', 3:'音乐', 7:'微博'}) - print '%s 给你分享了一个%s:' % (name, appMsgType[msg['AppMsgType']]) + print '%s 分享了一个%s:' % (name, appMsgType[msg['AppMsgType']]) print '=========================' print '= 标题: %s' % msg['FileName'] print '= 描述: %s' % self._searchContent('des', content, 'xml') print '= 链接: %s' % msg['Url'] print '= 来自: %s' % self._searchContent('appname', content, 'xml') print '=========================' - string = "%s 给你分享了一个%s:" % (name, appMsgType[msg['AppMsgType']]) + string = "%s 分享了一个%s:" % (name, appMsgType[msg['AppMsgType']]) elif msgType == 62: - print name+' 给你发了一个小视频,请在手机上查看' - logging.info(name+' 给你发了一个小视频,请在手机上查看') video = self.webwxgetvideo(msgid) + raw_msg = { 'raw_msg': msg, 'message': '%s 发了一段语音: %s' % (name, video) } + self._showMsg(raw_msg) self._safe_open(video) elif msgType == 10002: print name+' 撤回消息' logging.info(name+' 撤回消息') else: print '[*] 该消息类型为: %d,可能是表情,图片或链接' % msg['MsgType'] - print msg logging.debug('[*] 该消息类型为: %d,可能是表情,图片或链接: %s' % (msg['MsgType'], json.dumps(msg))) def listenMsgMode(self): @@ -475,6 +511,10 @@ class WebWeixin(object): print '[*] 你在手机上登出了微信,债见' logging.debug('[*] 你在手机上登出了微信,债见') break + if retcode == '1101': + print '[*] 你在其他地方登录了 WEB 版微信,债见' + logging.debug('[*] 你在其他地方登录了 WEB 版微信,债见') + break elif retcode == '0': if selector == '2': r = self.webwxsync() @@ -649,7 +689,7 @@ class WebWeixin(object): pm = re.search(key+'\s?=\s?"([^"<]+)"', content) if pm: return pm.group(1) elif fmat == 'xml': - pm=re.search('<{0}>([^<]+)'.format(key),content) + pm = re.search('<{0}>([^<]+)'.format(key),content) if pm: return pm.group(1) return '未知'