def _get_qr_code(self): """ 生成微信登录二维码 :return: """ params = { 'appid': WECHAT_APP_ID, 'fun': 'new', 'lang': 'zh_CN', '_': now() * 1000 + random.randint(1, 999), } r = self.session.get(WECHAT_FIRST_LOGIN_URL, params=params) r.encoding = 'utf-8' data = r.text regex = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)"' pm = re.search(regex, data) if pm: code = pm.group(1) self.params['uuid'] = pm.group(2) assert code == '200' else: raise BotServerException(BotErrorCode.GET_UUID_ERROR) img = qrcode.make(WECHAT_QR_CODE_STRING.format(self.params['uuid'])) img_in_memory = io.BytesIO() img.save(img_in_memory, 'png') img_in_memory.seek(0) files = {'smfile': img_in_memory} resp = requests.post(UPLOAD_IMG_URL, files=files) qr_code_url = json.loads(resp.content)['data']['url'] self.logger.info(red_alert(u"请打开此网页并扫描二维码:{}".format(qr_code_url))) img_in_memory.truncate()
def sync_check(self): """ sync check. """ params = { 'r': now(), 'skey': self.params['skey'], 'sid': self.params['sid'], 'uin': self.params['uin'], 'deviceid': self.params['device_id'], 'synckey': self.params['sync_key_str'], '_': now() } url = WECHAT_BOT_SYNC_CHECK_URL.format( sync_host=self.params['sync_host'], params=urllib.urlencode(params)) while True: try: r = self.session.get(url, timeout=20) r.encoding = 'utf-8' data = r.text pm = re.search( r'window.synccheck=\{retcode:"(\d+)",selector:"(\d+)"\}', data) retcode = pm.group(1) selector = pm.group(2) return [retcode, selector] except requests.exceptions.ReadTimeout: pass except: raise BotServerException(BotErrorCode.SYNC_CHECK_ERROR)
def sync_host_check(self): for host in ['webpush.', 'webpush2.']: self.params['sync_host'] = host + self.params['base_host'] try: code, selector = self.sync_check() if code == '0': return True except Exception as e: self.logger.info(e) raise BotServerException(BotErrorCode.SYNC_HOST_CHECK_ERROR)
def send_msg(self, reply): url = self.params['base_uri'] + '/webwxsendmsg' msg_id = str(now() * 1000) + str(random.random())[:5].replace('.', '') reply['Msg'].update({'LocalId': msg_id, 'ClientMsgId': msg_id}) data = json.dumps(reply, ensure_ascii=False).encode('utf-8') for i in range(5): try: r = self.session.post(url, data=data, headers=WECHAT_SEND_MSG_HEADER) except (requests.exceptions.ConnectTimeout, requests.exceptions.ReadTimeout): pass if r.status_code == 200: return raise BotServerException(BotErrorCode.SEND_MSG_ERROR)
def sync(self): url = WECHAT_BOT_SYNC_URL.format( base_uri=self.params['base_uri'], sid=self.params['sid'], skey=self.params['skey'], pass_ticket=self.params['pass_ticket']) params = { 'BaseRequest': self.params['base_request'], 'SyncKey': self.params['sync_key'], 'rr': ~int(now()) } try: r = self.session.post(url, data=json.dumps(params), timeout=60) r.encoding = 'utf-8' dic = json.loads(r.text) if dic['BaseResponse']['Ret'] == 0: self.params['sync_key'] = dic['SyncKey'] self.params['sync_key_str'] = '|'.join( str(data['Key']) + '_' + str(data['Val']) for data in self.params['sync_key']['List']) return dic except Exception: raise BotServerException(BotErrorCode.SYNC_ERROR)
def login(self, using_snap_shot=True): """ 登录 :return: """ self._get_qr_code() if not using_snap_shot else self.read_snapshot() redirect_url = None tip = 1 while not redirect_url: url = WECHAT_SECONT_LOGIN_URL.format(tip=tip, uuid=self.params['uuid'], now=now()) resp = self.session.get(url, headers=WECHAT_HEADERS) param = re.search(r'window.code=(\d+);', resp.text) code = param.group(1) if code == '201': tip = 0 elif code == '200': redirect_urls = re.search(r'\"(?P<redirect_url>.*)\"', resp.content) if redirect_urls: redirect_url = redirect_urls.group( 'redirect_url') + '&fun=new' self.params['base_uri'] = redirect_url[:redirect_url. rfind('/')] temp_host = self.params['base_uri'][8:] self.params['base_host'] = temp_host[:temp_host.find("/")] elif code == '400': raise BotServerException(BotErrorCode.SNAPSHOT_EXPIRED) else: tip = 1 resp = self.session.get(redirect_url) doc = xml.dom.minidom.parseString(resp.text.encode('utf-8')) root = doc.documentElement for node in root.childNodes: if node.nodeName == 'skey': self.params['skey'] = node.childNodes[0].data elif node.nodeName == 'wxsid': self.params['sid'] = node.childNodes[0].data elif node.nodeName == 'wxuin': self.params['uin'] = node.childNodes[0].data elif node.nodeName == 'pass_ticket': self.params['pass_ticket'] = node.childNodes[0].data if all([ self.params['skey'], self.params['sid'], self.params['uin'], self.params['pass_ticket'] ]): self.params['base_request'] = { 'DeviceID': self.params['device_id'], 'Sid': self.params['sid'], 'Skey': self.params['skey'], 'Uin': self.params['uin'] } self.init() self.save_snapshot() return True raise BotServerException(BotErrorCode.LOGIN_ERROR)