Fix PEP8 complaints: use all spaces for indent

This commit is contained in:
Joker Qyou
2016-04-08 22:27:12 +08:00
parent e841b70187
commit 63f94525f0
+222 -122
View File
@@ -1,12 +1,17 @@
#!/usr/bin/env python #!/usr/bin/env python
# coding: utf-8 # coding: utf-8
import qrcode import qrcode
import urllib, urllib2 import urllib
import urllib2
import cookielib import cookielib
import requests import requests
import xml.dom.minidom import xml.dom.minidom
import json import json
import time, re, sys, os, random import time
import re
import sys
import os
import random
import multiprocessing import multiprocessing
import platform import platform
import logging import logging
@@ -15,10 +20,10 @@ from urlparse import urlparse
from lxml import html from lxml import html
# for media upload # for media upload
import os
import mimetypes import mimetypes
from requests_toolbelt.multipart.encoder import MultipartEncoder from requests_toolbelt.multipart.encoder import MultipartEncoder
def catchKeyboardInterrupt(fn): def catchKeyboardInterrupt(fn):
def wrapper(*args): def wrapper(*args):
try: try:
@@ -28,6 +33,7 @@ def catchKeyboardInterrupt(fn):
logging.debug('[*] 强制退出程序') logging.debug('[*] 强制退出程序')
return wrapper return wrapper
def _decode_list(data): def _decode_list(data):
rv = [] rv = []
for item in data: for item in data:
@@ -40,6 +46,7 @@ def _decode_list(data):
rv.append(item) rv.append(item)
return rv return rv
def _decode_dict(data): def _decode_dict(data):
rv = {} rv = {}
for key, value in data.iteritems(): for key, value in data.iteritems():
@@ -54,7 +61,9 @@ def _decode_dict(data):
rv[key] = value rv[key] = value
return rv return rv
class WebWeixin(object): class WebWeixin(object):
def __str__(self): def __str__(self):
description = \ description = \
"=========================\n" + \ "=========================\n" + \
@@ -73,7 +82,7 @@ class WebWeixin(object):
self.DEBUG = False self.DEBUG = False
self.uuid = '' self.uuid = ''
self.base_uri = '' self.base_uri = ''
self.redirect_uri= '' self.redirect_uri = ''
self.uin = '' self.uin = ''
self.sid = '' self.sid = ''
self.skey = '' self.skey = ''
@@ -95,12 +104,14 @@ class WebWeixin(object):
self.interactive = False self.interactive = False
self.autoOpen = False self.autoOpen = False
self.saveFolder = os.path.join(os.getcwd(), 'saved') self.saveFolder = os.path.join(os.getcwd(), 'saved')
self.saveSubFolders = {'webwxgeticon': 'icons', 'webwxgetheadimg': 'headimgs', 'webwxgetmsgimg': 'msgimgs', 'webwxgetvideo': 'videos', 'webwxgetvoice': 'voices', '_showQRCodeImg': 'qrcodes'} self.saveSubFolders = {'webwxgeticon': 'icons', 'webwxgetheadimg': 'headimgs', 'webwxgetmsgimg': 'msgimgs',
'webwxgetvideo': 'videos', 'webwxgetvoice': 'voices', '_showQRCodeImg': 'qrcodes'}
self.appid = 'wx782c26e4c19acffb' self.appid = 'wx782c26e4c19acffb'
self.lang = 'zh_CN' self.lang = 'zh_CN'
self.lastCheckTs = time.time() self.lastCheckTs = time.time()
self.memberCount = 0 self.memberCount = 0
self.SpecialUsers = ['newsapp', 'fmessage', 'filehelper', 'weibo', 'qqmail', 'fmessage', 'tmessage', 'qmessage', 'qqsync', 'floatbottle', 'lbsapp', 'shakeapp', 'medianote', 'qqfriend', 'readerapp', 'blogapp', 'facebookapp', 'masssendapp', 'meishiapp', 'feedsapp', 'voip', 'blogappweixin', 'weixin', 'brandsessionholder', 'weixinreminder', 'wxid_novlwrv3lqwv11', 'gh_22b87fa7cb3c', 'officialaccounts', 'notification_messages', 'wxid_novlwrv3lqwv11', 'gh_22b87fa7cb3c', 'wxitil', 'userexperience_alarm', 'notification_messages'] self.SpecialUsers = ['newsapp', 'fmessage', 'filehelper', 'weibo', 'qqmail', 'fmessage', 'tmessage', 'qmessage', 'qqsync', 'floatbottle', 'lbsapp', 'shakeapp', 'medianote', 'qqfriend', 'readerapp', 'blogapp', 'facebookapp', 'masssendapp', 'meishiapp', 'feedsapp',
'voip', 'blogappweixin', 'weixin', 'brandsessionholder', 'weixinreminder', 'wxid_novlwrv3lqwv11', 'gh_22b87fa7cb3c', 'officialaccounts', 'notification_messages', 'wxid_novlwrv3lqwv11', 'gh_22b87fa7cb3c', 'wxitil', 'userexperience_alarm', 'notification_messages']
self.TimeOut = 20 # 同步最短时间间隔(单位:秒) self.TimeOut = 20 # 同步最短时间间隔(单位:秒)
self.media_count = -1 self.media_count = -1
@@ -110,11 +121,16 @@ class WebWeixin(object):
urllib2.install_opener(opener) urllib2.install_opener(opener)
def loadConfig(self, config): def loadConfig(self, config):
if config['DEBUG']: self.DEBUG = config['DEBUG'] if config['DEBUG']:
if config['autoReplyMode']: self.autoReplyMode = config['autoReplyMode'] self.DEBUG = config['DEBUG']
if config['user_agent']: self.user_agent = config['user_agent'] if config['autoReplyMode']:
if config['interactive']: self.interactive = config['interactive'] self.autoReplyMode = config['autoReplyMode']
if config['autoOpen']: self.autoOpen = config['autoOpen'] 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): def getUUID(self):
url = 'https://login.weixin.qq.com/jslogin' url = 'https://login.weixin.qq.com/jslogin'
@@ -142,22 +158,24 @@ class WebWeixin(object):
def _showQRCodeImg(self): def _showQRCodeImg(self):
url = 'https://login.weixin.qq.com/qrcode/' + self.uuid url = 'https://login.weixin.qq.com/qrcode/' + self.uuid
params = { params = {
't' : 'webwx', 't': 'webwx',
'_' : int(time.time()) '_': int(time.time())
} }
data = self._post(url, params, False) data = self._post(url, params, False)
QRCODE_PATH = self._saveFile('qrcode.jpg', data, '_showQRCodeImg') QRCODE_PATH = self._saveFile('qrcode.jpg', data, '_showQRCodeImg')
os.startfile(QRCODE_PATH) os.startfile(QRCODE_PATH)
def waitForLogin(self, tip = 1): def waitForLogin(self, tip=1):
time.sleep(tip) time.sleep(tip)
url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' % (tip, self.uuid, int(time.time())) url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' % (
tip, self.uuid, int(time.time()))
data = self._get(url) data = self._get(url)
pm = re.search(r'window.code=(\d+);', data) pm = re.search(r'window.code=(\d+);', data)
code = pm.group(1) code = pm.group(1)
if code == '201': return True if code == '201':
return True
elif code == '200': elif code == '200':
pm = re.search(r'window.redirect_uri="(\S+?)";', data) pm = re.search(r'window.redirect_uri="(\S+?)";', data)
r_uri = pm.group(1) + '&fun=new' r_uri = pm.group(1) + '&fun=new'
@@ -197,7 +215,8 @@ class WebWeixin(object):
return True return True
def webwxinit(self): def webwxinit(self):
url = self.base_uri + '/webwxinit?pass_ticket=%s&skey=%s&r=%s' % (self.pass_ticket, self.skey, int(time.time())) url = self.base_uri + '/webwxinit?pass_ticket=%s&skey=%s&r=%s' % (
self.pass_ticket, self.skey, int(time.time()))
params = { params = {
'BaseRequest': self.BaseRequest 'BaseRequest': self.BaseRequest
} }
@@ -205,12 +224,14 @@ class WebWeixin(object):
self.SyncKey = dic['SyncKey'] self.SyncKey = dic['SyncKey']
self.User = dic['User'] self.User = dic['User']
# synckey for synccheck # synckey for synccheck
self.synckey = '|'.join([ str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List'] ]) self.synckey = '|'.join(
[str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List']])
return dic['BaseResponse']['Ret'] == 0 return dic['BaseResponse']['Ret'] == 0
def webwxstatusnotify(self): def webwxstatusnotify(self):
url = self.base_uri + '/webwxstatusnotify?lang=zh_CN&pass_ticket=%s' % (self.pass_ticket) url = self.base_uri + \
'/webwxstatusnotify?lang=zh_CN&pass_ticket=%s' % (self.pass_ticket)
params = { params = {
'BaseRequest': self.BaseRequest, 'BaseRequest': self.BaseRequest,
"Code": 3, "Code": 3,
@@ -225,7 +246,8 @@ class WebWeixin(object):
def webwxgetcontact(self): def webwxgetcontact(self):
SpecialUsers = self.SpecialUsers SpecialUsers = self.SpecialUsers
print self.base_uri print self.base_uri
url = self.base_uri + '/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' % (self.pass_ticket, self.skey, int(time.time())) url = self.base_uri + '/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' % (
self.pass_ticket, self.skey, int(time.time()))
dic = self._post(url, {}) dic = self._post(url, {})
self.MemberCount = dic['MemberCount'] self.MemberCount = dic['MemberCount']
@@ -253,11 +275,13 @@ class WebWeixin(object):
return True return True
def webwxbatchgetcontact(self): def webwxbatchgetcontact(self):
url = self.base_uri + '/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s' % (int(time.time()), self.pass_ticket) url = self.base_uri + \
'/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s' % (
int(time.time()), self.pass_ticket)
params = { params = {
'BaseRequest': self.BaseRequest, 'BaseRequest': self.BaseRequest,
"Count": len(self.GroupList), "Count": len(self.GroupList),
"List": [ {"UserName": g['UserName'], "EncryChatRoomId":""} for g in self.GroupList ] "List": [{"UserName": g['UserName'], "EncryChatRoomId":""} for g in self.GroupList]
} }
dic = self._post(url, params) dic = self._post(url, params)
@@ -274,11 +298,13 @@ class WebWeixin(object):
return True return True
def getNameById(self, id): def getNameById(self, id):
url = self.base_uri + '/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s' % (int(time.time()), self.pass_ticket) url = self.base_uri + \
'/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s' % (
int(time.time()), self.pass_ticket)
params = { params = {
'BaseRequest': self.BaseRequest, 'BaseRequest': self.BaseRequest,
"Count": 1, "Count": 1,
"List": [ {"UserName": id, "EncryChatRoomId":""} ] "List": [{"UserName": id, "EncryChatRoomId": ""}]
} }
dic = self._post(url, params) dic = self._post(url, params)
@@ -298,7 +324,8 @@ class WebWeixin(object):
for host in SyncHost: for host in SyncHost:
self.syncHost = host self.syncHost = host
[retcode, selector] = self.synccheck() [retcode, selector] = self.synccheck()
if retcode == '0': return True if retcode == '0':
return True
return False return False
def synccheck(self): def synccheck(self):
@@ -311,15 +338,19 @@ class WebWeixin(object):
'synckey': self.synckey, 'synckey': self.synckey,
'_': int(time.time()), '_': int(time.time()),
} }
url = 'https://' + self.syncHost + '/cgi-bin/mmwebwx-bin/synccheck?' + urllib.urlencode(params) url = 'https://' + self.syncHost + \
'/cgi-bin/mmwebwx-bin/synccheck?' + urllib.urlencode(params)
data = self._get(url) data = self._get(url)
pm = re.search(r'window.synccheck={retcode:"(\d+)",selector:"(\d+)"}', data) pm = re.search(
r'window.synccheck={retcode:"(\d+)",selector:"(\d+)"}', data)
retcode = pm.group(1) retcode = pm.group(1)
selector = pm.group(2) selector = pm.group(2)
return [retcode, selector] return [retcode, selector]
def webwxsync(self): def webwxsync(self):
url = self.base_uri + '/webwxsync?sid=%s&skey=%s&pass_ticket=%s' % (self.sid, self.skey, self.pass_ticket) url = self.base_uri + \
'/webwxsync?sid=%s&skey=%s&pass_ticket=%s' % (
self.sid, self.skey, self.pass_ticket)
params = { params = {
'BaseRequest': self.BaseRequest, 'BaseRequest': self.BaseRequest,
'SyncKey': self.SyncKey, 'SyncKey': self.SyncKey,
@@ -332,12 +363,15 @@ class WebWeixin(object):
if dic['BaseResponse']['Ret'] == 0: if dic['BaseResponse']['Ret'] == 0:
self.SyncKey = dic['SyncKey'] self.SyncKey = dic['SyncKey']
self.synckey = '|'.join([ str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List'] ]) self.synckey = '|'.join(
[str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List']])
return dic return dic
def webwxsendmsg(self, word, to = 'filehelper'): def webwxsendmsg(self, word, to='filehelper'):
url = self.base_uri + '/webwxsendmsg?pass_ticket=%s' % (self.pass_ticket) url = self.base_uri + \
clientMsgId = str(int(time.time()*1000)) + str(random.random())[:5].replace('.','') '/webwxsendmsg?pass_ticket=%s' % (self.pass_ticket)
clientMsgId = str(int(time.time() * 1000)) + \
str(random.random())[:5].replace('.', '')
params = { params = {
'BaseRequest': self.BaseRequest, 'BaseRequest': self.BaseRequest,
'Msg': { 'Msg': {
@@ -351,7 +385,7 @@ class WebWeixin(object):
} }
headers = {'content-type': 'application/json; charset=UTF-8'} headers = {'content-type': 'application/json; charset=UTF-8'}
data = json.dumps(params, ensure_ascii=False).encode('utf8') data = json.dumps(params, ensure_ascii=False).encode('utf8')
r = requests.post(url, data = data, headers = headers) r = requests.post(url, data=data, headers=headers)
dic = r.json() dic = r.json()
return dic['BaseResponse']['Ret'] == 0 return dic['BaseResponse']['Ret'] == 0
@@ -363,7 +397,7 @@ class WebWeixin(object):
file_name = image_name file_name = image_name
# MIME格式 # MIME格式
# mime_type = application/pdf, image/jpeg, image/png, etc. # mime_type = application/pdf, image/jpeg, image/png, etc.
mime_type = mimetypes.guess_type(image_name,strict=False)[0] mime_type = mimetypes.guess_type(image_name, strict=False)[0]
# 微信识别的文档格式,微信服务器应该只支持两种类型的格式。pic和doc # 微信识别的文档格式,微信服务器应该只支持两种类型的格式。pic和doc
# pic格式,直接显示。doc格式则显示为文件。 # pic格式,直接显示。doc格式则显示为文件。
media_type = 'pic' if mime_type.split('/')[0] == 'image' else 'doc' media_type = 'pic' if mime_type.split('/')[0] == 'image' else 'doc'
@@ -374,13 +408,14 @@ class WebWeixin(object):
# PassTicket # PassTicket
pass_ticket = self.pass_ticket pass_ticket = self.pass_ticket
# clientMediaId # clientMediaId
client_media_id = str(int(time.time()*1000)) + str(random.random())[:5].replace('.','') client_media_id = str(int(time.time() * 1000)) + \
str(random.random())[:5].replace('.', '')
# webwx_data_ticket # webwx_data_ticket
webwx_data_ticket = '' webwx_data_ticket = ''
for item in self.cookie: for item in self.cookie:
if item.name == 'webwx_data_ticket': if item.name == 'webwx_data_ticket':
webwx_data_ticket = item.value webwx_data_ticket = item.value
break; break
if (webwx_data_ticket == ''): if (webwx_data_ticket == ''):
return "None Fuck Cookie" return "None Fuck Cookie"
@@ -394,7 +429,7 @@ class WebWeixin(object):
}, ensure_ascii=False).encode('utf8') }, ensure_ascii=False).encode('utf8')
multipart_encoder = MultipartEncoder( multipart_encoder = MultipartEncoder(
fields = { fields={
'id': 'WU_FILE_' + str(self.media_count), 'id': 'WU_FILE_' + str(self.media_count),
'name': file_name, 'name': file_name,
'type': mime_type, 'type': mime_type,
@@ -406,7 +441,7 @@ class WebWeixin(object):
'pass_ticket': pass_ticket, 'pass_ticket': pass_ticket,
'filename': (file_name, open(file_name, 'rb'), mime_type.split('/')[1]) 'filename': (file_name, open(file_name, 'rb'), mime_type.split('/')[1])
}, },
boundary = '-----------------------------1575017231431605357584454111' boundary='-----------------------------1575017231431605357584454111'
) )
headers = { headers = {
@@ -423,7 +458,7 @@ class WebWeixin(object):
'Cache-Control': 'no-cache' 'Cache-Control': 'no-cache'
} }
r = requests.post(url, data = multipart_encoder, headers = headers) r = requests.post(url, data=multipart_encoder, headers=headers)
response_json = r.json() response_json = r.json()
if response_json['BaseResponse']['Ret'] == 0: if response_json['BaseResponse']['Ret'] == 0:
return response_json return response_json
@@ -431,7 +466,8 @@ class WebWeixin(object):
def webwxsendmsgimg(self, user_id, media_id): def webwxsendmsgimg(self, user_id, media_id):
url = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg?fun=async&f=json&pass_ticket=%s' % self.pass_ticket url = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg?fun=async&f=json&pass_ticket=%s' % self.pass_ticket
clientMsgId = str(int(time.time()*1000)) + str(random.random())[:5].replace('.','') clientMsgId = str(int(time.time() * 1000)) + \
str(random.random())[:5].replace('.', '')
data_json = { data_json = {
"BaseRequest": self.BaseRequest, "BaseRequest": self.BaseRequest,
"Msg": { "Msg": {
@@ -445,7 +481,7 @@ class WebWeixin(object):
} }
headers = {'content-type': 'application/json; charset=UTF-8'} headers = {'content-type': 'application/json; charset=UTF-8'}
data = json.dumps(data_json, ensure_ascii=False).encode('utf8') data = json.dumps(data_json, ensure_ascii=False).encode('utf8')
r = requests.post(url, data = data, headers = headers) r = requests.post(url, data=data, headers=headers)
dic = r.json() dic = r.json()
return dic['BaseResponse']['Ret'] == 0 return dic['BaseResponse']['Ret'] == 0
@@ -457,38 +493,45 @@ class WebWeixin(object):
os.makedirs(dirName) os.makedirs(dirName)
fn = os.path.join(dirName, filename) fn = os.path.join(dirName, filename)
logging.debug('Saved file: %s' % fn) logging.debug('Saved file: %s' % fn)
with open(fn, 'wb') as f: f.write(data); f.close() with open(fn, 'wb') as f:
f.write(data)
f.close()
return fn return fn
def webwxgeticon(self, id): def webwxgeticon(self, id):
url = self.base_uri + '/webwxgeticon?username=%s&skey=%s' % (id, self.skey) url = self.base_uri + \
'/webwxgeticon?username=%s&skey=%s' % (id, self.skey)
data = self._get(url) data = self._get(url)
fn = 'img_'+id+'.jpg' fn = 'img_' + id + '.jpg'
return self._saveFile(fn, data, 'webwxgeticon') return self._saveFile(fn, data, 'webwxgeticon')
def webwxgetheadimg(self, id): def webwxgetheadimg(self, id):
url = self.base_uri + '/webwxgetheadimg?username=%s&skey=%s' % (id, self.skey) url = self.base_uri + \
'/webwxgetheadimg?username=%s&skey=%s' % (id, self.skey)
data = self._get(url) data = self._get(url)
fn = 'img_'+id+'.jpg' fn = 'img_' + id + '.jpg'
return self._saveFile(fn, data, 'webwxgetheadimg') return self._saveFile(fn, data, 'webwxgetheadimg')
def webwxgetmsgimg(self, msgid): def webwxgetmsgimg(self, msgid):
url = self.base_uri + '/webwxgetmsgimg?MsgID=%s&skey=%s' % (msgid, self.skey) url = self.base_uri + \
'/webwxgetmsgimg?MsgID=%s&skey=%s' % (msgid, self.skey)
data = self._get(url) data = self._get(url)
fn = 'img_'+msgid+'.jpg' fn = 'img_' + msgid + '.jpg'
return self._saveFile(fn, data, 'webwxgetmsgimg') return self._saveFile(fn, data, 'webwxgetmsgimg')
# Not work now for weixin haven't support this API # Not work now for weixin haven't support this API
def webwxgetvideo(self, msgid): def webwxgetvideo(self, msgid):
url = self.base_uri + '/webwxgetvideo?msgid=%s&skey=%s' % (msgid, self.skey) url = self.base_uri + \
'/webwxgetvideo?msgid=%s&skey=%s' % (msgid, self.skey)
data = self._get(url, api='webwxgetvideo') data = self._get(url, api='webwxgetvideo')
fn = 'video_'+msgid+'.mp4' fn = 'video_' + msgid + '.mp4'
return self._saveFile(fn, data, 'webwxgetvideo') return self._saveFile(fn, data, 'webwxgetvideo')
def webwxgetvoice(self, msgid): def webwxgetvoice(self, msgid):
url = self.base_uri + '/webwxgetvoice?msgid=%s&skey=%s' % (msgid, self.skey) url = self.base_uri + \
'/webwxgetvoice?msgid=%s&skey=%s' % (msgid, self.skey)
data = self._get(url) data = self._get(url)
fn = 'voice_'+msgid+'.mp3' fn = 'voice_' + msgid + '.mp3'
return self._saveFile(fn, data, 'webwxgetvoice') return self._saveFile(fn, data, 'webwxgetvoice')
def getGroupName(self, id): def getGroupName(self, id):
@@ -510,7 +553,8 @@ class WebWeixin(object):
def getUserRemarkName(self, id): def getUserRemarkName(self, id):
name = '未知群' if id[:2] == '@@' else '陌生人' name = '未知群' if id[:2] == '@@' else '陌生人'
if id == self.User['UserName']: return self.User['NickName'] # 自己 if id == self.User['UserName']:
return self.User['NickName'] # 自己
if id[:2] == '@@': if id[:2] == '@@':
# 群 # 群
@@ -519,23 +563,28 @@ class WebWeixin(object):
# 特殊账号 # 特殊账号
for member in self.SpecialUsersList: for member in self.SpecialUsersList:
if member['UserName'] == id: if member['UserName'] == id:
name = member['RemarkName'] if member['RemarkName'] else member['NickName'] name = member['RemarkName'] if member[
'RemarkName'] else member['NickName']
# 公众号或服务号 # 公众号或服务号
for member in self.PublicUsersList: for member in self.PublicUsersList:
if member['UserName'] == id: if member['UserName'] == id:
name = member['RemarkName'] if member['RemarkName'] else member['NickName'] name = member['RemarkName'] if member[
'RemarkName'] else member['NickName']
# 直接联系人 # 直接联系人
for member in self.ContactList: for member in self.ContactList:
if member['UserName'] == id: if member['UserName'] == id:
name = member['RemarkName'] if member['RemarkName'] else member['NickName'] name = member['RemarkName'] if member[
'RemarkName'] else member['NickName']
# 群友 # 群友
for member in self.GroupMemeberList: for member in self.GroupMemeberList:
if member['UserName'] == id: if member['UserName'] == id:
name = member['DisplayName'] if member['DisplayName'] else member['NickName'] name = member['DisplayName'] if member[
'DisplayName'] else member['NickName']
if name == '未知群' or name == '陌生人': logging.debug(id) if name == '未知群' or name == '陌生人':
logging.debug(id)
return name return name
def getUSerID(self, name): def getUSerID(self, name):
@@ -557,7 +606,8 @@ class WebWeixin(object):
if msg['raw_msg']: if msg['raw_msg']:
srcName = self.getUserRemarkName(msg['raw_msg']['FromUserName']) srcName = self.getUserRemarkName(msg['raw_msg']['FromUserName'])
dstName = self.getUserRemarkName(msg['raw_msg']['ToUserName']) dstName = self.getUserRemarkName(msg['raw_msg']['ToUserName'])
content = msg['raw_msg']['Content'].replace('&lt;','<').replace('&gt;','>') content = msg['raw_msg']['Content'].replace(
'&lt;', '<').replace('&gt;', '>')
message_id = msg['raw_msg']['MsgId'] message_id = msg['raw_msg']['MsgId']
if content.find('http://weixin.qq.com/cgi-bin/redirectforward?args=') != -1: if content.find('http://weixin.qq.com/cgi-bin/redirectforward?args=') != -1:
@@ -568,9 +618,11 @@ class WebWeixin(object):
url = tree.xpath('//html/body/div/img')[0].attrib['src'] url = tree.xpath('//html/body/div/img')[0].attrib['src']
for item in urlparse(url).query.split('&'): for item in urlparse(url).query.split('&'):
if item.split('=')[0] == 'center': loc = item.split('=')[-1:] if item.split('=')[0] == 'center':
loc = item.split('=')[-1:]
content = '%s 发送了一个 位置消息 - 我在 [%s](%s) @ %s]' % (srcName, pos, url, loc) content = '%s 发送了一个 位置消息 - 我在 [%s](%s) @ %s]' % (
srcName, pos, url, loc)
if msg['raw_msg']['ToUserName'] == 'filehelper': if msg['raw_msg']['ToUserName'] == 'filehelper':
# 文件传输助手 # 文件传输助手
@@ -592,18 +644,21 @@ class WebWeixin(object):
dstName = 'GROUP' dstName = 'GROUP'
# 收到了红包 # 收到了红包
if content == '收到红包,请在手机上查看': msg['message'] = content if content == '收到红包,请在手机上查看':
msg['message'] = content
# 指定了消息内容 # 指定了消息内容
if 'message' in msg.keys(): content = msg['message'] if 'message' in msg.keys():
content = msg['message']
if groupName != None: if groupName != None:
print '%s |%s| %s -> %s: %s' % (message_id, groupName.strip(), srcName.strip(), dstName.strip(), content.replace('<br/>','\n')) print '%s |%s| %s -> %s: %s' % (message_id, groupName.strip(), srcName.strip(), dstName.strip(), content.replace('<br/>', '\n'))
logging.info('%s |%s| %s -> %s: %s' % (message_id, groupName.strip(), srcName.strip(), dstName.strip(), content.replace('<br/>','\n'))) logging.info('%s |%s| %s -> %s: %s' % (message_id, groupName.strip(),
srcName.strip(), dstName.strip(), content.replace('<br/>', '\n')))
else: else:
print '%s %s -> %s: %s' % (message_id, srcName.strip(), dstName.strip(), content.replace('<br/>','\n')) print '%s %s -> %s: %s' % (message_id, srcName.strip(), dstName.strip(), content.replace('<br/>', '\n'))
logging.info('%s %s -> %s: %s' % (message_id, srcName.strip(), dstName.strip(), content.replace('<br/>','\n'))) logging.info('%s %s -> %s: %s' % (message_id, srcName.strip(),
dstName.strip(), content.replace('<br/>', '\n')))
def handleMsg(self, r): def handleMsg(self, r):
for msg in r['AddMsgList']: for msg in r['AddMsgList']:
@@ -612,34 +667,37 @@ class WebWeixin(object):
if self.DEBUG: if self.DEBUG:
fn = 'msg' + str(int(random.random() * 1000)) + '.json' fn = 'msg' + str(int(random.random() * 1000)) + '.json'
with open(fn, 'w') as f: f.write(json.dumps(msg)) with open(fn, 'w') as f:
f.write(json.dumps(msg))
print '[*] 该消息已储存到文件: ' + fn print '[*] 该消息已储存到文件: ' + fn
logging.debug('[*] 该消息已储存到文件: %s' % (fn)) logging.debug('[*] 该消息已储存到文件: %s' % (fn))
msgType = msg['MsgType'] msgType = msg['MsgType']
name = self.getUserRemarkName(msg['FromUserName']) name = self.getUserRemarkName(msg['FromUserName'])
content = msg['Content'].replace('&lt;','<').replace('&gt;','>') content = msg['Content'].replace('&lt;', '<').replace('&gt;', '>')
msgid = msg['MsgId'] msgid = msg['MsgId']
if msgType == 1: if msgType == 1:
raw_msg = { 'raw_msg': msg } raw_msg = {'raw_msg': msg}
self._showMsg(raw_msg) self._showMsg(raw_msg)
if self.autoReplyMode: if self.autoReplyMode:
ans = self._xiaodoubi(content)+'\n[微信机器人自动回复]' ans = self._xiaodoubi(content) + '\n[微信机器人自动回复]'
if self.webwxsendmsg(ans, msg['FromUserName']): if self.webwxsendmsg(ans, msg['FromUserName']):
print '自动回复: '+ans print '自动回复: ' + ans
logging.info('自动回复: '+ans) logging.info('自动回复: ' + ans)
else: else:
print '自动回复失败' print '自动回复失败'
logging.info('自动回复失败') logging.info('自动回复失败')
elif msgType == 3: elif msgType == 3:
image = self.webwxgetmsgimg(msgid) image = self.webwxgetmsgimg(msgid)
raw_msg = { 'raw_msg': msg, 'message': '%s 发送了一张图片: %s' % (name, image) } raw_msg = {'raw_msg': msg,
'message': '%s 发送了一张图片: %s' % (name, image)}
self._showMsg(raw_msg) self._showMsg(raw_msg)
self._safe_open(image) self._safe_open(image)
elif msgType == 34: elif msgType == 34:
voice = self.webwxgetvoice(msgid) voice = self.webwxgetvoice(msgid)
raw_msg = { 'raw_msg': msg, 'message': '%s 发了一段语音: %s' % (name, voice) } raw_msg = {'raw_msg': msg,
'message': '%s 发了一段语音: %s' % (name, voice)}
self._showMsg(raw_msg) self._showMsg(raw_msg)
self._safe_open(voice) self._safe_open(voice)
elif msgType == 42: elif msgType == 42:
@@ -651,16 +709,18 @@ class WebWeixin(object):
print '= 地区: %s %s' % (info['Province'], info['City']) print '= 地区: %s %s' % (info['Province'], info['City'])
print '= 性别: %s' % ['未知', '', ''][info['Sex']] print '= 性别: %s' % ['未知', '', ''][info['Sex']]
print '=========================' print '========================='
raw_msg = { 'raw_msg': msg, 'message': '%s 发送了一张名片: %s' % (name.strip(), json.dumps(info)) } raw_msg = {'raw_msg': msg, 'message': '%s 发送了一张名片: %s' % (
name.strip(), json.dumps(info))}
self._showMsg(raw_msg) self._showMsg(raw_msg)
elif msgType == 47: elif msgType == 47:
url = self._searchContent('cdnurl', content) url = self._searchContent('cdnurl', content)
raw_msg = { 'raw_msg': msg, 'message': '%s 发了一个动画表情,点击下面链接查看: %s' % (name, url) } raw_msg = {'raw_msg': msg,
'message': '%s 发了一个动画表情,点击下面链接查看: %s' % (name, url)}
self._showMsg(raw_msg) self._showMsg(raw_msg)
self._safe_open(url) self._safe_open(url)
elif msgType == 49: elif msgType == 49:
appMsgType = defaultdict(lambda : "") appMsgType = defaultdict(lambda: "")
appMsgType.update({5:'链接', 3:'音乐', 7:'微博'}) appMsgType.update({5: '链接', 3: '音乐', 7: '微博'})
print '%s 分享了一个%s:' % (name, appMsgType[msg['AppMsgType']]) print '%s 分享了一个%s:' % (name, appMsgType[msg['AppMsgType']])
print '=========================' print '========================='
print '= 标题: %s' % msg['FileName'] print '= 标题: %s' % msg['FileName']
@@ -674,22 +734,26 @@ class WebWeixin(object):
'url': msg['Url'], 'url': msg['Url'],
'appname': self._searchContent('appname', content, 'xml') 'appname': self._searchContent('appname', content, 'xml')
} }
raw_msg = { 'raw_msg': msg, 'message': '%s 分享了一个%s: %s' % (name, appMsgType[msg['AppMsgType']], json.dumps(card)) } raw_msg = {'raw_msg': msg, 'message': '%s 分享了一个%s: %s' % (
name, appMsgType[msg['AppMsgType']], json.dumps(card))}
self._showMsg(raw_msg) self._showMsg(raw_msg)
elif msgType == 51: elif msgType == 51:
raw_msg = { 'raw_msg': msg, 'message': '[*] 成功获取联系人信息' } raw_msg = {'raw_msg': msg, 'message': '[*] 成功获取联系人信息'}
self._showMsg(raw_msg) self._showMsg(raw_msg)
elif msgType == 62: elif msgType == 62:
video = self.webwxgetvideo(msgid) video = self.webwxgetvideo(msgid)
raw_msg = { 'raw_msg': msg, 'message': '%s 发了一段小视频: %s' % (name, video) } raw_msg = {'raw_msg': msg,
'message': '%s 发了一段小视频: %s' % (name, video)}
self._showMsg(raw_msg) self._showMsg(raw_msg)
self._safe_open(video) self._safe_open(video)
elif msgType == 10002: elif msgType == 10002:
raw_msg = { 'raw_msg': msg, 'message': '%s 撤回了一条消息' % name } raw_msg = {'raw_msg': msg, 'message': '%s 撤回了一条消息' % name}
self._showMsg(raw_msg) self._showMsg(raw_msg)
else: else:
logging.debug('[*] 该消息类型为: %d,可能是表情,图片, 链接或红包: %s' % (msg['MsgType'], json.dumps(msg))) logging.debug('[*] 该消息类型为: %d,可能是表情,图片, 链接或红包: %s' %
raw_msg = { 'raw_msg': msg, 'message': '[*] 该消息类型为: %d,可能是表情,图片, 链接或红包' % msg['MsgType'] } (msg['MsgType'], json.dumps(msg)))
raw_msg = {
'raw_msg': msg, 'message': '[*] 该消息类型为: %d,可能是表情,图片, 链接或红包' % msg['MsgType']}
self._showMsg(raw_msg) self._showMsg(raw_msg)
def listenMsgMode(self): def listenMsgMode(self):
@@ -701,7 +765,8 @@ class WebWeixin(object):
while True: while True:
self.lastCheckTs = time.time() self.lastCheckTs = time.time()
[retcode, selector] = self.synccheck() [retcode, selector] = self.synccheck()
if self.DEBUG: print 'retcode: %s, selector: %s' % (retcode, selector) if self.DEBUG:
print 'retcode: %s, selector: %s' % (retcode, selector)
logging.debug('retcode: %s, selector: %s' % (retcode, selector)) logging.debug('retcode: %s, selector: %s' % (retcode, selector))
if retcode == '1100': if retcode == '1100':
print '[*] 你在手机上登出了微信,债见' print '[*] 你在手机上登出了微信,债见'
@@ -714,7 +779,8 @@ class WebWeixin(object):
elif retcode == '0': elif retcode == '0':
if selector == '2': if selector == '2':
r = self.webwxsync() r = self.webwxsync()
if r is not None: self.handleMsg(r) if r is not None:
self.handleMsg(r)
elif selector == '6': elif selector == '6':
# TODO # TODO
redEnvelope += 1 redEnvelope += 1
@@ -727,16 +793,17 @@ class WebWeixin(object):
r = self.webwxsync() r = self.webwxsync()
elif selector == '0': elif selector == '0':
time.sleep(1) time.sleep(1)
if (time.time() - self.lastCheckTs) <= 20: time.sleep(time.time() - self.lastCheckTs) if (time.time() - self.lastCheckTs) <= 20:
time.sleep(time.time() - self.lastCheckTs)
def sendMsg(self, name, word, isfile = False): def sendMsg(self, name, word, isfile=False):
id = self.getUSerID(name) id = self.getUSerID(name)
if id: if id:
if isfile: if isfile:
with open(word, 'r') as f: with open(word, 'r') as f:
for line in f.readlines(): for line in f.readlines():
line = line.replace('\n','') line = line.replace('\n', '')
self._echo('-> '+name+': '+line) self._echo('-> ' + name + ': ' + line)
if self.webwxsendmsg(line, id): if self.webwxsendmsg(line, id):
print ' [成功]' print ' [成功]'
else: else:
@@ -755,9 +822,10 @@ class WebWeixin(object):
def sendMsgToAll(self, word): def sendMsgToAll(self, word):
for contact in self.ContactList: for contact in self.ContactList:
name = contact['RemarkName'] if contact['RemarkName'] else contact['NickName'] name = contact['RemarkName'] if contact[
'RemarkName'] else contact['NickName']
id = contact['UserName'] id = contact['UserName']
self._echo('-> '+name+': '+word) self._echo('-> ' + name + ': ' + word)
if self.webwxsendmsg(word, id): if self.webwxsendmsg(word, id):
print ' [成功]' print ' [成功]'
else: else:
@@ -774,10 +842,15 @@ class WebWeixin(object):
@catchKeyboardInterrupt @catchKeyboardInterrupt
def start(self): def start(self):
self._echo('[*] 微信网页版 ... 开动'); print; logging.debug('[*] 微信网页版 ... 开动') self._echo('[*] 微信网页版 ... 开动')
print
logging.debug('[*] 微信网页版 ... 开动')
while True: while True:
self._run('[*] 正在获取 uuid ... ', self.getUUID) self._run('[*] 正在获取 uuid ... ', self.getUUID)
self._echo('[*] 正在获取二维码 ... 成功'); print; logging.debug('[*] 微信网页版 ... 开动'); self.genQRCode() self._echo('[*] 正在获取二维码 ... 成功')
print
logging.debug('[*] 微信网页版 ... 开动')
self.genQRCode()
print '[*] 请使用微信扫描二维码以登录 ... ' print '[*] 请使用微信扫描二维码以登录 ... '
if not self.waitForLogin(): if not self.waitForLogin():
continue continue
@@ -790,11 +863,16 @@ class WebWeixin(object):
self._run('[*] 微信初始化 ... ', self.webwxinit) self._run('[*] 微信初始化 ... ', self.webwxinit)
self._run('[*] 开启状态通知 ... ', self.webwxstatusnotify) self._run('[*] 开启状态通知 ... ', self.webwxstatusnotify)
self._run('[*] 获取联系人 ... ', self.webwxgetcontact) self._run('[*] 获取联系人 ... ', self.webwxgetcontact)
self._echo('[*] 应有 %s 个联系人,读取到联系人 %d' % (self.MemberCount, len(self.MemberList))); print self._echo('[*] 应有 %s 个联系人,读取到联系人 %d' %
self._echo('[*] 共有 %d 个群 | %d 个直接联系人 | %d 个特殊账号 %d 公众号或服务号' % (len(self.GroupList), len(self.ContactList), len(self.SpecialUsersList), len(self.PublicUsersList) )); print (self.MemberCount, len(self.MemberList)))
print
self._echo('[*] 共有 %d 个群 | %d 个直接联系人 | %d 个特殊账号 %d 公众号或服务号' % (len(self.GroupList),
len(self.ContactList), len(self.SpecialUsersList), len(self.PublicUsersList)))
print
self._run('[*] 获取群 ... ', self.webwxbatchgetcontact) self._run('[*] 获取群 ... ', self.webwxbatchgetcontact)
logging.debug('[*] 微信网页版 ... 开动') logging.debug('[*] 微信网页版 ... 开动')
if self.DEBUG: print self if self.DEBUG:
print self
logging.debug(self) logging.debug(self)
if self.interactive and raw_input('[*] 是否开启自动回复模式(y/n): ') == 'y': if self.interactive and raw_input('[*] 是否开启自动回复模式(y/n): ') == 'y':
@@ -817,8 +895,10 @@ class WebWeixin(object):
exit() exit()
elif text[:2] == '->': elif text[:2] == '->':
[name, word] = text[2:].split(':') [name, word] = text[2:].split(':')
if name == 'all': self.sendMsgToAll(word) if name == 'all':
else: self.sendMsg(name, word) self.sendMsgToAll(word)
else:
self.sendMsg(name, word)
elif text[:3] == 'm->': elif text[:3] == 'm->':
[name, file] = text[3:].split(':') [name, file] = text[3:].split(':')
self.sendMsg(name, file, True) self.sendMsg(name, file, True)
@@ -840,8 +920,14 @@ class WebWeixin(object):
def _run(self, str, func, *args): def _run(self, str, func, *args):
self._echo(str) self._echo(str)
if func(*args): print '成功'; logging.debug('%s... 成功' % (str)) if func(*args):
else: print('失败\n[*] 退出程序'); logging.debug('%s... 失败' % (str)); logging.debug('[*] 退出程序'); exit() print '成功'
logging.debug('%s... 成功' % (str))
else:
print('失败\n[*] 退出程序')
logging.debug('%s... 失败' % (str))
logging.debug('[*] 退出程序')
exit()
def _echo(self, str): def _echo(self, str):
sys.stdout.write(str) sys.stdout.write(str)
@@ -861,7 +947,8 @@ class WebWeixin(object):
self._printQR(mat) # qr.print_tty() or qr.print_ascii() self._printQR(mat) # qr.print_tty() or qr.print_ascii()
def _transcoding(self, data): def _transcoding(self, data):
if not data: return data if not data:
return data
result = None result = None
if type(data) == unicode: if type(data) == unicode:
result = data result = data
@@ -870,53 +957,66 @@ class WebWeixin(object):
return result return result
def _get(self, url, api=None): def _get(self, url, api=None):
request = urllib2.Request(url = url) request = urllib2.Request(url=url)
request.add_header('Referer', 'https://wx.qq.com/') request.add_header('Referer', 'https://wx.qq.com/')
if api == 'webwxgetvoice': request.add_header('Range', 'bytes=0-') if api == 'webwxgetvoice':
if api == 'webwxgetvideo': request.add_header('Range', 'bytes=0-') request.add_header('Range', 'bytes=0-')
if api == 'webwxgetvideo':
request.add_header('Range', 'bytes=0-')
response = urllib2.urlopen(request) response = urllib2.urlopen(request)
data = response.read() data = response.read()
logging.debug(url) logging.debug(url)
return data return data
def _post(self, url, params, jsonfmt = True): def _post(self, url, params, jsonfmt=True):
if jsonfmt: if jsonfmt:
request = urllib2.Request(url = url, data = json.dumps(params)) request = urllib2.Request(url=url, data=json.dumps(params))
request.add_header('ContentType', 'application/json; charset=UTF-8') request.add_header(
'ContentType', 'application/json; charset=UTF-8')
else: else:
request = urllib2.Request(url = url, data = urllib.urlencode(params)) request = urllib2.Request(url=url, data=urllib.urlencode(params))
response = urllib2.urlopen(request) response = urllib2.urlopen(request)
data = response.read() data = response.read()
if jsonfmt: return json.loads(data, object_hook=_decode_dict) if jsonfmt:
return json.loads(data, object_hook=_decode_dict)
return data return data
def _xiaodoubi(self, word): def _xiaodoubi(self, word):
url = 'http://www.xiaodoubi.com/bot/chat.php' url = 'http://www.xiaodoubi.com/bot/chat.php'
try: try:
r = requests.post(url, data = {'chat': word}) r = requests.post(url, data={'chat': word})
return r.content return r.content
except: except:
return "让我一个人静静 T_T..." return "让我一个人静静 T_T..."
def _simsimi(self, word): def _simsimi(self, word):
key = '' key = ''
url = 'http://sandbox.api.simsimi.com/request.p?key=%s&lc=ch&ft=0.0&text=%s' % (key, word) url = 'http://sandbox.api.simsimi.com/request.p?key=%s&lc=ch&ft=0.0&text=%s' % (
key, word)
r = requests.get(url) r = requests.get(url)
ans = r.json() ans = r.json()
if ans['result'] == '100': return ans['response'] if ans['result'] == '100':
else: return '你在说什么,风太大听不清列' return ans['response']
else:
return '你在说什么,风太大听不清列'
def _searchContent(self, key, content, fmat = 'attr'): def _searchContent(self, key, content, fmat='attr'):
if fmat == 'attr': if fmat == 'attr':
pm = re.search(key+'\s?=\s?"([^"<]+)"', content) pm = re.search(key + '\s?=\s?"([^"<]+)"', content)
if pm: return pm.group(1) if pm:
return pm.group(1)
elif fmat == 'xml': elif fmat == 'xml':
pm = re.search('<{0}>([^<]+)</{0}>'.format(key),content) pm = re.search('<{0}>([^<]+)</{0}>'.format(key), content)
if not pm: pm = re.search('<{0}><\!\[CDATA\[(.*?)\]\]></{0}>'.format(key),content) if not pm:
if pm: return pm.group(1) pm = re.search(
'<{0}><\!\[CDATA\[(.*?)\]\]></{0}>'.format(key), content)
if pm:
return pm.group(1)
return '未知' return '未知'
class UnicodeStreamFilter: class UnicodeStreamFilter:
def __init__(self, target): def __init__(self, target):
self.target = target self.target = target
self.encoding = 'utf-8' self.encoding = 'utf-8'