You've already forked pruchase_jhw
110 lines
4.6 KiB
Python
110 lines
4.6 KiB
Python
import os
|
|
from functools import lru_cache
|
|
from typing import Annotated, Any
|
|
|
|
from pydantic import Field, field_validator
|
|
from pydantic_settings import BaseSettings, NoDecode, SettingsConfigDict
|
|
|
|
# 根据 APP_ENV 确定环境配置文件(默认为 dev)
|
|
APP_ENV = os.getenv("APP_ENV", "dev").lower()
|
|
ENV_FILE = f".env.{APP_ENV}"
|
|
|
|
class Settings(BaseSettings):
|
|
"""
|
|
全局应用配置模型。
|
|
使用 pydantic-settings 校验类型并自动解析复杂数据类型。
|
|
"""
|
|
# 运行环境
|
|
app_env: str = Field(default="dev", alias="APP_ENV")
|
|
|
|
# 日志配置
|
|
log_level: str = Field(default="INFO", alias="LOG_LEVEL")
|
|
log_dir: str = Field(default="./logs", alias="LOG_DIR")
|
|
|
|
# 节点配置
|
|
node_id: str = Field(default="node_1", alias="NODE_ID")
|
|
|
|
# Redis 配置
|
|
redis_host: str = Field(default="127.0.0.1", alias="REDIS_HOST")
|
|
redis_port: int = Field(default=6379, alias="REDIS_PORT")
|
|
redis_password: str | None = Field(default=None, alias="REDIS_PASSWORD")
|
|
redis_db: int = Field(default=0, alias="REDIS_DB")
|
|
redis_stream_key: str = Field(default="jp_surugaya_purchase_task", alias="REDIS_STREAM_KEY")
|
|
redis_consumer_group: str = Field(default="surugaya_purchase_task_group", alias="REDIS_CONSUMER_GROUP")
|
|
redis_consumer_name: str = Field(default="surugaya_purchase_task_worker", alias="REDIS_CONSUMER_NAME")
|
|
redis_delay_zset_key: str = Field(default="jp_surugaya_trade_delay", alias="REDIS_DELAY_ZSET_KEY")
|
|
redis_delay_poll_interval: int = Field(default=3600, alias="REDIS_DELAY_POLL_INTERVAL")
|
|
redis_delay_batch_size: int = Field(default=10, alias="REDIS_DELAY_BATCH_SIZE")
|
|
|
|
|
|
# 浏览器控制
|
|
browser_headless: bool = Field(default=True, alias="BROWSER_HEADLESS")
|
|
browser_executable_path: str | None = Field(default=None, alias="BROWSER_EXECUTABLE_PATH")
|
|
browser_keep_open: bool = Field(default=False, alias="BROWSER_KEEP_OPEN")
|
|
|
|
# 配置与资源路径
|
|
accounts_config_path: str = Field(default="./accounts.yaml", alias="ACCOUNTS_CONFIG_PATH")
|
|
screenshot_dir: str = Field(default="./archives", alias="SCREENSHOT_DIR")
|
|
|
|
# 任务上报配置
|
|
callback_url: str | None = Field(default=None, alias="CALLBACK_URL")
|
|
appid: str | None = Field(default=None, alias="APPID")
|
|
app_secret: str | None = Field(default=None, alias="APP_SECRET")
|
|
|
|
# PayPay 配置
|
|
paypay_phone: str | None = Field(default=None, alias="PAYPAY_PHONE")
|
|
paypay_password: str | None = Field(default=None, alias="PAYPAY_PASSWORD")
|
|
|
|
# 通知配置
|
|
notify_enabled: bool = Field(default=False, alias="NOTIFY_ENABLED")
|
|
notify_channels: Annotated[list[str], NoDecode] = Field(
|
|
default_factory=lambda: ["email"],
|
|
alias="NOTIFY_CHANNELS",
|
|
)
|
|
notify_on_task_failed: bool = Field(default=True, alias="NOTIFY_ON_TASK_FAILED")
|
|
|
|
# 邮件通知配置
|
|
mail_enabled: bool = Field(default=True, alias="MAIL_ENABLED")
|
|
mail_smtp_host: str | None = Field(default=None, alias="MAIL_SMTP_HOST")
|
|
mail_smtp_port: int = Field(default=465, alias="MAIL_SMTP_PORT")
|
|
mail_smtp_use_ssl: bool = Field(default=True, alias="MAIL_SMTP_USE_SSL")
|
|
mail_smtp_starttls: bool = Field(default=False, alias="MAIL_SMTP_STARTTLS")
|
|
mail_username: str | None = Field(default=None, alias="MAIL_USERNAME")
|
|
mail_password: str | None = Field(default=None, alias="MAIL_PASSWORD")
|
|
mail_from_address: str | None = Field(default=None, alias="MAIL_FROM_ADDRESS")
|
|
mail_from_name: str = Field(default="JP Purchase Bot", alias="MAIL_FROM_NAME")
|
|
mail_to_addresses: Annotated[list[str], NoDecode] = Field(
|
|
default_factory=list,
|
|
alias="MAIL_TO_ADDRESSES",
|
|
)
|
|
mail_subject_prefix: str = Field(default="[JP-Purchase]", alias="MAIL_SUBJECT_PREFIX")
|
|
mail_timeout_seconds: int = Field(default=10, alias="MAIL_TIMEOUT_SECONDS")
|
|
|
|
@field_validator("notify_channels", "mail_to_addresses", mode="before")
|
|
@classmethod
|
|
def _parse_csv_list(cls, value: Any) -> list[str]:
|
|
if value is None:
|
|
return []
|
|
|
|
if isinstance(value, str):
|
|
return [item.strip() for item in value.split(",") if item.strip()]
|
|
|
|
if isinstance(value, (list, tuple, set)):
|
|
return [str(item).strip() for item in value if str(item).strip()]
|
|
|
|
return [str(value).strip()] if str(value).strip() else []
|
|
|
|
# Pydantic Settings 配置项
|
|
model_config = SettingsConfigDict(
|
|
env_file=ENV_FILE,
|
|
env_file_encoding="utf-8",
|
|
extra="ignore" # 忽略其他系统环境变量
|
|
)
|
|
|
|
@lru_cache
|
|
def get_settings() -> Settings:
|
|
"""
|
|
获取缓存的全局配置单例。
|
|
"""
|
|
return Settings()
|