def get_friend_info(self, tuin): """ 获取好友详情信息 get_friend_info {"retcode":0,"result":{"face":0,"birthday":{"month":1,"year":1989,"day":30},"occupation":"","phone":"","allow":1,"college":"","uin":3964575484,"constel":1,"blood":3,"homepage":"http://blog.lovewinne.com","stat":20,"vip_info":0,"country":"中国","city":"","personal":"","nick":" 信","shengxiao":5,"email":"*****@*****.**","province":"山东","gender":"male","mobile":"158********"}} :return:dict """ uin = str(tuin) if uin not in self.friend_uin_list: logger.info("RUNTIMELOG Requesting the account info by uin: {}".format(uin)) info = json.loads(self.client.get( 'http://s.web2.qq.com/api/get_friend_info2?tuin={0}&vfwebqq={1}&clientid={2}&psessionid={3}&t={4}'.format( uin, self.vfwebqq, self.client_id, self.psessionid, self.client.get_timestamp() ) )) logger.debug("get_friend_info2 html: {}".format(str(info))) if info['retcode'] != 0: logger.warning('get_friend_info2 retcode unknown: {}'.format(info)) return None info = info['result'] info['account'] = self.uin_to_account(uin) info['longnick'] = self.get_friend_longnick(uin) self.friend_uin_list[uin] = info try: return self.friend_uin_list[uin] except: logger.warning("RUNTIMELOG get_friend_info return fail.") logger.debug("RUNTIMELOG now uin list: " + str(self.friend_uin_list[uin]))
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 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 get_group_member_info(self, group_code, uin): """ 获取群中某一指定成员的信息 :type group_code: int, can be "ture" of "fake" group_code :type uin: int :return: dict { u 'province': u '', u 'city': u '', u 'country': u '', u 'uin': 2927049915, u 'nick': u 'Yinzo', u 'gender': u 'male' } """ group_code = str(group_code) if group_code not in self.group_member_info: logger.info("group_code not in cache, try to request info") result = self.get_group_member_info_list(group_code) if result is False: logger.warning("没有所查询的group_code信息") return for member in self.group_member_info[group_code]['minfo']: if member['uin'] == uin: return member
def get_group_name_list_mask2(self): """ 获取群列表 get_group_name_list_mask2 {u'gmarklist': [], u'gmasklist': [], u'gnamelist': [{u'code': 2676518731, u'flag': 1090520065, u'gid': 222968641(这是group_uin), u'name': u'测试'}]} :return:dict """ logger.info("RUNTIMELOG Requesting the group list.") response = self.client.post( 'http://s.web2.qq.com/api/get_group_name_list_mask2', { 'r': json.dumps( { "vfwebqq": self.vfwebqq, "hash": self._hash_digest(self._self_info['uin'], self.ptwebqq), } ) }, ) try: response = json.loads(response) except ValueError: logger.warning("RUNTIMELOG The response of group list request can't be load as json") logger.debug("RESPONSE get_group_name_list_mask2 html: " + str(response)) if response['retcode'] != 0: raise TypeError('get_online_buddies2 result error') return response['result']
def repeat(msg, bot): global recorder reply = bot.reply_msg(msg, return_function=True) if recorder.last_msg == msg.content and recorder.last_reply != msg.content and "@" not in msg.content: if str(msg.content).strip() not in ("", " ", "[图片]", "[表情]"): logger.info("RUNTIMELOG " + str(msg.did) + " repeating, trying to reply " + str(msg.content)) reply(msg.content) recorder.last_reply = msg.content recorder.last_msg = msg.content # @on_group_message(name='basic[三个问题]') # def nick_call(msg, bot): # if "我是谁" == msg.content: # bot.reply_msg(msg, "你是{}({})!".format(msg.src_sender_card or msg.src_sender_name, msg.src_sender_id)) # # elif "我在哪" == msg.content: # bot.reply_msg(msg, "你在{name}({id})!".format(name=msg.src_group_name, id=msg.src_group_id)) # # elif msg.content in ("我在干什么", "我在做什么"): # bot.reply_msg(msg, "你在调戏我!!") # @on_discuss_message(name='basic[讨论组三个问题]') # def discuss_three_questions(msg, bot): # if "我是谁" == msg.content: # bot.reply_msg(msg, "你是{}!".format(msg.src_sender_name)) # # elif "我在哪" == msg.content: # bot.reply_msg(msg, "你在{name}!".format(name=msg.src_discuss_name)) # # elif msg.content in ("我在干什么", "我在做什么"): # bot.reply_msg(msg, "你在调戏我!!")
def current_tucao_list(msg, bot): # webqq接受的消息会以空格结尾 global core reply = bot.reply_msg(msg, return_function=True) group_code = str(msg.group_code) group_id = bot.get_group_info(group_code=group_code).get('id') match = re.match(r'^(?:!|!)([^\s\{\}]+)\s*$', msg.content) if match: core.load(group_id) command = str(match.group(1)) logger.info("RUNTIMELOG command format detected, command: " + command) if command == "吐槽列表": result = "" for key in core.tucao_dict[group_code].keys(): result += "关键字:{0}\t\t回复:{1}\n".format( key, " / ".join(core.tucao_dict[group_code][key])) result = result[:-1] logger.info( "RUNTIMELOG Replying the list of tucao for group {}".format( group_code)) reply(result) return
def callcute(msg, bot): if "@上海人形" in msg.content and "摸" in msg.content: reply = bot.reply_msg(msg, return_function=True) logger.info("RUNTIMELOG " + str(msg.from_uin) + " calling me out, trying to reply....") reply_content = random.choice(REPLY_CUTE) reply(reply_content)
def send_group_msg(self, reply_content, group_code, msg_id, fail_times=0): fix_content = str(reply_content.replace("\\", "\\\\\\\\").replace("\n", "\\\\n").replace("\t", "\\\\t")) rsp = "" try: logger.info("Starting send group message: %s" % reply_content) req_url = "http://d1.web2.qq.com/channel/send_qun_msg2" data = ( ('r', '{{"group_uin":{0}, "face":564,"content":"[\\"{4}\\",[\\"font\\",{{\\"name\\":\\"Arial\\",\\"size\\":\\"10\\",\\"style\\":[0,0,0],\\"color\\":\\"000000\\"}}]]","clientid":{1},"msg_id":{2},"psessionid":"{3}"}}'.format( group_code, self.client_id, msg_id, self.psessionid, fix_content)), ('clientid', self.client_id), ('psessionid', self.psessionid) ) rsp = self.client.post(req_url, data, SMART_QQ_REFER) rsp_json = json.loads(rsp) if 'retcode' in rsp_json and rsp_json['retcode'] not in MESSAGE_SENT: raise ValueError("RUNTIMELOG reply group chat error" + str(rsp_json['retcode'])) logger.info("RUNTIMELOG send_qun_msg: Reply '{}' successfully.".format(reply_content)) logger.debug("RESPONSE send_qun_msg: Reply response: " + str(rsp)) return rsp_json except: logger.warning("RUNTIMELOG send_qun_msg fail") if fail_times < 5: logger.warning("RUNTIMELOG send_qun_msg: Response Error.Wait for 2s and Retrying." + str(fail_times)) logger.debug("RESPONSE send_qun_msg rsp:" + str(rsp)) time.sleep(2) self.send_group_msg(reply_content, group_code, msg_id, fail_times + 1) else: logger.warning("RUNTIMELOG send_qun_msg: Response Error over 5 times.Exit.reply content:" + str(reply_content)) return False
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 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 get_friend_info2(self, tuin): """ 获取好友详情信息 get_friend_info2 {"retcode":0,"result":{"face":0,"birthday":{"month":1,"year":1989,"day":30},"occupation":"","phone":"","allow":1,"college":"","uin":3964575484,"constel":1,"blood":3,"homepage":"http://blog.lovewinne.com","stat":20,"vip_info":0,"country":"中国","city":"","personal":"","nick":" 信","shengxiao":5,"email":"*****@*****.**","province":"山东","gender":"male","mobile":"158********"}} :return:dict """ uin_str = str(tuin) try: logger.info("RUNTIMELOG Requesting the account info by uin: " + str(tuin)) info = json.loads(self.client.get( 'http://s.web2.qq.com/api/get_friend_info2?tuin={0}&vfwebqq={1}&clientid={2}&psessionid={3}&t={4}' .format( uin_str, self.vfwebqq, self.client_id, self.psessionid, self.client.get_timestamp()), )) logger.debug("RESPONSE get_friend_info2 html: " + str(info)) if info['retcode'] != 0: raise TypeError('get_friend_info2 result error') info = info['result'] return info except: logger.warning("RUNTIMELOG get_friend_info2 fail") return None
def testSendGroup(msg, bot): #logger.info('testSendGroup'+msg.content) match = re.match(r'reminder', str(msg.content)) logger.info('match : ' + str(match)) if match: t = threading.Thread(target=loop, args=(bot, msg)) t.start()
def get_friend_info2(self, tuin): """ 获取好友详情信息 get_friend_info2 {"retcode":0,"result":{"face":0,"birthday":{"month":1,"year":1989,"day":30},"occupation":"","phone":"","allow":1,"college":"","uin":3964575484,"constel":1,"blood":3,"homepage":"http://blog.lovewinne.com","stat":20,"vip_info":0,"country":"中国","city":"","personal":"","nick":" 信","shengxiao":5,"email":"*****@*****.**","province":"山东","gender":"male","mobile":"158********"}} :return:dict """ uin_str = str(tuin) try: logger.info("RUNTIMELOG Requesting the account info by uin: " + str(tuin)) info = json.loads( self.client.get( 'http://s.web2.qq.com/api/get_friend_info2?tuin={0}&vfwebqq={1}&clientid={2}&psessionid={3}&t={4}' .format(uin_str, self.vfwebqq, self.client_id, self.psessionid, self.client.get_timestamp()), )) logger.debug("RESPONSE get_friend_info2 html: " + str(info)) if info['retcode'] != 0: raise TypeError('get_friend_info2 result error') info = info['result'] return info except: logger.warning("RUNTIMELOG get_friend_info2 fail") return None
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 = self.client.post(req_url, data, SMART_QQ_REFER) rsp_json = json.loads(rsp) if 'errCode' in rsp_json and rsp_json['errCode'] != 0: raise ValueError("reply pmchat error" + str(rsp_json['retcode'])) logger.info("RUNTIMELOG Reply successfully.") logger.debug("RESPONSE Reply response: " + str(rsp)) return rsp_json except: if fail_times < 5: logger.warning("RUNTIMELOG Response Error.Wait for 2s and Retrying." + str(fail_times)) logger.debug("RESPONSE " + str(rsp)) time.sleep(2) self.send_friend_msg(reply_content, uin, msg_id, fail_times + 1) else: logger.warning("RUNTIMELOG Response Error over 5 times.Exit.reply content:" + str(reply_content)) return False
def callout(msg, bot): if "智障机器人" in msg.content: reply = bot.reply_msg(msg, return_function=True) logger.info("RUNTIMELOG " + str(msg.from_uin) + " calling me out, trying to reply....") reply_content = "干嘛(‘·д·)" + random.choice(REPLY_SUFFIX) reply(reply_content)
def get_online_friends_list(self): """ 获取在线好友列表 get_online_buddies2 :return:list """ logger.info("RUNTIMELOG Requesting the online buddies.") response = self.client.get( 'http://d1.web2.qq.com/channel/get_online_buddies2?vfwebqq={0}&clientid={1}&psessionid={2}&t={3}'.format( self.vfwebqq, self.client_id, self.psessionid, self.client.get_timestamp(), ) ) # {"result":[],"retcode":0} logger.debug("RESPONSE get_online_buddies2 html:{}".format(response)) try: online_buddies = json.loads(response) except ValueError: logger.warning("get_online_buddies2 response decode as json fail.") return None if online_buddies['retcode'] != 0: logger.warning('get_online_buddies2 retcode is not 0. returning.') return None online_buddies = online_buddies['result'] return online_buddies
def get_group_name_list_mask2(self): """ 获取群列表 get_group_name_list_mask2 :return:list """ logger.info("RUNTIMELOG Requesting the group list.") response = self.client.post( 'http://s.web2.qq.com/api/get_group_name_list_mask2', { 'r': json.dumps( { "vfwebqq": self.vfwebqq, "hash": self._hash_digest(self._self_info['uin'], self.ptwebqq), } ) }, ) try: response = json.loads(response) except ValueError: logger.warning("RUNTIMELOG The response of group list request can't be load as json") return logger.debug("RESPONSE get_group_name_list_mask2 html: " + str(response)) if response['retcode'] != 0: raise TypeError('get_online_buddies2 result error') return response['result']
def send_friend_msg(self, reply_content, uin, msg_id, fail_times=0): fix_content = str(reply_content.replace("\\", "\\\\\\\\").replace("\n", "\\\\n").replace("\t", "\\\\t")) 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 = self.client.post(req_url, data, SMART_QQ_REFER) rsp_json = json.loads(rsp) if 'errCode' in rsp_json and rsp_json['errCode'] != 0: raise ValueError("reply pmchat error" + str(rsp_json['retcode'])) logger.info("RUNTIMELOG Reply successfully.") logger.debug("RESPONSE Reply response: " + str(rsp)) return rsp_json except: if fail_times < 5: logger.warning("RUNTIMELOG Response Error.Wait for 2s and Retrying." + str(fail_times)) logger.debug("RESPONSE " + str(rsp)) time.sleep(2) self.send_friend_msg(reply_content, uin, msg_id, fail_times + 1) else: logger.warning("RUNTIMELOG Response Error over 5 times.Exit.reply content:" + str(reply_content)) return False
def get_online_buddies2(self): """ 获取在线好友列表 get_online_buddies2 :return:list """ try: logger.info("RUNTIMELOG Requesting the online buddies.") online_buddies = json.loads(self.client.get( 'http://d1.web2.qq.com/channel/get_online_buddies2?vfwebqq={0}&clientid={1}&psessionid={2}&t={3}' .format( self.vfwebqq, self.client_id, self.psessionid, self.client.get_timestamp()), )) logger.debug("RESPONSE get_online_buddies2 html: " + str(online_buddies)) if online_buddies['retcode'] != 0: raise TypeError('get_online_buddies2 result error') online_buddies = online_buddies['result'] return online_buddies except: logger.warning("RUNTIMELOG get_online_buddies2 fail") return None
def uin_to_account(self, tuin): """ 将uin转换成用户QQ号 :param tuin: :return:str 用户QQ号 """ uin_str = str(tuin) try: logger.info("Requesting the account by uin:\t" + str(tuin)) rsp = 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("uin_to_account html:\t" + str(rsp)) info = json.loads(rsp) 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 get_online_friends_list(self): """ 获取在线好友列表 get_online_buddies2 :return:list """ retry_times = 10 while retry_times: logger.info("RUNTIMELOG Requesting the online buddies.") response = self.client.get( 'http://d1.web2.qq.com/channel/get_online_buddies2?vfwebqq={0}&clientid={1}&psessionid={2}&t={3}'.format( self.vfwebqq, self.client_id, self.psessionid, self.client.get_timestamp(), ) ) # {"result":[],"retcode":0} logger.debug("RESPONSE get_online_buddies2 html:{}".format(response)) try: online_buddies = json.loads(response) except ValueError: logger.warning("get_online_buddies2 response decode as json fail.") return None if online_buddies['retcode'] != 0: logger.warning('get_online_buddies2 retcode is not 0. returning.') return None online_buddies = online_buddies['result'] return online_buddies
def _login_by_cookie(self): logger.info("Try cookie login...") 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) ret = json.loads(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 " % ret) 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 login(self, no_gui=False): try: self._login_by_cookie() except CookieLoginFailed as e: logger.exception(e) 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 send_discuss_msg(self, reply_content, did, msg_id, fail_times=0): fix_content = self.quote(reply_content) rsp = "" try: logger.info("Starting send discuss group message: %s" % reply_content) req_url = "http://d1.web2.qq.com/channel/send_discu_msg2" data = { 'r': '{{"did":{0}, "face":564,"content":"[\\"{4}\\",[\\"font\\",{{\\"name\\":\\"Arial\\",\\"size\\":\\"10\\",\\"style\\":[0,0,0],\\"color\\":\\"000000\\"}}]]","clientid":{1},"msg_id":{2},"psessionid":"{3}"}}'.format( did, self.client_id, msg_id, self.psessionid, fix_content), 'clientid': self.client_id, 'psessionid': self.psessionid } rsp = self.client.post(req_url, data, SMART_QQ_REFER) rsp_json = json.loads(rsp) if 'retcode' in rsp_json and rsp_json['retcode'] not in MESSAGE_SENT: raise ValueError("RUNTIMELOG reply discuss group error" + str(rsp_json['retcode'])) logger.info("send_discuss_msg: Reply '{}' successfully.".format(reply_content)) logger.debug("send_discuss_msg: Reply response: " + str(rsp)) return rsp_json except: logger.warning("send_discuss_msg fail") if fail_times < 5: logger.warning("send_discuss_msg: Response Error.Wait for 2s and Retrying." + str(fail_times)) logger.debug("send_discuss_msg response:" + str(rsp)) time.sleep(2) self.send_group_msg(reply_content, did, msg_id, fail_times + 1) else: logger.warning("RUNTIMELOG send_qun_msg: Response Error over 5 times.Exit.reply content:" + str(reply_content)) return False
def get_group_member_info(self, group_code, uin): """ 获取群中某一指定成员的信息 :type group_code: int, can be "ture" of "fake" group_code :type uin: int :return: dict { "city": "广州", "country": "中国", "gender": "male", "nick": 493658555, "province": "广东", "uin": 2123489118 } """ group_code = str(group_code) if group_code not in self.group_member_info: logger.info("group_code not in cache, try to request info") result = self.get_group_member_info_list(group_code) if not result: logger.warning("没有所查询的group_code信息") return result_dict = {} for member in self.group_member_info[group_code].get('minfo') or []: if member.get('uin') == uin: result_dict = member break for card_dict in self.group_member_info[group_code].get('cards') or []: if card_dict.get('muin') == uin: result_dict['card'] = card_dict.get('card') break return result_dict
def _load_package_plugin(self): for package_name in self.config[PLUGIN_PACKAGES]: try: __import__(package_name) logger.info("Package plugin [%s] loaded." % package_name) except ImportError: logger.error( "Package plugin import error: can not import [%s]" % package_name)
def _load_default(self): for plugin_name in self.config[PLUGIN_ON]: try: __import__(self._gen_plugin_name(plugin_name)) logger.info("Plugin [%s] loaded." % plugin_name) except ImportError: logger.error( "Internal plugin import error: can not import [%s]" % plugin_name)
def repeat(msg, bot): global recorder reply = bot.reply_msg(msg, return_function=True) if len(recorder.msg_list) > 0 and recorder.msg_list[-1].content == msg.content: if str(msg.content).strip() not in ("", " ", "[图片]", "[表情]"): logger.info("RUNTIMELOG " + str(msg.group_code) + " repeating, trying to reply " + str(msg.content)) reply(msg.content) recorder.msg_list.append(msg)
def loop(bot, msg): now = datetime.now() to = now + timedelta(weeks=1) while True: time.sleep(60 * 60 * 12) now = datetime.now() logger.info("now:" + str(now) + "to:" + str(to)) if now > to: bot.send_discuss_msg('今天打球有人吗?', msg.did, randint(1, 100000)) to = now + timedelta(minutes=10)
def _load_package_plugin(self): for package_name in self.config[PLUGIN_PACKAGES]: try: __import__(package_name) logger.info("Package plugin [%s] loaded." % package_name) except ImportError: logger.error( "Package plugin import error: can not import [%s]" % package_name )
def _load_default(self): for plugin_name in self.config[PLUGIN_ON]: try: __import__(self._gen_plugin_name(plugin_name)) logger.info("Plugin [%s] loaded." % plugin_name) except ImportError: logger.error( "Internal plugin import error: can not import [%s]" % plugin_name )
def check_msg(self): # Pooling the message response = self.client.post( 'http://d1.web2.qq.com/channel/poll2', { 'r': json.dumps( { "ptwebqq": self.ptwebqq, "clientid": self.client_id, "psessionid": self.psessionid, "key": "" } ) }, SMART_QQ_REFER ) logger.debug("Pooling returns response: %s" % response) if response == "": return try: ret = json.loads(response.replace(r"\u0026lt;", "<").replace(r"\u0026gt;", ">")) except ValueError: logger.warning("decode poll response error.") logger.debug("{}".format(response)) 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, ): logger.info("Pooling received retcode: {}, trying to load online friends".format(str(ret_code))) result = self.get_online_friends_list() if result is None: logger.warning("Session expired, need to relogin.") 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 == 100012: raise NeedRelogin("Login is expired. Please relogin by qrcode") else: logger.warning("Pooling returns unknown retcode %s" % ret_code) return None
def check_msg(self): # Pooling the message response = self.client.post( 'http://d1.web2.qq.com/channel/poll2', { 'r': json.dumps( { "ptwebqq": self.ptwebqq, "clientid": self.client_id, "psessionid": self.psessionid, "key": "" } ) }, SMART_QQ_REFER ) logger.debug("Pooling returns response: %s" % response) if response == "": return try: ret = json.loads(response) except ValueError: logger.warning("RUNTIMELOG decode poll response error.") logger.debug("RESPONSE {}".format(response)) return ret_code = ret['retcode'] if ret_code in (0, 116): 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.") self.login(no_gui=True) 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, ): logger.warning("Pooling received retcode: " + str(ret_code)) self.login(no_gui=True) 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 == 100012: raise NeedRelogin("Login is expired. Please relogin by qrcode") else: logger.warning("Pooling returns unknown retcode %s" % ret_code) return None
def callout(msg, bot): if "智障机器人" in msg.content: reply = bot.reply_msg(msg, return_function=True) logger.info("RUNTIMELOG " + str(msg.from_uin) + " calling me out, trying to reply....") reply_content = "干嘛(‘·д·)" + random.choice(REPLY_SUFFIX) reply(reply_content) elif "副部" in msg.content: reply = bot.reply_msg(msg, return_function=True) logger.info("RUNTIMELOG " + str(msg.from_uin) + " calling me out, trying to reply....") reply_content = "副部最帅啦😝 " + random.choice(REPLY_SUFFIX) reply(reply_content)
def inactivate(dispatcher_name): try: _active.remove(dispatcher_name) logger.info( 'Plugin %s inactivated.' % dispatcher_name ) except KeyError: logger.info( 'Plugin name %s does not exist, failed to inactivate.' % dispatcher_name )
def repeat(msg, bot): global recorder reply = bot.reply_msg(msg, return_function=True) if recorder.last_msg == msg.content and recorder.last_reply != msg.content \ and "@" not in msg.content and "d" not in msg.content and "timer" not in msg.content: if str(msg.content).strip() not in ("", " ", "[图片]", "[表情]"): logger.info("RUNTIMELOG " + str(msg.group_code) + " repeating, trying to reply " + str(msg.content)) reply(msg.content) recorder.last_reply = msg.content recorder.last_msg = msg.content
def get_group_name_list_mask2(self): """ 获取群列表, 并存入cache, 其中code为group_code get_group_name_list_mask2 :return:list { u 'gmarklist': [], u 'gmasklist': [], u 'gnamelist': [ { u 'code': 1131597161, # 这是真实group_code u 'flag': 184550417, u 'gid': 1802239929, # 这是msg.group_code, 即假group_code u 'name': u '测试' }, { u 'code': 1131597161, u 'flag': 184550417, u 'gid': 1802239929, u 'name': u '测试' } ] } """ logger.info("RUNTIMELOG Requesting the group list.") response = self.client.post( 'http://s.web2.qq.com/api/get_group_name_list_mask2', { 'r': json.dumps({ "vfwebqq": self.vfwebqq, "hash": self._hash_digest(self._self_info['uin'], self.ptwebqq), }) }, ) try: response = json.loads(response) except ValueError: logger.warning( "RUNTIMELOG The response of group list request can't be load as json" ) return logger.debug("RESPONSE get_group_name_list_mask2 html: " + str(response)) if response['retcode'] != 0: raise TypeError('get_online_buddies2 result error') for group in response['result']['gnamelist']: self.group_code_list[str(group['gid'])] = group return response['result']
def msg_to_group_id(self,msg): #从msg.from_uin获取到的uin #得到真实群号 if str(msg.from_uin) not in self.group_code_list: logger.info("尝试更新群列表信息") self.get_group_list_with_group_code() if str(msg.from_uin) not in self.group_code_list: logger.warning("没有所查询的group_code, 请检查group_code是否错误") return 0 else: self.group_database() else: return sql.fetch_one('select group_id from group_data where group_code = "{0}";'.format(msg.from_uin))[0]
def save(self, group_id): """ :type group_id: int, 用于保存指定群的吐槽存档 """ global TUCAO_PATH try: tucao_file_path = TUCAO_PATH + str(group_id) + ".tucao" with open(tucao_file_path, "w+") as tucao_file: cPickle.dump(self.tucao_dict[str(group_id)], tucao_file) logger.info("RUNTIMELOG tucao saved. Now tucao list: {0}".format(str(self.tucao_dict))) except Exception: logger.error("RUNTIMELOG Fail to save tucao.") raise IOError("Fail to save tucao.")
def get_true_group_code(self, fake_group_code): """ :type fake_group_code: int """ fake_group_code = str(fake_group_code) logger.debug("正在查询group_code:{}对应的真实group_code".format(fake_group_code)) if fake_group_code not in self.group_code_list: logger.info("尝试更新群列表信息") self.get_group_name_list_mask2() # 先尝试更新群列表 if fake_group_code not in self.group_code_list: logger.warning("没有所查询的group_code, 请检查group_code是否错误") return 0 return self.group_code_list[fake_group_code]['code']
def get_group_list_with_group_code(self): """ 获取包含群名和group_code的列表, 并存入cache, 其中code为group_code :type group_code: str :return:list [ { u 'code': 1131597161, # 这是真实group_code u 'flag': 184550417, u 'gid': 1802239929, # 这是msg.group_code, 即假group_code u 'name': u '测试' }, { u 'code': 1131597161, u 'flag': 184550417, u 'gid': 1802239929, u 'name': u '测试' } ] """ logger.info("Requesting the group list.") response = self.client.post( 'http://s.web2.qq.com/api/get_group_name_list_mask2', { 'r': json.dumps({ "vfwebqq": self.vfwebqq, "hash": self._hash_digest(self._self_info['uin'], self.ptwebqq), }) }, ) try: logger.debug("get_group_name_list_mask2 html:\t{}".format( str(response))) response = json.loads(response) except ValueError: logger.warning( "RUNTIMELOG The response of group list request can't be load as json" ) return if response['retcode'] != 0: raise TypeError('get_group_list_with_group_code result error') for group in response['result']['gnamelist']: self.group_code_list[str(group['gid'])] = group self.group_code_list[str(group['code'])] = group return response['result']['gnamelist']
def check_msg(self): # Pooling the message response = self.client.post( 'http://d1.web2.qq.com/channel/poll2', { 'r': json.dumps( { "ptwebqq": self.ptwebqq, "clientid": self.client_id, "psessionid": self.psessionid, "key": "" } ) }, SMART_QQ_REFER ) logger.debug("Pooling returns response: %s" % response) if response == "": return try: ret = json.loads(response) except ValueError: logger.warning("RUNTIMELOG decode poll response error.") logger.debug("RESPONSE {}".format(response)) return ret_code = ret['retcode'] if ret_code in (0, 116): 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, ): logger.warning("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) else: logger.warning("Pooling returns unknown retcode %s" % ret_code) return None
def get_true_group_code(self, fake_group_code): """ :type fake_group_code: int """ fake_group_code = str(fake_group_code) logger.debug( "正在查询group_code:{}对应的真实group_code".format(fake_group_code)) if fake_group_code not in self.group_code_list: logger.info("尝试更新群列表信息") self.get_group_name_list_mask2() # 先尝试更新群列表 if fake_group_code not in self.group_code_list: logger.warning("没有所查询的group_code, 请检查group_code是否错误") return 0 return self.group_code_list[fake_group_code]['code']
def send_sess_msg2_fromGroup(self, reply_content, guin, tuin, msg_id, service_type=0, fail_times=0): group_sig = self._get_group_sig(guin, tuin, service_type) fix_content = str( reply_content.replace("\\", "\\\\\\\\").replace("\n", "\\\\n").replace( "\t", "\\\\t")) rsp = "" try: req_url = "http://d1.web2.qq.com/channel/send_sess_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}", "group_sig":"{5}", "service_type":{6}}}' .format(tuin, self.client_id, msg_id, self.psessionid, fix_content, group_sig, service_type)), ('clientid', self.client_id), ('psessionid', self.psessionid), ('group_sig', group_sig), ('service_type', service_type)) rsp = self.client.post(req_url, data, SMART_QQ_REFER) rsp_json = json.loads(rsp) if 'retcode' in rsp_json and rsp_json['retcode'] != 0: raise ValueError("RUNTIMELOG reply sess chat error" + str(rsp_json['retcode'])) logger.info( "RUNTIMELOG send_sess_msg2_fromGroup: Reply successfully.") logger.debug( "RESPONSE send_sess_msg2_fromGroup: Reply response: " + str(rsp)) return rsp_json except: if fail_times < 5: logger.warning( "RUNTIMELOG send_sess_msg2_fromGroup: Response Error.Wait for 2s and Retrying." + str(fail_times)) logger.debug("RESPONSE " + str(rsp)) time.sleep(2) self.send_sess_msg2_fromGroup(guin, tuin, reply_content, msg_id, service_type, fail_times + 1) else: logger.warning( "RUNTIMELOG send_sess_msg2_fromGroup: Response Error over 5 times.Exit.reply content:" + str(reply_content)) return False
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_true_group_code(self, fake_group_code): """ 通过假group_code获取真group_code :type fake_group_code: str :return str """ fake_group_code = str(fake_group_code) logger.debug("正在查询group_code:{}对应的真实group_code".format(fake_group_code)) if fake_group_code not in self.group_code_list: logger.info("尝试更新群列表信息") self.get_group_list_with_group_code() # 先尝试更新群列表 if fake_group_code not in self.group_code_list: logger.warning("没有所查询的group_code, 请检查group_code是否错误") return 0 return str(self.group_code_list[fake_group_code]['code'])
def get_group_name_list_mask2(self): """ 获取群列表, 并存入cache, 其中code为group_code get_group_name_list_mask2 :return:list { u 'gmarklist': [], u 'gmasklist': [], u 'gnamelist': [ { u 'code': 1131597161, # 这是真实group_code u 'flag': 184550417, u 'gid': 1802239929, # 这是msg.group_code, 即假group_code u 'name': u '测试' }, { u 'code': 1131597161, u 'flag': 184550417, u 'gid': 1802239929, u 'name': u '测试' } ] } """ logger.info("RUNTIMELOG Requesting the group list.") response = self.client.post( 'http://s.web2.qq.com/api/get_group_name_list_mask2', { 'r': json.dumps( { "vfwebqq": self.vfwebqq, "hash": self._hash_digest(self._self_info['uin'], self.ptwebqq), } ) }, ) try: response = json.loads(response) except ValueError: logger.warning("RUNTIMELOG The response of group list request can't be load as json") return logger.debug("RESPONSE get_group_name_list_mask2 html: " + str(response)) if response['retcode'] != 0: raise TypeError('get_online_buddies2 result error') for group in response['result']['gnamelist']: self.group_code_list[str(group['gid'])] = group return response['result']
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
def get_group_member_info(self, group_code, uin): """ :type group_code: int, can be "ture" of "fake" group_code :type uin: int :return: dict """ group_code = str(group_code) if group_code not in self.group_info: logger.info("group_code not in cache, try to request info") result = self.get_group_info_ext2(group_code) if result is False: logger.warning("没有所查询的group_code信息") return for member in self.group_info[group_code]['minfo']: if member['uin'] == uin: return member
def delete_tucao(msg, bot): global core reply = bot.reply_msg(msg, return_function=True) group_code = str(msg.group_code) match = re.match(r'^(?:!|!)([^\s\{\}]+)(?:\s?)\{([^\s\{\}]+)\}\s*$', msg.content) if match: core.load(group_code) command = str(match.group(1)) arg1 = str(match.group(2)) logger.info("RUNTIMELOG command format detected, command:{0}, arg1:{1}".format(command, arg1)) if command == "删除关键字" and unicode(arg1) in core.tucao_dict[group_code]: core.tucao_dict[group_code].pop(unicode(arg1)) reply("已删除关键字:{0}".format(arg1)) core.save(group_code) return True return False
def dice(msg, bot): result = is_dice(msg.content) if result: num, numrange, reason = result[0],result[1],result[2] if num: num = int(num) else: num = DEFAULT_DICE_NUM if numrange: numrange = int(numrange) else: numrange = DEFAULT_DICE_RANGE reply = bot.reply_msg(msg, return_function=True) logger.info("RUNTIMELOG " + str(msg.from_uin) + " dice, trying to reply....") result = [random.randint(1,numrange) for x in range(num)] reply_content = "因为:"+reason+",投出了:" for num in result: reply_content += str(num)+"+" reply_content = reply_content[:-1]+'='+str(sum(result)) reply(reply_content)
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 load(self, group_id): """ :type group_id: int, 用于读取指定群的吐槽存档 """ global TUCAO_PATH if str(group_id) in self.tucao_dict.keys(): return tucao_file_path = TUCAO_PATH + str(group_id) + ".tucao" if not os.path.isdir(TUCAO_PATH): os.makedirs(TUCAO_PATH) if not os.path.exists(tucao_file_path): with open(tucao_file_path, "w") as tmp: tmp.close() with open(tucao_file_path, "r") as tucao_file: try: self.tucao_dict[str(group_id)] = cPickle.load(tucao_file) logger.info("RUNTIMELOG tucao loaded. Now tucao list: {0}".format(str(self.tucao_dict))) except EOFError: self.tucao_dict[str(group_id)] = dict() logger.info("RUNTIMELOG tucao file is empty.")
def weather(msg, bot): global query match = re.match(ur'^(weather|天气) (\w+|[\u4e00-\u9fa5]+)', msg.content) if match: logger.info("RUNTIMELOG 查询天气...") command = match.group(1) city = match.group(2) logger.info("RUNTIMELOG 查询天气语句: " + msg.content) if command == 'weather' or command == u'天气': try: city_name = urllib2.quote(city.encode('utf-8')) url_str = "http://api.map.baidu.com/telematics/v3/weather?location={city}&ak={key}&output=json".format( city=city_name, key=KEY ) response = urllib2.urlopen(url_str) data_html = response.read() logger.debug("RESPONSE " + data_html) json_result = json.loads(data_html)['results'][0] str_data = "" str_data += json_result['currentCity'] + " PM:" + json_result['pm25'] + "\n" try: str_data += json_result["index"][0]['des'] + "\n" except: pass for data in json_result["weather_data"]: str_data += data['date'] + " " str_data += data['weather'] + " " str_data += data['wind'] + " " str_data += data['temperature'] str_data += '\n' except: str_data = "Not found city" bot.reply_msg(msg, str_data) return True return False