from functools import lru_cache from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): database_url: str = "postgresql+asyncpg://drivers:drivers@localhost:5432/drivers" bot_token: str = "" bot_username: str = "" api_base_url: str = "http://localhost:8000" webapp_url: str = "http://localhost:8000" public_webapp_url: str | None = None app_host: str = "0.0.0.0" app_port: int = 8000 app_env: str = "production" cors_origins: str = "" internal_api_token: str = "" vapid_public_key: str = "" allow_dev_auth: bool = False ocr_provider: str = "tesseract" ocr_languages: str = "eng+rus+kor" llm_base_url: str = "" llm_model: str = "" model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore") @property def cors_origin_list(self) -> list[str]: return [item.strip().rstrip("/") for item in self.cors_origins.split(",") if item.strip()] @property def effective_webapp_url(self) -> str: return (self.public_webapp_url or self.webapp_url).rstrip("/") @property def is_production(self) -> bool: return self.app_env.lower() == "production" def validate_webapp_url_for_telegram(self) -> None: url = self.effective_webapp_url if self.is_production and not url.startswith("https://"): raise RuntimeError("WEBAPP_URL/PUBLIC_WEBAPP_URL must be public HTTPS in production") forbidden = ("localhost", "127.0.0.1", "0.0.0.0", "http://") if self.is_production and any(item in url for item in forbidden): raise RuntimeError("Telegram Mini App URL must not use localhost, internal IP, or http://") @lru_cache def get_settings() -> Settings: return Settings() settings = get_settings()