def _load_config(self, config_file): config = None if config_file is not None: if os.path.isfile(config_file): with open(config_file, "r") as f: config = json.load(f) else: raise ConfigFileDoesNotExist( "Config file {} does not exist.".format(config_file)) elif os.path.isfile(DEFAULT_PLUGIN_CONFIG + ".example"): if not os.path.isfile(DEFAULT_PLUGIN_CONFIG): shutil.copy(DEFAULT_PLUGIN_CONFIG + ".example", DEFAULT_PLUGIN_CONFIG) logger.warning("No plugin config file found. Auto copied.") with open(DEFAULT_PLUGIN_CONFIG, "r") as f: config = json.load(f) else: # 缺少配置文件以及example文件 exception_str = "Config file does not exist, please check the config path." logger.exception(exception_str) raise ConfigFileDoesNotExist(exception_str) if config is not None: for key in ("plugin_package", PLUGIN_ON): if not isinstance(config.get("plugin_package", []), list): raise ConfigKeyError( "Config key [%s] has wrong type [%s]" % (key, type(config[PLUGIN_PACKAGES]))) self.config[PLUGIN_PACKAGES] = config[PLUGIN_PACKAGES] self.config[PLUGIN_ON] = config[PLUGIN_ON]
def uin_to_account(self, tuin): """ 将uin转换成用户QQ号 :param tuin: :return:str 用户QQ号 """ uin_str = str(tuin) try: logger.info("RUNTIMELOG Requesting the account by uin: " + str(tuin)) info = json.loads( self.client.get( 'http://s.web2.qq.com/api/get_friend_uin2?tuin={0}&type=1&vfwebqq={1}&t={2}'.format( uin_str, self.vfwebqq, self.client.get_timestamp() ), SMART_QQ_REFER ) ) logger.debug("RESPONSE uin_to_account html: " + str(info)) if info['retcode'] != 0: raise TypeError('uin_to_account retcode error') info = info['result']['account'] return info except Exception: logger.exception("RUNTIMELOG uin_to_account fail") return None
def _load_config(self, config_file): config = None if config_file is not None: if os.path.isfile(config_file): with open(config_file, "r") as f: config = json.load(f) else: raise ConfigFileDoesNotExist( "Config file {} does not exist.".format(config_file) ) elif os.path.isfile(DEFAULT_PLUGIN_CONFIG + ".example"): if not os.path.isfile(DEFAULT_PLUGIN_CONFIG): shutil.copy(DEFAULT_PLUGIN_CONFIG + ".example", DEFAULT_PLUGIN_CONFIG) logger.warning("No plugin config file found. Auto copied.") with open(DEFAULT_PLUGIN_CONFIG, "r") as f: config = json.load(f) else: # 缺少配置文件以及example文件 exception_str = "Config file does not exist, please check the config path." logger.exception(exception_str) raise ConfigFileDoesNotExist(exception_str) if config is not None: for key in ("plugin_package", PLUGIN_ON): if not isinstance(config.get("plugin_package", []), list): raise ConfigKeyError( "Config key [%s] has wrong type [%s]" % (key, type(config[PLUGIN_PACKAGES])) ) self.config[PLUGIN_PACKAGES] = config[PLUGIN_PACKAGES] self.config[PLUGIN_ON] = config[PLUGIN_ON]
def main_loop(no_gui=False, new_user=False, debug=False): patch() if debug: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) logger.info("Initializing...") plugin_manager.load_plugin() if new_user: clean_cookie() bot.login(no_gui) observer = MessageObserver(bot) while True: try: msg_list = bot.check_msg() if msg_list is not None: observer.handle_msg_list( [mk_msg(msg) for msg in msg_list] ) except ServerResponseEmpty: continue except (socket.timeout, IOError): logger.warning("Message pooling timeout, retrying...") except Exception: logger.exception("Exception occurs when checking msg.")
def _load_config(self, config_file): config = None if config_file is not None: # 指定了特定配置文件 if os.path.isfile(config_file): with open(config_file, "r") as f: config = json.load(f) else: raise ConfigFileDoesNotExist( "Config file {} does not exist.".format(config_file)) elif os.path.isfile(DEFAULT_PLUGIN_CONFIG): # 存在配置文件 with open(DEFAULT_PLUGIN_CONFIG, "r") as f: config = json.load(f) elif os.path.isfile(DEFAULT_PLUGIN_CONFIG + ".example"): # 不存在配置文件但有example文件 shutil.copy(DEFAULT_PLUGIN_CONFIG + ".example", DEFAULT_PLUGIN_CONFIG) logger.warning("No plugin config file found. Auto copied.") with open(DEFAULT_PLUGIN_CONFIG, "r") as f: config = json.load(f) else: # 缺少配置文件以及example文件 exception_str = "Config file does not exist, please check the config path." logger.exception(exception_str) raise ConfigFileDoesNotExist(exception_str) self.config[QQ] = config[QQ] self.config[PASSWORD] = config[PASSWORD]
def success(f): try: f() return True except Exception as e: logger.exception(e) return False
def login(self, no_gui=False): def success(f): try: f() return True except Exception as e: logger.exception(e) return False while not success(lambda: self._login_by_cookie()): while not success(lambda: self._login_by_qrcode(no_gui)): time.sleep(4) user_info = self.get_self_info() self.query_friends_accounts() self.get_online_friends_list() self.get_group_list_with_group_id() self.get_group_list_with_group_code() try: self.username = user_info['nick'] logger.info( "User information got: user name is [%s]" % self.username ) self._last_pool_success = True except KeyError: logger.exception( "User info access failed, check your login and response:\n%s" % user_info ) exit(1) logger.info("RUNTIMELOG QQ:{0} login successfully, Username:{1}".format(self.account, self.username))
def uin_to_account(self, tuin): """ 将uin转换成用户QQ号 :param tuin: :return:str 用户QQ号 """ uin_str = str(tuin) if sql.fetch_one('select account_id from account_data where account_code={0};'.format(uin_str)): return sql.fetch_one('select account_id from account_data where account_code={0};'.format(uin_str))[0]; else: try: logger.debug("[UIN_TO_ACCOUNT] " + str(tuin)) info = json.loads( self.client.get( 'http://s.web2.qq.com/api/get_friend_uin2?tuin={0}&type=1&vfwebqq={1}&t={2}'.format( uin_str, self.vfwebqq, self.client.get_timestamp() ), SMART_QQ_REFER ) ) logger.debug("RESPONSE uin_to_account html: " + str(info)) if info['retcode'] != 0: raise TypeError('uin_to_account retcode error') info = info['result']['account'] if sql.fetch_one('select * from account_data where account_id={0};'.format(info)): sql.execute('update account_data set account_code={0} where account_id={1};'.format(uin_str,info)) else: sql.execute("insert into account_data(account_id,account_code) values('{0}','{1}');".format(info,uin_str)) return info except Exception: logger.exception("RUNTIMELOG uin_to_account fail") return None
def login(self, no_gui=False): try: self._login_by_cookie() except CookieLoginFailed: logger.exception(CookieLoginFailed) while True: if self._login_by_qrcode(no_gui): if self._login_by_cookie(): break time.sleep(4) user_info = self.get_self_info() self.get_online_friends_list() self.get_group_list_with_group_id() self.get_group_list_with_group_code() try: self.username = user_info['nick'] logger.info("User information got: user name is [%s]" % self.username) self._last_pool_success = True except KeyError: logger.exception( "User info access failed, check your login and response:\n%s" % user_info) exit(1) logger.info( "RUNTIMELOG QQ:{0} login successfully, Username:{1}".format( self.account, self.username))
def main_loop(no_gui=False, new_user=False, debug=False): patch() if debug: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) logger.info("Initializing...") plugin_manager.load_plugin() if new_user: clean_cookie() bot.login(no_gui) observer = MessageObserver(bot) for name, func in bot_inited_registry.iteritems(): try: func(bot) except Exception: logging.exception( "Error occurs while loading plugin [%s]." % name ) while True: try: msg_list = bot.check_msg() if msg_list is not None: observer.handle_msg_list( [mk_msg(msg) for msg in msg_list] ) except ServerResponseEmpty: continue except (socket.timeout, IOError): logger.warning("Message pooling timeout, retrying...") except Exception: logger.exception("Exception occurs when checking msg.")
def login(self, no_gui=False): try: self._login_by_cookie() except CookieLoginFailed: logger.info("Cookie login failed.") while True: if self._login_by_qrcode(no_gui): if self._login_by_cookie(): break time.sleep(4) user_info = self.get_self_info() self.get_online_friends_list() self.get_group_list_with_group_id() self.get_group_list_with_group_code() try: self.username = user_info['nick'] logger.info( "User information got: user name is [%s]" % self.username ) except KeyError: logger.exception( "User info access failed, check your login and response:\n%s" % user_info ) exit(1) logger.info("RUNTIMELOG QQ:{0} login successfully, Username:{1}".format(self.account, self.username))
def run(self): while True: if self._stopped: break task = self.queue.get() try: task.func(**task.kwargs) except Exception: logger.exception( "Error occurs when running task from plugin [%s]." % task.name) self._stop_done = True
def _login_by_cookie(self): logger.info("Try cookie login...") self.client.load_cookie() self.ptwebqq = self.client.get_cookie('ptwebqq') response = self.client.post( 'http://d1.web2.qq.com/channel/login2', { 'r': '{{"ptwebqq":"{0}","clientid":{1},"psessionid":"{2}","status":"online"}}'.format( self.ptwebqq, self.client_id, self.psessionid ) }, SMART_QQ_REFER ) retry_times = 5 while True: try: ret = json.loads(response) break except ValueError: retry_times -= 1 logger.exception( "Cookies login fail, response decode error:{0}".format(response) ) if retry_times == 0: raise CookieLoginFailed("Cookies login fail, response decode error too many times") if ret['retcode'] != 0: raise CookieLoginFailed("Login step 1 failed with response:\n %s " % ret) response2 = self.client.get( "http://s.web2.qq.com/api/getvfwebqq?ptwebqq={0}&clientid={1}&psessionid={2}&t={3}".format( self.ptwebqq, self.client_id, self.psessionid, self.client.get_timestamp() ) ) ret2 = json.loads(response2) if ret2['retcode'] != 0: raise CookieLoginFailed( "Login step 2 failed with response:\n %s " % ret2 ) self.psessionid = ret['result']['psessionid'] self.account = ret['result']['uin'] self.vfwebqq = ret2['result']['vfwebqq'] logger.info("Login by cookie succeed. account: %s" % self.account) return True
def run(self): while True: if self._stopped: break task = self.queue.get() try: task.func(**task.kwargs) except Exception: logger.exception( "Error occurs when running task from plugin [%s]." % task.name ) self._stop_done = True
def load(self, url, data=None, refer=None, parser=json_loads, validator=None, retries=5): while True: try: if data: logger.debug("POST {} with data {}".format(url, data)) resp = self.session.post( url, data, headers=self._get_headers( {'Referer': refer or SMART_QQ_REFER}), verify=SSL_VERIFY, ) else: logger.debug("GET {}".format(url)) resp = self.session.get( url, headers=self._get_headers( {'Referer': refer or SMART_QQ_REFER}), verify=SSL_VERIFY, ) resp = resp.text logger.debug("response: {}".format(resp)) if parser: resp = parser(resp) if validator: validator(resp) except requests.exceptions.SSLError: logger.exception( "SSL连接验证失败,请检查您所在的网络环境。如果需要禁用SSL验证,请修改config.py中的SSL_VERIFY为False" ) raise except Exception as e: logger.exception(e) retries -= 1 if retries == 0: raise else: self._cookies.save(COOKIE_FILE, ignore_discard=True, ignore_expires=True) return resp logger.error("request failed, retrying in 2 seconds") time.sleep(2)
def download(self, url, fname): with open(fname, "wb") as o_file: try: resp = self.session.get(url, stream=True, verify=SSL_VERIFY) except requests.exceptions.SSLError: logger.exception("SSL连接验证失败,请检查您所在的网络环境。如果需要禁用SSL验证,请修改config.py中的SSL_VERIFY为False") except (excps.ConnectTimeout, excps.HTTPError): error_msg = "Failed to send request to `{0}`".format( url ) logger.exception(error_msg) return error_msg else: o_file.write(resp.raw.read())
def download(self, url, fname): with open(fname, "wb") as o_file: try: resp = self.session.get(url, stream=True, verify=SSL_VERIFY) except requests.exceptions.SSLError: logger.exception( "SSL连接验证失败,请检查您所在的网络环境。如果需要禁用SSL验证,请修改config.py中的SSL_VERIFY为False" ) except (excps.ConnectTimeout, excps.HTTPError): error_msg = "Failed to send request to `{0}`".format(url) logger.exception(error_msg) return error_msg else: o_file.write(resp.raw.read())
def check_msg(self): # Pooling the message try: ret = self.client.load( 'http://d1.web2.qq.com/channel/poll2', { 'r': json.dumps( { "ptwebqq": self.ptwebqq, "clientid": self.client_id, "psessionid": self.psessionid, "key": "" } ) }, SMART_QQ_REFER, parser=lambda resp: json.loads(resp.replace(r"\u0026lt;", "<").replace(r"\u0026gt;", ">")) ) except Exception as e: logger.exception(e) return ret_code = ret['retcode'] if ret_code in (0, 116, 1202): self._last_pool_success = True if ret_code == 0: if 'result' not in ret or len(ret['result']) == 0: logger.info("Pooling ends, no new message received.") else: return ret['result'] elif ret_code == 116: self.ptwebqq = ret['p'] logger.debug("ptwebqq updated in this pooling") else: self._last_pool_success = False if ret_code in (103, ): raise NeedRelogin("Pooling received retcode: " + str(ret_code)) elif ret_code in (121,): logger.warning("Pooling error with retcode %s" % ret_code) elif ret_code == 100006: logger.error("Pooling request error, response is: %s" % ret) elif ret_code in (100001, 100012): raise NeedRelogin("Login is expired. Please relogin by qrcode") else: logger.warning("Pooling returns unknown retcode %s" % ret_code) time.sleep(2) return None
def uin_to_account(self, tuin): """ 将uin转换成用户QQ号 :param tuin: :return:str 用户QQ号 """ uin_str = str(tuin) try: logger.info("searching the account by uin:\t{}".format(str(tuin))) return self.friend_uin_list.get(uin_str, {}).get('account', "") except Exception as e: logger.exception("uin_to_account fail, {}".format(e)) return ""
def get(self, url, refer=None): try: resp = self.session.get( url, headers=self._get_headers({'Referer': refer or SMART_QQ_REFER}), ) except (excps.ConnectTimeout, excps.HTTPError): error_msg = "Failed to send finish request to `{0}`".format(url) logger.exception(error_msg) return error_msg else: self._cookies.save(COOKIE_FILE, ignore_discard=True, ignore_expires=True) return resp.text
def monitorLoop(): #监听消息用的循环,用以实现被动回复消息 while True: try: msg_list = bot.check_msg() if msg_list is not None: print('msg_list = {}'.format(msg_list)) observer.handle_msg_list( [mk_msg(msg, bot) for msg in msg_list]) except ServerResponseEmpty: continue except (socket.timeout, IOError): logger.warning("Message pooling timeout, retrying...") except NeedRelogin: exit(0) except Exception: logger.exception("Exception occurs when checking msg.")
def post(self, url, data, refer=None): try: resp = self.session.post( url, data, headers=self._get_headers({'Referer': refer or SMART_QQ_REFER}), ) except Exception: error_msg = "Failed to send request to `{0}`".format(url) logger.exception(error_msg) return error_msg else: self._cookies.save(COOKIE_FILE, ignore_discard=True, ignore_expires=True) return resp.text
def get(self, url, refer=None): try: resp = self.session.get( url, headers=self._get_headers({'Referer': refer or SMART_QQ_REFER}), verify=SSL_VERIFY, ) except (excps.ConnectTimeout, excps.HTTPError): error_msg = "Failed to send finish request to `{0}`".format( url ) logger.exception(error_msg) return error_msg except requests.exceptions.SSLError: logger.exception("SSL连接验证失败,请检查您所在的网络环境。如果需要禁用SSL验证,请修改config.py中的SSL_VERIFY为False") else: self._cookies.save(COOKIE_FILE, ignore_discard=True, ignore_expires=True) return resp.text
def run(): patch() logger.setLevel(logging.INFO) logger.info("Initializing...") plugin_manager.load_plugin() bot.login() observer = MessageObserver(bot) while True: try: msg_list = bot.check_msg() if msg_list is not None: observer.handle_msg_list([mk_msg(msg) for msg in msg_list]) except ServerResponseEmpty: continue except (socket.timeout, IOError): logger.warning("Message pooling timeout, retrying...") except Exception: logger.exception("Exception occurs when checking msg.")
def account_to_uin(self, qq_account): """ 用户好友的QQ号转换成uin,注意,仅支持查询好友的uin :param qq_account: :return:str 用户uin """ qq_account = str(qq_account) try: logger.info("searching the uin by account:\t{}".format(str(qq_account))) for uin, info in self.friend_uin_list.items(): if info.get('account', '') == qq_account: return uin logger.warning("没有找到{}对应的uin,请确认这个qq号是否是你的好友".format(qq_account)) logger.warning(str(self.friend_uin_list)) return "" except Exception as e: logger.exception("account_to_uin fail, {}".format(e)) return ""
def send_friend_msg(self, reply_content, uin, msg_id, fail_times=0): fix_content = self.quote(reply_content) rsp = "" try: req_url = "http://d1.web2.qq.com/channel/send_buddy_msg2" data = { 'r': '{{"to":{0}, "face":594, "content":"[\\"{4}\\", [\\"font\\", {{\\"name\\":\\"Arial\\", \\"size\\":\\"10\\", \\"style\\":[0, 0, 0], \\"color\\":\\"000000\\"}}]]", "clientid":{1}, "msg_id":{2}, "psessionid":"{3}"}}'.format( uin, self.client_id, msg_id, self.psessionid, fix_content), 'clientid': self.client_id, 'psessionid': self.psessionid } rsp_json = self.client.load(req_url, data, SMART_QQ_REFER, validator=self._msg_result_validator, retries=5) logger.info("RUNTIMELOG Reply successfully.") return rsp_json except Exception, e: logger.exception(e) logger.warning("RUNTIMELOG Response Error over 5 times. Giving up. reply content:" + str(reply_content)) return False
def run(): patch() logger.setLevel(logging.INFO) logger.info("Initializing...") plugin_manager.load_plugin() bot.login() observer = MessageObserver(bot) while True: try: msg_list = bot.check_msg() if msg_list is not None: observer.handle_msg_list( [mk_msg(msg) for msg in msg_list] ) except ServerResponseEmpty: continue except (socket.timeout, IOError): logger.warning("Message pooling timeout, retrying...") except Exception: logger.exception("Exception occurs when checking msg.")
def main_loop(no_gui=False, new_user=False, debug=False, http=False, password=False): if debug: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) if http: run_http_daemon() logger.info("Initializing...") plugin_manager.load_plugin() if new_user: clean_cookie() bot.login(no_gui, password) observer = MessageObserver(bot) for name, func in bot_inited_registry.items(): try: t = threading.Thread(target=func, args=(bot, )) t.daemon = True t.start() except Exception: logging.exception("Error occurs while loading plugin [%s]." % name) while True: try: msg_list = bot.check_msg() if msg_list is not None: observer.handle_msg_list( [mk_msg(msg, bot) for msg in msg_list]) except ServerResponseEmpty: continue except (socket.timeout, IOError): logger.debug("Message pooling timeout, retrying...") except NeedRelogin: exit(0) except Exception: logger.exception("Exception occurs when checking msg.")
def login(self): try: self._login_by_cookie() except CookieLoginFailed: logger.info("Cookie login failed.") while True: if self._login_by_qrcode(): if self._login_by_cookie(): break time.sleep(4) user_info = self.get_self_info2() try: self.username = user_info['nick'] logger.info("User information got: user name is [%s]" % self.username) except KeyError: logger.exception( "User info access failed, check your login and response:\n%s" % user_info) exit(1) logger.info( "RUNTIMELOG QQ:{0} login successfully, Username:{1}".format( self.account, self.username))
def main_loop(no_gui=False, new_user=False, debug=False, http=False): patch() if debug: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) if http: run_http_daemon() logger.info("Initializing...") plugin_manager.load_plugin() if new_user: clean_cookie() bot.login(no_gui) observer = MessageObserver(bot) for name, func in iteritems(bot_inited_registry): try: func(bot) except Exception: logging.exception( "Error occurs while loading plugin [%s]." % name ) while True: try: msg_list = bot.check_msg() if msg_list is not None: observer.handle_msg_list( [mk_msg(msg, bot) for msg in msg_list] ) except ServerResponseEmpty: continue except (socket.timeout, IOError): logger.warning("Message pooling timeout, retrying...") except NeedRelogin: exit(0) except Exception: logger.exception("Exception occurs when checking msg.")
def _login_by_cookie(self): logger.info("Try cookie login...") self.client.load_cookie() self.ptwebqq = self.client.get_cookie('ptwebqq') response = self.client.post( 'http://d1.web2.qq.com/channel/login2', { 'r': '{{"ptwebqq":"{0}","clientid":{1},"psessionid":"{2}","status":"online"}}'.format( self.ptwebqq, self.client_id, self.psessionid ) }, SMART_QQ_REFER ) try: ret = json.loads(response) except ValueError: return logger.exception( "Cookies login fail, response decode error:{0}".format(response) ) if ret['retcode'] != 0: raise CookieLoginFailed("Login step 1 failed with response:\n %s " % ret) response2 = self.client.get( "http://s.web2.qq.com/api/getvfwebqq?ptwebqq={0}&clientid={1}&psessionid={2}&t={3}".format( self.ptwebqq, self.client_id, self.psessionid, self.client.get_timestamp() ) ) ret2 = json.loads(response2) if ret2['retcode'] != 0: raise CookieLoginFailed( "Login step 2 failed with response:\n %s " % ret2 ) self.psessionid = ret['result']['psessionid'] self.account = ret['result']['uin'] self.vfwebqq = ret2['result']['vfwebqq'] logger.info("Login by cookie succeed. account: %s" % self.account) return True