Skip to content

Commit c30ae9a

Browse files
committed
Enhanced pkl storage & add qrCallback & fix contact self bug
1 parent 015639c commit c30ae9a

File tree

7 files changed

+69
-37
lines changed

7 files changed

+69
-37
lines changed

itchat/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
from .core import Core
21
from . import content
2+
from .core import Core
3+
from .config import VERSION
34
from .log import set_logging
45

5-
__version__ = '1.2.9'
6+
__version__ = VERSION
67

78
instanceList = []
89

itchat/components/contact.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ def update_local_chatrooms(core, l):
118118
for member in chatroom['MemberList']:
119119
utils.emoji_formatter(member, 'NickName')
120120
utils.emoji_formatter(member, 'DisplayName')
121-
if core.storageClass.userName == member['UserName']:
122-
chatroom['self'] = member
123121
# update it to old chatrooms
124122
oldChatroom = utils.search_dict_list(
125123
core.chatroomList, 'UserName', chatroom['UserName'])
@@ -149,6 +147,10 @@ def update_local_chatrooms(core, l):
149147
oldChatroom['OwnerUin'] == int(core.loginInfo['wxuin'])
150148
else:
151149
oldChatroom['isAdmin'] = None
150+
# - update self
151+
newSelf = utils.search_dict_list(oldChatroom['MemberList'],
152+
'UserName', core.storageClass.userName)
153+
oldChatroom['self'] = newSelf or copy.deepcopy(core.loginInfo['User'])
152154
return {
153155
'Type' : 'System',
154156
'Text' : [chatroom['UserName'] for chatroom in l],

itchat/components/hotreload.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import requests
55

6+
from ..config import VERSION
67
from ..returnvalues import ReturnValue
78
from .contact import update_local_chatrooms
89
from .messages import produce_msg
@@ -22,6 +23,7 @@ def dump_login_status(self, fileDir=None):
2223
except:
2324
raise Exception('Incorrect fileDir')
2425
status = {
26+
'version' : VERSION,
2527
'loginInfo' : self.loginInfo,
2628
'cookies' : self.s.cookies.get_dict(),
2729
'storage' : self.storageClass.dumps()}
@@ -40,6 +42,13 @@ def load_login_status(self, fileDir,
4042
'ErrMsg': 'No such file, loading login status failed.',
4143
'Ret': -1002, }})
4244

45+
if j.get('version', '') != VERSION:
46+
logger.debug(('you have updated itchat from %s to %s, ' +
47+
'so cached status is ignored') % (
48+
j.get('version', 'old version'), VERSION))
49+
return ReturnValue({'BaseResponse': {
50+
'ErrMsg': 'cached status ignored because of version',
51+
'Ret': -1005, }})
4352
self.loginInfo = j['loginInfo']
4453
self.s.cookies = requests.utils.cookiejar_from_dict(j['cookies'])
4554
self.storageClass.loads(j['storage'])

itchat/components/login.py

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import os, sys, time, re
1+
import os, sys, time, re, io
22
import threading
33
import json, xml.dom.minidom
44
import copy, pickle, random
@@ -24,7 +24,7 @@ def load_login(core):
2424
core.get_msg = get_msg
2525
core.logout = logout
2626

27-
def login(self, enableCmdQR=False, picDir=None,
27+
def login(self, enableCmdQR=False, picDir=None, qrCallback=None,
2828
loginCallback=None, exitCallback=None):
2929
if self.alive:
3030
logger.debug('itchat has already logged in.')
@@ -34,19 +34,28 @@ def login(self, enableCmdQR=False, picDir=None,
3434
logger.info('Getting uuid of QR code.')
3535
while not self.get_QRuuid(): time.sleep(1)
3636
logger.info('Downloading QR code.')
37-
if self.get_QR(enableCmdQR=enableCmdQR, picDir=picDir):
37+
qrStorage = self.get_QR(enableCmdQR=enableCmdQR,
38+
picDir=picDir, qrCallback=qrCallback)
39+
if qrStorage:
3840
break
3941
elif 9 == getCount:
4042
logger.info('Failed to get QR code, please restart the program.')
4143
sys.exit()
4244
logger.info('Please scan the QR code to log in.')
43-
status = self.check_login()
44-
if status == '201':
45-
logger.info('Please press confirm on your phone.')
46-
while status == '201':
47-
status = self.check_login()
48-
time.sleep(1)
49-
if status == '200': break
45+
isLoggedIn = False
46+
while not isLoggedIn:
47+
status = self.check_login()
48+
if hasattr(qrCallback, '__call__'):
49+
qrCallback(uuid=self.uuid, status=status, qrcode=qrStorage.getvalue())
50+
if status == '200':
51+
isLoggedIn = True
52+
elif status == '201':
53+
if isLoggedIn is not None:
54+
logger.info('Please press confirm on your phone.')
55+
isLoggedIn = None
56+
elif status != '408':
57+
break
58+
if isLoggedIn: break
5059
logger.info('Log in time out, reloading QR code')
5160
self.web_init()
5261
self.show_mobile_login()
@@ -72,39 +81,43 @@ def get_QRuuid(self):
7281
self.uuid = data.group(2)
7382
return self.uuid
7483

75-
def get_QR(self, uuid=None, enableCmdQR=False, picDir=None):
84+
def get_QR(self, uuid=None, enableCmdQR=False, picDir=None, qrCallback=None):
85+
uuid = uuid or self.uuid
86+
picDir = picDir or config.DEFAULT_QR
87+
url = '%s/qrcode/%s' % (config.BASE_URL, uuid)
88+
headers = { 'User-Agent' : config.USER_AGENT }
7689
try:
77-
uuid = uuid or self.uuid
78-
picDir = picDir or config.DEFAULT_QR
79-
url = '%s/qrcode/%s' % (config.BASE_URL, uuid)
80-
headers = { 'User-Agent' : config.USER_AGENT }
8190
r = self.s.get(url, stream=True, headers=headers)
82-
with open(picDir, 'wb') as f: f.write(r.content)
8391
except:
8492
return False
85-
if enableCmdQR:
86-
utils.print_cmd_qr(picDir, enableCmdQR = enableCmdQR)
93+
qrStorage = io.BytesIO(r.content)
94+
if hasattr(qrCallback, '__call__'):
95+
qrCallback(uuid=uuid, status='0', qrcode=qrStorage.getvalue())
8796
else:
88-
utils.print_qr(picDir)
89-
return True
97+
with open(picDir, 'wb') as f: f.write(r.content)
98+
if enableCmdQR:
99+
utils.print_cmd_qr(picDir, enableCmdQR=enableCmdQR)
100+
else:
101+
utils.print_qr(picDir)
102+
return qrStorage
90103

91104
def check_login(self, uuid=None):
92105
uuid = uuid or self.uuid
93106
url = '%s/cgi-bin/mmwebwx-bin/login' % config.BASE_URL
94-
params = 'tip=1&uuid=%s&_=%s' % (uuid, int(time.time()))
107+
localTime = int(time.time())
108+
params = 'loginicon=true&uuid=%s&tip=0&r=%s&_=%s' % (
109+
uuid, localTime / 1579, localTime)
95110
headers = { 'User-Agent' : config.USER_AGENT }
96111
r = self.s.get(url, params=params, headers=headers)
97112
regx = r'window.code=(\d+)'
98113
data = re.search(regx, r.text)
99114
if data and data.group(1) == '200':
100115
process_login_info(self, r.text)
101116
return '200'
102-
elif data and data.group(1) == '201':
103-
return '201'
104-
elif data and data.group(1) == '408':
105-
return '408'
117+
elif data:
118+
return data.group(1)
106119
else:
107-
return '0'
120+
return '400'
108121

109122
def process_login_info(core, loginContent):
110123
''' when finish login (scanning qrcode)

itchat/components/register.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,19 @@ def load_register(core):
1515
core.run = run
1616

1717
def auto_login(self, hotReload=False, statusStorageDir='itchat.pkl',
18-
enableCmdQR=False, picDir=None, loginCallback=None, exitCallback=None):
18+
enableCmdQR=False, picDir=None, qrCallback=None,
19+
loginCallback=None, exitCallback=None):
1920
self.useHotReload = hotReload
2021
if hotReload:
21-
if self.load_login_status(statusStorageDir, loginCallback=loginCallback, exitCallback=exitCallback): return
22-
self.login(enableCmdQR=enableCmdQR, picDir=picDir,
22+
if self.load_login_status(statusStorageDir,
23+
loginCallback=loginCallback, exitCallback=exitCallback):
24+
return
25+
self.login(enableCmdQR=enableCmdQR, picDir=picDir, qrCallback=qrCallback,
2326
loginCallback=loginCallback, exitCallback=exitCallback)
2427
self.dump_login_status(statusStorageDir)
2528
self.hotReloadDir = statusStorageDir
2629
else:
27-
self.login(enableCmdQR=enableCmdQR, picDir=picDir,
30+
self.login(enableCmdQR=enableCmdQR, picDir=picDir, qrCallback=qrCallback,
2831
loginCallback=loginCallback, exitCallback=exitCallback)
2932

3033
def configured_reply(self):

itchat/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os, platform
22

3+
VERSION = '1.2.10'
34
BASE_URL = 'https://login.weixin.qq.com'
45
OS = platform.system() #Windows, Linux, Darwin
56
DIR = os.getcwd()

itchat/core.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def __init__(self):
2929
self.functionDict = {'FriendChat': {}, 'GroupChat': {}, 'MpChat': {}}
3030
self.useHotReload, self.hotReloadDir = False, 'itchat.pkl'
3131
self.receivingRetryCount = 5
32-
def login(self, enableCmdQR=False, picDir=None,
32+
def login(self, enableCmdQR=False, picDir=None, qrCallback=None,
3333
loginCallback=None, exitCallback=None):
3434
''' log in like web wechat does
3535
for log in
@@ -40,6 +40,7 @@ def login(self, enableCmdQR=False, picDir=None,
4040
- enableCmdQR: show qrcode in command line
4141
- integers can be used to fit strange char length
4242
- picDir: place for storing qrcode
43+
- qrCallback: method that should accept uuid, status, qrcode
4344
- loginCallback: callback after successfully logged in
4445
- if not set, screen is cleared and qrcode is deleted
4546
- exitCallback: callback after logged out
@@ -66,12 +67,13 @@ def get_QRuuid(self):
6667
it is defined in components/login.py
6768
'''
6869
raise NotImplementedError()
69-
def get_QR(self, uuid=None, enableCmdQR=False, picDir=None):
70+
def get_QR(self, uuid=None, enableCmdQR=False, picDir=None, qrCallback=None):
7071
''' download and show qrcode
7172
for options
7273
- uuid: if uuid is not set, latest uuid you fetched will be used
7374
- enableCmdQR: show qrcode in cmd
7475
- picDir: where to store qrcode
76+
- qrCallback: method that should accept uuid, status, qrcode
7577
it is defined in components/login.py
7678
'''
7779
raise NotImplementedError()
@@ -385,7 +387,7 @@ def load_login_status(self, fileDir,
385387
'''
386388
raise NotImplementedError()
387389
def auto_login(self, hotReload=False, statusStorageDir='itchat.pkl',
388-
enableCmdQR=False, picDir=None,
390+
enableCmdQR=False, picDir=None, qrCallback=None,
389391
loginCallback=None, exitCallback=None):
390392
''' log in like web wechat does
391393
for log in
@@ -402,6 +404,7 @@ def auto_login(self, hotReload=False, statusStorageDir='itchat.pkl',
402404
- if not set, screen is cleared and qrcode is deleted
403405
- exitCallback: callback after logged out
404406
- it contains calling of logout
407+
- qrCallback: method that should accept uuid, status, qrcode
405408
for usage
406409
..code::python
407410

0 commit comments

Comments
 (0)