diff --git a/itchat/components/contact.py b/itchat/components/contact.py index a4c8c944..a529c66d 100644 --- a/itchat/components/contact.py +++ b/itchat/components/contact.py @@ -274,6 +274,8 @@ def _get_contact(seq=0): r = self.s.get(url, headers=headers) except: logger.info('Failed to fetch contact, that may because of the amount of your chatrooms') + for chatroom in self.get_chatrooms(): + self.update_chatroom(chatroom['UserName'], detailedMember=True) return 0, [] j = json.loads(r.content.decode('utf-8', 'replace')) return j.get('Seq', 0), j.get('MemberList') diff --git a/itchat/components/hotreload.py b/itchat/components/hotreload.py index 7b65c157..4e203ebb 100644 --- a/itchat/components/hotreload.py +++ b/itchat/components/hotreload.py @@ -55,6 +55,7 @@ def load_login_status(self, fileDir, msgList, contactList = self.get_msg() if (msgList or contactList) is None: self.logout() + load_last_login_status(self.s, j['cookies']) logger.debug('server refused, loading login status failed.') return ReturnValue({'BaseResponse': { 'ErrMsg': 'server refused, loading login status failed.', @@ -76,3 +77,20 @@ def load_login_status(self, fileDir, return ReturnValue({'BaseResponse': { 'ErrMsg': 'loading login status succeeded.', 'Ret': 0, }}) + +def load_last_login_status(session, cookiesDict): + try: + session.cookies = requests.utils.cookiejar_from_dict({ + 'webwxuvid': cookiesDict['webwxuvid'], + 'webwx_auth_ticket': cookiesDict['webwx_auth_ticket'], + 'login_frequency': '2', + 'last_wxuin': cookiesDict['wxuin'], + 'wxloadtime': cookiesDict['wxloadtime'] + '_expired', + 'wxpluginkey': cookiesDict['wxloadtime'], + 'wxuin': cookiesDict['wxuin'], + 'mm_lang': 'zh_CN', + 'MM_WX_NOTIFY_STATE': '1', + 'MM_WX_SOUND_STATE': '1', }) + except: + logger.info('Load status for push login failed, we may have experienced a cookies change.') + logger.info('If you are using the newest version of itchat, you may report a bug.') diff --git a/itchat/components/login.py b/itchat/components/login.py index 759028dc..3bba665c 100644 --- a/itchat/components/login.py +++ b/itchat/components/login.py @@ -31,13 +31,15 @@ def login(self, enableCmdQR=False, picDir=None, qrCallback=None, logger.warning('itchat has already logged in.') return while 1: - logger.info('Getting uuid of QR code.') - while not self.get_QRuuid(): - time.sleep(1) - logger.info('Downloading QR code.') - qrStorage = self.get_QR(enableCmdQR=enableCmdQR, - picDir=picDir, qrCallback=qrCallback) - logger.info('Please scan the QR code to log in.') + uuid = push_login(self) + if not uuid: + logger.info('Getting uuid of QR code.') + while not self.get_QRuuid(): + time.sleep(1) + logger.info('Downloading QR code.') + qrStorage = self.get_QR(enableCmdQR=enableCmdQR, + picDir=picDir, qrCallback=qrCallback) + logger.info('Please scan the QR code to log in.') isLoggedIn = False while not isLoggedIn: status = self.check_login() @@ -53,7 +55,8 @@ def login(self, enableCmdQR=False, picDir=None, qrCallback=None, break if isLoggedIn: break - logger.info('Log in time out, reloading QR code') + logger.info('Log in time out, reloading QR code.') + logger.info('Loading the contact, this may take a little while.') self.web_init() self.show_mobile_login() self.get_contact(True) @@ -66,6 +69,18 @@ def login(self, enableCmdQR=False, picDir=None, qrCallback=None, logger.info('Login successfully as %s' % self.storageClass.nickName) self.start_receiving(exitCallback) +def push_login(core): + cookiesDict = core.s.cookies.get_dict() + if 'wxuin' in cookiesDict: + url = '%s/cgi-bin/mmwebwx-bin/webwxpushloginurl?uin=%s' % ( + config.BASE_URL, cookiesDict['wxuin']) + headers = { 'User-Agent' : config.USER_AGENT } + r = core.s.get(url, headers=headers).json() + if 'uuid' in r and r.get('ret') in (0, '0'): + core.uuid = r['uuid'] + return r['uuid'] + return False + def get_QRuuid(self): url = '%s/jslogin' % config.BASE_URL params = { @@ -168,6 +183,22 @@ def web_init(self): for item in dic['SyncKey']['List']]) self.storageClass.userName = dic['User']['UserName'] self.storageClass.nickName = dic['User']['NickName'] + # deal with contact list returned when init + contactList = dic.get('ContactList', []) + chatroomList, otherList = [], [] + for m in contactList: + if m['Sex'] != 0: + otherList.append(m) + elif '@@' in m['UserName']: + m['MemberList'] = [] # don't let dirty info pollute the list + chatroomList.append(m) + elif '@' in m['UserName']: + # mp will be dealt in update_local_friends as well + otherList.append(m) + if chatroomList: + update_local_chatrooms(self, chatroomList) + if otherList: + update_local_friends(self, otherList) return dic def show_mobile_login(self): @@ -195,12 +226,13 @@ def maintain_loop(): if i is None: self.alive = False elif i == '0': - continue + pass else: msgList, contactList = self.get_msg() if msgList: msgList = produce_msg(self, msgList) - for msg in msgList: self.msgList.put(msg) + for msg in msgList: + self.msgList.put(msg) if contactList: chatroomList, otherList = [], [] for contact in contactList: diff --git a/itchat/components/messages.py b/itchat/components/messages.py index 260d16b6..5c685140 100644 --- a/itchat/components/messages.py +++ b/itchat/components/messages.py @@ -198,6 +198,9 @@ def produce_group_chat(core, msg): content = msg['Content'] chatroomUserName = msg['ToUserName'] else: + msg['ActualUserName'] = core.storageClass.userName + msg['ActualNickName'] = core.storageClass.nickName + msg['isAt'] = False return chatroom = core.storageClass.search_chatrooms(userName=chatroomUserName) member = utils.search_dict_list((chatroom or {}).get( diff --git a/itchat/config.py b/itchat/config.py index c05fbd60..41c7e7df 100644 --- a/itchat/config.py +++ b/itchat/config.py @@ -1,9 +1,9 @@ import os, platform -VERSION = '1.2.27' +VERSION = '1.2.28' BASE_URL = 'https://login.weixin.qq.com' OS = platform.system() #Windows, Linux, Darwin DIR = os.getcwd() -DEFAULT_QR = 'QR.jpg' +DEFAULT_QR = 'QR.png' USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36' diff --git a/itchat/core.py b/itchat/core.py index 3ce410d0..9866fc4d 100644 --- a/itchat/core.py +++ b/itchat/core.py @@ -54,7 +54,7 @@ def login(self, enableCmdQR=False, picDir=None, qrCallback=None, it is defined in components/login.py and of course every single move in login can be called outside - you may scan source code to see how - - and modified according to your own demond + - and modified according to your own demand ''' raise NotImplementedError() def get_QRuuid(self):