Exemplo n.º 1
0
def log_output():
    """
    日志
    :return:
    """
    last_line = int(request.args.get('line', 0))
    limit = int(request.args.get('limit', 10))
    max_old = 200  # 取最新时 往后再取的数
    file = Config().OUT_PUT_LOG_TO_FILE_PATH
    res = []

    if last_line == -1:
        total_line = get_file_total_line_num(file)
        last_line = total_line - max_old if total_line > max_old else 0
        ranges = range(max_old + limit)
    else:
        ranges = range(limit)

    if Config().OUT_PUT_LOG_TO_FILE_ENABLED:
        # with open(Config().OUT_PUT_LOG_TO_FILE_PATH, 'r', encoding='utf-8') as f:
        #     res = f.readlines()[last_line:limit]
        linecache.updatecache(file)
        for i in ranges:
            tmp = linecache.getline(file, last_line + i)
            if tmp != '': res.append(tmp)
        last_line += len(res)
    else:
        res = CommonLog.MESSAGE_OUTPUT_TO_FILE_IS_UN_ENABLE
    return jsonify({'last_line': last_line, 'data': res})
Exemplo n.º 2
0
 def check_auto_code(cls):
     if Config().AUTO_CODE_PLATFORM == 'free':
         return True
     account_config = Config().AUTO_CODE_ACCOUNT
     if not account_config.get('user') or not account_config.get('pwd'):
         return False
     return True
Exemplo n.º 3
0
    def test_send_notifications(cls):
        if Config().NOTIFICATION_BY_VOICE_CODE:  # 语音通知
            CommonLog.add_quick_log(
                CommonLog.MESSAGE_TEST_SEND_VOICE_CODE).flush()
            Notification.voice_code(
                Config().NOTIFICATION_VOICE_CODE_PHONE, '张三',
                OrderLog.
                MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_VOICE_CODE_CONTENT.
                format('北京', '深圳'))
        if Config().EMAIL_ENABLED:  # 邮件通知
            CommonLog.add_quick_log(CommonLog.MESSAGE_TEST_SEND_EMAIL).flush()
            Notification.send_email(Config().EMAIL_RECEIVER, '测试发送邮件',
                                    'By py12306')

        if Config().DINGTALK_ENABLED:  # 钉钉通知
            CommonLog.add_quick_log(
                CommonLog.MESSAGE_TEST_SEND_DINGTALK).flush()
            Notification.dingtalk_webhook('测试发送信息')

        if Config().TELEGRAM_ENABLED:  # Telegram通知
            CommonLog.add_quick_log(
                CommonLog.MESSAGE_TEST_SEND_TELEGRAM).flush()
            Notification.send_to_telegram('测试发送信息')

        if Config().SERVERCHAN_ENABLED:  # ServerChan通知
            CommonLog.add_quick_log(
                CommonLog.MESSAGE_TEST_SEND_SERVER_CHAN).flush()
            Notification.server_chan(Config().SERVERCHAN_KEY, '测试发送消息',
                                     'By py12306')

        if Config().PUSHBEAR_ENABLED:  # PushBear通知
            CommonLog.add_quick_log(
                CommonLog.MESSAGE_TEST_SEND_PUSH_BEAR).flush()
            Notification.push_bear(Config().PUSHBEAR_KEY, '测试发送消息',
                                   'By py12306')
Exemplo n.º 4
0
 def request_device_id(self):
     """
     获取加密后的浏览器特征 ID
     :return:
     """
     response = self.session.get(API_GET_BROWSER_DEVICE_ID)
     if response.status_code == 200:
         try:
             result = json.loads(response.text)
             response = self.session.get(b64decode(result['id']).decode())
             if response.text.find('callbackFunction') >= 0:
                 result = response.text[18:-2]
             result = json.loads(result)
             if not Config().is_cache_rail_id_enabled():
                 self.session.cookies.update({
                     'RAIL_EXPIRATION':
                     result.get('exp'),
                     'RAIL_DEVICEID':
                     result.get('dfp'),
                 })
             else:
                 self.session.cookies.update({
                     'RAIL_EXPIRATION':
                     Config().RAIL_EXPIRATION,
                     'RAIL_DEVICEID':
                     Config().RAIL_DEVICEID,
                 })
         except:
             return False
Exemplo n.º 5
0
    def join_cluster(self):
        """
        加入到集群
        :return:
        """
        self.node_name = node_name = Config().NODE_NAME

        if Config().NODE_IS_MASTER:
            if self.node_name in self.nodes:  # 重复运行主节点
                ClusterLog.add_quick_log(ClusterLog.MESSAGE_MASTER_NODE_ALREADY_RUN.format(node_name)).flush(
                    publish=False)
                os._exit(1)
            if self.have_master():  # 子节点提升为主节点情况,交回控制
                message = ClusterLog.MESSAGE_NODE_BECOME_MASTER_AGAIN.format(node_name)
                self.publish_log_message(message)
                self.make_nodes_as_slave()
        elif not self.have_master():  # 只能通过主节点启动
            ClusterLog.add_quick_log(ClusterLog.MESSAGE_MASTER_NODE_NOT_FOUND).flush(publish=False)
            os._exit(1)

        if node_name in self.nodes:
            self.node_name = node_name = node_name + '_' + str(dict_count_key_num(self.nodes, node_name))
            ClusterLog.add_quick_log(ClusterLog.MESSAGE_NODE_ALREADY_IN_CLUSTER.format(node_name)).flush()

        self.session.hset(self.KEY_NODES, node_name, Config().NODE_IS_MASTER)
        message = ClusterLog.MESSAGE_JOIN_CLUSTER_SUCCESS.format(self.node_name, ClusterLog.get_print_nodes(
            self.get_nodes()))  # 手动 get nodes
        self.publish_log_message(message)
Exemplo n.º 6
0
    def restore_items(self):
        """
        恢复已有数据
        :return: bool
        """
        result = False
        if path.exists(Config().CDN_ENABLED_AVAILABLE_ITEM_FILE):
            with open(Config().CDN_ENABLED_AVAILABLE_ITEM_FILE,
                      encoding='utf-8') as f:
                result = f.read()
                try:
                    result = json.loads(result)
                except json.JSONDecodeError as e:
                    result = {}

        # if Config.is_cluster_enabled(): # 集群不用同步 cdn
        #     result = self.get_data_from_cluster()

        if result:
            self.last_check_at = result.get('last_check_at', '')
            if self.last_check_at:
                self.last_check_at = str_to_time(self.last_check_at)
            self.available_items = result.get('items', [])
            self.unavailable_items = result.get('fail_items', [])
            CommonLog.add_quick_log(
                CommonLog.MESSAGE_CDN_RESTORE_SUCCESS.format(
                    self.last_check_at)).flush()
            return True
        return False
Exemplo n.º 7
0
    def send_notification(self):
        num = 0  # 通知次数
        sustain_time = self.notification_sustain_time
        if Config().EMAIL_ENABLED:  # 邮件通知
            Notification.send_email(Config().EMAIL_RECEIVER, OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_TITLE,
                                    OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_EMAIL_CONTENT.format(self.order_id))
        if Config().DINGTALK_ENABLED:  # 钉钉通知
            Notification.dingtalk_webhook(
                OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_EMAIL_CONTENT.format(self.order_id))
        if Config().TELEGRAM_ENABLED:  # Telegram推送
            Notification.send_to_telegram(
                OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_EMAIL_CONTENT.format(self.order_id))
        if Config().SERVERCHAN_ENABLED:  # ServerChan通知
            Notification.server_chan(Config().SERVERCHAN_KEY, OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_TITLE,
                                     OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_EMAIL_CONTENT.format(self.order_id))
        if Config().PUSHBEAR_ENABLED:  # PushBear通知
            Notification.push_bear(Config().PUSHBEAR_KEY, OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_TITLE,
                                   OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_EMAIL_CONTENT.format(self.order_id))
        while sustain_time:  # TODO 后面直接查询有没有待支付的订单就可以
            num += 1
            if Config().NOTIFICATION_BY_VOICE_CODE:  # 语音通知
                OrderLog.add_quick_log(OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_VOICE_CODE_START_SEND.format(num))
                Notification.voice_code(Config().NOTIFICATION_VOICE_CODE_PHONE, self.user_ins.get_name(),
                                        OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_VOICE_CODE_CONTENT.format(
                                            self.query_ins.left_station, self.query_ins.arrive_station))
            else:
                break
            sustain_time -= self.notification_interval
            sleep(self.notification_interval)

        OrderLog.add_quick_log(OrderLog.MESSAGE_JOB_CLOSED).flush()
Exemplo n.º 8
0
 def update_query_jobs(self, auto=False):
     self.query_jobs = Config().QUERY_JOBS
     if auto:
         QueryLog.add_quick_log(QueryLog.MESSAGE_JOBS_DID_CHANGED).flush()
         self.refresh_jobs()
         if not Config().is_slave():
             jobs_do(self.jobs, 'check_passengers')
Exemplo n.º 9
0
 def check_auto_code(cls):
     if Config().AUTO_CODE_PLATFORM == 'free' or Config(
     ).AUTO_CODE_PLATFORM == 'user':
         return True
     if not Config().AUTO_CODE_ACCOUNT.get(
             'user') or not Config().AUTO_CODE_ACCOUNT.get('pwd'):
         return False
     return True
Exemplo n.º 10
0
 def test_send_notifications(cls):
     if Config().NOTIFICATION_BY_VOICE_CODE:  # 语音通知
         CommonLog.add_quick_log(
             CommonLog.MESSAGE_TEST_SEND_VOICE_CODE).flush()
         Notification.voice_code(
             Config().NOTIFICATION_VOICE_CODE_PHONE, '张三',
             OrderLog.
             MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_VOICE_CODE_CONTENT.
             format('北京', '深圳'))
Exemplo n.º 11
0
 def get_img_position(cls, img):
     """
     获取图像坐标
     :param img_path:
     :return:
     """
     self = cls()
     if Config().AUTO_CODE_PLATFORM == 'free' or Config().AUTO_CODE_PLATFORM == 'user':
         return self.get_image_by_free_site(img)
     return self.get_img_position_by_ruokuai(img)
Exemplo n.º 12
0
    def user_loaded(self, data={}, callback=False):  # 用户初始化完成
        if Config().is_cluster_enabled() and not callback:
            return self.cluster.publish_event(self.KEY_USER_LOADED,
                                              data)  # 通知其它节点退出
        from py12306.query.query import Query

        if not Config().is_cluster_enabled() or Config().is_master():
            query = Query.wait_for_ready()
            for job in query.jobs:
                if job.account_key == data.get('key'):
                    create_thread_and_run(job, 'check_passengers',
                                          Const.IS_TEST)  # 检查乘客信息 防止提交订单时才检查
Exemplo n.º 13
0
 def get_img_position(cls, img):
     """
     获取图像坐标
     :param img_path:
     :return:
     """
     self = cls()
     if Config().AUTO_CODE_PLATFORM == 'free_1':
         return self.get_image_by_free_site(img)
     elif Config().AUTO_CODE_PLATFORM == 'free_2':
         return self.get_image_by_local_verify(img)
     return self.get_img_position_by_ruokuai(img)
Exemplo n.º 14
0
 def __init__(self):
     if path.exists(Config().STATION_FILE):
         result = open(Config().STATION_FILE, encoding='utf-8').read()
         result = result.lstrip('@').split('@')
         for i in result:
             tmp_info = i.split('|')
             self.stations.append({
                 'key': tmp_info[2],
                 'name': tmp_info[1],
                 'pinyin': tmp_info[3],
                 'id': tmp_info[5]
             })
             self.station_kvs[tmp_info[1]] = tmp_info[2]
Exemplo n.º 15
0
 def test_send_notifications(cls):
     if Config().NOTIFICATION_BY_VOICE_CODE:  # 语音通知
         CommonLog.add_quick_log(
             CommonLog.MESSAGE_TEST_SEND_VOICE_CODE).flush()
         Notification.voice_code(
             Config().NOTIFICATION_VOICE_CODE_PHONE, '张三',
             OrderLog.
             MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_VOICE_CODE_CONTENT.
             format('北京', '深圳'))
     if Config().EMAIL_ENABLED:  # 语音通知
         CommonLog.add_quick_log(CommonLog.MESSAGE_TEST_SEND_EMAIL).flush()
         Notification.send_email(Config().EMAIL_RECEIVER, '测试发送邮件',
                                 'By py12306')
Exemplo n.º 16
0
 def __init__(self, *args):
     if Config.is_cluster_enabled():
         args = {
             'host': Config().REDIS_HOST,
             'port': Config().REDIS_PORT,
             'db': 0,
             'password': Config().REDIS_PASSWORD,
             'decode_responses': True
         }
         super().__init__(**args)
         RedisLog.add_quick_log(RedisLog.MESSAGE_REDIS_INIT_SUCCESS)
     else:
         super().__init__(**args)
     return self
Exemplo n.º 17
0
    def send_notification(self):
        num = 0  # 通知次数
        sustain_time = self.notification_sustain_time
        while sustain_time:  # TODO 后面直接查询有没有待支付的订单就可以
            num += 1
            if Config().NOTIFICATION_BY_VOICE_CODE:  # 语音通知
                OrderLog.add_quick_log(OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_VOICE_CODE_START_SEND.format(num))
                Notification.voice_code(Config().NOTIFICATION_VOICE_CODE_PHONE, self.user_ins.get_name(),
                                        OrderLog.MESSAGE_ORDER_SUCCESS_NOTIFICATION_OF_VOICE_CODE_CONTENT.format(
                                            self.query_ins.left_station, self.query_ins.arrive_station))
            sustain_time -= self.notification_interval
            sleep(self.notification_interval)

        OrderLog.add_quick_log(OrderLog.MESSAGE_JOB_CLOSED)
Exemplo n.º 18
0
    def get_image_by_free_site(self, img):
        data = {
            'img': img
        }
        if Config().AUTO_CODE_PLATFORM == 'free':
           response = self.session.post(API_FREE_CODE_QCR_API, data=data, timeout=30)
        else:
           response = self.session.post(Config().API_USER_CODE_QCR_API, data=data, timeout=30)
        result = response.json()
        if result.get('msg') == 'success':
            pos = result.get('result')
            return self.get_image_position_by_offset(pos)

        CommonLog.print_auto_code_fail(CommonLog.MESSAGE_GET_RESPONSE_FROM_FREE_AUTO_CODE)
        return None
Exemplo n.º 19
0
    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()
Exemplo n.º 20
0
 def start(self):
     """
     检测心跳
     :return:
     """
     while True and self.is_alive:
         app_available_check()
         if Config().is_slave():
             self.load_user_from_remote()
         else:
             if Config().is_master() and not self.cookie:
                 self.load_user_from_remote()  # 主节点加载一次 Cookie
             self.check_heartbeat()
         if Const.IS_TEST:
             return
         stay_second(self.check_interval)
Exemplo n.º 21
0
 def update_cdn_status(self, auto=False):
     if auto:
         self.init_config()
         if Config().is_cdn_enabled():
             self.run()
         else:
             self.destroy()
Exemplo n.º 22
0
 def send_voice_code_of_yiyuan(self, phone, name='', content=''):
     """
     发送语音验证码
     购买地址 https://market.aliyun.com/products/57126001/cmapi019902.html?spm=5176.2020520132.101.5.37857218O6iJ3n
     :return:
     """
     appcode = Config().NOTIFICATION_API_APP_CODE
     if not appcode:
         CommonLog.add_quick_log(CommonLog.MESSAGE_EMPTY_APP_CODE).flush()
         return False
     body = {
         'userName': name,
         'mailNo': content
     }
     params = {
         'content': body,
         'mobile': phone,
         'sex': 2,
         'tNum': 'T170701001056'
     }
     response = self.session.request(url=API_NOTIFICATION_BY_VOICE_CODE + urllib.parse.urlencode(params),
                                     method='GET', headers={
             'Authorization': 'APPCODE {}'.format(appcode)
         })
     result = response.json()
     response_message = result.get('showapi_res_body.remark')
     if response.status_code in [400, 401, 403]:
         return CommonLog.add_quick_log(CommonLog.MESSAGE_VOICE_API_FORBID).flush()
     if response.status_code == 200 and result.get('showapi_res_body.flag'):
         CommonLog.add_quick_log(CommonLog.MESSAGE_VOICE_API_SEND_SUCCESS.format(response_message)).flush()
         return True
     else:
         return CommonLog.add_quick_log(CommonLog.MESSAGE_VOICE_API_SEND_FAIL.format(response_message)).flush()
Exemplo n.º 23
0
    def check_master(self):
        """
        检测主节点是否可用
        :return:
        """
        master = self.have_master()
        if master == self.node_name:  # 动态提升
            self.is_master = True
        else:
            self.is_master = False

        if not master:
            if Config().NODE_SLAVE_CAN_BE_MASTER:
                # 提升子节点为主节点
                slave = list(self.nodes)[0]
                self.session.hset(self.KEY_NODES, slave, self.KEY_MASTER)
                self.publish_log_message(
                    ClusterLog.MESSAGE_ASCENDING_MASTER_NODE.format(
                        slave, ClusterLog.get_print_nodes(self.get_nodes())))
                return True
            else:
                self.publish_log_message(
                    ClusterLog.MESSAGE_MASTER_DID_LOST.format(self.retry_time))
                stay_second(self.retry_time)
                os._exit(1)  # 退出整个程序
Exemplo n.º 24
0
 def send_voice_code_of_dingxin(self, phone, name='', info={}):
     """
     发送语音验证码 ( 鼎信 )
     购买地址 https://market.aliyun.com/products/56928004/cmapi026600.html?spm=5176.2020520132.101.2.51547218rkAXxy
     :return:
     """
     appcode = Config().NOTIFICATION_API_APP_CODE
     if not appcode:
         CommonLog.add_quick_log(CommonLog.MESSAGE_EMPTY_APP_CODE).flush()
         return False
     data = {
         'tpl_id': 'TP1901174',
         'phone': phone,
         'param': 'name:{name},job_name:{left_station}到{arrive_station}{set_type},orderno:{orderno}'.format(
             name=name, left_station=info.get('left_station'), arrive_station=info.get('arrive_station'),
             set_type=info.get('set_type'), orderno=info.get('orderno'))
     }
     response = self.session.request(url=API_NOTIFICATION_BY_VOICE_CODE_DINGXIN, method='POST', data=data,
                                     headers={'Authorization': 'APPCODE {}'.format(appcode)})
     result = response.json()
     response_message = result.get('return_code')
     if response.status_code in [400, 401, 403]:
         return CommonLog.add_quick_log(CommonLog.MESSAGE_VOICE_API_FORBID).flush()
     if response.status_code == 200 and result.get('return_code') == '00000':
         CommonLog.add_quick_log(CommonLog.MESSAGE_VOICE_API_SEND_SUCCESS.format(response_message)).flush()
         return True
     else:
         return CommonLog.add_quick_log(CommonLog.MESSAGE_VOICE_API_SEND_FAIL.format(response_message)).flush()
Exemplo n.º 25
0
 def start(self):
     """
     处理单个任务
     根据日期循环查询, 展示处理时间
     :param job:
     :return:
     """
     while True and self.is_alive:
         app_available_check()
         QueryLog.print_job_start(self.job_name)
         for station in self.stations:
             self.refresh_station(station)
             for date in self.left_dates:
                 self.left_date = date
                 response = self.query_by_date(date)
                 self.handle_response(response)
                 QueryLog.add_query_time_log(
                     time=response.elapsed.total_seconds(),
                     is_cdn=self.is_cdn)
                 if not self.is_alive: return
                 self.safe_stay()
                 if is_main_thread():
                     QueryLog.flush(sep='\t\t', publish=False)
         if not Config().QUERY_JOB_THREAD_ENABLED:
             QueryLog.add_quick_log('').flush(publish=False)
             break
         else:
             QueryLog.add_log('\n').flush(sep='\t\t', publish=False)
         if Const.IS_TEST: return
Exemplo n.º 26
0
 def keep_alive(self):
     while True:
         if self.node_name not in self.get_nodes():  # 已经被 kict out  重新加下
             self.join_cluster()
         self.session.set(self.KEY_NODES_ALIVE_PREFIX + self.node_name,
                          Config().NODE_IS_MASTER,
                          ex=self.lost_alive_time)
         stay_second(self.keep_alive_time)
Exemplo n.º 27
0
 def send_email_by_smtp(self, to, title, content):
     import smtplib
     from email.message import EmailMessage
     to = to if isinstance(to, list) else [to]
     message = EmailMessage()
     message['Subject'] = title
     message['From'] = Config().EMAIL_SENDER
     message['To'] = to
     message.set_content(content)
     try:
         server = smtplib.SMTP(Config().EMAIL_SERVER_HOST)
         server.login(Config().EMAIL_SERVER_USER, Config().EMAIL_SERVER_PASSWORD)
         server.send_message(message)
         server.quit()
         CommonLog.add_quick_log(CommonLog.MESSAGE_SEND_EMAIL_SUCCESS).flush()
     except Exception as e:
         CommonLog.add_quick_log(CommonLog.MESSAGE_SEND_EMAIL_FAIL.format(e)).flush()
Exemplo n.º 28
0
    def job_destroy(self, data={}, callback=False):  # 停止查询任务
        from py12306.query.query import Query
        if Config().is_cluster_enabled() and not callback:
            return self.cluster.publish_event(self.KEY_JOB_DESTROY,
                                              data)  # 通知其它节点退出

        job = Query.job_by_name(data.get('name'))
        if job:
            job.destroy()
Exemplo n.º 29
0
 def save_available_items(self):
     self.last_check_at = time_now()
     data = {
         'items': self.available_items,
         'fail_items': self.unavailable_items,
         'last_check_at': str(self.last_check_at)
     }
     with open(Config().CDN_ENABLED_AVAILABLE_ITEM_FILE, 'w') as f:
         f.write(json.dumps(data))
Exemplo n.º 30
0
    def user_job_destroy(self, data={}, callback=False):
        from py12306.user.user import User
        if Config().is_cluster_enabled() and not callback:
            return self.cluster.publish_event(self.KEY_JOB_DESTROY,
                                              data)  # 通知其它节点退出

        user = User.get_user(data.get('key'))
        if user:
            user.destroy()