def login(self): """ 获取验证码结果 :return 权限校验码 """ data = { 'username': self.user_name, 'password': self.password, 'appid': 'otn' } answer = AuthCode.get_auth_code(self.session) data['answer'] = answer response = self.session.post(API_BASE_LOGIN.get('url'), data) result = response.json() if result.get('result_code') == 0: # 登录成功 """ login 获得 cookie uamtk auth/uamtk 不请求,会返回 uamtk票据内容为空 /otn/uamauthclient 能拿到用户名 """ new_tk = self.auth_uamtk() user_name = self.auth_uamauthclient(new_tk) self.update_user_info({'user_name': user_name}) self.login_did_success() elif result.get('result_code') == 2: # 账号之内错误 # 登录失败,用户名或密码为空 # 密码输入错误 UserLog.add_quick_log(UserLog.MESSAGE_LOGIN_FAIL.format(result.get('result_message'))) else: UserLog.add_quick_log( UserLog.MESSAGE_LOGIN_FAIL.format(result.get('result_message', result.get('message', '-')))) return False pass
def wait_for_ready(self): if self.is_ready: return self UserLog.add_quick_log( UserLog.MESSAGE_WAIT_USER_INIT_COMPLETE.format( self.retry_time)).flush() stay_second(self.retry_time) return self.wait_for_ready()
def download_code(self): img_path = './tkcode.png' url = API_AUTH_CODE_BASE64_DOWNLOAD.format(random=random.random()) # code_path = self.data_path + 'code.png' try: UserLog.add_quick_log(UserLog.MESSAGE_DOWNLAODING_THE_CODE).flush() # response = self.session.save_to_file(url, code_path) # TODO 返回错误情况 response = self.session.get(url) result = response.json().get('image') if result: try: with open(img_path, 'wb', encoding="utf-8") as img: img.write(base64.b64decode(result)) # img.write(result) except Exception: with open(img_path, 'wb') as img: img.write(base64.b64decode(result)) return result raise SSLError('返回数据为空') except SSLError as e: UserLog.add_quick_log( UserLog.MESSAGE_DOWNLAOD_AUTH_CODE_FAIL.format( e, self.retry_time)).flush() time.sleep(self.retry_time) return self.download_code()
def destroy(self): """ 退出用户 :return: """ UserLog.add_quick_log(UserLog.MESSAGE_USER_BEING_DESTROY.format(self.user_name)).flush() self.is_alive = False
def get_passengers_by_members(self, members): """ 获取格式化后的乘客信息 :param members: :return: [{ name: '项羽', type: 1, id_card: 0000000000000000000, type_text: '成人', enc_str: 'aaaaaa' }] """ self.get_user_passengers() results = [] for member in members: is_member_code = is_number(member) if not is_member_code: child_check = array_dict_find_by_key_value( results, 'name', member) if not is_member_code and child_check: new_member = child_check.copy() new_member['type'] = UserType.CHILD new_member['type_text'] = dict_find_key_by_value( UserType.dicts, int(new_member['type'])) else: if is_member_code: passenger = array_dict_find_by_key_value( self.passengers, 'code', member) else: passenger = array_dict_find_by_key_value( self.passengers, 'passenger_name', member) if not passenger: UserLog.add_quick_log( UserLog.MESSAGE_USER_PASSENGERS_IS_INVALID.format( self.user_name, member)).flush() return False new_member = { 'name': passenger.get('passenger_name'), 'id_card': passenger.get('passenger_id_no'), 'id_card_type': passenger.get('passenger_id_type_code'), 'mobile': passenger.get('mobile_no'), 'type': passenger.get('passenger_type'), 'type_text': dict_find_key_by_value( UserType.dicts, int(passenger.get('passenger_type'))), 'enc_str': passenger.get('allEncStr') } results.append(new_member) return results
def check_heartbeat(self): # 心跳检测 if self.last_heartbeat and (time_now() - self.last_heartbeat).seconds < self.heartbeat: return True if self.is_first_time() or not self.check_user_is_login(): self.handle_login() self.is_ready = True UserLog.add_quick_log(UserLog.MESSAGE_USER_HEARTBEAT_NORMAL.format(self.get_name(), self.heartbeat)).flush() self.last_heartbeat = time_now()
def check_heartbeat(self): # 心跳检测 if self.get_last_heartbeat() and (time_int() - self.get_last_heartbeat()) < Config().USER_HEARTBEAT_INTERVAL: return True # 只有主节点才能走到这 if self.is_first_time() or not self.check_user_is_login(): if not self.handle_login(): return self.user_did_load() message = UserLog.MESSAGE_USER_HEARTBEAT_NORMAL.format(self.get_name(), Config().USER_HEARTBEAT_INTERVAL) UserLog.add_quick_log(message).flush()
def get_user_passengers(self): if self.passengers: return self.passengers response = self.session.post(API_USER_PASSENGERS) result = response.json() if result.get('data.normal_passengers'): self.passengers = result.get('data.normal_passengers') return self.passengers else: UserLog.add_quick_log( UserLog.MESSAGE_GET_USER_PASSENGERS_FAIL.format(result.get('messages', '-'), self.retry_time)).flush() stay_second(self.retry_time) return self.get_user_passengers()
def download_code(self): url = API_AUTH_CODE_DOWNLOAD.get('url').format(random=random.random()) code_path = self.data_path + 'code.png' try: UserLog.add_quick_log(UserLog.MESSAGE_DOWNLAODING_THE_CODE).flush() response = self.session.save_to_file(url, code_path) # TODO 返回错误情况 except SSLError as e: UserLog.add_quick_log( UserLog.MESSAGE_DOWNLAOD_AUTH_CODE_FAIL.format( e, self.retry_time)).flush() time.sleep(self.retry_time) return self.download_code() return code_path
def load_user_from_remote(self): cookie = self.cluster.get_user_cookie(self.key) if not cookie and Config().is_slave(): while True: # 子节点只能取 UserLog.add_quick_log(UserLog.MESSAGE_USER_COOKIE_NOT_FOUND_FROM_REMOTE.format(self.user_name)).flush() stay_second(self.retry_time) return self.load_user_from_remote() if cookie: self.session.cookies.update(cookie) if not self.cookie: # 第一次加载 self.cookie = True self.did_loaded_user() return True return False
def check_heartbeat(self): # 心跳检测 if self.get_last_heartbeat() and (time_int() - self.get_last_heartbeat()) < self.heartbeat_interval: return True # 只有主节点才能走到这 if self.is_first_time() or not self.check_user_is_login(): self.is_ready = False if not self.handle_login(): return self.is_ready = True message = UserLog.MESSAGE_USER_HEARTBEAT_NORMAL.format(self.get_name(), self.heartbeat_interval) if not Config.is_cluster_enabled(): UserLog.add_quick_log(message).flush() else: self.cluster.publish_log_message(message) self.set_last_heartbeat()
def get_user_passengers(self): if self.passengers: return self.passengers response = self.session.post(API_USER_PASSENGERS) result = response.json() if result.get('data.normal_passengers'): self.passengers = result.get('data.normal_passengers') # 将乘客写入到文件 with open(Config().USER_PASSENGERS_FILE % self.user_name, 'w') as f: f.write(json.dumps(self.passengers,indent=4, ensure_ascii=False)) return self.passengers else: UserLog.add_quick_log( UserLog.MESSAGE_GET_USER_PASSENGERS_FAIL.format( result.get('messages', CommonLog.MESSAGE_RESPONSE_EMPTY_ERROR), self.retry_time)).flush() stay_second(self.retry_time) return self.get_user_passengers()
def download_code(self): url = API_AUTH_CODE_BASE64_DOWNLOAD.format(random=random.random()) # code_path = self.data_path + 'code.png' try: UserLog.add_quick_log(UserLog.MESSAGE_DOWNLAODING_THE_CODE).flush() # response = self.session.save_to_file(url, code_path) # TODO 返回错误情况 response = self.session.get(url) result = response.json() if result.get('image'): return result.get('image') raise SSLError('返回数据为空') except SSLError as e: UserLog.add_quick_log( UserLog.MESSAGE_DOWNLAOD_AUTH_CODE_FAIL.format( e, self.retry_time)).flush() time.sleep(self.retry_time) return self.download_code()
def check_heartbeat(self): # 心跳检测 if self.get_last_heartbeat() and (time_int() - self.get_last_heartbeat()) < Config().USER_HEARTBEAT_INTERVAL: return True # 只有主节点才能走到这 if self.is_first_time() or not self.check_user_is_login(): #if not self.handle_login(): return login_times = 0 while not self.handle_login(): login_times += 1 if login_times == 3: print("登录失败次数过多,程序退出。") os._exit(0) self.user_did_load() message = UserLog.MESSAGE_USER_HEARTBEAT_NORMAL.format(self.get_name(), Config().USER_HEARTBEAT_INTERVAL) UserLog.add_quick_log(message).flush()
def login(self): """ 获取验证码结果 :return 权限校验码 """ data = { 'username': self.user_name, 'password': self.password, 'appid': 'otn' } self.request_device_id() answer = AuthCode.get_auth_code(self.session) data['answer'] = answer response = self.session.post(API_BASE_LOGIN.get('url'), data) result = response.json() print(result) if result.get('result_code') == 0: # 登录成功 """ login 获得 cookie uamtk auth/uamtk 不请求,会返回 uamtk票据内容为空 /otn/uamauthclient 能拿到用户名 """ new_tk = self.auth_uamtk() user_name = self.auth_uamauthclient(new_tk) # self.init_my_12306_api() self.update_user_info({'user_name': user_name}) self.login_did_success() return True elif result.get('result_code') == 2: # 账号之内错误 # 登录失败,用户名或密码为空 # 密码输入错误 UserLog.add_quick_log( UserLog.MESSAGE_LOGIN_FAIL.format( result.get('result_message'))).flush() else: UserLog.add_quick_log( UserLog.MESSAGE_LOGIN_FAIL.format( result.get( 'result_message', result.get( 'message', CommonLog.MESSAGE_RESPONSE_EMPTY_ERROR)))).flush() return False
def check_members(cls, members, key, call_back): """ 检测乘客信息 :param passengers: :return: """ self = cls() for user in self.users: assert isinstance(user, UserJob) if user.key == key and user.check_is_ready(): passengers = user.get_passengers_by_members(members) return call_back(passengers) UserLog.add_quick_log( UserLog.MESSAGE_WAIT_USER_INIT_COMPLETE.format( self.retry_time)).flush() stay_second(self.retry_time) return self.check_members(members, key, call_back)
def login(self): """ 获取验证码结果 :return 权限校验码 """ #self.password = '' while (self.password is None or self.password == ''): self.password = input("请输入用户{}的12306登录密码...\n".format(self.user_name)) #print("\n你输入的密码是:{}".format(self.password)) data = { 'username': self.user_name, 'password': self.password, 'appid': 'otn' } answer = AuthCode.get_auth_code(self.session) print("auth code answer=%s"%answer) data['answer'] = answer self.request_device_id() response = self.session.post(API_BASE_LOGIN.get('url'), data) result = response.json() if result.get('result_code') == 0: # 登录成功 """ login 获得 cookie uamtk auth/uamtk 不请求,会返回 uamtk票据内容为空 /otn/uamauthclient 能拿到用户名 """ new_tk = self.auth_uamtk() user_name = self.auth_uamauthclient(new_tk) self.update_user_info({'user_name': user_name}) self.login_did_success() return True elif result.get('result_code') == 2: # 账号之内错误 # 登录失败,用户名或密码为空 # 密码输入错误 UserLog.add_quick_log(UserLog.MESSAGE_LOGIN_FAIL.format(result.get('result_message'))).flush() else: UserLog.add_quick_log( UserLog.MESSAGE_LOGIN_FAIL.format(result.get('result_message', result.get('message', CommonLog.MESSAGE_RESPONSE_EMPTY_ERROR)))).flush() return False
def check_code(self, answer): """ 校验验证码 :return: """ url = API_AUTH_CODE_CHECK.get('url').format(answer=answer, random=random.random()) response = self.session.get(url) result = response.json() if result.get('result_code') == '4': UserLog.add_quick_log(UserLog.MESSAGE_CODE_AUTH_SUCCESS).flush() return True else: UserLog.add_quick_log( UserLog.MESSAGE_CODE_AUTH_FAIL.format( result.get('result_message'))).flush() self.session.cookies.clear_session_cookies() return False
def load_user_from_remote(self): cookie = self.cluster.get_user_cookie(self.key) info = self.cluster.get_user_info(self.key) if Config().is_slave() and (not cookie or not info): while True: # 子节点只能取 UserLog.add_quick_log(UserLog.MESSAGE_USER_COOKIE_NOT_FOUND_FROM_REMOTE.format(self.user_name)).flush() stay_second(self.retry_time) return self.load_user_from_remote() if info: self.info = info if cookie: self.session.cookies.update(cookie) if not self.cookie: # 第一次加载 self.cookie = True if not Config().is_slave(): self.did_loaded_user() else: self.is_ready = True # 设置子节点用户 已准备好 UserLog.print_welcome_user(self) return True return False
def download_code(self): try: UserLog.add_quick_log(UserLog.MESSAGE_QRCODE_DOWNLOADING).flush() response = self.session.post(API_AUTH_QRCODE_BASE64_DOWNLOAD.get('url'), data={'appid': 'otn'}) result = response.json() if result.get('result_code') == '0': img_bytes = base64.b64decode(result.get('image')) try: os.mkdir(Config().USER_DATA_DIR + '/qrcode') except FileExistsError: pass png_path = path.normpath(Config().USER_DATA_DIR + '/qrcode/%d.png' % time.time()) with open(png_path, 'wb') as file: file.write(img_bytes) file.close() if os.name == 'nt': os.startfile(png_path) else: print_qrcode(png_path) UserLog.add_log(UserLog.MESSAGE_QRCODE_DOWNLOADED.format(png_path)).flush() Notification.send_email_with_qrcode(Config().EMAIL_RECEIVER, '你有新的登录二维码啦!', png_path) self.retry_count = 0 return result.get('uuid'), png_path raise KeyError('获取二维码失败: {}'.format(result.get('result_message'))) except Exception as e: UserLog.add_quick_log( UserLog.MESSAGE_QRCODE_FAIL.format(e, self.retry_time)).flush() self.retry_count = self.retry_count + 1 if self.retry_count == 20: self.retry_count = 0 try: os.remove(self.get_cookie_path()) except: pass time.sleep(self.retry_time) return self.download_code()
def did_loaded_user(self): """ 恢复用户成功 :return: """ UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER.format(self.user_name)) if self.check_user_is_login(): UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER_SUCCESS.format(self.user_name)) self.get_user_info() UserLog.print_welcome_user(self) else: UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER_BUT_EXPIRED)
def did_loaded_user(self): """ 恢复用户成功 :return: """ UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER.format(self.user_name)).flush() if self.check_user_is_login() and self.get_user_info(): UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER_SUCCESS.format(self.user_name)).flush() Event().user_loaded({'key': self.key}) # 发布通知 self.is_ready = True UserLog.print_welcome_user(self) else: UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER_BUT_EXPIRED).flush()
def did_loaded_user(self): """ 恢复用户成功 :return: """ UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER.format(self.user_name)).flush() if self.check_user_is_login() and self.get_user_info(): UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER_SUCCESS.format(self.user_name)).flush() UserLog.print_welcome_user(self) self.user_did_load() else: UserLog.add_quick_log(UserLog.MESSAGE_LOADED_USER_BUT_EXPIRED).flush() self.set_last_heartbeat(0)
def qr_login(self): self.request_device_id() image_uuid, png_path = self.download_code() while True: data = { 'RAIL_DEVICEID': self.session.cookies.get('RAIL_DEVICEID'), 'RAIL_EXPIRATION': self.session.cookies.get('RAIL_EXPIRATION'), 'uuid': image_uuid, 'appid': 'otn' } response = self.session.post(API_AUTH_QRCODE_CHECK.get('url'), data) result = response.json() result_code = int(result.get('result_code')) if result_code == 0: time.sleep(2) elif result_code == 1: UserLog.add_quick_log('请确认登录').flush() time.sleep(2) elif result_code == 2: break elif result_code == 3: try: os.remove(png_path) except Exception as e: UserLog.add_quick_log('无法删除文件: {}'.format(e)).flush() image_uuid = self.download_code() try: os.remove(png_path) except Exception as e: UserLog.add_quick_log('无法删除文件: {}'.format(e)).flush() self.session.get(API_USER_LOGIN, allow_redirects=True) new_tk = self.auth_uamtk() user_name = self.auth_uamauthclient(new_tk) self.update_user_info({'user_name': user_name}) self.session.get(API_USER_LOGIN, allow_redirects=True) self.login_did_success() return True
def update_user_accounts(self, auto=False, old=None): self.user_accounts = Config().USER_ACCOUNTS if auto: UserLog.add_quick_log(UserLog.MESSAGE_USERS_DID_CHANGED).flush() self.refresh_users(old)