from pathlib import Path from pydantic_settings import BaseSettings, SettingsConfigDict BASE_DIR = Path(__file__).resolve().parent.parent DATA_DIR = BASE_DIR / "data" DATA_DIR.mkdir(exist_ok=True) def _resolve_sqlite_url(url: str) -> str: """SQLAlchemy SQLite URL with a relative path is interpreted against CWD, which breaks when the app is started from any directory other than the project root. Anchor relative SQLite paths to BASE_DIR.""" prefix = "sqlite:///" if not url.startswith(prefix): return url path_part = url[len(prefix):] p = Path(path_part) if p.is_absolute(): return url resolved = (BASE_DIR / p).resolve() resolved.parent.mkdir(parents=True, exist_ok=True) return f"{prefix}{resolved}" class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=BASE_DIR / ".env", env_file_encoding="utf-8", extra="ignore", ) tg_bot_token: str = "" web_host: str = "127.0.0.1" web_port: int = 8000 public_base_path: str = "" scrape_interval_hours: int = 4 database_url: str = f"sqlite:///{DATA_DIR / 'monitor.db'}" admin_chat_id: str = "" # Shared PIN that unlocks destructive web actions (delete/edit). Empty = gate # disabled (everything allowed). See app/auth.py. admin_pin: str = "" def model_post_init(self, __context) -> None: self.database_url = _resolve_sqlite_url(self.database_url) settings = Settings()