mirror of
https://github.com/0-8-4/miui-auto-tasks.git
synced 2024-12-04 12:20:06 +00:00
202 lines
7.1 KiB
Python
202 lines
7.1 KiB
Python
""""配置文件"""
|
||
import os
|
||
import platform
|
||
from hashlib import md5
|
||
from json import JSONDecodeError
|
||
from pathlib import Path
|
||
from typing import Dict, List, Optional, Union
|
||
|
||
import orjson
|
||
import yaml # pylint: disable=wrong-import-order
|
||
from pydantic import BaseModel, ValidationError, field_validator # pylint: disable=no-name-in-module
|
||
|
||
from .logger import log
|
||
|
||
ROOT_PATH = Path(__file__).parent.parent.absolute()
|
||
|
||
DATA_PATH = ROOT_PATH / "data"
|
||
"""数据保存目录"""
|
||
|
||
CONFIG_TYPE = "json" if os.path.isfile(DATA_PATH / "config.json") else "yaml"
|
||
"""数据文件类型"""
|
||
|
||
CONFIG_PATH = DATA_PATH / f"config.{CONFIG_TYPE}" if os.getenv("MIUITASK_CONFIG_PATH") is None else Path(os.getenv("MIUITASK_CONFIG_PATH"))
|
||
"""数据文件默认路径"""
|
||
|
||
os.makedirs(DATA_PATH, exist_ok=True)
|
||
|
||
|
||
def md5_crypto(passwd: str) -> str:
|
||
"""MD5加密"""
|
||
return md5(passwd.encode('utf8')).hexdigest().upper()
|
||
|
||
|
||
def cookies_to_dict(cookies: str):
|
||
"""将cookies字符串转换为字典"""
|
||
cookies_dict = {}
|
||
if not cookies or "=" not in cookies:
|
||
return cookies_dict
|
||
for cookie in cookies.split(';'):
|
||
key, value = cookie.strip().split('=', 1) # 分割键和值
|
||
cookies_dict[key] = value
|
||
return cookies_dict
|
||
|
||
def get_platform() -> str:
|
||
"""获取当前运行平台"""
|
||
if os.path.exists('/.dockerenv'):
|
||
if os.environ.get('QL_DIR') and os.environ.get('QL_BRANCH'):
|
||
return "qinglong"
|
||
else:
|
||
return "docker"
|
||
return platform.system().lower()
|
||
|
||
|
||
class Account(BaseModel):
|
||
"""账号处理器"""
|
||
uid: str = "100000"
|
||
"""账户ID 非账户用户名或手机号"""
|
||
password: str = ""
|
||
"""账户密码或其MD5哈希"""
|
||
cookies: Union[dict, str] = {}
|
||
"""账户登录后的cookies"""
|
||
login_user_agent: str = ""
|
||
"""登录账户时所用浏览器的 User-Agent"""
|
||
user_agent: str = 'Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Safari/537.36'
|
||
"""登录社区时所用浏览器的 User-Agent"""
|
||
device: str = ""
|
||
"""设备代号"""
|
||
device_model: str = ""
|
||
"""设备名称"""
|
||
CheckIn: bool = False
|
||
"""社区成长值签到,启用功能意味着你愿意自行承担相关风险"""
|
||
BrowseUserPage: bool = False
|
||
"""社区浏览个人主页10秒,启用功能意味着你愿意自行承担相关风险"""
|
||
BrowsePost: bool = False
|
||
"""社区浏览帖子10秒,启用功能意味着你愿意自行承担相关风险"""
|
||
BrowseVideoPost: bool = False
|
||
"""社区浏览视频帖子5分钟,启用功能意味着你愿意自行承担相关风险"""
|
||
ThumbUp: bool = False
|
||
"""点赞帖子,启用功能意味着你愿意自行承担相关风险"""
|
||
BrowseSpecialPage: bool = False
|
||
"""社区在活动期间可能会出现限时的“浏览指定专题页”任务,启用功能意味着你愿意自行承担相关风险"""
|
||
BoardFollow: bool = False
|
||
"""社区可能会出现限时的“加入圈子”任务,启用功能意味着你愿意自行承担相关风险"""
|
||
CarrotPull: bool = False
|
||
"""社区拔萝卜,启用功能意味着你愿意自行承担相关风险"""
|
||
|
||
@field_validator("password")
|
||
@classmethod
|
||
def _password(cls, value: Optional[str]): # pylint: disable=no-self-argument
|
||
if len(value) == 32:
|
||
return value
|
||
return md5_crypto(value)
|
||
|
||
@field_validator("cookies")
|
||
@classmethod
|
||
def _cookies(cls, value: Union[dict, str]): # pylint: disable=no-self-argument
|
||
if isinstance(value, str):
|
||
return cookies_to_dict(value)
|
||
return value
|
||
|
||
|
||
class OnePush(BaseModel):
|
||
"""推送配置"""
|
||
notifier: Union[str, bool] = ""
|
||
"""是否开启消息推送"""
|
||
params: Dict = {
|
||
"title": "",
|
||
"markdown": False,
|
||
"token": "",
|
||
"userid": ""
|
||
}
|
||
"""推送参数"""
|
||
|
||
|
||
class Preference(BaseModel):
|
||
"""偏好设置"""
|
||
geetest_url: str = ""
|
||
"""极验验证URL"""
|
||
geetest_params: Dict = {}
|
||
"""极验自定义params参数"""
|
||
geetest_data: Dict = {}
|
||
"""极验自定义data参数"""
|
||
|
||
class Config(BaseModel):
|
||
"""插件数据"""
|
||
preference: Preference = Preference()
|
||
"""偏好设置"""
|
||
accounts: List[Account] = [Account()]
|
||
"""账号设置"""
|
||
ONEPUSH: OnePush = OnePush()
|
||
"""消息推送"""
|
||
|
||
def write_plugin_data(data: Config = None):
|
||
"""
|
||
写入插件数据文件
|
||
|
||
:param data: 配置对象
|
||
"""
|
||
try:
|
||
if data is None:
|
||
data = ConfigManager.data_obj
|
||
try:
|
||
if CONFIG_TYPE == "json":
|
||
str_data = orjson.dumps(data.model_dump(), option=orjson.OPT_PASSTHROUGH_DATETIME | orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_INDENT_2)
|
||
with open(CONFIG_PATH, "wb") as file:
|
||
file.write(str_data)
|
||
else:
|
||
str_data = yaml.dump(data.model_dump(), indent=4, allow_unicode=True, sort_keys=False)
|
||
with open(CONFIG_PATH, "w", encoding="utf-8") as file:
|
||
file.write(str_data)
|
||
return True
|
||
except (AttributeError, TypeError, ValueError):
|
||
log.exception("数据对象序列化失败,可能是数据类型错误")
|
||
return False
|
||
except OSError:
|
||
return False
|
||
|
||
|
||
class ConfigManager:
|
||
"""配置管理器"""
|
||
data_obj = Config()
|
||
"""加载出的插件数据对象"""
|
||
platform = get_platform()
|
||
"""运行平台"""
|
||
|
||
@classmethod
|
||
def load_config(cls):
|
||
"""
|
||
加载插件数据文件
|
||
"""
|
||
if os.path.exists(DATA_PATH) and os.path.isfile(CONFIG_PATH):
|
||
try:
|
||
with open(CONFIG_PATH, 'r', encoding="utf-8") as file:
|
||
if CONFIG_TYPE == "json":
|
||
data = orjson.loads(file.read())
|
||
else:
|
||
data = yaml.safe_load(file)
|
||
new_model = Config.model_validate(data)
|
||
for attr in new_model.model_fields:
|
||
# ConfigManager.data_obj.__setattr__(attr, new_model.__getattribute__(attr))
|
||
setattr(ConfigManager.data_obj, attr, getattr(new_model, attr))
|
||
write_plugin_data(ConfigManager.data_obj) # 同步配置
|
||
except (ValidationError, JSONDecodeError):
|
||
log.exception(f"读取数据文件失败,请检查数据文件 {CONFIG_PATH} 格式是否正确")
|
||
raise
|
||
except Exception:
|
||
log.exception(
|
||
f"读取数据文件失败,请检查数据文件 {CONFIG_PATH} 是否存在且有权限读取和写入")
|
||
raise
|
||
else:
|
||
try:
|
||
if not os.path.exists(DATA_PATH):
|
||
os.mkdir(DATA_PATH)
|
||
write_plugin_data()
|
||
except (AttributeError, TypeError, ValueError, PermissionError):
|
||
log.exception(f"创建数据文件失败,请检查是否有权限读取和写入 {CONFIG_PATH}")
|
||
raise
|
||
log.info(f"数据文件 {CONFIG_PATH} 不存在,已创建默认数据文件。")
|
||
|
||
|
||
ConfigManager.load_config()
|