from __future__ import annotations import os from functools import lru_cache from pathlib import Path from pydantic import AliasChoices, Field, field_validator from pydantic_settings import BaseSettings, SettingsConfigDict ROOT_DIR = Path(__file__).resolve().parent.parent CONFIG_DIR = ROOT_DIR / "config" DATA_DIR = ROOT_DIR / "data" class Settings(BaseSettings): app_name: str = "sub-provider" app_env: str = "prod" host: str = "0.0.0.0" port: int = 18080 log_level: str = "info" public_path: str = Field(default="change-me-random-hash-path") public_base_url: str | None = None request_timeout_seconds: float = 20.0 cache_ttl_seconds: int = 900 bundle_cache_ttl_seconds: int = 600 max_proxy_name_length: int = 80 default_user_agent: str = Field( default="sub-provider/0.2", validation_alias=AliasChoices("UPSTREAM_USER_AGENT", "DEFAULT_USER_AGENT"), ) sources_file: Path = CONFIG_DIR / "sources.yaml" conf_base_file: Path = CONFIG_DIR / "conf" / "base.conf" conf_profiles_dir: Path = CONFIG_DIR / "conf" / "profiles" rules_dir: Path = CONFIG_DIR / "rules" bundle_cache_dir: Path = ROOT_DIR / "output" / "bundle-cache" fetch_cache_dir: Path = DATA_DIR / "fetch-cache" model_config = SettingsConfigDict( env_file=ROOT_DIR / ".env", env_file_encoding="utf-8", extra="ignore", ) @field_validator("default_user_agent", mode="before") @classmethod def _coalesce_default_user_agent(cls, value: str) -> str: if isinstance(value, str) and value.strip(): return value legacy = os.getenv("DEFAULT_USER_AGENT", "").strip() if legacy: return legacy return "sub-provider/0.2" @lru_cache(maxsize=1) def get_settings() -> Settings: return Settings()