Skip to content

Commit

Permalink
Make master branch compatibile to py3
Browse files Browse the repository at this point in the history
  • Loading branch information
littlecodersh committed Jul 19, 2016
1 parent 8847d95 commit fad672a
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 90 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ def text_reply(msg):
itchat.send(u'@%s\u2005I received: %s'%(msg['ActualNickName'], msg['Content']), msg['FromUserName'])

itchat.auto_login()
# if you don't want to use hot reload, you may use the following login command instead
# itchat.auto_login(hotReload = False)
itchat.run()
```

Expand Down
2 changes: 0 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ Here is the `code <https://github.com/littlecodersh/ItChat/tree/robot>`__.
itchat.send(u'@%s\u2005I received: %s'%(msg['ActualNickName'], msg['Content']), msg['FromUserName'])
itchat.auto_login()
# if you don't want to use hot reload, you may use the following login command instead
# itchat.auto_login(hotReload = False)
itchat.run()
**FAQ**
Expand Down
2 changes: 0 additions & 2 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ def text_reply(msg):
itchat.send(u'@%s\u2005I received: %s'%(msg['ActualNickName'], msg['Content']), msg['FromUserName'])

itchat.auto_login()
# if you don't want to use hot reload, you may use the following login command instead
# itchat.auto_login(hotReload = False)
itchat.run()
```

Expand Down
15 changes: 15 additions & 0 deletions docs/2.Login.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,27 @@ if itchat.load_login_status():
def simple_reply(msg):
print(msg['Text'])
itchat.run()
itchat.dump_login_status()
else:
itchat.auto_login()
itchat.dump_login_status()
print('Config stored')
```

或者直接使用内置的代码也可:

```python
import itchat

@itchat.msg_register('Text')
def simple_reply(msg):
print(msg['Text'])

itchat.auto_login(hotReload = True)
itchat.run()
itchat.dump_login_status()
```

## 自定义登录过程

如果需要控制登录的过程,可以阅读下面的内容。
Expand Down
20 changes: 10 additions & 10 deletions itchat/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import time, thread
from client import client
import time
from .client import client

import traceback

__version__ = '1.0.12'
__version__ = '1.0.13'

__client = client()
def auto_login(hotReload = True, statusStorageDir = 'itchat.pkl'):
def auto_login(hotReload = False, statusStorageDir = 'itchat.pkl'):
if hotReload:
if __client.load_login_status(statusStorageDir): return
__client.auto_login()
Expand Down Expand Up @@ -78,7 +76,9 @@ def _msg_register(fn, *_args, **_kwargs):
# in-build run
def run():
print('Start auto replying')
while 1:
configured_reply()
time.sleep(.3)

try:
while 1:
configured_reply()
time.sleep(.3)
except KeyboardInterrupt:
print('Bye~')
130 changes: 63 additions & 67 deletions itchat/client.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import os, sys, pickle
import requests, time, re
import thread, subprocess
import threading, subprocess
import json, xml.dom.minidom, mimetypes
import config, storage, out, tools
from . import config, storage, out, tools

BASE_URL = config.BASE_URL

Expand Down Expand Up @@ -37,7 +37,7 @@ def load_login_status(self, fileDir):
self.s.cookies = requests.utils.cookiejar_from_dict(j['cookies'])
self.storageClass.loads(j['storage'])
if self.__sync_check():
out.print_line('Login successfully as %s\n'%self.storageClass.nickName, False)
out.print_line('Login successfully as %s\n'%self.storageClass.nickName, True)
self.start_receiving()
return True
else:
Expand All @@ -49,7 +49,7 @@ def open_QR():
while not self.get_QRuuid(): time.sleep(1)
out.print_line('Getting QR Code', True)
if self.get_QR(): break
elif get_count >= 9:
elif 9 <= get_count:
out.print_line('Failed to get QR Code, please restart the program')
sys.exit()
out.print_line('Please scan the QR Code', True)
Expand All @@ -72,11 +72,9 @@ def open_QR():
def get_QRuuid(self):
url = '%s/jslogin'%BASE_URL
payloads = {
'appid': 'wx782c26e4c19acffb',
'fun': 'new',
}
'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':
Expand Down Expand Up @@ -114,13 +112,13 @@ def check_login(self, uuid = None):
self.loginInfo['BaseRequest'] = {}
for node in xml.dom.minidom.parseString(r.text).documentElement.childNodes:
if node.nodeName == 'skey':
self.loginInfo['skey'] = self.loginInfo['BaseRequest']['Skey'] = node.childNodes[0].data.encode('utf8')
self.loginInfo['skey'] = self.loginInfo['BaseRequest']['Skey'] = node.childNodes[0].data
elif node.nodeName == 'wxsid':
self.loginInfo['wxsid'] = self.loginInfo['BaseRequest']['Sid'] = node.childNodes[0].data.encode('utf8')
self.loginInfo['wxsid'] = self.loginInfo['BaseRequest']['Sid'] = node.childNodes[0].data
elif node.nodeName == 'wxuin':
self.loginInfo['wxuin'] = self.loginInfo['BaseRequest']['Uin'] = node.childNodes[0].data.encode('utf8')
self.loginInfo['wxuin'] = self.loginInfo['BaseRequest']['Uin'] = node.childNodes[0].data
elif node.nodeName == 'pass_ticket':
self.loginInfo['pass_ticket'] = self.loginInfo['BaseRequest']['DeviceID'] = node.childNodes[0].data.encode('utf8')
self.loginInfo['pass_ticket'] = self.loginInfo['BaseRequest']['DeviceID'] = node.childNodes[0].data
return '200'
elif data and data.group(1) == '201':
return '201'
Expand All @@ -131,8 +129,7 @@ def check_login(self, uuid = None):
def web_init(self):
url = '%s/webwxinit?r=%s' % (self.loginInfo['url'], int(time.time()))
payloads = {
'BaseRequest': self.loginInfo['BaseRequest']
}
'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'))
Expand Down Expand Up @@ -172,7 +169,8 @@ def get_contract(self, update = False):
self.memberList.append(tools.emoji_dealer(m))
elif not (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))])):
list(range(ord('a'), ord('z') + 1)) +
list(range(ord('A'), ord('Z') + 1)))])):
continue # userName have number and str
elif '@@' in m['UserName']:
self.chatroomList.append(tools.emoji_dealer(m))
Expand Down Expand Up @@ -209,11 +207,13 @@ def maintain_loop():
time.sleep(pauseTime)
i = self.__sync_check()
count = 0
except Exception, e:
except Exception as e:
count += 1
time.sleep(count*3)
out.print_line('LOG OUT', False)
thread.start_new_thread(maintain_loop, ())
maintainThread = threading.Thread(target = maintain_loop)
maintainThread.setDaemon(True)
maintainThread.start()
def __sync_check(self):
url = '%s/synccheck'%self.loginInfo['url']
payloads = {
Expand Down Expand Up @@ -342,7 +342,7 @@ def download_video(videoDir):
payloads = {
'msgid': m['MsgId'],
'skey': self.loginInfo['skey'],}
headers = { 'Range:': 'bytes=0-'}
headers = {'Range': 'bytes=0-'}
r = self.s.get(url, params = payloads, headers = headers, stream = True)
with open(videoDir, 'wb') as f:
for chunk in r.iter_content(chunk_size = 1024):
Expand Down Expand Up @@ -418,14 +418,14 @@ def send_msg(self, msg = 'Test Message', toUserName = None):
'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'),
'Content': msg,
'FromUserName': self.storageClass.userName,
'ToUserName': (toUserName if toUserName else self.storageClass.userName),
'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)
r = self.s.post(url, data = json.dumps(payloads, ensure_ascii = False).encode('utf8'), headers = headers)
def __upload_file(self, fileDir, isPicture = False):
if not tools.check_file(fileDir): return
url = 'https://file%s.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json'%('2' if '2' in self.loginInfo['url'] else '')
Expand All @@ -434,24 +434,22 @@ def __upload_file(self, fileDir, isPicture = False):
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),
}
'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']
Expand All @@ -461,45 +459,44 @@ def send_file(self, fileDir, toUserName = None):
if mediaId is None: return False
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), }, }
'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('.','')),
'FromUserName': self.storageClass.userName,
'ToUserName': toUserName,
'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)
r = self.s.post(url, data = json.dumps(payloads, ensure_ascii = False).encode('utf8'), headers = headers)
return True
def send_image(self, fileDir, toUserName = None):
if toUserName is None: toUserName = self.storageClass.userName
mediaId = self.__upload_file(fileDir, isPicture = not fileDir[-4:] == '.gif')
if mediaId is None: return False
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), }, }
'BaseRequest': self.loginInfo['BaseRequest'],
'Msg': {
'Type': 3,
'MediaId': mediaId,
'FromUserName': self.storageClass.userName,
'ToUserName': toUserName,
'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)
r = self.s.post(url, data = json.dumps(payloads, ensure_ascii = False).encode('utf8'), headers = headers)
return True
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'])
Expand All @@ -509,12 +506,11 @@ def add_friend(self, Status, UserName, Ticket):
'VerifyUserListSize': 1,
'VerifyUserList': [{
'Value': UserName,
'VerifyUserTicket': Ticket,
}],
'VerifyUserTicket': Ticket, }],
'VerifyContent': '',
'SceneListCount': 1,
'SceneList': 33,
'skey': self.loginInfo['skey'],}
'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 = ''):
Expand All @@ -536,7 +532,7 @@ def delete_member_from_chatroom(self, chatRoomName, memberList):
params = {
'BaseRequest': self.loginInfo['BaseRequest'],
'ChatRoomName': chatRoomName,
'DelMemberList': ','.join([member['UserName'] for member in memberList]),}
'DelMemberList': ','.join([member['UserName'] for member in memberList]), }
headers = {'content-type': 'application/json; charset=UTF-8'}
return self.s.post(url, data=json.dumps(params),headers=headers)
def add_member_into_chatroom(self, chatRoomName, memberList):
Expand All @@ -545,7 +541,7 @@ def add_member_into_chatroom(self, chatRoomName, memberList):
params = {
'BaseRequest': self.loginInfo['BaseRequest'],
'ChatRoomName': chatRoomName,
'AddMemberList': ','.join([member['UserName'] for member in memberList]),}
'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)

Expand Down
5 changes: 3 additions & 2 deletions itchat/out.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import sys
import config

from . import config

def ErrorIgnore(fn, *args, **kwargs):
def wrapped(*args, **kwargs):
try:
result = fn(*args, **kwargs)
return result
except:
print 'Encode Fail'
print('Encode Fail')
return None
return wrapped

Expand Down
4 changes: 2 additions & 2 deletions itchat/storage.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os, time
import config
from . import config

class Storage:
def __init__(self):
Expand All @@ -26,7 +26,7 @@ def loads(self, j):
del self.chatroomList[:]
for i in j.get('chatroomList', []): self.chatroomList.append(i)
self.groupDict.clear()
for k, v in j.get('groupDict', {}).iteritems(): self.groupDict[k] = v
for k, v in j.get('groupDict', {}).items(): self.groupDict[k] = v
self.lastInputUserName = j.get('lastInputUserName', None)
def find_username(self, n):
r = []
Expand Down
5 changes: 2 additions & 3 deletions itchat/tools.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import re
import re, os

import os
import config
from . import config

def clear_screen():
os.system('cls' if config.OS == 'Windows' else 'clear')
Expand Down

0 comments on commit fad672a

Please sign in to comment.