Browse Source

Bug fix and README change.

liuwons 9 years ago
parent
commit
3e37d66d60
4 changed files with 67 additions and 79 deletions
  1. 6 6
      README.md
  2. BIN
      img/backfront.jpg
  3. BIN
      img/send_msg.png
  4. 61 73
      wxbot.py

+ 6 - 6
README.md

@@ -1,8 +1,8 @@
 # wxBot [![star this repo](http://github-svg-buttons.herokuapp.com/star.svg?user=liuwons&repo=wxBot&style=flat&background=1081C1)](http://github.com/liuwons/wxBot) [![fork this repo](http://github-svg-buttons.herokuapp.com/fork.svg?user=liuwons&repo=wxBot&style=flat&background=1081C1)](http://github.com/liuwons/wxBot/fork) ![python](https://img.shields.io/badge/python-2.7-ff69b4.svg)
 
-Python包装的网页微信API。可以很容易地实现微信机器人。
+Python包装WEB微信实现的微信机器人框架。可以很容易地实现微信机器人。
 
-## Dependencies
+## 依赖
 程序用到了Python requests 和 pyqrcode库,使用之前需要安装这两个库:
 
 ```bash
@@ -10,7 +10,7 @@ pip install requests
 pip install pyqrcode
 ```
 
-## Example
+## 快速开发
 ### 代码
 
 利用 **wxBot** 最简单的方法就是继承WXBot类并实现handle_msg_all函数,然后实例化子类并run,如下的代码对所有的文本消息回复 hi 。
@@ -36,7 +36,7 @@ if __name__ == '__main__':
 
 ### 运行
 
-直接用python运行代码(如代码main.py)
+直接用python运行代码(如运行测试代码main.py):
 
 ``` python
 python main.py
@@ -49,8 +49,8 @@ python main.py
 
 ![1](img/1.png)
 
-## Demo
-利用 **[图灵机器人](http://www.tuling123.com/)** 做自动回复之后,通过测试账号发送各种消息的效果:
+## 效果展示
+测试代码main.py的运行效果:
 
 ![向机器人发送消息](img/send_msg.png)
 

BIN
img/backfront.jpg


BIN
img/send_msg.png


+ 61 - 73
wxbot.py

@@ -32,14 +32,14 @@ class WXBot:
         self.skey = ''
         self.pass_ticket = ''
         self.deviceId = 'e' + repr(random.random())[2:17]
-        self.BaseRequest = {}
-        self.synckey = ''
-        self.SyncKey = []
-        self.User = []
-        self.MemberList = []
-        self.ContactList = []
-        self.GroupList = []
-        self.syncHost = ''
+        self.base_request = {}
+        self.sync_key_str = ''
+        self.sync_key = []
+        self.user = []
+        self.member_list = []
+        self.contact_list = []
+        self.group_list = []
+        self.sync_host = ''
         self.session = requests.Session()
         self.session.headers.update({'User-Agent': 'Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5'})
 
@@ -89,9 +89,9 @@ class WXBot:
             self.base_uri = redirect_uri[:redirect_uri.rfind('/')]
             return True
         elif code == '408':
-            print '[login timeout]'
+            print '[ERROR] WeChat login timeout .'
         else:
-            print '[login exception]'
+            print '[ERROR] WeChat login exception .'
         return False
 
     def login(self):
@@ -114,7 +114,7 @@ class WXBot:
         if '' in (self.skey, self.sid, self.uin, self.pass_ticket):
             return False
 
-        self.BaseRequest = {
+        self.base_request = {
             'Uin': self.uin,
             'Sid': self.sid,
             'Skey': self.skey,
@@ -125,24 +125,24 @@ class WXBot:
     def init(self):
         url = self.base_uri + '/webwxinit?r=%i&lang=en_US&pass_ticket=%s' % (int(time.time()), self.pass_ticket)
         params = {
-            'BaseRequest': self.BaseRequest
+            'BaseRequest': self.base_request
         }
         r = self.session.post(url, json=params)
         r.encoding = 'utf-8'
         dic = json.loads(r.text)
-        self.SyncKey = dic['SyncKey']
-        self.User = dic['User']
-        self.synckey = '|'.join([ str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List'] ])
+        self.sync_key = dic['SyncKey']
+        self.user = dic['User']
+        self.sync_key_str = '|'.join([ str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.sync_key['List'] ])
         return dic['BaseResponse']['Ret'] == 0
 
     def status_notify(self):
         url = self.base_uri + '/webwxstatusnotify?lang=zh_CN&pass_ticket=%s' % (self.pass_ticket)
-        self.BaseRequest['Uin'] = int(self.BaseRequest['Uin'])
+        self.base_request['Uin'] = int(self.base_request['Uin'])
         params = {
-            'BaseRequest': self.BaseRequest,
+            'BaseRequest': self.base_request,
             "Code": 3,
-            "FromUserName": self.User['UserName'],
-            "ToUserName": self.User['UserName'],
+            "FromUserName": self.user['UserName'],
+            "ToUserName": self.user['UserName'],
             "ClientMsgId": int(time.time())
         }
         r = self.session.post(url, json=params)
@@ -158,32 +158,36 @@ class WXBot:
             with open('contacts.json', 'w') as f:
                 f.write(r.text.encode('utf-8'))
         dic = json.loads(r.text)
-        self.MemberList = dic['MemberList']
+        self.member_list = dic['MemberList']
 
-        ContactList = self.MemberList[:]
+        contact_list = self.member_list[:]
         SpecialUsers = ['newsapp','fmessage','filehelper','weibo','qqmail','fmessage','tmessage','qmessage','qqsync','floatbottle','lbsapp','shakeapp','medianote',
             'qqfriend','readerapp','blogapp','facebookapp','masssendapp','meishiapp','feedsapp','voip','blogappweixin','weixin','brandsessionholder','weixinreminder','wxid_novlwrv3lqwv11',
             'gh_22b87fa7cb3c','officialaccounts','notification_messages','wxid_novlwrv3lqwv11','gh_22b87fa7cb3c','wxitil','userexperience_alarm','notification_messages']
-        for contact in ContactList:
+        for contact in contact_list:
             if contact['VerifyFlag'] & 8 != 0: # public account
-                ContactList.remove(contact)
+                contact_list.remove(contact)
             elif contact['UserName'] in SpecialUsers: # special account
-                ContactList.remove(contact)
+                contact_list.remove(contact)
             elif contact['UserName'].find('@@') != -1: # group
-                self.GroupList.append(contact)
-                ContactList.remove(contact)
-            elif contact['UserName'] == self.User['UserName']: # self
-                ContactList.remove(contact)
-        self.ContactList = ContactList
+                self.group_list.append(contact)
+                contact_list.remove(contact)
+            elif contact['UserName'] == self.user['UserName']: # self
+                contact_list.remove(contact)
+        self.contact_list = contact_list
+
+        if self.DEBUG:
+            with open('contactlist.json', 'w') as f:
+                f.write(json.dumps(self.contact_list))
 
         return True
 
     def batch_get_contact(self):
         url = self.base_uri + '/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s' % (int(time.time()), self.pass_ticket)
         params = {
-            'BaseRequest': self.BaseRequest,
-            "Count": len(self.GroupList),
-            "List": [ {"UserName": g['UserName'], "EncryChatRoomId":""} for g in self.GroupList ]
+            'BaseRequest': self.base_request,
+            "Count": len(self.group_list),
+            "List": [ {"UserName": g['UserName'], "EncryChatRoomId":""} for g in self.group_list ]
         }
         r = self.session.post(url, data=params)
         r.encoding = 'utf-8'
@@ -192,7 +196,7 @@ class WXBot:
 
     def test_sync_check(self):
         for host in ['webpush', 'webpush2']:
-            self.syncHost = host
+            self.sync_host = host
             [retcode, selector] = self.sync_check()
             if retcode == '0':
                 return True
@@ -205,10 +209,10 @@ class WXBot:
             'uin': self.uin,
             'skey': self.skey,
             'deviceid': self.deviceId,
-            'synckey': self.synckey,
+            'synckey': self.sync_key_str,
             '_': int(time.time()),
         }
-        url = 'https://' + self.syncHost + '.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck?' + urllib.urlencode(params)
+        url = 'https://' + self.sync_host + '.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck?' + urllib.urlencode(params)
         r = self.session.get(url)
         r.encoding = 'utf-8'
         data = r.text
@@ -220,18 +224,16 @@ class WXBot:
     def sync(self):
         url = self.base_uri + '/webwxsync?sid=%s&skey=%s&lang=en_US&pass_ticket=%s' % (self.sid, self.skey, self.pass_ticket)
         params = {
-            'BaseRequest': self.BaseRequest,
-            'SyncKey': self.SyncKey,
+            'BaseRequest': self.base_request,
+            'SyncKey': self.sync_key,
             'rr': ~int(time.time())
         }
         r = self.session.post(url, json=params)
         r.encoding = 'utf-8'
         dic = json.loads(r.text)
-        if self.DEBUG:
-            print json.dumps(dic, indent=4)
         if dic['BaseResponse']['Ret'] == 0:
-            self.SyncKey = dic['SyncKey']
-            self.synckey = '|'.join([ str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List'] ])
+            self.sync_key = dic['SyncKey']
+            self.sync_key_str = '|'.join([ str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.sync_key['List'] ])
         return dic
 
     def get_icon(self, id):
@@ -264,16 +266,6 @@ class WXBot:
             f.write(data)
         return fn
 
-    # Not work now for weixin haven't support this API
-    def get_video(self, msgid):
-        url = self.base_uri + '/webwxgetvideo?msgid=%s&skey=%s' % (msgid, self.skey)
-        r = self.session.get(url)
-        data = r.content
-        fn = 'video_'+msgid+'.mp4'
-        with open(fn, 'wb') as f:
-            f.write(data)
-        return fn
-
     def get_voice_url(self, msgid):
         return self.base_uri + '/webwxgetvoice?msgid=%s&skey=%s' % (msgid, self.skey)
 
@@ -289,14 +281,14 @@ class WXBot:
     #Get the NickName or RemarkName of an user by user id
     def get_user_remark_name(self, uid):
         name = 'unknown group' if uid[:2] == '@@' else 'stranger'
-        for member in self.MemberList:
+        for member in self.member_list:
             if member['UserName'] == uid:
                 name = member['RemarkName'] if member['RemarkName'] else member['NickName']
         return name
 
     #Get user id of an user
     def get_user_id(self, name):
-        for member in self.MemberList:
+        for member in self.member_list:
             if name == member['RemarkName'] or name == member['NickName'] or name == member['UserName']:
                 return member['UserName']
         return None
@@ -359,7 +351,7 @@ class WXBot:
                     if self.DEBUG:
                         print '[File] %s : %s' % (name, )
 
-                elif msg['FromUserName'] == self.User['UserName']: #self
+                elif msg['FromUserName'] == self.user['UserName']: #self
                     msg_type_id = 3
 
                 elif msg['FromUserName'][:2] == '@@':
@@ -452,19 +444,17 @@ class WXBot:
             self.handle_msg_all(message)
 
     def proc_msg(self):
-        print 'proc start'
         self.test_sync_check()
         while True:
             [retcode, selector] = self.sync_check()
-            if retcode == '1100':
+            if retcode == '1100': # User have login on mobile
                 pass
-                #print '[*] you have login on mobile'
             elif retcode == '0':
                 if selector == '2':
                     r = self.sync()
                     if r is not None:
                         self.handle_msg(r)
-                elif selector == '7': # play WeChat on mobile
+                elif selector == '7': # Play WeChat on mobile
                     r = self.sync()
                     if r is not None:
                         self.handle_msg(r)
@@ -475,11 +465,11 @@ class WXBot:
         url = self.base_uri + '/webwxsendmsg?pass_ticket=%s' % (self.pass_ticket)
         msg_id = str(int(time.time()*1000)) + str(random.random())[:5].replace('.','')
         params = {
-            'BaseRequest': self.BaseRequest,
+            'BaseRequest': self.base_request,
             'Msg': {
                 "Type": 1,
                 "Content": make_unicode(word),
-                "FromUserName": self.User['UserName'],
+                "FromUserName": self.user['UserName'],
                 "ToUserName": dst,
                 "LocalID": msg_id,
                 "ClientMsgId": msg_id
@@ -512,8 +502,10 @@ class WXBot:
                 else:
                     return False
         else:
-            print '[*] this user does not exist'
+            if self.DEBUG:
+                print '[ERROR] This user does not exist .'
             return False
+
     def search_content(self, key, content, fmat = 'attr'):
         if fmat == 'attr':
             pm = re.search(key+'\s?=\s?"([^"<]+)"', content)
@@ -525,27 +517,23 @@ class WXBot:
 
     def run(self):
         self.get_uuid()
-        print 'get uuid end'
         self.gen_qr_code('qr.jpg')
-        print 'gen qr code end'
+        print '[INFO] Please use WeCaht to scan QR code in qr.jpg .'
         self.wait4login(1)
-        print 'wait4login end'
+        print '[INFO] Please confirm to login .'
         self.wait4login(0)
-        print 'wait4login end'
         if self.login():
-            print 'login succeed'
+            print '[INFO] Web WeChat login succeed .'
         else:
-            print 'login failed'
+            print '[ERROR] Web WeChat login failed .'
             return
         if self.init():
-            print 'init succeed'
+            print '[INFO] Web WeChat init succeed .'
         else:
-            print 'init failed'
+            print '[INFO] Web WeChat init failed'
             return
-        print 'init end'
         self.status_notify()
-        print 'status notify end'
         self.get_contact()
-        print 'get %d contacts' % len(self.ContactList)
-
+        print '[INFO] Get %d contacts' % len(self.contact_list)
+        print '[INFO] Start to process messages .'
         self.proc_msg()