mirror of
https://github.com/littlecodersh/ItChat.git
synced 2026-10-29 05:46:59 +08:00
521 lines
26 KiB
Python
521 lines
26 KiB
Python
import os, sys
|
|
import requests, time, re
|
|
import thread, subprocess
|
|
import json, xml.dom.minidom, mimetypes
|
|
from urllib import unquote
|
|
import config, storage, out, log, tools
|
|
|
|
try:
|
|
from plugin.QRCode import QRCode
|
|
CMD_QRCODE = True
|
|
except:
|
|
CMD_QRCODE = False
|
|
|
|
BASE_URL = config.BASE_URL
|
|
DEBUG = False
|
|
|
|
class WeChatClient:
|
|
def __init__(self, storageClass = None, robot = False):
|
|
self.storageClass = storageClass if storageClass else storage.Storage()
|
|
self.robot = robot
|
|
self.msgList = self.storageClass.msgList
|
|
self.loginInfo = {}
|
|
self.s = requests.Session()
|
|
self.uuid = None
|
|
def login(self):
|
|
for get_count in range(10):
|
|
out.print_line('Getting uuid', True)
|
|
while self.get_QRuuid(): time.sleep(1)
|
|
out.print_line('Getting QR Code', True)
|
|
if self.get_QR():
|
|
break
|
|
elif get_count >= 9:
|
|
out.print_line('Failed to get QR Code, please restart the program')
|
|
sys.exit()
|
|
out.print_line('Please scan the QR Code', True)
|
|
while self.check_login(): time.sleep(1)
|
|
self.web_init()
|
|
self.show_mobile_login()
|
|
while 1:
|
|
voidUserList = self.get_contract()
|
|
if not voidUserList: break
|
|
out.print_line('These uses need new RemarkNames and are added to a group', True)
|
|
chatRoomName = self.create_chatroom(voidUserList, 'RemarkNames')
|
|
self.delete_member(chatRoomName, [voidUserList[0]])
|
|
self.add_member(chatRoomName, [voidUserList[0]])
|
|
while raw_input('Enter "ready" after you rename all of them and DELETE the group: ') != 'ready': pass
|
|
out.print_line('Start reload contract list', False)
|
|
out.print_line('Login successfully as %s\n'%(
|
|
self.storageClass.find_nickname(self.storageClass.userName)), False)
|
|
log.log('SIGN IN', True)
|
|
thread.start_new_thread(self.maintain_loop, ())
|
|
def get_QRuuid(self):
|
|
url = '%s/jslogin'%BASE_URL
|
|
payloads = {
|
|
'appid': 'wx782c26e4c19acffb',
|
|
'fun': 'new',
|
|
}
|
|
r = self.s.get(url, params = payloads)
|
|
|
|
regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)";'
|
|
data = re.search(regx, r.text)
|
|
if data and data.group(1) == '200': self.uuid = data.group(2);return False
|
|
def get_QR(self):
|
|
try:
|
|
url = '%s/qrcode/%s'%(BASE_URL, self.uuid)
|
|
r = self.s.get(url, stream = True)# params = payloads, headers = HEADER,
|
|
QR_DIR = os.path.join(config.QR_DIR, 'QR.jpg')
|
|
with open(QR_DIR, 'wb') as f: f.write(r.content)
|
|
if CMD_QRCODE:
|
|
q = QRCode(QR_DIR, 37, 3, 'BLACK')
|
|
q.print_qr()
|
|
elif config.OS == 'Darwin':
|
|
subprocess.call(['open', QR_DIR])
|
|
elif config.OS == 'Linux':
|
|
subprocess.call(['xdg-open', QR_DIR])
|
|
else:
|
|
os.startfile(QR_DIR)
|
|
return True
|
|
except:
|
|
return False
|
|
def check_login(self):
|
|
url = '%s/cgi-bin/mmwebwx-bin/login'%BASE_URL
|
|
# add tip so that we can get many reply, use string payloads to avoid auto-urlencode
|
|
payloads = 'tip=1&uuid=%s&_=%s'%(self.uuid, int(time.time()))
|
|
r = self.s.get(url, params = payloads)
|
|
regx = r'window.code=(\d+)'
|
|
data = re.search(regx, r.text)
|
|
if data and data.group(1) == '200':
|
|
regx = r'window.redirect_uri="(\S+)";'
|
|
self.loginInfo['url'] = re.search(regx, r.text).group(1)
|
|
r = self.s.get(self.loginInfo['url'], allow_redirects=False)
|
|
self.loginInfo['url'] = self.loginInfo['url'][:self.loginInfo['url'].rfind('/')]
|
|
self.get_login_info(r.text)
|
|
tools.clear_screen()
|
|
return False
|
|
if data and data.group(1) == '201':
|
|
tools.clear_screen()
|
|
out.print_line('Please press confirm', True)
|
|
if data and data.group(1) == '408':
|
|
tools.clear_screen()
|
|
out.print_line('Reloading QR Code\n', True)
|
|
while 1:
|
|
while self.get_QRuuid(): time.sleep(1)
|
|
if self.get_QR(): break
|
|
return True
|
|
def get_login_info(self, s):
|
|
self.loginInfo['BaseRequest'] = {}
|
|
for node in xml.dom.minidom.parseString(s).documentElement.childNodes:
|
|
if node.nodeName == 'skey':
|
|
self.loginInfo['skey'] = self.loginInfo['BaseRequest']['Skey'] = node.childNodes[0].data.encode('utf8')
|
|
elif node.nodeName == 'wxsid':
|
|
self.loginInfo['wxsid'] = self.loginInfo['BaseRequest']['Sid'] = node.childNodes[0].data.encode('utf8')
|
|
elif node.nodeName == 'wxuin':
|
|
self.loginInfo['wxuin'] = self.loginInfo['BaseRequest']['Uin'] = node.childNodes[0].data.encode('utf8')
|
|
elif node.nodeName == 'pass_ticket':
|
|
self.loginInfo['pass_ticket'] = self.loginInfo['BaseRequest']['DeviceID'] = node.childNodes[0].data.encode('utf8')
|
|
def web_init(self):
|
|
url = '%s/webwxinit?r=%s' % (self.loginInfo['url'], int(time.time()))
|
|
payloads = {
|
|
'BaseRequest': self.loginInfo['BaseRequest']
|
|
}
|
|
headers = { 'ContentType': 'application/json; charset=UTF-8' }
|
|
r = self.s.post(url, data = json.dumps(payloads), headers = headers)
|
|
dic = json.loads(r.content.decode('utf-8', 'replace'))
|
|
# deal with emoji
|
|
dic['User'] = tools.emoji_dealer([dic['User']])[0]
|
|
self.storageClass.userName = dic['User']['UserName']
|
|
self.storageClass.nickName = dic['User']['NickName']
|
|
self.storageClass.load_sql_storage()
|
|
self.storageClass.update_user(dic['User']['PYQuanPin'] or dic['User']['NickName'],
|
|
NickName = dic['User']['NickName'], UserName = dic['User']['UserName'])
|
|
self.loginInfo['SyncKey'] = dic['SyncKey']
|
|
self.loginInfo['synckey'] = '|'.join(['%s_%s' % (item['Key'], item['Val']) for item in dic['SyncKey']['List']])
|
|
def get_batch_contract(self, userName):
|
|
url = '%s/webwxbatchgetcontact?type=ex&r=%s' % (self.loginInfo['url'], int(time.time()))
|
|
headers = { 'ContentType': 'application/json; charset=UTF-8' }
|
|
payloads = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'Count': 1,
|
|
'List': [{
|
|
'UserName': userName,
|
|
'ChatRoomId': '', }], }
|
|
r = self.s.post(url, data = json.dumps(payloads), headers = headers)
|
|
return json.loads(r.content.decode('utf-8', 'replace'))['ContactList'][0]['MemberList']
|
|
def get_contract(self):
|
|
url = '%s/webwxgetcontact?r=%s&seq=0&skey=%s' % (self.loginInfo['url'],
|
|
int(time.time()), self.loginInfo['skey'])
|
|
headers = { 'ContentType': 'application/json; charset=UTF-8' }
|
|
r = self.s.get(url, headers = headers)
|
|
memberList = json.loads(r.content.decode('utf-8', 'replace'))['MemberList']
|
|
while 1:
|
|
i = 0
|
|
for m in memberList:
|
|
if m['Sex'] != 0 or (m['VerifyFlag'] & 8 == 0 and '@' in m['UserName'] and not '@@' in m['UserName'] and
|
|
any([str(n) in m['UserName'] for n in range(10)]) and any([chr(n) in m['UserName'] for n in (
|
|
range(ord('a'), ord('z') + 1) + range(ord('A'), ord('Z') + 1))])): continue
|
|
memberList.remove(m);i+=1
|
|
if i == 0: break
|
|
# deal with emoji
|
|
memberList = tools.emoji_dealer(memberList)
|
|
# RemarkPYQuanPin & PYQuanPin is used as identifier
|
|
voidUserList = []
|
|
validUserList = []
|
|
unknownCount = 0
|
|
for m in memberList:
|
|
if m['RemarkPYQuanPin'] != '': m['PYQuanPin'] = m['RemarkPYQuanPin']
|
|
if m['PYQuanPin'] == '' and m['Alias'] != '': m['PYQuanPin'] == m['Alias']
|
|
if m['UserName'] == self.storageClass.userName:
|
|
m['PYQuanPin'] = m['NickName']
|
|
elif m['PYQuanPin'] == '':
|
|
voidUserList.append(m)
|
|
m['PYQuanPin'] = '@Unknown%s'%unknownCount
|
|
unknownCount += 1
|
|
while 1:
|
|
insertResult = self.storageClass.update_user(m['PYQuanPin'], NickName = m['RemarkName'] or m['NickName'],
|
|
UserName = m['UserName'])
|
|
if insertResult and not m['PYQuanPin'] in validUserList:
|
|
validUserList.append(m['PYQuanPin']);break
|
|
else:
|
|
voidUserList.append(m)
|
|
m['PYQuanPin'] = '@Unknown%s'%unknownCount
|
|
unknownCount += 1
|
|
if DEBUG:
|
|
with open('MemberList.txt', 'w') as f: f.write(str(memberList))
|
|
if len(voidUserList) == 1:
|
|
m = voidUserList[0]
|
|
self.storageClass.update_user('', NickName = m['RemarkName'] or m['NickName'], UserName = m['UserName'])
|
|
return []
|
|
else:
|
|
return voidUserList
|
|
def show_mobile_login(self):
|
|
url = '%s/webwxstatusnotify'%self.loginInfo['url']
|
|
payloads = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'Code': 3,
|
|
'FromUserName': self.storageClass.userName,
|
|
'ToUserName': self.storageClass.userName,
|
|
'ClientMsgId': int(time.time()),
|
|
}
|
|
headers = { 'ContentType': 'application/json; charset=UTF-8' }
|
|
r = self.s.post(url, data = json.dumps(payloads), headers = headers)
|
|
def maintain_loop(self):
|
|
i = self.sync_check()
|
|
count = 0
|
|
pauseTime = 1
|
|
while i and count <4:
|
|
try:
|
|
if pauseTime < 5: pauseTime += 2
|
|
if i != '0': msgList = self.get_msg()
|
|
if msgList:
|
|
msgList = self.produce_msg(msgList)
|
|
self.store_msg(msgList)
|
|
pauseTime = 1
|
|
time.sleep(pauseTime)
|
|
i = self.sync_check()
|
|
count = 0
|
|
except Exception, e:
|
|
count += 1
|
|
log.log('Exception %s:'%count, False, exception = e)
|
|
time.sleep(count*3)
|
|
log.log('LOG OUT', False)
|
|
def sync_check(self):
|
|
url = '%s/synccheck'%self.loginInfo['url']
|
|
payloads = {
|
|
'r': int(time.time()),
|
|
'skey': self.loginInfo['skey'],
|
|
'sid': self.loginInfo['wxsid'],
|
|
'uin': self.loginInfo['wxuin'],
|
|
'deviceid': self.loginInfo['pass_ticket'],
|
|
'synckey': self.loginInfo['synckey'],
|
|
}
|
|
r = self.s.get(url, params = payloads)
|
|
|
|
regx = r'window.synccheck={retcode:"(\d+)",selector:"(\d+)"}'
|
|
pm = re.search(regx, r.text)
|
|
|
|
if pm.group(1) != '0' : return None
|
|
return pm.group(2)
|
|
def get_msg(self):
|
|
url = '%s/webwxsync?sid=%s&skey=%s'%(
|
|
self.loginInfo['url'], self.loginInfo['wxsid'], self.loginInfo['skey'])
|
|
payloads = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'SyncKey': self.loginInfo['SyncKey'],
|
|
'rr': int(time.time()), }
|
|
headers = { 'ContentType': 'application/json; charset=UTF-8' }
|
|
r = self.s.post(url, data = json.dumps(payloads), headers = headers)
|
|
|
|
dic = json.loads(r.content.decode('utf-8', 'replace'))
|
|
self.loginInfo['SyncKey'] = dic['SyncKey']
|
|
if dic['AddMsgCount'] != 0: return dic['AddMsgList']
|
|
def produce_msg(self, l):
|
|
rl = []
|
|
srl = [51, 53] # 51 messy code, 53 webwxvoipnotifymsg
|
|
for m in l:
|
|
if m['MsgType'] == 1: # words
|
|
if m['Url']:
|
|
regx = r'(.+?\(.+?\))'
|
|
data = re.search(regx, m['Content'])
|
|
msg = {
|
|
'MsgType': 'Map',
|
|
'FromUserName': m['FromUserName'],
|
|
'ToUserName': m['ToUserName'],
|
|
'Content': data.group(1),}
|
|
else:
|
|
msg = {
|
|
'MsgType': 'Text',
|
|
'FromUserName': m['FromUserName'],
|
|
'ToUserName': m['ToUserName'],
|
|
'Content': m['Content'],}
|
|
elif m['MsgType'] == 3 or m['MsgType'] == 47: # picture
|
|
pic_dir = os.path.join(config.PIC_DIR, '%s.jpg'%int(time.time()))
|
|
msg = {
|
|
'MsgType': 'Picture',
|
|
'FromUserName': m['FromUserName'],
|
|
'ToUserName': m['ToUserName'],
|
|
'Content': pic_dir,}
|
|
url = '%s/webwxgetmsgimg'%self.loginInfo['url']
|
|
payloads = {
|
|
'MsgID': m['NewMsgId'],
|
|
'skey': self.loginInfo['skey'],}
|
|
r = self.s.get(url, params = payloads, stream = True)
|
|
with open(pic_dir, 'wb') as f:
|
|
for block in r.iter_content(1024):
|
|
f.write(block)
|
|
elif m['MsgType'] == 34: # voice
|
|
rec_dir = os.path.join(config.REC_DIR, '%s.mp3'%int(time.time()))
|
|
msg = {
|
|
'MsgType': 'Recording',
|
|
'FromUserName': m['FromUserName'],
|
|
'ToUserName': m['ToUserName'],
|
|
'Content': rec_dir,}
|
|
url = '%s/webwxgetvoice'%self.loginInfo['url']
|
|
payloads = {
|
|
'msgid': m['NewMsgId'],
|
|
'skey': self.loginInfo['skey'],}
|
|
r = self.s.get(url, params = payloads, stream = True)
|
|
with open(rec_dir, 'wb') as f:
|
|
for block in r.iter_content(1024):
|
|
f.write(block)
|
|
elif m['MsgType'] == 37: # friends
|
|
self.add_friend(m['Status'], m['RecommendInfo']['UserName'], m['Ticket'])
|
|
self.get_contract()
|
|
self.send_msg(m['RecommendInfo']['UserName'], config.WELCOME_WORDS)
|
|
continue
|
|
elif m['MsgType'] == 42: # name card
|
|
msg = {
|
|
'MsgType': 'Card',
|
|
'FromUserName': m['FromUserName'],
|
|
'ToUserName': m['ToUserName'],
|
|
'Content': m['RecommendInfo']['NickName'],}
|
|
elif m['MsgType'] == 49: # sharing
|
|
msg = {
|
|
'MsgType': 'Sharing',
|
|
'FromUserName': m['FromUserName'],
|
|
'ToUserName': m['ToUserName'],
|
|
'Content': m['FileName'],}
|
|
if m['AppMsgType'] == 2000:
|
|
msg['MsgType'] = 'Note'
|
|
regx = r'\[CDATA\[(.+?)\].+?\[CDATA\[(.+?)\]'
|
|
data = re.search(regx, m['Content'])
|
|
msg['Content'] = data.group(2)
|
|
elif m['AppMsgType'] == 6:
|
|
msg['MsgType'] = 'Attachment'
|
|
cookiesList = {name:data for name,data in self.s.cookies.items()}
|
|
url = 'https://file2.wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia'
|
|
payloads = {
|
|
'sender': m['FromUserName'],
|
|
'mediaid': m['MediaId'],
|
|
'filename': m['FileName'],
|
|
'fromuser': self.loginInfo['wxuin'],
|
|
'pass_ticket': 'undefined',
|
|
'webwx_data_ticket': cookiesList['webwx_data_ticket'],}
|
|
r = self.s.get(url, params = payloads, stream = True)
|
|
att_dir = os.path.join(config.ATT_DIR, '%s-%s'%(int(time.time()), m['FileName'],))
|
|
msg['Location'] = att_dir
|
|
with open(att_dir, 'wb') as f:
|
|
for block in r.iter_content(1024):
|
|
f.write(block)
|
|
else:
|
|
pass
|
|
elif m['MsgType'] == 62: # tiny video
|
|
vid_dir = os.path.join(config.VID_DIR, '%s.mp4'%int(time.time()))
|
|
msg = {
|
|
'MsgType': 'Video',
|
|
'FromUserName': m['FromUserName'],
|
|
'ToUserName': m['ToUserName'],
|
|
'Content': vid_dir,}
|
|
url = '%s/webwxgetvideo'%self.loginInfo['url']
|
|
payloads = {
|
|
'msgid': m['MsgId'],
|
|
'skey': self.loginInfo['skey'],}
|
|
headers = { 'Range:': 'bytes=0-'}
|
|
r = self.s.get(url, params = payloads, headers = headers, stream = True)
|
|
with open(vid_dir, 'wb') as f:
|
|
for chunk in r.iter_content(chunk_size = 1024):
|
|
if chunk:
|
|
f.write(chunk)
|
|
f.flush()
|
|
os.fsync(f.fileno())
|
|
elif m['MsgType'] == 10000:
|
|
msg = {
|
|
'MsgType': 'Note',
|
|
'FromUserName': self.storageClass.userName,
|
|
'Content': m['Content'],}
|
|
elif m['MsgType'] in srl:
|
|
continue
|
|
else:
|
|
log.log('MsgType Unknown: %s\n%s'%(m['MsgType'], str(m)), False)
|
|
srl.append(m['MsgType'])
|
|
continue
|
|
rl.append(msg)
|
|
return rl
|
|
def store_msg(self, l):
|
|
for m in l:
|
|
if m['FromUserName'] == self.storageClass.userName: continue
|
|
if '@@' in m['FromUserName']:
|
|
if not self.robot: break
|
|
self.msgList.append(m)
|
|
elif self.storageClass.find_nickname(m['FromUserName']):
|
|
self.msgList.append(m if self.robot else '%s: %s'%(self.storageClass.find_nickname(m['FromUserName']), m['Content']))
|
|
self.storageClass.store_msg(m['FromUserName'], m['Content'], 'from')
|
|
def send_msg(self, toUserName = None, msg = 'Test Message'):
|
|
if self.storageClass.find_user(toUserName): toUserName = self.storageClass.find_user(toUserName)
|
|
url = '%s/webwxsendmsg'%self.loginInfo['url']
|
|
payloads = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'Msg': {
|
|
'Type': 1,
|
|
'Content': msg.encode('utf8') if isinstance(msg, unicode) else msg,
|
|
'FromUserName': self.storageClass.userName.encode('utf8'),
|
|
'ToUserName': (toUserName if toUserName else self.storageClass.userName).encode('utf8'),
|
|
'LocalID': int(time.time()),
|
|
'ClientMsgId': int(time.time()),
|
|
},
|
|
}
|
|
headers = { 'ContentType': 'application/json; charset=UTF-8' }
|
|
r = self.s.post(url, data = json.dumps(payloads, ensure_ascii = False), headers = headers)
|
|
self.storageClass.store_msg(toUserName, msg, 'to') #encoding problems
|
|
def upload_file(self, fileDir, isPicture = False):
|
|
url = 'https://file%s.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json'%('2' if '2' in self.loginInfo['url'] else '')
|
|
# save it on server
|
|
fileSize = str(os.path.getsize(fileDir))
|
|
cookiesList = {name:data for name,data in self.s.cookies.items()}
|
|
fileType = mimetypes.guess_type(fileDir)[0] or 'application/octet-stream'
|
|
files = {
|
|
'id': (None, 'WU_FILE_0'),
|
|
'name': (None, os.path.basename(fileDir)),
|
|
'type': (None, fileType),
|
|
'lastModifiedDate': (None, time.strftime('%a %b %d %Y %H:%M:%S GMT+0800 (CST)')),
|
|
'size': (None, fileSize),
|
|
'mediatype': (None, 'pic' if isPicture else 'doc'),
|
|
'uploadmediarequest': (None, json.dumps({
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'ClientMediaId': int(time.time()),
|
|
'TotalLen': fileSize,
|
|
'StartPos': 0,
|
|
'DataLen': fileSize,
|
|
'MediaType': 4,
|
|
}, separators = (',', ':'))),
|
|
'webwx_data_ticket': (None, cookiesList['webwx_data_ticket']),
|
|
'pass_ticket': (None, 'undefined'),
|
|
'filename' : (os.path.basename(fileDir), open(fileDir, 'rb'), fileType),
|
|
}
|
|
headers = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36', }
|
|
r = self.s.post(url, files = files, headers = headers)
|
|
return json.loads(r.text)['MediaId']
|
|
def send_file(self, fileDir, toUserName):
|
|
mediaId = self.upload_file(fileDir)
|
|
url = '%s/webwxsendappmsg?fun=async&f=json'%self.loginInfo['url']
|
|
payloads = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'Msg': {
|
|
'Type': 6,
|
|
'Content': ("<appmsg appid='wxeb7ec651dd0aefa9' sdkver=''><title>%s</title>"%os.path.basename(fileDir) +
|
|
"<des></des><action></action><type>6</type><content></content><url></url><lowurl></lowurl>" +
|
|
"<appattach><totallen>%s</totallen><attachid>%s</attachid>"%(str(os.path.getsize(fileDir)), mediaId) +
|
|
"<fileext>%s</fileext></appattach><extinfo></extinfo></appmsg>"%os.path.splitext(fileDir)[1].replace('.','')
|
|
).encode('utf8'),
|
|
'FromUserName': self.storageClass.userName.encode('utf8'),
|
|
'ToUserName': toUserName.encode('utf8'),
|
|
'LocalID': str(time.time() * 1e7),
|
|
'ClientMsgId': str(time.time() * 1e7), }, }
|
|
headers = {
|
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36',
|
|
'Content-Type': 'application/json;charset=UTF-8', }
|
|
r = self.s.post(url, data = json.dumps(payloads, ensure_ascii = False), headers = headers)
|
|
def send_image(self, fileDir, toUserName):
|
|
mediaId = self.upload_file(fileDir, isPicture = not fileDir[-4:] == '.gif')
|
|
url = '%s/webwxsendmsgimg?fun=async&f=json'%self.loginInfo['url']
|
|
payloads = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'Msg': {
|
|
'Type': 3,
|
|
'MediaId': mediaId,
|
|
'FromUserName': self.storageClass.userName.encode('utf8'),
|
|
'ToUserName': toUserName.encode('utf8'),
|
|
'LocalID': str(time.time() * 1e7),
|
|
'ClientMsgId': str(time.time() * 1e7), }, }
|
|
if fileDir[-4:] == '.gif':
|
|
url = '%s/webwxsendemoticon?fun=sys'%self.loginInfo['url']
|
|
payloads['Msg']['Type'] = 47
|
|
payloads['Msg']['EmojiFlag'] = 2
|
|
headers = {
|
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36',
|
|
'Content-Type': 'application/json;charset=UTF-8', }
|
|
r = self.s.post(url, data = json.dumps(payloads, ensure_ascii = False), headers = headers)
|
|
def add_friend(self, Status, UserName, Ticket):
|
|
url = '%s/webwxverifyuser?r=%s&pass_ticket=%s'%(self.loginInfo['url'], int(time.time()), self.loginInfo['pass_ticket'])
|
|
payloads = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'Opcode': Status,
|
|
'VerifyUserListSize': 1,
|
|
'VerifyUserList': [{
|
|
'Value': UserName,
|
|
'VerifyUserTicket': Ticket,
|
|
}],
|
|
'VerifyContent': '',
|
|
'SceneListCount': 1,
|
|
'SceneList': 33,
|
|
'skey': self.loginInfo['skey'],}
|
|
headers = { 'ContentType': 'application/json; charset=UTF-8' }
|
|
r = self.s.post(url, data = json.dumps(payloads), headers = headers)
|
|
def create_chatroom(self, memberList, topic = ''):
|
|
url = ('%s/webwxcreatechatroom?pass_ticket=%s&r=%s'%(
|
|
self.loginInfo['url'], self.loginInfo['pass_ticket'], int(time.time())))
|
|
params = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'MemberCount': len(memberList),
|
|
'MemberList': [{'UserName': member['UserName']} for member in memberList],
|
|
'Topic': topic, }
|
|
headers = {'content-type': 'application/json; charset=UTF-8'}
|
|
|
|
r = self.s.post(url, data=json.dumps(params),headers=headers)
|
|
dic = json.loads(r.content.decode('utf8', 'replace'))
|
|
return dic['ChatRoomName']
|
|
def delete_member(self, chatRoomName, memberList):
|
|
url = ('%s/webwxupdatechatroom?fun=delmember&pass_ticket=%s'%(
|
|
self.loginInfo['url'], self.loginInfo['pass_ticket']))
|
|
params = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'ChatRoomName': chatRoomName,
|
|
'DelMemberList': ','.join([member['UserName'] for member in memberList]),}
|
|
headers = {'content-type': 'application/json; charset=UTF-8'}
|
|
r = self.s.post(url, data=json.dumps(params),headers=headers)
|
|
def add_member(self, chatRoomName, memberList):
|
|
url = ('%s/webwxupdatechatroom?fun=addmember&pass_ticket=%s'%(
|
|
self.loginInfo['url'], self.loginInfo['pass_ticket']))
|
|
params = {
|
|
'BaseRequest': self.loginInfo['BaseRequest'],
|
|
'ChatRoomName': chatRoomName,
|
|
'AddMemberList': ','.join([member['UserName'] for member in memberList]),}
|
|
headers = {'content-type': 'application/json; charset=UTF-8'}
|
|
r = self.s.post(url, data=json.dumps(params),headers=headers)
|
|
def storage(self):
|
|
return self.msgList
|
|
|
|
if __name__ == '__main__':
|
|
wcc = WeChatClient()
|
|
wcc.login()
|