Ctrl K
ComunidadGuías…

backend/songbird/config.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""Application configuration via pydantic-settings.

`CONCORD_BASE_URL` is the one knob that points songbird at Concord. Its default is a
convenience (the common same-host case), never an assumption that Concord is co-located —
songbird calls whatever URL it is given (CLAUDE.md invariant 2).
"""

from functools import lru_cache
from pathlib import Path

from pydantic import field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

REPO_ROOT: Path = Path(__file__).resolve().parents[2]


class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        env_file=REPO_ROOT / ".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
        extra="ignore",
    )

    port: int = 8077
    bind_host: str = "0.0.0.0"
    data_dir: Path = Path("./data")

    # Concord — songbird's hard runtime HTTP dependency.
    concord_base_url: str = "http://localhost:8000"
    concord_timeout: float = 5.0

    # YouTube — the sermon-source collector's data feed (v1.7). Unlike Concord, this is NOT a
    # hard dependency: with no key the feature is simply off, and nothing else changes. The key
    # is a secret — it is never logged and never sent to the browser.
    youtube_api_key: str | None = None
    sermon_check_interval_hours: int = 168  # weekly; 0 turns the scheduled check off
    sermon_min_minutes: int = 10  # videos shorter than this are skipped

    # Session cookie `Secure` flag. Default False suits the LAN-HTTP single-unit deploy; set
    # COOKIE_SECURE=1 the moment songbird is fronted with TLS (see docs/SECURITY.md).
    cookie_secure: bool = False

    # Set in production (by the Docker image) to the built SPA's dist dir.
    frontend_dist_dir: Path | None = None

    @field_validator("data_dir")
    @classmethod
    def _resolve_data_dir(cls, value: Path) -> Path:
        if not value.is_absolute():
            value = REPO_ROOT / value
        return value.resolve()

    @property
    def database_url(self) -> str:
        db_path = self.data_dir / "songbird.db"
        return f"sqlite+aiosqlite:///{db_path}"


@lru_cache(maxsize=1)
def get_settings() -> Settings:
    return Settings()