from functools import lru_cache from pathlib import Path from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore", ) app_name: str = "AIVideo" app_env: str = "development" app_host: str = "0.0.0.0" app_port: int = 8000 app_debug: bool = True database_url: str = "sqlite:///./aivideo.sqlite3" redis_url: str = "redis://127.0.0.1:6379/0" celery_task_always_eager: bool = True jwt_secret: str = "replace_me" jwt_refresh_secret: str = "replace_me_too" jwt_access_expire_minutes: int = 120 jwt_refresh_expire_days: int = 30 jwt_cookie_domain: str | None = None cors_origins: str = Field( default="http://localhost:3000,http://localhost:3001" ) storage_provider: str = "local" local_storage_path: str = "storage_data" storage_bucket: str = "ai-video" storage_public_base_url: str = "http://127.0.0.1:8000/storage" point_exchange_ratio: int = 100 invite_reward_min_consume_points: int = 100 redeem_code_fail_limit_per_hour: int = 20 task_default_poll_interval_seconds: int = 5 task_max_poll_minutes: int = 30 task_daily_create_limit: int = 50 mock_task_run_seconds: int = 18 mock_task_progress_step: int = 25 admin_username: str = "admin" admin_password: str = "Admin@123456" admin_nickname: str = "Super Admin" @property def parsed_cors_origins(self) -> list[str]: return [origin.strip() for origin in self.cors_origins.split(",") if origin.strip()] @property def project_root(self) -> Path: return Path(__file__).resolve().parents[3] @property def storage_root(self) -> Path: return self.project_root / self.local_storage_path @lru_cache def get_settings() -> Settings: return Settings()