def sendEmail(self): lastSubject = '' while True: qrcode = self.qrcode.getVal() if qrcode is None: break if lastSubject != self.qrcodeMail['subject']: qrcode = '' if self.qrcodeServer else qrcode try: with self.mailAgent.SMTP() as smtp: smtp.send(png_content=qrcode, **self.qrcodeMail) except Exception as e: WARN('无法将二维码发送至邮箱%s %s', self.mailAgent.account, e) else: INFO('已将二维码发送至邮箱%s', self.mailAgent.account) if self.qrcodeServer: break else: lastSubject = self.qrcodeMail['subject'] else: time.sleep(30) try: DEBUG('开始查询邮箱 %s 中的最近的邮件', self.mailAgent.account) with self.mailAgent.IMAP() as imap: lastSubject = imap.getSubject(-1) except Exception as e: WARN('查询邮箱 %s 中的邮件失败 %s', self.mailAgent.account, e) else: DEBUG('最近的邮件: %s', lastSubject)
def smartRequest(self, url, data=None, repeatOnDeny=2, sessionObj=None, **kw): session = sessionObj or self.session i, j = 0, 0 while True: html, timeOut = '', False session.headers.update(**kw) try: if data is None: resp = session.get(url) else: resp = session.post(url, data=data) if url == 'https://d1.web2.qq.com/channel/poll2': # DEBUG('POLL RESULT: status_code=%s, html=%s', # resp.status_code, resp.content) if resp.status_code in (502, 504): timeOut = True else: html = resp.content try: result = JsonLoads(html) except ValueError: timeOut = True if timeOut: session.get( ('http://pinghot.qq.com/pingd?dm=w.qq.com.hot&' 'url=/&hottag=smartqq.im.polltimeout&hotx=9999&' 'hoty=9999&rand=%s') % random.randint(10000, 99999)) continue else: html = resp.content result = JsonLoads(html) except (requests.ConnectionError, ValueError): i += 1 errorInfo = '网络错误或url地址错误' else: retcode = result.get('retcode', result.get('errCode', -1)) if retcode in (0, 1202, 100003): return result.get('result', result) else: j += 1 errorInfo = '请求被拒绝错误' # 出现网络错误可以多试几次 (i <= 4); # 若 retcode 有误,一般连续 3 次都出错就没必要再试了 (j <= 2) if i <= 4 and j <= repeatOnDeny: DEBUG('第%d次请求“%s”时出现“%s”, html:\n%s', i + j, url, errorInfo, html) else: CRITICAL('第%d次请求“%s”时出现“%s”,终止 QQBot', i + j, url, errorInfo) raise RequestError
def smartRequest(self, url, data=None, timeoutRetVal=None, repeateOnDeny=2, **kw): nCE, nTO, nUE, nDE = 0, 0, 0, 0 while True: url = url.format(rand=repr(random.random())) html = '' errorInfo = '' self.session.headers.update(**kw) try: if data is None: resp = self.session.get(url, verify=self.httpsVerify) else: resp = self.session.post(url, data=data, verify=self.httpsVerify) except requests.ConnectionError as e: nCE += 1 errorInfo = '网络错误 %s' % e else: html = resp.content if resp.status_code in (502, 504, 404): self.session.get( ('http://pinghot.qq.com/pingd?dm=w.qq.com.hot&' 'url=/&hottag=smartqq.im.polltimeout&hotx=9999&' 'hoty=9999&rand=%s') % random.randint(10000, 99999) ) if url == 'https://d1.web2.qq.com/channel/poll2': return {'errmsg': ''} nTO += 1 errorInfo = '超时' else: try: result = JsonLoads(html) except ValueError: nUE += 1 errorInfo = ' URL 地址错误' else: retcode = result.get('retcode', result.get('errCode', result.get('ec', -1))) if retcode in (0, 1202, 100003, 100100): return result.get('result', result) else: nDE += 1 errorInfo = '请求被拒绝错误' # 出现网络错误、超时、 URL 地址错误可以多试几次 # 若网络没有问题但 retcode 有误,一般连续 3 次都出错就没必要再试了 if nCE < 5 and nTO < 20 and nUE < 5 and nDE <= repeateOnDeny: DEBUG('第%d次请求“%s”时出现“%s”, html=%s', nCE+nTO+nUE+nDE, url, errorInfo, repr(html)) time.sleep(0.5) elif nTO == 20 and timeoutRetVal: # by @killerhack return timeoutRetVal else: CRITICAL('第%d次请求“%s”时出现“%s”', nCE+nTO+nUE+nDE, url, errorInfo) raise QSession.Error
def fetchForever(self): INFO('已在后台运行 fetchForever 方法,每隔 5 分钟获取一次联系人资料') while True: time.sleep(300) try: contacts = self.fetch() except (QSession.Error, Exception): WARN(' fetchForever 方法出错') DEBUG('', exc_info=True) else: yield Message('fetchcomplete', contacts=contacts)
def poll(self): result = self.smartRequest( url='https://d1.web2.qq.com/channel/poll2', data={ 'r': JsonDumps({ 'ptwebqq': self.ptwebqq, 'clientid': self.clientid, 'psessionid': self.psessionid, 'key': '' }) }, sessionObj=self.pollSession, Referer=('http://d1.web2.qq.com/proxy.html?v=20151105001&' 'callback=1&id=2')) if not result or 'errmsg' in result: DEBUG('无消息') return ('', 0, 0, '') # 无消息 else: result = result[0] msgType = { 'message': 'buddy', 'group_message': 'group', 'discu_message': 'discuss' }[result['poll_type']] from_uin = result['value']['from_uin'] buddy_uin = result['value'].get('send_uin', from_uin) msg = ''.join( ('[face%d]' % m[1]) if isinstance(m, list) else str(m) for m in result['value']['content'][1:]) if msgType == 'buddy': bName = self.getBuddyByUin(buddy_uin)['name'] INFO('来自 好友“%s” 的消息: "%s"' % (bName, msg)) elif msgType == 'group': group = self.getGroupByUin(from_uin) gName = group['name'] bName = group['member'].get(buddy_uin, 'unknown') INFO('来自 群“%s”[成员“%s”] 的消息: "%s"' % (gName, bName, msg)) else: discuss = self.getDiscussByUin(from_uin) gName = discuss['name'] bName = discuss['member'].get(buddy_uin, 'unknown') INFO('来自 讨论组“%s”[成员“%s”] 的消息: "%s"' % (gName, bName, msg)) return (msgType, from_uin, buddy_uin, msg)
def smartRequest(self, url, data=None, repeatOnDeny=2, sessionObj=None, **kw): session = sessionObj or self.session nCE, nTO, nUE, nDE = 0, 0, 0, 0 while True: url = url.format(rand=repr(random.random())) html, errorInfo = '', '' session.headers.update(**kw) try: if data is None: resp = session.get(url) else: resp = session.post(url, data=data) except requests.ConnectionError as e: nCE += 1 errorInfo = '网络错误 %s' % e else: html = resp.content if resp.status_code in (502, 504): session.get( ('http://pinghot.qq.com/pingd?dm=w.qq.com.hot&' 'url=/&hottag=smartqq.im.polltimeout&hotx=9999&' 'hoty=9999&rand=%s') % random.randint(10000, 99999)) if url == 'https://d1.web2.qq.com/channel/poll2': return {'errmsg': ''} nTO += 1 errorInfo = '超时' else: try: result = JsonLoads(html) except ValueError: nUE += 1 errorInfo = ' URL 地址错误' else: retcode = \ result.get('retcode', result.get('errCode', -1)) if retcode in (0, 1202, 100003): return result.get('result', result) else: nDE += 1 errorInfo = '请求被拒绝错误' # 出现网络错误或超时可以多试几次 (nCE < 5, nTO < 20); # 根据腾讯服务器的改标,增加了尝试次数 # 若出现 URL 地址错误或 retcode 有误,一般连续 3 次都出错就没必要再试了 if nCE < 5 and nTO < 20 and nUE < 3 and nDE <= repeatOnDeny: DEBUG('第%d次请求“%s”时出现“%s”, html=%s', nCE + nTO + nUE + nDE, url, errorInfo, repr(html)) else: if nTO == 20 and url.startswith( 'http://s.web2.qq.com/api/get_friend_uin2'): # 针对某个好友获取不到的情况,先返回一个空值,以确保成功登陆 # 防止因个别好友无法获得触发SystemExit,如果是因为其他原因则退出 return {'account': -1} CRITICAL('第%d次请求“%s”时出现“%s”,终止 QQBot', nCE + nTO + nUE + nDE, url, errorInfo) raise RequestError # (SystemExit)
def smartRequest(self, url, data=None, repeatOnDeny=2, sessionObj=None, **kw): session = sessionObj or self.session nCE, nUE, nDE = 0, 0, 0 while True: html, errorInfo = '', '' session.headers.update(**kw) try: if data is None: resp = session.get(url) else: resp = session.post(url, data=data) except requests.ConnectionError: nCE += 1 errorInfo = '网络错误' else: if url == 'https://d1.web2.qq.com/channel/poll2': timeOut = False if resp.status_code in (502, 504): timeOut = True else: html = resp.content try: result = JsonLoads(html) except ValueError: timeOut = True if timeOut: session.get( ('http://pinghot.qq.com/pingd?dm=w.qq.com.hot&' 'url=/&hottag=smartqq.im.polltimeout&hotx=9999&' 'hoty=9999&rand=%s') % random.randint(10000, 99999)) return {'errmsg': ''} else: html = resp.content try: result = JsonLoads(html) except ValueError: nUE += 1 errorInfo = 'URL地址错误' if not errorInfo: retcode = result.get('retcode', result.get('errCode', -1)) if retcode in (0, 1202, 100003): return result.get('result', result) else: nDE += 1 errorInfo = '请求被拒绝错误' # 出现网络错误或URL地址错误可以多试几次 (nCE<=4 and nUE<=3); # 若 retcode 有误,一般连续 3 次都出错就没必要再试了(nDE<=2) if nCE <= 4 and nUE <= 3 and nDE <= repeatOnDeny: DEBUG('第%d次请求“%s”时出现“%s”, html=%s', nCE + nUE + nDE, url, errorInfo, repr(html)) else: CRITICAL('第%d次请求“%s”时出现“%s”,终止 QQBot', nCE + nUE + nDE, url, errorInfo) raise RequestError # (SystemExit)