示例#1
0
 def check_and_confirm_and_load(self, qrcode_rsp, device_id):
     qr_code = self.check_qrcode_login(qrcode_rsp, device_id)
     if qr_code is not False:
         if self.confirm_qrcode_login(qr_code, keep_heart_beat=False):
             v_user_pickle = red.get('v_user_' + str(qr_code['Username']))
             v_user = pickle.loads(v_user_pickle)
             if self.new_init(v_user):
                 v_user = pickle.loads(
                     red.get('v_user_' + str(qr_code['Username'])))
                 self.async_check(v_user)
                 from taobaoke.heartbeat_manager import HeartBeatManager
                 HeartBeatManager.begin_heartbeat(str(qr_code['Username']))
示例#2
0
    def process_notify_package(self, data):
        # 接收到notify包时的回调处理
        cmd = common_utils.read_int(data, 8)
        if cmd == 318:
            print "cmd 318"
            # 这里decode出来的都是微信的官网的html,所以没必要print出来了
            # v_user = pickle.loads(red.get('v_user_' + self.wx_username))
            # if v_user is not None:
            #     threading.Thread(target=self.decode_cmd_318, args=(v_user, data,)).start()

        if data is not None and len(data) >= 4:
            selector = common_utils.read_int(data, 16)
            if selector > 0:
                print "selector:{0} start sync thread".format(selector)

                # TODO:在 set_user_context 中定义的wx_username, 这么写不好, 待修改
                if self.wx_username is not None and self.wx_username != "":
                    if self.__lock.acquire():
                        # 确保只有一个线程在执行async_check,否则会接受多次相同的消息
                        if not self.__is_async_check:
                            self.__is_async_check = True
                            self.__lock.release()
                        else:
                            print "*********skip async check*********"
                            self.__lock.release()
                            return

                    # 拉取消息之前先查询是否是登陆状态
                    # 因为用户ipad登陆的同时登陆其他平台,socket仍然会收到notify包
                    with app.app_context():
                        user_db = model.User.query.filter_by(
                            userame=self.wx_username).first()
                        is_login = user_db.login == 1

                    if is_login:
                        bot = WXBot()
                        v_user = pickle.loads(
                            red.get('v_user_' + self.wx_username))
                        bot.async_check(v_user)
                    self.__is_async_check = False
    def heartbeat(cls, wx_username, md_username):
        is_first = True
        wx_bot = weixin_bot.WXBot()
        wx_bot.set_user_context(wx_username)

        # 微信有新消息就会往socket推20字节的notify包
        # 防止该socket断开,每30秒发一次同步消息包
        heart_beat_count = 0
        user = WxUser.objects.filter(username=wx_username).first()
        if user is not None:
            while True:
                try:
                    # 用户退出登陆,退出线程
                    if user.login == 0 and wx_bot._auto_retry == 30:
                        logger.info("{}: 用户重启心跳失败,结束心跳".format(user.nickname))
                        oss_utils.beary_chat("{0}: 用户重启心跳失败,机器人已下线".format(user.nickname))
                        # 登出时需要把socket断开,否则会一直收到退出登陆的消息
                        wx_bot.wechat_client.close_when_done()
                        return

                    # 防止心跳无法关闭,采用外部控制
                    heart_status = red.get('v_user_heart_' + wx_username)
                    if heart_status:
                        if int(heart_status) == 2:
                            v_user = pickle.loads(red.get('v_user_' + wx_username))
                            wx_bot.logout_bot(v_user)
                            del HeartBeatManager.heartbeat_thread_dict[wx_username]
                            logger.info("{}: 心跳终止成功".format(user.nickname))
                            oss_utils.beary_chat("{}: 心跳终止成功".format(user.nickname))
                            wx_bot.wechat_client.close_when_done()
                            red.set('v_user_heart_' + wx_username, 0)
                            return

                        # 如果有多个心跳的时候,只能逐一终止,不能使用logout,否则会使用户变成僵尸用户
                        if int(heart_status) == 3:
                            wx_bot.wechat_client.close_when_done()
                            del HeartBeatManager.heartbeat_thread_dict[wx_username]
                            logger.info("{}: 心跳终止成功".format(user.nickname))
                            oss_utils.beary_chat("{}: 心跳终止成功".format(user.nickname))
                            red.set('v_user_heart_' + wx_username, 1)
                            return

                    if not wx_bot.wechat_client.connected:
                        # 测试过后发现好像没有哪个包能阻止socket断开,断开只是时间问题
                        # 检测一下socket有没断开,如果断开,重新起一个socket即可
                        time.sleep(5)
                        # 再一次初始化
                        is_first = True
                        temp = wx_bot._auto_retry
                        wx_bot = weixin_bot.WXBot()
                        wx_bot._auto_retry = temp
                        wx_bot.set_user_context(wx_username)

                    v_user = pickle.loads(red.get('v_user_' + wx_username))

                    if is_first:
                        UUid = user.uuid
                        DeviceType = user.device_type
                        logger.info("%s: 进行心跳二次登录中" % user.nickname)
                        res_auto = wx_bot.auto_auth(v_user, UUid, DeviceType, False)
                        is_first = False
                        if res_auto is True:
                            if wx_bot.set_user_login(wx_username):
                                wx_bot.open_notify_callback()
                                v_user = pickle.loads(red.get('v_user_' + wx_username))
                                t = threading.Thread(target=wx_bot.contact_init, args=(v_user, 0, 0))
                                t.start()
                                red.set('v_user_heart_' + wx_username, 1)
                                logger.info("{}: 心跳二次登录成功".format(user.nickname))
                                user = WxUser.objects.filter(username=wx_username).first()
                                oss_utils.beary_chat("{0}: 机器人已上线, 心跳开启成功--{1}, {2}, login为{3}".format(user.nickname,
                                                                                                       time.asctime(time.localtime(time.time())),
                                                                                                       user.username, user.login))
                            else:
                                logger.info("{}: 用户设置login失败" % user.nickname)
                                return
                        elif res_auto is 'Logout':
                            red.set('v_user_heart_' + wx_username, 0)
                            del HeartBeatManager.heartbeat_thread_dict[wx_username]
                            auth_user = User.objects.filter(username=md_username).first()
                            user.user.remove(auth_user)
                            logger.info("{}: 用户主动退出登录,退出心跳,机器人下线".format(user.nickname))
                            oss_utils.beary_chat("{0}: 用户主动退出登录,退出机器人".format(user.nickname))
                            # wx_bot.wechat_client.close_when_done()
                            wx_bot.logout_bot(v_user)
                            return
                        else:
                            red.set('v_user_heart_' + wx_username, 0)
                            del HeartBeatManager.heartbeat_thread_dict[wx_username]
                            # auth_user = User.objects.filter(username=md_username).first()
                            # user.user.remove(auth_user)
                            logger.info("{}: 心跳二次登录失败,退出心跳,登录失败".format(user.nickname))
                            oss_utils.beary_chat("{}: 啊哦,机器人心跳失败,上线失败".format(user.nickname))
                            wx_bot.wechat_client.close_when_done()
                            wx_bot.logout_bot(v_user)
                            return

                    # c# demo 中的heart_beat包,能延长socket的持续时间
                    # 但始终会断开
                    if wx_bot._lock.acquire():
                        logger.info("%s: 开始发送心跳包" % user.nickname)
                        start_time = datetime.datetime.now()
                        if wx_bot.heart_beat(v_user):
                            logger.info("%s: 心跳包发送成功" % user.nickname)
                            heart_beat_count += 1

                            if heart_beat_count % 10 == 0:
                                user.last_heart_beat = timezone.now()
                                user.save()
                        else:
                            logger.info("%s: 心跳包发送失败" % user.nickname)
                        # 如果心跳超过10分钟才发送完毕,认定socket阻塞了,重启心跳
                        if (datetime.datetime.now() - start_time).seconds > 10 * 60:
                            wx_bot.wechat_client.close_when_done()
                            logger.info("%s: 心跳完成发送超时,尝试重启心跳" % user.nickname)

                        wx_bot._lock.release()
                    connection.close()
                    time.sleep(30)

                except Exception as e:
                    connection.close()
                    logger.error(e)
                    logger.info("{0}heartbeat exception:{1}".format(wx_username, e.message))
                    oss_utils.beary_chat("{0}heartbeat exception:{1}".format(wx_username, e.message))
                    return
        else:
            logger.info("%s: user不存在", wx_username)
示例#4
0
    def async_check(self, v_user, new_socket=True):
        with app.app_context():
            bot_param = model.BotParam.query.filter_by(
                Username=v_user.userame).first()
            if bot_param:
                self.long_host = bot_param.LongHost
                if new_socket:
                    self.wechat_client = WechatClient.WechatClient(
                        self.long_host, 80, True)

        sync_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'],
                             version=CONST_PROTOCOL_DICT['version'],
                             timeStamp=get_time_stamp(),
                             iP=get_public_ip(),
                             baseMsg=BaseMsg(cmd=138, user=v_user))
        sync_rsp = grpc_client.send(sync_req)
        (buffers, seq) = grpc_utils.get_seq_buffer(sync_rsp)
        buffers = self.wechat_client.sync_send_and_return(
            buffers, close_socket=new_socket)
        if not check_buffer_16_is_191(buffers):
            try:
                # TODO:uuid 和 devicetype 存起来?
                UUid = u"667D18B1-BCE3-4AA2-8ED1-1FDC19446567"
                DeviceType = u"<k21>TP_lINKS_5G</k21><k22>中国移动</k22><k24>c1:cd:2d:1c:5b:11</k24>"
                if self.auto_auth(v_user,
                                  UUid,
                                  DeviceType,
                                  new_socket=new_socket):
                    v_user = pickle.loads(red.get('v_user_' + v_user.userame))
                    self.async_check(v_user, new_socket=new_socket)
                    return True

                self.logout_bot(v_user)

                print(read_int(buffers, 18))
                if read_int(buffers, 18) == -13:
                    print("Session Time out 离线或用户取消登陆 需执行二次登录")
            except Exception as e:
                print(e)
            return False
        else:
            sync_rsp.baseMsg.cmd = -138
            sync_rsp.baseMsg.payloads = char_to_str(buffers)
            sync_rsp = grpc_client.send(sync_rsp)
            # 刷新用户信息
            v_user = sync_rsp.baseMsg.user

            v_user_pickle = pickle.dumps(v_user)
            red.set('v_user_' + v_user.userame, v_user_pickle)

            msg_list = json.loads(sync_rsp.baseMsg.payloads)
            if msg_list is not None:
                for msg_dict in msg_list:
                    try:
                        if msg_dict['MsgType'] == 2:
                            with app.app_context():
                                model.save_contact(msg_dict)
                        elif msg_dict['Status'] is not None:
                            try:
                                action_rule.filter_keyword_rule(
                                    v_user.userame, msg_dict)
                            except Exception as e:
                                print(e)
                            with app.app_context():
                                model.save_message(msg_dict)
                        else:
                            print(msg_dict)
                    except Exception as e:
                        print(e)
                        print(msg_dict)
                self.async_check(v_user, new_socket=new_socket)
            else:
                print "sync 完成"
示例#5
0
 def try_room_detail(self, username, roomid):
     v_user_pickle = red.get('v_user_' + username)
     v_user = pickle.loads(v_user_pickle)
     self.get_chatroom_detail(v_user, roomid)
示例#6
0
 def try_search_contact(self, username):
     v_user_pickle = red.get('v_user_' + username)
     v_user = pickle.loads(v_user_pickle)
     self.search_contact("zhengyaohong0724", v_user)
示例#7
0
 def try_re_login(self, username):
     v_user_pickle = red.get('v_user_' + username)
     v_user = pickle.loads(v_user_pickle)
     self.auto_auth(v_user, 'Q-z_hUogcAFKCP8rWgdF', '')
示例#8
0
 def try_heart_beat(self, username):
     v_user_pickle = red.get('v_user_' + username)
     v_user = pickle.loads(v_user_pickle)
     return self.heart_beat(v_user)
示例#9
0
 def try_get_new_message(self, username):
     v_user_pickle = red.get('v_user_' + username)
     v_user = pickle.loads(v_user_pickle)
     self.async_check(v_user)
     return True
示例#10
0
 def try_new_init(self, username):
     v_user_pickle = red.get('v_user_' + username)
     v_user = pickle.loads(v_user_pickle)
     # v_user = self.auto_auth(v_user, 'Q-z_hUogcAFKCP8rWgdF', '')
     self.new_init(v_user)
示例#11
0
 def try_send_message(self, username):
     v_user_pickle = red.get('v_user_' + username)
     v_user = pickle.loads(v_user_pickle)
     # self.send_text_msg(u"7784635084@chatroom", u"咚咚咚 现在是12点咯 我是你们的老公彭于晏 大家吃了吗", v_user)
     self.send_text_msg(u"zhengyaohong0724", u"11111", v_user)
示例#12
0
            # wx_user = "******"
            wx_user = "******"  # 小小
            # wx_user = "******"
            # wx_user = "******"  # 点金
            # wxid_sygscg13nr0g21
            # wx_user = "******"
            # wxid_mynvgzqgnb5x22
            # wx_user = "******"
            print "**************************"
            print "enter cmd :{}".format(wx_user)
            print "**************************"
            cmd = input()
            if cmd == 0:
                wx_bot.set_user_context(wx_user)

                v_user_pickle = red.get('v_user_' + wx_user)
                v_user = pickle.loads(v_user_pickle)
                UUid = u"667D18B1-BCE3-4AA2-8ED1-1FDC19446567"
                DeviceType = u"<k21>TP_lINKS_5G</k21><k22>中国移动</k22><k24>c1:cd:2d:1c:5b:11</k24>"
                wx_bot.auto_auth(v_user, UUid, DeviceType, False)

            elif cmd == 1:
                # wxid_ceapoyxs555k22
                v_user_pickle = red.get('v_user_' + wx_user)
                # v_user_pickle = red.get('v_user_' + 'wxid_3cimlsancyfg22')
                v_user = pickle.loads(v_user_pickle)
                # wx_bot.send_text_msg('fat-phone', '112233', v_user)
                wx_bot.send_text_msg('8043482794@chatroom', '112233', v_user)

            elif cmd == 2:
                v_user_pickle = red.get('v_user_' + wx_user)