236 lines
6.9 KiB
Python
236 lines
6.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
import json
|
|
import re
|
|
from os import path
|
|
|
|
# 12306 账号
|
|
from py12306.helpers.func import *
|
|
|
|
|
|
@singleton
|
|
class Config:
|
|
IS_DEBUG = False
|
|
|
|
USER_ACCOUNTS = []
|
|
# 查询任务
|
|
QUERY_JOBS = []
|
|
# 查询间隔
|
|
QUERY_INTERVAL = 1
|
|
# 用户心跳检测间隔
|
|
USER_HEARTBEAT_INTERVAL = 120
|
|
# 多线程查询
|
|
QUERY_JOB_THREAD_ENABLED = 0
|
|
# 打码平台账号
|
|
AUTO_CODE_PLATFORM = ''
|
|
AUTO_CODE_ACCOUNT = {'user': '', 'pwd': ''}
|
|
# 输出日志到文件
|
|
OUT_PUT_LOG_TO_FILE_ENABLED = 0
|
|
OUT_PUT_LOG_TO_FILE_PATH = 'runtime/12306.log'
|
|
|
|
SEAT_TYPES = {'特等座': 25, '商务座': 32, '一等座': 31, '二等座': 30, '软卧': 23, '硬卧': 28, '硬座': 29, '无座': 26, }
|
|
|
|
ORDER_SEAT_TYPES = {'特等座': 'P', '商务座': 9, '一等座': 'M', '二等座': 'O', '软卧': 4, '硬卧': 3, '硬座': 1, '无座': 1}
|
|
|
|
PROJECT_DIR = path.dirname(path.dirname(path.abspath(__file__))) + '/'
|
|
|
|
# Query
|
|
RUNTIME_DIR = PROJECT_DIR + 'runtime/'
|
|
QUERY_DATA_DIR = RUNTIME_DIR + 'query/'
|
|
USER_DATA_DIR = RUNTIME_DIR + 'user/'
|
|
USER_PASSENGERS_FILE = RUNTIME_DIR + 'user/%s_passengers.json'
|
|
|
|
STATION_FILE = PROJECT_DIR + 'data/stations.txt'
|
|
CONFIG_FILE = PROJECT_DIR + 'env.py'
|
|
|
|
# 语音验证码
|
|
NOTIFICATION_BY_VOICE_CODE = 0
|
|
NOTIFICATION_VOICE_CODE_TYPE = ''
|
|
NOTIFICATION_VOICE_CODE_PHONE = ''
|
|
NOTIFICATION_API_APP_CODE = ''
|
|
|
|
# 集群配置
|
|
CLUSTER_ENABLED = 0
|
|
NODE_SLAVE_CAN_BE_MASTER = 1
|
|
NODE_IS_MASTER = 1
|
|
NODE_NAME = ''
|
|
REDIS_HOST = ''
|
|
REDIS_PORT = '6379'
|
|
REDIS_PASSWORD = ''
|
|
|
|
# 钉钉配置
|
|
DINGTALK_ENABLED = 0
|
|
DINGTALK_WEBHOOK = ''
|
|
|
|
# Telegram推送配置
|
|
TELEGRAM_ENABLED = 0
|
|
TELEGRAM_BOT_API_URL = ''
|
|
|
|
# Bark 推送配置
|
|
BARK_ENABLED = 0
|
|
BARK_PUSH_URL = ''
|
|
|
|
# ServerChan和PushBear配置
|
|
SERVERCHAN_ENABLED = 0
|
|
SERVERCHAN_KEY = '8474-ca071ADSFADSF'
|
|
PUSHBEAR_ENABLED = 0
|
|
PUSHBEAR_KEY = 'SCUdafadsfasfdafdf45234234234'
|
|
|
|
# 邮箱配置
|
|
EMAIL_ENABLED = 0
|
|
EMAIL_SENDER = ''
|
|
EMAIL_RECEIVER = ''
|
|
EMAIL_SERVER_HOST = ''
|
|
EMAIL_SERVER_USER = ''
|
|
EMAIL_SERVER_PASSWORD = ''
|
|
|
|
WEB_ENABLE = 0
|
|
WEB_USER = {}
|
|
WEB_PORT = 8080
|
|
WEB_ENTER_HTML_PATH = PROJECT_DIR + 'py12306/web/static/index.html'
|
|
|
|
# CDN
|
|
CDN_ENABLED = 0
|
|
CDN_CHECK_TIME_OUT = 2
|
|
CDN_ITEM_FILE = PROJECT_DIR + 'data/cdn.txt'
|
|
CDN_ENABLED_AVAILABLE_ITEM_FILE = QUERY_DATA_DIR + 'available.json'
|
|
|
|
# Default time out
|
|
TIME_OUT_OF_REQUEST = 5
|
|
|
|
envs = []
|
|
retry_time = 5
|
|
last_modify_time = 0
|
|
|
|
disallow_update_configs = [
|
|
'CLUSTER_ENABLED',
|
|
'NODE_IS_MASTER',
|
|
'NODE_NAME',
|
|
'REDIS_HOST',
|
|
'REDIS_PORT',
|
|
'REDIS_PASSWORD',
|
|
]
|
|
|
|
def __init__(self):
|
|
self.init_envs()
|
|
self.last_modify_time = get_file_modify_time(self.CONFIG_FILE)
|
|
if Config().is_slave():
|
|
self.refresh_configs(True)
|
|
else:
|
|
create_thread_and_run(self, 'watch_file_change', False)
|
|
|
|
@classmethod
|
|
def run(cls):
|
|
self = cls()
|
|
self.start()
|
|
|
|
# @classmethod
|
|
# def keep_work(cls):
|
|
# self = cls()
|
|
|
|
def start(self):
|
|
self.save_to_remote()
|
|
create_thread_and_run(self, 'refresh_configs', wait=Const.IS_TEST)
|
|
|
|
def refresh_configs(self, once=False):
|
|
if not self.is_cluster_enabled(): return
|
|
while True:
|
|
remote_configs = self.get_remote_config()
|
|
self.update_configs_from_remote(remote_configs, once)
|
|
if once or Const.IS_TEST: return
|
|
stay_second(self.retry_time)
|
|
|
|
def get_remote_config(self):
|
|
if not self.is_cluster_enabled(): return
|
|
from py12306.cluster.cluster import Cluster
|
|
return Cluster().session.get_pickle(Cluster().KEY_CONFIGS, {})
|
|
|
|
def save_to_remote(self):
|
|
if not self.is_master(): return
|
|
from py12306.cluster.cluster import Cluster
|
|
Cluster().session.set_pickle(Cluster().KEY_CONFIGS, self.envs)
|
|
|
|
def init_envs(self):
|
|
self.envs = EnvLoader.load_with_file(self.CONFIG_FILE)
|
|
self.update_configs(self.envs)
|
|
|
|
def update_configs(self, envs):
|
|
for key, value in envs:
|
|
setattr(self, key, value)
|
|
|
|
def watch_file_change(self):
|
|
"""
|
|
监听配置文件修改
|
|
:return:
|
|
"""
|
|
if Config().is_slave(): return
|
|
from py12306.log.common_log import CommonLog
|
|
while True:
|
|
value = get_file_modify_time(self.CONFIG_FILE)
|
|
if value > self.last_modify_time:
|
|
self.last_modify_time = value
|
|
CommonLog.add_quick_log(CommonLog.MESSAGE_CONFIG_FILE_DID_CHANGED).flush()
|
|
envs = EnvLoader.load_with_file(self.CONFIG_FILE)
|
|
self.update_configs_from_remote(envs)
|
|
if Config().is_master(): # 保存配置
|
|
self.save_to_remote()
|
|
stay_second(self.retry_time)
|
|
|
|
def update_configs_from_remote(self, envs, first=False):
|
|
if envs == self.envs: return
|
|
from py12306.query.query import Query
|
|
from py12306.user.user import User
|
|
from py12306.helpers.cdn import Cdn
|
|
self.envs = envs
|
|
for key, value in envs:
|
|
if key in self.disallow_update_configs: continue
|
|
if value != -1:
|
|
old = getattr(self, key)
|
|
setattr(self, key, value)
|
|
if not first and old != value:
|
|
if key == 'USER_ACCOUNTS':
|
|
User().update_user_accounts(auto=True, old=old)
|
|
elif key == 'QUERY_JOBS':
|
|
Query().update_query_jobs(auto=True) # 任务修改
|
|
elif key == 'QUERY_INTERVAL':
|
|
Query().update_query_interval(auto=True)
|
|
elif key == 'CDN_ENABLED':
|
|
Cdn().update_cdn_status(auto=True)
|
|
|
|
@staticmethod
|
|
def is_master(): # 是不是 主
|
|
from py12306.cluster.cluster import Cluster
|
|
return Config().CLUSTER_ENABLED and (Config().NODE_IS_MASTER or Cluster().is_master)
|
|
|
|
@staticmethod
|
|
def is_slave(): # 是不是 从
|
|
return Config().CLUSTER_ENABLED and not Config.is_master()
|
|
|
|
@staticmethod
|
|
def is_cluster_enabled():
|
|
return Config().CLUSTER_ENABLED
|
|
|
|
@staticmethod
|
|
def is_cdn_enabled():
|
|
return Config().CDN_ENABLED
|
|
|
|
|
|
class EnvLoader:
|
|
envs = []
|
|
|
|
def __init__(self):
|
|
self.envs = []
|
|
|
|
@classmethod
|
|
def load_with_file(cls, file):
|
|
self = cls()
|
|
if path.exists(file):
|
|
env_content = open(file, encoding='utf8').read()
|
|
content = re.sub(r'^([A-Z]+)_', r'self.\1_', env_content, flags=re.M)
|
|
exec(content)
|
|
return self.envs
|
|
|
|
def __setattr__(self, key, value):
|
|
super().__setattr__(key, value)
|
|
if re.search(r'^[A-Z]+_', key):
|
|
self.envs.append(([key, value]))
|