提交 6fcce75e 编写于 作者: L LittleCoder

Merge 1.3.0 into master and update to 1.3.1

...@@ -3,6 +3,7 @@ dist/* ...@@ -3,6 +3,7 @@ dist/*
tests/* tests/*
itchat.egg-info/* itchat.egg-info/*
*.pyc *.pyc
*.pkl
*.swp *.swp
test.py test.py
itchat.pkl itchat.pkl
......
...@@ -59,36 +59,61 @@ itchat.run() ...@@ -59,36 +59,61 @@ itchat.run()
## 进阶应用 ## 进阶应用
### 特殊的字典使用方式
通过打印itchat的用户以及注册消息的参数,可以发现这些值都是字典。
但实际上itchat精心构造了相应的消息、用户、群聊、公众号类。
其所有的键值都可以通过这一方式访问:
```python
@itchat.msg_register(TEXT)
def _(msg):
# equals to print(msg['FromUserName'])
print(msg.fromUserName)
```
属性名为键值首字母小写后的内容。
```python
author = itchat.search_friends(nickName='LittleCoder')[0]
author.send('greeting, littlecoder!')
```
### 各类型消息的注册 ### 各类型消息的注册
通过如下代码,微信已经可以就日常的各种信息进行获取与回复。 通过如下代码,微信已经可以就日常的各种信息进行获取与回复。
```python ```python
#coding=utf8
import itchat, time import itchat, time
from itchat.content import * from itchat.content import *
@itchat.msg_register([TEXT, MAP, CARD, NOTE, SHARING]) @itchat.msg_register([TEXT, MAP, CARD, NOTE, SHARING])
def text_reply(msg): def text_reply(msg):
itchat.send('%s: %s' % (msg['Type'], msg['Text']), msg['FromUserName']) msg.user.send('%s: %s' % (msg.type, msg.text))
@itchat.msg_register([PICTURE, RECORDING, ATTACHMENT, VIDEO]) @itchat.msg_register([PICTURE, RECORDING, ATTACHMENT, VIDEO])
def download_files(msg): def download_files(msg):
msg['Text'](msg['FileName']) msg.download(msg.fileName)
return '@%s@%s' % ({'Picture': 'img', 'Video': 'vid'}.get(msg['Type'], 'fil'), msg['FileName']) typeSymbol = {
PICTURE: 'img',
VIDEO: 'vid', }.get(msg.type, 'fil')
return '@%s@%s' % (typeSymbol, msg.fileName)
@itchat.msg_register(FRIENDS) @itchat.msg_register(FRIENDS)
def add_friend(msg): def add_friend(msg):
itchat.add_friend(**msg['Text']) # 该操作会自动将新好友的消息录入,不需要重载通讯录 msg.user.verify()
itchat.send_msg('Nice to meet you!', msg['RecommendInfo']['UserName']) msg.user.send('Nice to meet you!')
@itchat.msg_register(TEXT, isGroupChat=True) @itchat.msg_register(TEXT, isGroupChat=True)
def text_reply(msg): def text_reply(msg):
if msg['isAt']: if msg.isAt:
itchat.send(u'@%s\u2005I received: %s' % (msg['ActualNickName'], msg['Content']), msg['FromUserName']) msg.user.send(u'@%s\u2005I received: %s' % (
msg.actualNickName, msg.text))
itchat.auto_login(True) itchat.auto_login(True)
itchat.run() itchat.run(True)
``` ```
### 命令行二维码 ### 命令行二维码
...@@ -234,6 +259,8 @@ A: 有些账号是天生无法给自己的账号发送信息的,建议使用`f ...@@ -234,6 +259,8 @@ A: 有些账号是天生无法给自己的账号发送信息的,建议使用`f
## 类似项目 ## 类似项目
[youfou/wxpy][youfou-wxpy]: 优秀的api包装和配套插件,微信机器人/优雅的微信个人号API
[liuwons/wxBot][liuwons-wxBot]: 类似的基于Python的微信机器人 [liuwons/wxBot][liuwons-wxBot]: 类似的基于Python的微信机器人
[zixia/wechaty][zixia-wechaty]: 基于Javascript(ES6)的微信个人账号机器人NodeJS框架/库 [zixia/wechaty][zixia-wechaty]: 基于Javascript(ES6)的微信个人账号机器人NodeJS框架/库
...@@ -267,6 +294,7 @@ A: 有些账号是天生无法给自己的账号发送信息的,建议使用`f ...@@ -267,6 +294,7 @@ A: 有些账号是天生无法给自己的账号发送信息的,建议使用`f
[littlecodersh]: https://github.com/littlecodersh [littlecodersh]: https://github.com/littlecodersh
[tempdban]: https://github.com/tempdban [tempdban]: https://github.com/tempdban
[Chyroc]: https://github.com/Chyroc [Chyroc]: https://github.com/Chyroc
[youfou-wxpy]: https://github.com/youfou/wxpy
[liuwons-wxBot]: https://github.com/liuwons/wxBot [liuwons-wxBot]: https://github.com/liuwons/wxBot
[zixia-wechaty]: https://github.com/zixia/wechaty [zixia-wechaty]: https://github.com/zixia/wechaty
[Mojo-Weixin]: https://github.com/sjdy521/Mojo-Weixin [Mojo-Weixin]: https://github.com/sjdy521/Mojo-Weixin
......
...@@ -6,7 +6,7 @@ import requests ...@@ -6,7 +6,7 @@ import requests
from .. import config, utils from .. import config, utils
from ..returnvalues import ReturnValue from ..returnvalues import ReturnValue
from ..storage import contact_change from ..storage import contact_change, templates
logger = logging.getLogger('itchat') logger = logging.getLogger('itchat')
...@@ -99,8 +99,8 @@ def update_friend(self, userName): ...@@ -99,8 +99,8 @@ def update_friend(self, userName):
return r if len(r) != 1 else r[0] return r if len(r) != 1 else r[0]
def update_info_dict(oldInfoDict, newInfoDict): def update_info_dict(oldInfoDict, newInfoDict):
''' ''' only normal values will be updated here
only normal values will be updated here because newInfoDict is normal dict, so it's not necessary to consider templates
''' '''
for k, v in newInfoDict.items(): for k, v in newInfoDict.items():
if any((isinstance(v, t) for t in (tuple, list, dict))): if any((isinstance(v, t) for t in (tuple, list, dict))):
...@@ -130,8 +130,8 @@ def update_local_chatrooms(core, l): ...@@ -130,8 +130,8 @@ def update_local_chatrooms(core, l):
if oldChatroom: if oldChatroom:
update_info_dict(oldChatroom, chatroom) update_info_dict(oldChatroom, chatroom)
# - update other values # - update other values
memberList, oldMemberList = (c.get('MemberList', []) memberList = chatroom.get('MemberList', [])
for c in (chatroom, oldChatroom)) oldMemberList = oldChatroom.memberList
if memberList: if memberList:
for member in memberList: for member in memberList:
oldMember = utils.search_dict_list( oldMember = utils.search_dict_list(
...@@ -141,17 +141,19 @@ def update_local_chatrooms(core, l): ...@@ -141,17 +141,19 @@ def update_local_chatrooms(core, l):
else: else:
oldMemberList.append(member) oldMemberList.append(member)
else: else:
oldChatroom = chatroom oldChatroom = templates.wrap_user_dict(chatroom)
core.chatroomList.append(chatroom) core.chatroomList.append(oldChatroom)
# delete useless members # delete useless members
if len(chatroom['MemberList']) != len(oldChatroom['MemberList']) and \ if len(chatroom['MemberList']) != len(oldChatroom['MemberList']) and \
chatroom['MemberList']: chatroom['MemberList']:
existsUserNames = [member['UserName'] for member in chatroom['MemberList']] existsUserNames = [member['UserName'] for member in chatroom['MemberList']]
delList = [] delList = []
for i, member in enumerate(oldChatroom['MemberList']): for i, member in enumerate(oldChatroom['MemberList']):
if member['UserName'] not in existsUserNames: delList.append(i) if member['UserName'] not in existsUserNames:
delList.append(i)
delList.sort(reverse=True) delList.sort(reverse=True)
for i in delList: del oldChatroom['MemberList'][i] for i in delList:
del oldChatroom['MemberList'][i]
# - update OwnerUin # - update OwnerUin
if oldChatroom.get('ChatRoomOwner') and oldChatroom.get('MemberList'): if oldChatroom.get('ChatRoomOwner') and oldChatroom.get('MemberList'):
oldChatroom['OwnerUin'] = utils.search_dict_list(oldChatroom['MemberList'], oldChatroom['OwnerUin'] = utils.search_dict_list(oldChatroom['MemberList'],
...@@ -184,8 +186,8 @@ def update_local_friends(core, l): ...@@ -184,8 +186,8 @@ def update_local_friends(core, l):
utils.emoji_formatter(friend, 'NickName') utils.emoji_formatter(friend, 'NickName')
if 'DisplayName' in friend: if 'DisplayName' in friend:
utils.emoji_formatter(friend, 'DisplayName') utils.emoji_formatter(friend, 'DisplayName')
if 'RemarkName' in member: if 'RemarkName' in friend:
utils.emoji_formatter(member, 'RemarkName') utils.emoji_formatter(friend, 'RemarkName')
oldInfoDict = utils.search_dict_list( oldInfoDict = utils.search_dict_list(
fullList, 'UserName', friend['UserName']) fullList, 'UserName', friend['UserName'])
if oldInfoDict is None: if oldInfoDict is None:
......
...@@ -5,6 +5,7 @@ import requests ...@@ -5,6 +5,7 @@ import requests
from ..config import VERSION from ..config import VERSION
from ..returnvalues import ReturnValue from ..returnvalues import ReturnValue
from ..storage import templates
from .contact import update_local_chatrooms, update_local_friends from .contact import update_local_chatrooms, update_local_friends
from .messages import produce_msg from .messages import produce_msg
...@@ -50,6 +51,8 @@ def load_login_status(self, fileDir, ...@@ -50,6 +51,8 @@ def load_login_status(self, fileDir,
'ErrMsg': 'cached status ignored because of version', 'ErrMsg': 'cached status ignored because of version',
'Ret': -1005, }}) 'Ret': -1005, }})
self.loginInfo = j['loginInfo'] self.loginInfo = j['loginInfo']
self.loginInfo['User'] = templates.User(self.loginInfo['User'])
self.loginInfo['User'].core = self
self.s.cookies = requests.utils.cookiejar_from_dict(j['cookies']) self.s.cookies = requests.utils.cookiejar_from_dict(j['cookies'])
self.storageClass.loads(j['storage']) self.storageClass.loads(j['storage'])
msgList, contactList = self.get_msg() msgList, contactList = self.get_msg()
......
...@@ -9,6 +9,7 @@ from pyqrcode import QRCode ...@@ -9,6 +9,7 @@ from pyqrcode import QRCode
from .. import config, utils from .. import config, utils
from ..returnvalues import ReturnValue from ..returnvalues import ReturnValue
from ..storage.templates import wrap_user_dict
from .contact import update_local_chatrooms, update_local_friends from .contact import update_local_chatrooms, update_local_friends
from .messages import produce_msg from .messages import produce_msg
...@@ -182,7 +183,7 @@ def web_init(self): ...@@ -182,7 +183,7 @@ def web_init(self):
# deal with login info # deal with login info
utils.emoji_formatter(dic['User'], 'NickName') utils.emoji_formatter(dic['User'], 'NickName')
self.loginInfo['InviteStartCount'] = int(dic['InviteStartCount']) self.loginInfo['InviteStartCount'] = int(dic['InviteStartCount'])
self.loginInfo['User'] = utils.struct_friend_info(dic['User']) self.loginInfo['User'] = wrap_user_dict(utils.struct_friend_info(dic['User']))
self.memberList.append(self.loginInfo['User']) self.memberList.append(self.loginInfo['User'])
self.loginInfo['SyncKey'] = dic['SyncKey'] self.loginInfo['SyncKey'] = dic['SyncKey']
self.loginInfo['synckey'] = '|'.join(['%s_%s' % (item['Key'], item['Val']) self.loginInfo['synckey'] = '|'.join(['%s_%s' % (item['Key'], item['Val'])
...@@ -247,6 +248,7 @@ def start_receiving(self, exitCallback=None, getReceivingFnOnly=False): ...@@ -247,6 +248,7 @@ def start_receiving(self, exitCallback=None, getReceivingFnOnly=False):
else: else:
otherList.append(contact) otherList.append(contact)
chatroomMsg = update_local_chatrooms(self, chatroomList) chatroomMsg = update_local_chatrooms(self, chatroomList)
chatroomMsg['User'] = self.loginInfo['User']
self.msgList.put(chatroomMsg) self.msgList.put(chatroomMsg)
update_local_friends(self, otherList) update_local_friends(self, otherList)
retryCount = 0 retryCount = 0
......
此差异已折叠。
...@@ -6,6 +6,7 @@ except ImportError: ...@@ -6,6 +6,7 @@ except ImportError:
from ..log import set_logging from ..log import set_logging
from ..utils import test_connect from ..utils import test_connect
from ..storage import templates
logger = logging.getLogger('itchat') logger = logging.getLogger('itchat')
...@@ -46,19 +47,12 @@ def configured_reply(self): ...@@ -46,19 +47,12 @@ def configured_reply(self):
except Queue.Empty: except Queue.Empty:
pass pass
else: else:
if msg['FromUserName'] == self.storageClass.userName: if isinstance(msg['User'], templates.User):
actualOpposite = msg['ToUserName']
else:
actualOpposite = msg['FromUserName']
if '@@' in actualOpposite:
replyFn = self.functionDict['GroupChat'].get(msg['Type'])
elif self.search_mps(userName=msg['FromUserName']):
replyFn = self.functionDict['MpChat'].get(msg['Type'])
elif '@' in actualOpposite or \
actualOpposite in ('filehelper', 'fmessage'):
replyFn = self.functionDict['FriendChat'].get(msg['Type']) replyFn = self.functionDict['FriendChat'].get(msg['Type'])
else: elif isinstance(msg['User'], templates.MassivePlatform):
replyFn = self.functionDict['MpChat'].get(msg['Type']) replyFn = self.functionDict['MpChat'].get(msg['Type'])
elif isinstance(msg['User'], templates.Chatroom):
replyFn = self.functionDict['GroupChat'].get(msg['Type'])
if replyFn is None: if replyFn is None:
r = None r = None
else: else:
...@@ -72,7 +66,7 @@ def configured_reply(self): ...@@ -72,7 +66,7 @@ def configured_reply(self):
def msg_register(self, msgType, isFriendChat=False, isGroupChat=False, isMpChat=False): def msg_register(self, msgType, isFriendChat=False, isGroupChat=False, isMpChat=False):
''' a decorator constructor ''' a decorator constructor
return a specific decorator based on information given ''' return a specific decorator based on information given '''
if not isinstance(msgType, list): if not (isinstance(msgType, list) or isinstance(msgType, tuple)):
msgType = [msgType] msgType = [msgType]
def _msg_register(fn): def _msg_register(fn):
for _msgType in msgType: for _msgType in msgType:
...@@ -84,6 +78,7 @@ def msg_register(self, msgType, isFriendChat=False, isGroupChat=False, isMpChat= ...@@ -84,6 +78,7 @@ def msg_register(self, msgType, isFriendChat=False, isGroupChat=False, isMpChat=
self.functionDict['MpChat'][_msgType] = fn self.functionDict['MpChat'][_msgType] = fn
if not any((isFriendChat, isGroupChat, isMpChat)): if not any((isFriendChat, isGroupChat, isMpChat)):
self.functionDict['FriendChat'][_msgType] = fn self.functionDict['FriendChat'][_msgType] = fn
return fn
return _msg_register return _msg_register
def run(self, debug=False, blockThread=True): def run(self, debug=False, blockThread=True):
......
import os, platform import os, platform
VERSION = '1.2.33' VERSION = '1.3.1'
BASE_URL = 'https://login.weixin.qq.com' BASE_URL = 'https://login.weixin.qq.com'
OS = platform.system() #Windows, Linux, Darwin OS = platform.system() #Windows, Linux, Darwin
DIR = os.getcwd() DIR = os.getcwd()
DEFAULT_QR = 'QR.png' 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' 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'
...@@ -18,7 +18,7 @@ class Core(object): ...@@ -18,7 +18,7 @@ class Core(object):
- failing is failing - failing is failing
''' '''
self.alive, self.isLogging = False, False self.alive, self.isLogging = False, False
self.storageClass = storage.Storage() self.storageClass = storage.Storage(self)
self.memberList = self.storageClass.memberList self.memberList = self.storageClass.memberList
self.mpList = self.storageClass.mpList self.mpList = self.storageClass.mpList
self.chatroomList = self.storageClass.chatroomList self.chatroomList = self.storageClass.chatroomList
...@@ -313,7 +313,7 @@ class Core(object): ...@@ -313,7 +313,7 @@ class Core(object):
''' '''
raise NotImplementedError() raise NotImplementedError()
def upload_file(self, fileDir, isPicture=False, isVideo=False, def upload_file(self, fileDir, isPicture=False, isVideo=False,
toUserName='filehelper'): toUserName='filehelper', file_=None, preparedFile=None):
''' upload file to server and get mediaId ''' upload file to server and get mediaId
for options for options
- fileDir: dir for file ready for upload - fileDir: dir for file ready for upload
...@@ -325,7 +325,7 @@ class Core(object): ...@@ -325,7 +325,7 @@ class Core(object):
it is defined in components/messages.py it is defined in components/messages.py
''' '''
raise NotImplementedError() raise NotImplementedError()
def send_file(self, fileDir, toUserName=None, mediaId=None): def send_file(self, fileDir, toUserName=None, mediaId=None, file_=None):
''' send attachment ''' send attachment
for options for options
- fileDir: dir for file ready for upload - fileDir: dir for file ready for upload
...@@ -335,7 +335,7 @@ class Core(object): ...@@ -335,7 +335,7 @@ class Core(object):
it is defined in components/messages.py it is defined in components/messages.py
''' '''
raise NotImplementedError() raise NotImplementedError()
def send_image(self, fileDir, toUserName=None, mediaId=None): def send_image(self, fileDir=None, toUserName=None, mediaId=None, file_=None):
''' send image ''' send image
for options for options
- fileDir: dir for file ready for upload - fileDir: dir for file ready for upload
...@@ -346,7 +346,7 @@ class Core(object): ...@@ -346,7 +346,7 @@ class Core(object):
it is defined in components/messages.py it is defined in components/messages.py
''' '''
raise NotImplementedError() raise NotImplementedError()
def send_video(self, fileDir=None, toUserName=None, mediaId=None): def send_video(self, fileDir=None, toUserName=None, mediaId=None, file_=None):
''' send video ''' send video
for options for options
- fileDir: dir for file ready for upload - fileDir: dir for file ready for upload
......
...@@ -4,6 +4,23 @@ import sys ...@@ -4,6 +4,23 @@ import sys
TRANSLATE = 'Chinese' TRANSLATE = 'Chinese'
class ReturnValue(dict): class ReturnValue(dict):
''' turn return value of itchat into a boolean value
for requests:
..code::python
import requests
r = requests.get('http://httpbin.org/get')
print(ReturnValue(rawResponse=r)
for normal dict:
..code::python
returnDict = {
'BaseResponse': {
'Ret': 0,
'ErrMsg': 'My error msg', }, }
print(ReturnValue(returnDict))
'''
def __init__(self, returnValueDict={}, rawResponse=None): def __init__(self, returnValueDict={}, rawResponse=None):
if rawResponse: if rawResponse:
try: try:
...@@ -14,7 +31,8 @@ class ReturnValue(dict): ...@@ -14,7 +31,8 @@ class ReturnValue(dict):
'Ret': -1004, 'Ret': -1004,
'ErrMsg': 'Unexpected return value', }, 'ErrMsg': 'Unexpected return value', },
'Data': rawResponse.content, } 'Data': rawResponse.content, }
for k, v in returnValueDict.items(): self[k] = v for k, v in returnValueDict.items():
self[k] = v
if not 'BaseResponse' in self: if not 'BaseResponse' in self:
self['BaseResponse'] = { self['BaseResponse'] = {
'ErrMsg': 'no BaseResponse in raw response', 'ErrMsg': 'no BaseResponse in raw response',
...@@ -45,6 +63,7 @@ TRANSLATION = { ...@@ -45,6 +63,7 @@ TRANSLATION = {
-1003: u'服务器拒绝连接', -1003: u'服务器拒绝连接',
-1004: u'服务器返回异常值', -1004: u'服务器返回异常值',
-1005: u'参数错误', -1005: u'参数错误',
-1006: u'无效操作',
0: u'请求成功', 0: u'请求成功',
}, },
} }
import os, time, copy import os, time, copy
try:
import Queue
except ImportError:
import queue as Queue
from threading import Lock from threading import Lock
from .messagequeue import Queue
from .templates import (
ContactList, AbstractUserDict, User,
MassivePlatform, Chatroom, ChatroomMember)
def contact_change(fn): def contact_change(fn):
def _contact_change(core, *args, **kwargs): def _contact_change(core, *args, **kwargs):
with core.storageClass.updateLock: with core.storageClass.updateLock:
...@@ -12,32 +13,41 @@ def contact_change(fn): ...@@ -12,32 +13,41 @@ def contact_change(fn):
return _contact_change return _contact_change
class Storage(object): class Storage(object):
def __init__(self): def __init__(self, core):
self.userName = None self.userName = None
self.nickName = None self.nickName = None
self.updateLock = Lock() self.updateLock = Lock()
self.memberList = [] self.memberList = ContactList()
self.mpList = [] self.mpList = ContactList()
self.chatroomList = [] self.chatroomList = ContactList()
self.msgList = Queue.Queue(-1) self.msgList = Queue(-1)
self.lastInputUserName = None self.lastInputUserName = None
self.memberList.set_default_value(contactClass=User)
self.memberList.core = core
self.mpList.set_default_value(contactClass=MassivePlatform)
self.mpList.core = core
self.chatroomList.set_default_value(contactClass=Chatroom)
self.chatroomList.core = core
def dumps(self): def dumps(self):
return { return {
'userName' : self.userName, 'userName' : self.userName,
'nickName' : self.nickName, 'nickName' : self.nickName,
'memberList' : self.memberList, 'memberList' : [dict(member) for member in self.memberList],
'mpList' : self.mpList, 'mpList' : [dict(mp) for mp in self.mpList],
'chatroomList' : self.chatroomList, 'chatroomList' : [dict(chatroom) for chatroom in self.chatroomList],
'lastInputUserName' : self.lastInputUserName, } 'lastInputUserName' : self.lastInputUserName, }
def loads(self, j): def loads(self, j):
self.userName = j.get('userName', None) self.userName = j.get('userName', None)
self.nickName = j.get('nickName', None) self.nickName = j.get('nickName', None)
del self.memberList[:] del self.memberList[:]
for i in j.get('memberList', []): self.memberList.append(i) for i in j.get('memberList', []):
self.memberList.append(i)
del self.mpList[:] del self.mpList[:]
for i in j.get('mpList', []): self.mpList.append(i) for i in j.get('mpList', []):
self.mpList.append(i)
del self.chatroomList[:] del self.chatroomList[:]
for i in j.get('chatroomList', []): self.chatroomList.append(i) for i in j.get('chatroomList', []):
self.chatroomList.append(i)
self.lastInputUserName = j.get('lastInputUserName', None) self.lastInputUserName = j.get('lastInputUserName', None)
def search_friends(self, name=None, userName=None, remarkName=None, nickName=None, def search_friends(self, name=None, userName=None, remarkName=None, nickName=None,
wechatAccount=None): wechatAccount=None):
...@@ -75,19 +85,23 @@ class Storage(object): ...@@ -75,19 +85,23 @@ class Storage(object):
with self.updateLock: with self.updateLock:
if userName is not None: if userName is not None:
for m in self.chatroomList: for m in self.chatroomList:
if m['UserName'] == userName: return copy.deepcopy(m) if m['UserName'] == userName:
return copy.deepcopy(m)
elif name is not None: elif name is not None:
matchList = [] matchList = []
for m in self.chatroomList: for m in self.chatroomList:
if name in m['NickName']: matchList.append(copy.deepcopy(m)) if name in m['NickName']:
matchList.append(copy.deepcopy(m))
return matchList return matchList
def search_mps(self, name=None, userName=None): def search_mps(self, name=None, userName=None):
with self.updateLock: with self.updateLock:
if userName is not None: if userName is not None:
for m in self.mpList: for m in self.mpList:
if m['UserName'] == userName: return copy.deepcopy(m) if m['UserName'] == userName:
return copy.deepcopy(m)
elif name is not None: elif name is not None:
matchList = [] matchList = []
for m in self.mpList: for m in self.mpList:
if name in m['NickName']: matchList.append(copy.deepcopy(m)) if name in m['NickName']:
matchList.append(copy.deepcopy(m))
return matchList return matchList
try:
import Queue as queue
except ImportError:
import queue
class Queue(queue.Queue):
def put(self, message):
if 'IsAt' in message:
message['isAt'] = message['IsAt']
queue.Queue.put(self, Message(message))
class Message(dict):
def download(self, fileName):
if hasattr(self.text, '__call__'):
return self.text(fileName)
else:
return b''
def __getattr__(self, value):
value = value[0].upper() + value[1:]
return self.get(value, '')
def __str__(self):
return '{%s}' % ', '.join(
['%s: %s' % (repr(k),repr(v)) for k,v in self.items()])
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
self.__str__())
import logging, copy, pickle
from ..returnvalues import ReturnValue
logger = logging.getLogger('itchat')
class UnInitializedItchat(object):
def _raise_error(self, *args, **kwargs):
logger.warning('An itchat instance is called before initialized')
def __getattr__(self, value):
return self._raise_error
fakeItchat = UnInitializedItchat()
class ContactList(list):
''' when a dict is append, init function will be called to format that dict
'''
def __init__(self, *args, **kwargs):
super(ContactList, self).__init__(*args, **kwargs)
self.contactInitFn = None
self.contactClass = User
self.core = fakeItchat
def set_default_value(self, initFunction=None, contactClass=None):
if hasattr(initFunction, '__call__'):
self.contactInitFn = initFunction
if hasattr(contactClass, '__call__'):
self.contactClass = contactClass
def append(self, value):
contact = self.contactClass(value)
contact.core = self.core
if self.contactInitFn is not None:
contact = self.contactInitFn(contact) or contact
super(ContactList, self).append(contact)
def __deepcopy__(self, memo):
return self.__class__([copy.deepcopy(v) for v in self])
def __getstate__(self):
return [pickle.dumps(v) for v in self]
def __setstate__(self, state):
for v in state:
super(ContactList, self).append(pickle.loads(v))
def __str__(self):
return '[%s]' % ', '.join([repr(v) for v in self])
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
self.__str__())
fakeContactList = ContactList
class AbstractUserDict(dict):
def __init__(self, *args, **kwargs):
super(AbstractUserDict, self).__init__(*args, **kwargs)
self.core = fakeItchat
def update(self):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not be updated' % \
self.__class__.__name__, }, })
def set_alias(self, alias):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not set alias' % \
self.__class__.__name__, }, })
def set_pinned(self, isPinned=True):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not be pinned' % \
self.__class__.__name__, }, })
def verify(self):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s do not need verify' % \
self.__class__.__name__, }, })
def get_head_image(self, imageDir=None):
return self.core.get_head_img(self.userName, picDir=imageDir)
def delete_member(self, userName):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not delete member' % \
self.__class__.__name__, }, })
def add_member(self, userName):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not add member' % \
self.__class__.__name__, }, })
def send_raw_msg(self, msgType, content):
return self.core.send_raw_msg(msgType, content, self.userName)
def send_msg(self, msg='Test Message'):
return self.core.send_msg(msgType, content, self.userName)
def send_file(self, fileDir, mediaId=None):
return self.core.send_file(fileDir, self.userName, mediaId)
def send_image(self, fileDir, mediaId=None):
return self.core.send_image(fileDir, self.userName, mediaId)
def send_video(self, fileDir=None, mediaId=None):
return self.core.send_video(fileDir, self.userName, mediaId)
def send(self, msg, mediaId=None):
return self.core.send(msg, self.userName, mediaId)
def search_member(self, name=None, userName=None, remarkName=None, nickName=None,
wechatAccount=None):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s do not have members' % \
self.__class__.__name__, }, })
def __getattr__(self, value):
value = value[0].upper() + value[1:]
return self.get(value, '')
def __deepcopy__(self, memo):
r = self.__class__({
copy.deepcopy(k, memo): copy.deepcopy(v, memo)
for k, v in self.items()})
r.core = self.core
return r
def __getstate__(self):
return dict(self)
def __setstate__(self, state):
for k, v in state.items():
self[k] = v
def __str__(self):
return '{%s}' % ', '.join(
['%s: %s' % (repr(k),repr(v)) for k,v in self.items()])
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
self.__str__())
class User(AbstractUserDict):
def __init__(self, *args, **kwargs):
super(User, self).__init__(*args, **kwargs)
self.verifyDict = {}
self.memberList = fakeContactList
def update(self):
return self.core.update_friend(self.userName)
def set_alias(self, alias):
return self.core.set_alias(self.userName, alias)
def set_pinned(self, isPinned=True):
return self.core.set_pinned(self.userName, isPinned)
def verify(self):
return self.core.add_friend(**self.verifyDict)
def __deepcopy__(self, memo):
r = super(User, self).__deepcopy__(memo)
r.verifyDict = copy.deepcopy(self.verifyDict)
return r
class MassivePlatform(AbstractUserDict):
def __init__(self, *args, **kwargs):
super(MassivePlatform, self).__init__(*args, **kwargs)
self.memberList = fakeContactList
class Chatroom(AbstractUserDict):
def __init__(self, *args, **kwargs):
super(Chatroom, self).__init__(*args, **kwargs)
memberList = ContactList()
def init_fn(d):
d.chatroom = self
memberList.set_default_value(init_fn, ChatroomMember)
for rawMember in self.memberList:
memberList.append(rawMember)
self['MemberList'] = memberList
def update(self, detailedMember=False):
return self.core.update_chatroom(self.userName, detailedMember)
def set_alias(self, alias):
return self.core.set_chatroom_name(self.userName, alias)
def set_pinned(self, isPinned=True):
return self.core.set_pinned(self.userName, isPinned)
def delete_member(self, userName):
return self.core.delete_member_from_chatroom(self.userName, userName)
def add_member(self, userName):
return self.core.add_member_into_chatroom(self.userName, userName)
def search_member(self, name=None, userName=None, remarkName=None, nickName=None,
wechatAccount=None):
with self.core.storageClass.updateLock:
if (name or userName or remarkName or nickName or wechatAccount) is None:
return None
elif userName: # return the only userName match
for m in self.memberList:
if m.userName == userName:
return copy.deepcopy(m)
else:
matchDict = {
'RemarkName' : remarkName,
'NickName' : nickName,
'Alias' : wechatAccount, }
for k in ('RemarkName', 'NickName', 'Alias'):
if matchDict[k] is None:
del matchDict[k]
if name: # select based on name
contact = []
for m in self.memberList:
if any([m.get(k) == name for k in ('RemarkName', 'NickName', 'Alias')]):
contact.append(m)
else:
contact = self.memberList[:]
if matchDict: # select again based on matchDict
friendList = []
for m in contact:
if all([m.get(k) == v for k, v in matchDict.items()]):
friendList.append(m)
return copy.deepcopy(friendList)
else:
return copy.deepcopy(contact)
class ChatroomMember(AbstractUserDict):
def __init__(self, *args, **kwargs):
super(AbstractUserDict, self).__init__(*args, **kwargs)
self.core = fakeItchat
self.chatroom = self.fakeChatroom
def get_head_image(self, imageDir=None):
return self.core.get_head_img(self.userName, self.chatroom.userName, picDir=imageDir)
def delete_member(self, userName):
return self.core.delete_member_from_chatroom(self.chatroom.userName, self.userName)
def send_raw_msg(self, msgType, content):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not send message directly' % \
self.__class__.__name__, }, })
def send_msg(self, msg='Test Message'):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not send message directly' % \
self.__class__.__name__, }, })
def send_file(self, fileDir, mediaId=None):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not send message directly' % \
self.__class__.__name__, }, })
def send_image(self, fileDir, mediaId=None):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not send message directly' % \
self.__class__.__name__, }, })
def send_video(self, fileDir=None, mediaId=None):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not send message directly' % \
self.__class__.__name__, }, })
def send(self, msg, mediaId=None):
return ReturnValue({'BaseResponse': {
'Ret': -1006,
'ErrMsg': '%s can not send message directly' % \
self.__class__.__name__, }, })
def __deepcopy__(self, memo):
r = super(ChatroomMember, self).__deepcopy__(memo)
r.core = self.core
return r
ChatroomMember.fakeChatroom = Chatroom()
def wrap_user_dict(d):
userName = d.get('UserName')
if '@@' in userName:
r = Chatroom(d)
elif d.get('VerifyFlag', 8) & 8 == 0:
r = User(d)
else:
r = MassivePlatform(d)
return r
...@@ -106,7 +106,8 @@ def search_dict_list(l, key, value): ...@@ -106,7 +106,8 @@ def search_dict_list(l, key, value):
''' Search a list of dict ''' Search a list of dict
* return dict with specific value & key ''' * return dict with specific value & key '''
for i in l: for i in l:
if i.get(key) == value: return i if i.get(key) == value:
return i
def print_line(msg, oneLine = False): def print_line(msg, oneLine = False):
if oneLine: if oneLine:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册