def new_init(self, v_user): """ 登陆初始化 :param v_user: :return: """ 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 self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) new_init_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=1002, user=v_user)) new_init_rsp = grpc_client.send(new_init_req) (buffers, seq) = grpc_utils.get_seq_buffer(new_init_rsp) buffers = self.wechat_client.sync_send_and_return(buffers, time_out=3) if not check_buffer_16_is_191(buffers): print("未知包 init") self.wechat_client.close_when_done() return False else: new_init_rsp.baseMsg.cmd = -1002 new_init_rsp.baseMsg.payloads = char_to_str(buffers) new_init_rsp = grpc_client.send(new_init_rsp) # 打印出同步消息的结构体 msg_list = json.loads(new_init_rsp.baseMsg.payloads) if msg_list is not None: for msg_dict in msg_list: # save msg # print(msg_dict) if msg_dict['MsgType'] == 2: with app.app_context(): model.save_contact(msg_dict) else: print(msg_dict) v_user = new_init_rsp.baseMsg.user v_user_pickle = pickle.dumps(v_user) red.set('v_user_' + v_user.userame, v_user_pickle) if new_init_rsp.baseMsg.ret == 8888: print("同步完成") self.wechat_client.close_when_done() else: self.wechat_client.close_when_done() self.new_init(v_user) return True
def add_chatroom_member(self, v_user, chatroom_id, wx_id): """ 添加微信群成员为好友 btn_AddChatRoomMember_Click :param v_user: :param wxid: :return: """ 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 self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) payloadJson = "{\"Roomeid\":\"" + chatroom_id + "\",\"Membernames\":\"" + wx_id + "\"}" req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=120, user=v_user, payloads=payloadJson.encode('utf-8'))) rsp = grpc_client.send(req) (buffers, seq) = grpc_utils.get_seq_buffer(rsp) buffers = self.wechat_client.sync_send_and_return(buffers) check_buffer_16_is_191(buffers) rsp.baseMsg.cmd = -120 rsp.baseMsg.payloads = char_to_str(buffers) payloads = grpc_client.send(rsp)
def delete_chatroom_member(self, v_user, chatroom_id, wx_id): """ 踢出微信群 btn_DelChatRoomUser_Click :param v_user: :param wxid: :return: """ with app.app_context(): bot_param = model.BotParam.query.filter_by( Username=v_user.userame).first() if bot_param: self.short_host = bot_param.ShortHost payloadJson = "{\"ChatRoom\":\"" + chatroom_id + "\",\"Username\":\"" + wx_id + "\"}" req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=179, user=v_user, payloads=payloadJson.encode('utf-8'))) rsp = grpc_client.send(req) (buffers, seq) = grpc_utils.get_seq_buffer(rsp) buffers = requests.post( "http://" + self.short_host + rsp.baseMsg.cmdUrl, buffers) # 检测buffers[0] == 191 if not ord(buffers.text.encode('utf-8')[0]): print "delete_chatroom_member 未知包" return False else: return True
def get_chatroom_detail(self, v_user, room_id): """ 获取群的信息 :param room_id: :param v_user: :return: """ with app.app_context(): bot_param = model.BotParam.query.filter_by( Username=v_user.userame).first() if bot_param: self.short_host = bot_param.ShortHost pay_load_json = "{\"Chatroom\":\"" + room_id + "\"}" get_room_detail_req = WechatMsg( token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=551, user=v_user, payloads=pay_load_json.encode('utf-8'))) get_room_detail_rsp = grpc_client.send(get_room_detail_req) # (buffers, seq) = grpc_utils.get_seq_buffer(get_room_detail_rsp) body = get_room_detail_rsp.baseMsg.payloads buffers = requests.post( "http://" + self.short_host + get_room_detail_rsp.baseMsg.cmdUrl, body) get_room_detail_rsp.baseMsg.cmd = -551 get_room_detail_rsp.baseMsg.payloads = buffers.content get_room_detail_rsp = grpc_client.send(get_room_detail_rsp) buffers = get_room_detail_rsp.baseMsg.payloads print buffers.encode('utf-8')
def logout_bot(self, v_user): # 退出机器人,并非退出微信登陆 with app.app_context(): user_db = model.User.query.filter_by( userame=v_user.userame).first() user_db.login = 0 db.session.commit()
def sns_post(self, v_user, xml): """ TODO 发送朋友圈 btn_SnsPost_Click :param v_user: :return: """ 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 self.short_host = bot_param.ShortHost self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) pay_load = "{\"Content\":\"" + xml + "\"}" sns_post_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg( cmd=209, user=v_user, payloads=pay_load.encode('utf-8'))) sns_post_rsp = grpc_client.send(sns_post_req) (buffers, seq) = grpc_utils.get_seq_buffer(sns_post_rsp) buffers = self.wechat_client.sync_send_and_return(buffers) if not self.wechat_client.check_buffer_16_is_191(buffers): print "sns post 未知包" return False else: return True
def is_uuid_login(): """ 检测该UUID是否被扫描登陆 # http://localhost:5000/is-uuid-login?qr-uuid=gZF8miqrkksZ9mrRk7mc :return:返回登陆的微信 nickname 和 login 状态 """ uuid = request.args.get('uuid', '') if uuid == '': return jsonify({"ret": str(0), "name": "uuid 为空"}) ret = 0 name = '' with app.app_context(): try: # username是手机号 qr_code_db = Qrcode.query.filter_by(Uuid=uuid).first() if qr_code_db is not None and qr_code_db.Username != '': wx_username = qr_code_db.Username # 筛选出wx_username print(wx_username) # 筛选出wx用户昵称 user_db = User.query.filter_by(userame=wx_username).first() ret = user_db.login name = user_db.nickname except Exception as e: print(e) return jsonify({"ret": str(ret), "name": name})
def is_logon(): """ 登陆接口 返回 昵称 群名 # http://localhost:5000/is_logon?username=15900000010 :return: """ username = request.args.get('username', '') if 'username' == '': return jsonify({"ret": str(0), "name": "未登录"}) ret = 0 name = '' with app.app_context(): try: # username是手机号 qr_code_db = Qrcode.query.filter_by(md_username=username).order_by(Qrcode.id.desc()).all() for qr_code in qr_code_db: if qr_code.Username != '': wx_username = qr_code.Username # 筛选出wx_username print(wx_username) # 筛选出wx用户昵称 user_db = User.query.filter_by(userame=wx_username).first() ret = user_db.login name = user_db.nickname except Exception as e: print(e) return jsonify({"ret": str(ret), "name": name})
def __start_thread_pool(self): with app.app_context(): online_user_list = model.User.query.filter( model.User.login > 0).all() print([user.userame for user in online_user_list]) for user in online_user_list: HeartBeatManager.begin_heartbeat(user.userame)
def invite_chatroom(self, v_user, chatroom_id, wx_id): """ 邀请进群: 向指定用户发送群名片进行邀请 :param v_user: :param chatroom_id: :param wx_id: :return: """ with app.app_context(): bot_param = model.BotParam.query.filter_by( Username=v_user.userame).first() if bot_param: self.short_host = bot_param.ShortHost payloadJson = "{\"ChatRoom\":\"" + chatroom_id + "\",\"Username\":\"" + wx_id + "\"}" req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=610, user=v_user, payloads=payloadJson.encode('utf-8'))) rsp = grpc_client.send(req) (buffers, seq) = grpc_utils.get_seq_buffer(rsp) buffers = requests.post("http://" + self.short_host + rsp.baseMsg.cmdUrl, data=buffers) # 似乎每次登陆后的返回都不一样 if not ord(buffers.text[0]) == 191: print "invite_chatroom_member 返回码{0}".format(ord(buffers.text[0])) return True
def create_chatroom(self, v_user, wx_id_list): """ 建群 private void btn_CreateChatRoom_Click(object sender, EventArgs e) :param v_user: :param wx_id_list: :return: """ 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 self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) payload_json = "{\"Membernames\":\"" + wx_id_list + "\"}" create_chatroom_req = WechatMsg( token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=119, user=v_user, payloads=payload_json.encode('utf-8'))) create_chatroom_rsp = grpc_client.send(create_chatroom_req) (buffers, seq) = grpc_utils.get_seq_buffer(create_chatroom_rsp) buffers = self.wechat_client.sync_send_and_return(buffers) check_buffer_16_is_191(buffers) create_chatroom_rsp.baseMsg.cmd = -119 create_chatroom_rsp.baseMsg.payloads = char_to_str(buffers) payloads = grpc_client.send(create_chatroom_rsp) chatroom_detail = json.loads(payloads.baseMsg.payloads) chatroom_id = chatroom_detail['Roomeid'] print('新建的群id是{}'.format(chatroom_id)) self.send_text_msg(chatroom_id, "欢迎进群", v_user)
def auto_auth(self, v_user, uuid, device_type, 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) pay_load = "{\"UUid\":\"" + uuid + "\",\"DeviceType\":\"" + device_type + "\"}" auto_auth_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg( cmd=702, user=v_user, payloads=pay_load.encode('utf-8'))) auto_auth_rsp = grpc_client.send(auto_auth_req) (buffers, seq) = grpc_utils.get_seq_buffer(auto_auth_rsp) buffers = self.wechat_client.sync_send_and_return( buffers, close_socket=new_socket) self.wechat_client.check_buffer_16_is_191(buffers) auto_auth_rsp.baseMsg.cmd = -702 auto_auth_rsp.baseMsg.payloads = buffers auto_auth_rsp_2 = grpc_client.send(auto_auth_rsp) if auto_auth_rsp_2.baseMsg.ret == 0: user = auto_auth_rsp_2.baseMsg.user print("二次登陆成功") v_user_pickle = pickle.dumps(user) red.set('v_user_' + v_user.userame, v_user_pickle) return True elif auto_auth_rsp_2.baseMsg.ret == -100 or auto_auth_rsp_2.baseMsg.ret == -2023: print("二次登陆失败,重新扫码吧朋友") ret_reason = '' try: payload = auto_auth_rsp_2.baseMsg.payloads start = "<Content><![CDATA[" end = "]]></Content>" ret_reason = payload[payload.find(start) + len(start):payload.find(end)] except Exception as e: ret_reason = "未知" # oss_utils.beary_chat("淘宝客:{0} 已掉线,原因:{1}".format(v_user.nickname, ret_reason)) self.wechat_client.close_when_done() return False else: print("二次登陆未知返回码") ret_code = auto_auth_rsp_2.baseMsg.ret # oss_utils.beary_chat("淘宝客:{0} 已掉线,未知返回码:{1}".format(v_user.nickname, ret_code)) self.wechat_client.close_when_done() return False
def decode_cmd_318(self, v_user, data): with app.app_context(): bot_param = model.BotParam.query.filter_by( Username=v_user.userame).first() if bot_param: self.short_host = bot_param.ShortHost self.long_host = bot_param.LongHost self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) # send notify_req notify_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=-318, user=v_user, payloads=data)) notify_rsp = grpc_client.send(notify_req) body = notify_rsp.baseMsg.payloads.encode('utf-8') add_msg_digest = json.loads(body) print add_msg_digest payload_dict = { "ChatroomId": add_msg_digest['ChatRoomId'], "MsgSeq": add_msg_digest['NewMsgSeq'] } payload_dict_json = json.dumps(payload_dict) # get chatroom req get_chatroom_msg_req = WechatMsg( token=CONST_PROTOCOL_DICT['machine_code'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=805, user=v_user, payloads=payload_dict_json.encode('utf-8'))) get_chatroom_msg_rsp = grpc_client.send(get_chatroom_msg_req) body = get_chatroom_msg_rsp.baseMsg.payloads upload_url = get_chatroom_msg_rsp.baseMsg.cmdUrl buffers = requests.post("http://" + self.short_host + upload_url, data=body) print buffers.text if buffers is None or buffers.text.encode('utf-8')[0] == 191: # TODO:hextostr print("unknown package:{0}".format(buffers)) return False # send grpc and decode again get_chatroom_msg_rsp.baseMsg.cmd = -805 get_chatroom_msg_rsp.baseMsg.payloads = buffers.text.encode('utf-8') get_chatroom_msg_rsp = grpc_client.send(get_chatroom_msg_rsp) buffers = get_chatroom_msg_rsp.baseMsg.payloads print buffers return True
def set_user_context(self, wx_username): # TODO:self.wx_username 不该在这初始化,待修改 self.wx_username = wx_username with app.app_context(): bot_param = model.BotParam.query.filter_by( Username=wx_username).first() if bot_param: self.long_host = bot_param.LongHost self.short_host = bot_param.ShortHost self.wechat_client = WechatClient.WechatClient(self.long_host, 80, True)
def filter_keyword_rule(wx_id, msg_dict): # http://s-prod-04.qunzhu666.com:8000/search-product-pad?username=15900000010&keyword=鞋子&gid=7682741189@chatroom # http://s-prod-04.qunzhu666.com:8000/interact/search-product-pad/?username=wxid_3cimlsancyfg22&keyword=%E9%9E%8B%E5%AD%90&gid=6362478985@chatroom # 条件1 文字符合要求 keyword = find_buy_start(msg_dict['Content']) if keyword and keyword is not '': # FromUserName 跟 ToUserName 是相对机器人来说的 # 机器人在群里说话,FromUserName是机器人的wx_id,ToUserName是gid # 但其他人在群里说话,ToUserName是机器人的wx_id,FromUserName是gid # 群是淘宝客群,找XX才生效 is_taobao_group = False gid = '' # 情况分类1 机器人自己说找XX if msg_dict['FromUserName'] == wx_id and "@chatroom" in msg_dict[ 'ToUserName']: gid = msg_dict['ToUserName'] is_taobao_group = True # 情况分类2 群成员说找XX elif "@chatroom" in msg_dict['FromUserName'] and msg_dict[ 'ToUserName'] == wx_id: gid = msg_dict['FromUserName'] is_taobao_group = True # gid名称是福利社 with app.app_context(): contact_db = model.Contact.query.filter( model.Contact.NickName.contains("福利社"), model.Contact.UserName == gid).first() gid_name_is = contact_db is not None if is_taobao_group and gid_name_is: # 根据id找到username with app.app_context(): qrcode_db = model.Qrcode.query.filter_by( Username=wx_id).first() username = qrcode_db.md_username print("username={}&keyword={}&gid={}".format( username, keyword, gid)) url = "http://s-prod-04.qunzhu666.com:8000/interact/search-product-pad/?username={}&keyword={}&gid={}&uin={}".format( username, keyword, gid, wx_id) rsp = requests.get(url) print(rsp.text)
def heartbeat_user(): with app.app_context(): user_list = model.User.query.filter(model.User.login > 0).all() print([user.userame for user in user_list]) for user in user_list: print(user.userame) wx_bot = weixin_bot.WXBot() try: if wx_bot.try_get_new_message(user.userame): print("suc in {}".format(user.userame)) else: print("fail in {}".format(user.userame)) except Exception as e: print(e)
def get_qrcode(self, md_username): """ 获取qrcode :return: """ # session_key = '5326451F200E0D130CE4AE27262B5897'.decode('hex') # 构造qrcode请求 self.wechat_client = WechatClient.WechatClient(self.long_host, 80, True) self.deviceId = get_md5(md_username) qrcode_req = WechatMsg( token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=502, user=User(sessionKey=int_list_convert_to_byte_list( CONST_PROTOCOL_DICT['random_encry_key']), deviceId=self.deviceId))) qrcode_rsp = grpc_client.send(qrcode_req) check_grpc_response(qrcode_rsp.baseMsg.ret) (buffers, seq) = grpc_utils.get_seq_buffer(qrcode_rsp) data = self.wechat_client.sync_send_and_return(buffers) qrcode_req.baseMsg.cmd = -502 qrcode_req.baseMsg.payloads = char_to_str(data) qrcode_rsp = grpc_client.send(qrcode_req) buffers = qrcode_rsp.baseMsg.payloads # 保存二维码图片 qr_code = json.loads(buffers) imgData = base64.b64decode(qr_code['ImgBuf']) uuid = qr_code['Uuid'] with app.app_context(): model.save_qr_code(qr_code) try: oss_path = oss_utils.put_object_to_oss(uuid + ".png", imgData) print("oss_path is: {}".format(oss_path)) except Exception as e: print(e) print('upload oss err by uuid:{}'.format(uuid)) return oss_path, qrcode_rsp, self.deviceId
def select(): with app.app_context(): # 筛选出已经登录的User user_list = model.User.query.filter(model.User.login > 0).all() print([user.userame for user in user_list]) for user in user_list: print("handling wxid {}, time {}".format(user.userame, time.time())) # 发单机器人id hid = user.userame # 通过 wx_id = hid 筛选出手机号 qr_code_db = model.Qrcode.query.filter_by( Username=user.userame).all() for qr_code in qr_code_db: if qr_code.md_username is not None: md_username = qr_code.md_username break # 询问当前时间此用户是否需要推送 rsp = requests.get( "http://s-prod-07.qunzhu666.com:8000/api/tk/is-push?username={0}&wx_id={1}" .format(md_username, hid), timeout=4) ret = json.loads(rsp.text)['ret'] if ret == 1: # 筛选出激活群 message_list = model.Message.query.filter( model.Message.Content == "激活", model.Message.FromUserName == user.userame).all() group_set = set( [message.ToUserName for message in message_list]) for group in group_set: # 发单人的wx_id, 群的id, 手机号 try: contact_db = model.Contact.query.filter( model.Contact.NickName.contains("福利社"), model.Contact.UserName == group).first() if contact_db is not None: print('昵称 {}, time {}'.format( contact_db.NickName, time.time())) post_taobaoke_url(group, hid, md_username) except Exception as e: print(e)
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 send_voice_msg(self, v_user, to_user_name, url): """ 发送语音 btn_SendVoice_Click :param v_user: :param url: :return: """ 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 self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) voice_path = 'img/test.mp3' with open(voice_path, 'rb') as voice_file: data = voice_file.read() payload = { 'ToUserName': to_user_name, 'Offset': 0, 'Length': len(data), 'EndFlag': 1, 'Data': data, 'VoiceFormat': 0 } payload_json = json.dumps(payload) send_voice_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg( cmd=127, user=v_user, payloads=payload_json.encode('utf-8'))) send_voice_rsp = grpc_client.send(send_voice_req) (buffers, seq) = grpc_utils.get_seq_buffer(send_voice_rsp) buffers = self.wechat_client.sync_send_and_return(buffers) self.wechat_client.close_when_done() return check_buffer_16_is_191(buffers)
def modify_chatroom_name(self, v_user, chatroom_id, room_name): with app.app_context(): bot_param = model.BotParam.query.filter_by( Username=v_user.userame).first() if bot_param: self.short_host = bot_param.ShortHost payload_json = "{\"Cmdid\":27,\"ChatRoom\":\"" + chatroom_id + "\",\"Roomname\":\"" + room_name + "\"}" modify_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg( cmd=681, user=v_user, payloads=payload_json.encode('utf-8'))) modify_rsp = grpc_client.send(modify_req) (buffers, seq) = grpc_utils.get_seq_buffer(modify_rsp) buffers = requests.post("http://" + self.short_host + modify_rsp.baseMsg.cmdUrl, data=buffers) self.wechat_client.close_when_done() return check_buffer_16_is_191(buffers)
def send_text_msg(self, user_name, content, v_user): """ 参考btn_SendMsg_Click :param user_name: :param content: :param at_user_list: :param v_user: :return: """ 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 self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) payLoadJson = "{\"ToUserName\":\"" + user_name + "\",\"Content\":\"" + content + "\",\"Type\":0,\"MsgSource\":\"\"}" send_text_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg( cmd=522, user=v_user, payloads=payLoadJson.encode('utf-8'))) send_text_rsp = grpc_client.send(send_text_req) (buffers, seq) = grpc_utils.get_seq_buffer(send_text_rsp) import binascii print(binascii.b2a_hex(buffers)) buffers = self.wechat_client.sync_send_and_return(buffers) if not check_buffer_16_is_191(buffers): if read_int(buffers, 18) == -13: print("Session Time out 离线或用户取消登陆 需执行二次登录") return False self.wechat_client.close_when_done() return True
def heartbeat(cls, wx_username): is_first = True wx_bot = weixin_bot.WXBot() wx_bot.set_user_context(wx_username) wx_bot.open_notify_callback() # 微信有新消息就会往socket推20字节的notify包 # 防止该socket断开,每30秒发一次同步消息包 while True: try: with app.app_context(): user = model.User.query.filter_by( userame=wx_username).first() if user is not None: # 用户退出登陆,退出线程 if user.login == 0: cls.__print_log( "[{0}:{1}]user logout,heartbeat thread exit". format(user.userame, user.nickname)) # 登出时需要把socket断开,否则会一直收到退出登陆的消息 wx_bot.wechat_client.close_when_done() return if not wx_bot.wechat_client.connected: # 测试过后发现好像没有哪个包能阻止socket断开,断开只是时间问题 # 检测一下socket有没断开,如果断开,重新起一个socket即可 # oss_utils.beary_chat("{} heart_beat socket 断开, 准备重新链接".format(wx_username), user='******') cls.__print_log("{0} socket state:{1}".format( wx_username, wx_bot.wechat_client.connected)) wx_bot.wechat_client.close_when_done() # 再一次初始化 is_first = True wx_bot = weixin_bot.WXBot() wx_bot.set_user_context(wx_username) wx_bot.open_notify_callback() v_user = pickle.loads(red.get('v_user_' + wx_username)) if is_first: 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 wx_bot.auto_auth(v_user, UUid, DeviceType, False): # oss_utils.beary_chat("{} auto_auth success in heartbeat".format(wx_username), # user='******') cls.__print_log( "{} auto_auth success in heartbeat".format( wx_username)) else: oss_utils.beary_chat( "{} auto_auth failed in heartbeat".format( wx_username), user='******') cls.__print_log( "{} auto_auth failed in heartbeat, thread exit". format(wx_username)) wx_bot.logout_bot(v_user) is_first = False # c# demo 中的heart_beat包,能延长socket的持续时间 # 但始终会断开 wx_bot.heart_beat(v_user) # print "{} heart best finished".format(wx_username) time.sleep(30) except Exception as e: print "[{0}]heartbeat exception:{1}".format( wx_username, e.message) continue
def check_qrcode_login(self, qrcode_rsp, device_id): """ 检测扫描是否登陆 :param qr_code: :return: """ buffers = qrcode_rsp.baseMsg.payloads qr_code = json.loads(buffers) uuid = qr_code['Uuid'] notify_key_str = base64.b64decode(qr_code['NotifyKey'].encode('utf-8')) long_head = qrcode_rsp.baseMsg.longHead start_time = datetime.now() self.deviceId = device_id while qr_code['Status'] is not 2: # 构造扫描确认请求 check_qrcode_grpc_req = WechatMsg( token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg( cmd=503, longHead=long_head, payloads=str(uuid), user=User(sessionKey=int_list_convert_to_byte_list( CONST_PROTOCOL_DICT['random_encry_key']), deviceId=self.deviceId, maxSyncKey=notify_key_str))) checkqrcode_grpc_rsp = grpc_client.send(check_qrcode_grpc_req) (buffers, seq) = grpc_utils.get_seq_buffer(checkqrcode_grpc_rsp) buffers = self.wechat_client.sync_send_and_return(buffers) check_buffer_16_is_191(buffers) # 将微信包传给grpc服务器,进行一次解包操作 checkqrcode_grpc_rsp.baseMsg.cmd = -503 checkqrcode_grpc_rsp.baseMsg.payloads = char_to_str(buffers) checkqrcode_grpc_rsp_2 = grpc_client.send(checkqrcode_grpc_rsp) payloads = checkqrcode_grpc_rsp_2.baseMsg.payloads if 'unpack err' not in payloads: qr_code = json.loads(payloads) if qr_code['Status'] is 2: # save qr_code with app.app_context(): qr_code_db = model.Qrcode.query.filter_by( Uuid=uuid).order_by(model.Qrcode.id.desc()).first() model.update_qr_code(qr_code, qr_code_db) # 成功登陆 return qr_code elif qr_code['Status'] is 0: # 未扫描等待扫描 pass elif qr_code['Status'] is 1: # 已扫描未确认 pass elif qr_code['Status'] is 4: # 已取消扫描 pass # 等待5s再检测 time.sleep(5) # 如果3分钟都没有正常返回status 2 返回False if (datetime.now() - start_time).seconds >= 60 * 3: return False
def confirm_qrcode_login(self, qr_code, keep_heart_beat): # 重置longHost with app.app_context(): bot_param = model.BotParam.query.filter_by( Username=qr_code['Username']).first() if bot_param and bot_param.LongHost is not None and bot_param.LongHost != "": self.long_host = bot_param.LongHost self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) # 微信确认登陆模块 UUid = u"667D18B1-BCE3-4AA2-8ED1-1FDC19446567" DeviceType = u"<k21>TP_lINKS_5G</k21><k22>中国移动</k22><k24>c1:cd:2d:1c:5b:11</k24>" payLoadJson = "{\"Username\":\"" + qr_code[ 'Username'] + "\",\"PassWord\":\"" + qr_code[ 'Password'] + "\",\"UUid\":\"" + UUid + "\",\"DeviceType\":\"" + DeviceType + "\"}" qrcode_login_req = WechatMsg( token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg(cmd=1111, user=User(sessionKey=int_list_convert_to_byte_list( CONST_PROTOCOL_DICT['random_encry_key']), deviceId=self.deviceId), payloads=payLoadJson.encode('utf-8'))) qrcode_login_rsp = grpc_client.send(qrcode_login_req) (buffers, seq) = grpc_utils.get_seq_buffer(qrcode_login_rsp) buffers = self.wechat_client.sync_send_and_return(buffers) check_buffer_16_is_191(buffers) # 解微信包 qrcode_login_rsp.baseMsg.cmd = -1001 qrcode_login_rsp.baseMsg.payloads = char_to_str(buffers) qrcode_login_rsp = grpc_client.send(qrcode_login_rsp) with app.app_context(): bot_param_db = model.BotParam.query.filter_by( Username=qr_code['Username']).first() if bot_param_db is None: model.save_bot_param(qr_code['Username'], self.deviceId, qrcode_login_rsp.baseMsg.longHost, qrcode_login_rsp.baseMsg.shortHost) else: model.update_bot_param(bot_param_db, qr_code['Username'], self.deviceId, qrcode_login_rsp.baseMsg.longHost, qrcode_login_rsp.baseMsg.shortHost) if qrcode_login_rsp.baseMsg.ret == -301: # 返回-301代表重定向 self.wechat_client.close_when_done() # 在user表写上gg,麻烦重新登录吧 return False elif qrcode_login_rsp.baseMsg.ret == 0: # 返回0代表登陆成功 print('login successful') # 将User赋值 v_user = qrcode_login_rsp.baseMsg.user # 存下v_user with app.app_context(): model.save_user(v_user) with app.app_context(): try: user_db = model.User.query.filter_by( userame=v_user.userame).first() user_db.login = 1 db.session.commit() except Exception as e: print(e) # if keep_heart_beat: # 登陆成功,维持心跳 # asyn_rec_thread = threading.Thread(target=self, WXBot.heart_beat(v_user)) # asyn_rec_thread.start() red.set('v_user_' + str(v_user.userame), pickle.dumps(v_user)) self.wechat_client.close_when_done() return True else: print("qrcode_login_rsp.baseMsg.ret is {}".format( qrcode_login_rsp.baseMsg.ret)) print("原因是{}".format(qrcode_login_rsp.baseMsg.payloads)) return False
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 完成"
def send_img_msg(self, user_name, v_user, url): """ btn_SendMsgimg_Click :param user_name: :param v_user: :return: """ 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 self.wechat_client = WechatClient.WechatClient( self.long_host, 80, True) data = urllib2.urlopen(url).read() # img_path = 'img/no.png' # with codecs.open(img_path, 'rb') as img_file: # data = img_file.read() # with open(img_path, 'rb') as img_file: # data = img_file.read() # 起始位置 start_pos = 0 # 数据分块长度 data_len = 16535 # 总长度 data_total_length = len(data) print('preparing sent img length length {}'.format(data_total_length)) # 客户图像id client_img_id = v_user.userame + "_" + str(get_time_stamp()) while start_pos != data_total_length: # 每次最多只传65535 count = 0 if data_total_length - start_pos > data_len: count = data_len else: count = data_total_length - start_pos upload_data = base64.b64encode(data[start_pos:start_pos + count]) payLoadJson = { 'ClientImgId': client_img_id.encode('utf-8'), 'ToUserName': user_name.encode('utf-8'), 'StartPos': start_pos, 'TotalLen': data_total_length, 'DataLen': len(data[start_pos:start_pos + count]), 'Data': upload_data } pay_load_json = json.dumps(payLoadJson) start_pos = start_pos + count print("Send Img Block {}".format(count)) print("start_pos is {}".format(start_pos)) print("data_total_length is {}".format(data_total_length)) img_msg_req = WechatMsg(token=CONST_PROTOCOL_DICT['machine_code'], version=CONST_PROTOCOL_DICT['version'], timeStamp=get_time_stamp(), iP=get_public_ip(), baseMsg=BaseMsg( cmd=110, user=v_user, payloads=pay_load_json.encode('utf-8'), )) img_msg_rsp = grpc_client.send(img_msg_req) (buffers, seq) = grpc_utils.get_seq_buffer(img_msg_rsp) buffers = self.wechat_client.sync_send_and_return(buffers, time_out=3) check_buffer_16_is_191(buffers) self.wechat_client.close_when_done() return True