Skip to content

Commit 04bcc11

Browse files
committed
Fix contact double bug
1 parent 439febe commit 04bcc11

File tree

6 files changed

+79
-44
lines changed

6 files changed

+79
-44
lines changed

itchat/components/contact.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from .. import config, utils
88
from ..returnvalues import ReturnValue
99
from ..storage import contact_change, templates
10+
from ..utils import update_info_dict
1011

1112
logger = logging.getLogger('itchat')
1213

@@ -98,16 +99,6 @@ def update_friend(self, userName):
9899
for f in friendList]
99100
return r if len(r) != 1 else r[0]
100101

101-
def update_info_dict(oldInfoDict, newInfoDict):
102-
''' only normal values will be updated here
103-
because newInfoDict is normal dict, so it's not necessary to consider templates
104-
'''
105-
for k, v in newInfoDict.items():
106-
if any((isinstance(v, t) for t in (tuple, list, dict))):
107-
pass # these values will be updated somewhere else
108-
elif oldInfoDict.get(k) is None or v not in (None, '', '0', 0):
109-
oldInfoDict[k] = v
110-
111102
@contact_change
112103
def update_local_chatrooms(core, l):
113104
'''
@@ -131,7 +122,7 @@ def update_local_chatrooms(core, l):
131122
update_info_dict(oldChatroom, chatroom)
132123
# - update other values
133124
memberList = chatroom.get('MemberList', [])
134-
oldMemberList = oldChatroom.memberList
125+
oldMemberList = oldChatroom['MemberList']
135126
if memberList:
136127
for member in memberList:
137128
oldMember = utils.search_dict_list(

itchat/components/messages.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,11 @@ def send_file(self, fileDir, toUserName=None, mediaId=None, file_=None):
369369
'Ret': -1005, }})
370370
if toUserName is None:
371371
toUserName = self.storageClass.userName
372+
preparedFile = _prepare_file(fileDir, file_)
373+
if not preparedFile:
374+
return preparedFile
375+
fileSize = preparedFile['fileSize']
372376
if mediaId is None:
373-
preparedFile = _prepare_file(fileDir, file_)
374-
if not preparedFile:
375-
return preparedFile
376-
fileSize = preparedFile['fileSize']
377377
r = self.upload_file(fileDir, preparedFile=preparedFile)
378378
if r:
379379
mediaId = r['MediaId']

itchat/config.py

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

3-
VERSION = '1.3.2'
3+
VERSION = '1.3.3'
44
BASE_URL = 'https://login.weixin.qq.com'
55
OS = platform.system() #Windows, Linux, Darwin
66
DIR = os.getcwd()

itchat/storage/__init__.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ def dumps(self):
3232
return {
3333
'userName' : self.userName,
3434
'nickName' : self.nickName,
35-
'memberList' : [dict(member) for member in self.memberList],
36-
'mpList' : [dict(mp) for mp in self.mpList],
37-
'chatroomList' : [dict(chatroom) for chatroom in self.chatroomList],
35+
'memberList' : self.memberList,
36+
'mpList' : self.mpList,
37+
'chatroomList' : self.chatroomList,
3838
'lastInputUserName' : self.lastInputUserName, }
3939
def loads(self, j):
4040
self.userName = j.get('userName', None)
@@ -48,6 +48,16 @@ def loads(self, j):
4848
del self.chatroomList[:]
4949
for i in j.get('chatroomList', []):
5050
self.chatroomList.append(i)
51+
# I tried to solve everything in pickle
52+
# but this way is easier and more storage-saving
53+
for chatroom in self.chatroomList:
54+
if 'MemberList' in chatroom:
55+
for member in chatroom['MemberList']:
56+
member.core = chatroom.core
57+
member.chatroom = chatroom
58+
if 'Self' in chatroom:
59+
chatroom['Self'].core = chatroom.core
60+
chatroom['Self'].chatroom = chatroom
5161
self.lastInputUserName = j.get('lastInputUserName', None)
5262
def search_friends(self, name=None, userName=None, remarkName=None, nickName=None,
5363
wechatAccount=None):

itchat/storage/templates.py

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging, copy, pickle
22

33
from ..returnvalues import ReturnValue
4+
from ..utils import update_info_dict
45

56
logger = logging.getLogger('itchat')
67

@@ -17,9 +18,7 @@ class ContactList(list):
1718
'''
1819
def __init__(self, *args, **kwargs):
1920
super(ContactList, self).__init__(*args, **kwargs)
20-
self.contactInitFn = None
21-
self.contactClass = User
22-
self.core = fakeItchat
21+
self.__setstate__(None)
2322
def set_default_value(self, initFunction=None, contactClass=None):
2423
if hasattr(initFunction, '__call__'):
2524
self.contactInitFn = initFunction
@@ -32,12 +31,17 @@ def append(self, value):
3231
contact = self.contactInitFn(contact) or contact
3332
super(ContactList, self).append(contact)
3433
def __deepcopy__(self, memo):
35-
return self.__class__([copy.deepcopy(v) for v in self])
34+
r = self.__class__([copy.deepcopy(v) for v in self])
35+
r.contactInitFn = self.contactInitFn
36+
r.contactClass = self.contactClass
37+
r.core = self.core
38+
return r
3639
def __getstate__(self):
37-
return [pickle.dumps(v) for v in self]
40+
return 1
3841
def __setstate__(self, state):
39-
for v in state:
40-
super(ContactList, self).append(pickle.loads(v))
42+
self.contactInitFn = None
43+
self.contactClass = User
44+
self.core = fakeItchat
4145
def __str__(self):
4246
return '[%s]' % ', '.join([repr(v) for v in self])
4347
def __repr__(self):
@@ -49,7 +53,7 @@ def __repr__(self):
4953
class AbstractUserDict(dict):
5054
def __init__(self, *args, **kwargs):
5155
super(AbstractUserDict, self).__init__(*args, **kwargs)
52-
self.core = fakeItchat
56+
self.__setstate__(None)
5357
def update(self):
5458
return ReturnValue({'BaseResponse': {
5559
'Ret': -1006,
@@ -104,30 +108,31 @@ def __getattr__(self, value):
104108
value = value[0].upper() + value[1:]
105109
return self.get(value, '')
106110
def __deepcopy__(self, memo):
107-
r = self.__class__({
108-
copy.deepcopy(k, memo): copy.deepcopy(v, memo)
109-
for k, v in self.items()})
111+
r = self.__class__()
112+
for k, v in self.items():
113+
r[copy.deepcopy(k)] = copy.deepcopy(v)
110114
r.core = self.core
111115
return r
112-
def __getstate__(self):
113-
return dict(self)
114-
def __setstate__(self, state):
115-
for k, v in state.items():
116-
self[k] = v
117116
def __str__(self):
118117
return '{%s}' % ', '.join(
119118
['%s: %s' % (repr(k),repr(v)) for k,v in self.items()])
120119
def __repr__(self):
121120
return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
122121
self.__str__())
122+
def __getstate__(self):
123+
return 1
124+
def __setstate__(self, state):
125+
self.core = fakeItchat
123126

124127
class User(AbstractUserDict):
125128
def __init__(self, *args, **kwargs):
126129
super(User, self).__init__(*args, **kwargs)
127-
self.verifyDict = {}
128-
self.memberList = fakeContactList
130+
self.__setstate__(None)
129131
def update(self):
130-
return self.core.update_friend(self.userName)
132+
r = self.core.update_friend(self.userName)
133+
if r:
134+
update_info_dict(self, r)
135+
return r
131136
def set_alias(self, alias):
132137
return self.core.set_alias(self.userName, alias)
133138
def set_pinned(self, isPinned=True):
@@ -138,10 +143,17 @@ def __deepcopy__(self, memo):
138143
r = super(User, self).__deepcopy__(memo)
139144
r.verifyDict = copy.deepcopy(self.verifyDict)
140145
return r
146+
def __setstate__(self, state):
147+
super(User, self).__setstate__(state)
148+
self.verifyDict = {}
149+
self.memberList = fakeContactList
141150

142151
class MassivePlatform(AbstractUserDict):
143152
def __init__(self, *args, **kwargs):
144153
super(MassivePlatform, self).__init__(*args, **kwargs)
154+
self.__setstate__(None)
155+
def __setstate__(self, state):
156+
super(MassivePlatform, self).__setstate__(state)
145157
self.memberList = fakeContactList
146158

147159
class Chatroom(AbstractUserDict):
@@ -151,11 +163,21 @@ def __init__(self, *args, **kwargs):
151163
def init_fn(d):
152164
d.chatroom = self
153165
memberList.set_default_value(init_fn, ChatroomMember)
154-
for rawMember in self.memberList:
155-
memberList.append(rawMember)
156-
self['MemberList'] = memberList
166+
if 'MemberList' in self:
167+
if not isinstance(self.memberList, ContactList):
168+
for member in self.memberList:
169+
memberList.append(member)
170+
self['MemberList'] = memberList
171+
else:
172+
for member in self.memberList:
173+
memberList.append(member)
174+
self['MemberList'] = memberList
157175
def update(self, detailedMember=False):
158-
return self.core.update_chatroom(self.userName, detailedMember)
176+
r = self.core.update_chatroom(self.userName, detailedMember)
177+
if r:
178+
update_info_dict(self, r)
179+
self['MemberList'] = r['MemberList']
180+
return r
159181
def set_alias(self, alias):
160182
return self.core.set_chatroom_name(self.userName, alias)
161183
def set_pinned(self, isPinned=True):
@@ -200,8 +222,7 @@ def search_member(self, name=None, userName=None, remarkName=None, nickName=None
200222
class ChatroomMember(AbstractUserDict):
201223
def __init__(self, *args, **kwargs):
202224
super(AbstractUserDict, self).__init__(*args, **kwargs)
203-
self.core = fakeItchat
204-
self.chatroom = self.fakeChatroom
225+
self.__setstate__(None)
205226
def get_head_image(self, imageDir=None):
206227
return self.core.get_head_img(self.userName, self.chatroom.userName, picDir=imageDir)
207228
def delete_member(self, userName):
@@ -240,6 +261,9 @@ def __deepcopy__(self, memo):
240261
r = super(ChatroomMember, self).__deepcopy__(memo)
241262
r.core = self.core
242263
return r
264+
def __setstate__(self, state):
265+
super(ChatroomMember, self).__setstate__(state)
266+
self.chatroom = self.fakeChatroom
243267

244268
ChatroomMember.fakeChatroom = Chatroom()
245269

itchat/utils.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,13 @@ def get_image_postfix(data):
142142
elif b'JFIF' in data:
143143
return 'jpg'
144144
return ''
145+
146+
def update_info_dict(oldInfoDict, newInfoDict):
147+
''' only normal values will be updated here
148+
because newInfoDict is normal dict, so it's not necessary to consider templates
149+
'''
150+
for k, v in newInfoDict.items():
151+
if any((isinstance(v, t) for t in (tuple, list, dict))):
152+
pass # these values will be updated somewhere else
153+
elif oldInfoDict.get(k) is None or v not in (None, '', '0', 0):
154+
oldInfoDict[k] = v

0 commit comments

Comments
 (0)