2026-04-08 06:03:48 -04:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
from functools import lru_cache
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
|
class Settings:
|
2026-04-12 20:15:33 -04:00
|
|
|
app_base_url: str | None
|
2026-04-12 22:02:47 -04:00
|
|
|
auth_secret_key: str | None
|
|
|
|
|
auth_cookie_secure: bool
|
2026-04-08 06:03:48 -04:00
|
|
|
forgejo_base_url: str
|
|
|
|
|
forgejo_token: str | None
|
2026-04-12 20:15:33 -04:00
|
|
|
forgejo_oauth_client_id: str | None
|
|
|
|
|
forgejo_oauth_client_secret: str | None
|
|
|
|
|
forgejo_oauth_scopes: tuple[str, ...]
|
2026-04-13 18:19:50 -04:00
|
|
|
forgejo_general_discussion_repo: str | None
|
|
|
|
|
forgejo_webhook_secret: str | None
|
2026-04-08 06:03:48 -04:00
|
|
|
forgejo_repo_scan_limit: int
|
|
|
|
|
forgejo_recent_issue_limit: int
|
2026-04-13 18:19:50 -04:00
|
|
|
forgejo_cache_ttl_seconds: float
|
2026-04-08 06:03:48 -04:00
|
|
|
forgejo_request_timeout_seconds: float
|
|
|
|
|
calendar_feed_urls: tuple[str, ...]
|
|
|
|
|
calendar_event_limit: int
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _normalize_base_url(raw_value: str | None) -> str:
|
|
|
|
|
value = (raw_value or "").strip()
|
|
|
|
|
if not value:
|
|
|
|
|
return "https://aksal.cloud"
|
|
|
|
|
if value.startswith(("http://", "https://")):
|
|
|
|
|
return value.rstrip("/")
|
|
|
|
|
return f"https://{value.rstrip('/')}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _parse_calendar_feed_urls(raw_value: str | None) -> tuple[str, ...]:
|
|
|
|
|
value = (raw_value or "").strip()
|
|
|
|
|
if not value:
|
|
|
|
|
return ()
|
|
|
|
|
|
|
|
|
|
return tuple(entry.strip() for entry in value.replace("\n", ",").split(",") if entry.strip())
|
|
|
|
|
|
|
|
|
|
|
2026-04-12 20:15:33 -04:00
|
|
|
def _parse_scopes(raw_value: str | None) -> tuple[str, ...]:
|
|
|
|
|
value = (raw_value or "").strip()
|
|
|
|
|
if not value:
|
|
|
|
|
return ("openid", "profile")
|
|
|
|
|
return tuple(scope for scope in value.replace(",", " ").split() if scope)
|
|
|
|
|
|
|
|
|
|
|
2026-04-12 22:02:47 -04:00
|
|
|
def _parse_bool(raw_value: str | None, *, default: bool = False) -> bool:
|
|
|
|
|
value = (raw_value or "").strip().lower()
|
|
|
|
|
if not value:
|
|
|
|
|
return default
|
|
|
|
|
return value in {"1", "true", "yes", "on"}
|
|
|
|
|
|
|
|
|
|
|
2026-04-08 06:03:48 -04:00
|
|
|
@lru_cache(maxsize=1)
|
|
|
|
|
def get_settings() -> Settings:
|
|
|
|
|
return Settings(
|
2026-04-12 20:15:33 -04:00
|
|
|
app_base_url=_normalize_base_url(os.getenv("APP_BASE_URL"))
|
|
|
|
|
if os.getenv("APP_BASE_URL")
|
|
|
|
|
else None,
|
2026-04-12 22:02:47 -04:00
|
|
|
auth_secret_key=os.getenv("AUTH_SECRET_KEY") or None,
|
|
|
|
|
auth_cookie_secure=_parse_bool(os.getenv("AUTH_COOKIE_SECURE")),
|
2026-04-08 06:03:48 -04:00
|
|
|
forgejo_base_url=_normalize_base_url(os.getenv("FORGEJO_BASE_URL")),
|
|
|
|
|
forgejo_token=os.getenv("FORGEJO_TOKEN") or None,
|
2026-04-12 20:15:33 -04:00
|
|
|
forgejo_oauth_client_id=os.getenv("FORGEJO_OAUTH_CLIENT_ID") or None,
|
|
|
|
|
forgejo_oauth_client_secret=os.getenv("FORGEJO_OAUTH_CLIENT_SECRET") or None,
|
|
|
|
|
forgejo_oauth_scopes=_parse_scopes(os.getenv("FORGEJO_OAUTH_SCOPES")),
|
2026-04-13 18:19:50 -04:00
|
|
|
forgejo_general_discussion_repo=os.getenv("FORGEJO_GENERAL_DISCUSSION_REPO") or None,
|
|
|
|
|
forgejo_webhook_secret=os.getenv("FORGEJO_WEBHOOK_SECRET") or None,
|
2026-04-08 06:03:48 -04:00
|
|
|
forgejo_repo_scan_limit=int(os.getenv("FORGEJO_REPO_SCAN_LIMIT", "30")),
|
2026-04-13 18:19:50 -04:00
|
|
|
forgejo_recent_issue_limit=int(os.getenv("FORGEJO_RECENT_ISSUE_LIMIT", "50")),
|
|
|
|
|
forgejo_cache_ttl_seconds=float(os.getenv("FORGEJO_CACHE_TTL_SECONDS", "60.0")),
|
2026-04-08 06:03:48 -04:00
|
|
|
forgejo_request_timeout_seconds=float(
|
|
|
|
|
os.getenv("FORGEJO_REQUEST_TIMEOUT_SECONDS", "10.0"),
|
|
|
|
|
),
|
|
|
|
|
calendar_feed_urls=_parse_calendar_feed_urls(os.getenv("CALENDAR_FEED_URLS")),
|
2026-04-12 20:15:33 -04:00
|
|
|
calendar_event_limit=int(os.getenv("CALENDAR_EVENT_LIMIT", "3")),
|
2026-04-08 06:03:48 -04:00
|
|
|
)
|