Initial sanitary RepoRadar release
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""
|
||||
config.py — Centralised configuration for RepoRadar.
|
||||
|
||||
Loads environment variables and defines git-server endpoints, the colour
|
||||
palette, cache TTLs and other tunables. Import `settings` everywhere instead of
|
||||
reading os.environ directly so configuration stays in one place.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load .env from the project root (the directory this file lives in).
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent
|
||||
load_dotenv(PROJECT_ROOT / ".env")
|
||||
|
||||
|
||||
def _get_int(name: str) -> int | None:
|
||||
"""Parse an optional integer env var, returning None when unset/blank."""
|
||||
raw = os.getenv(name, "").strip()
|
||||
if not raw:
|
||||
return None
|
||||
try:
|
||||
return int(raw)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Settings:
|
||||
"""Immutable runtime settings sourced from environment + defaults."""
|
||||
|
||||
# ── Discord ──────────────────────────────────────────────
|
||||
discord_token: str = os.getenv("DISCORD_TOKEN", "").strip()
|
||||
# Restrict slash-command sync to one guild for instant updates (recommended).
|
||||
guild_id: int | None = _get_int("GUILD_ID")
|
||||
|
||||
# ── Git server ───────────────────────────────────────────
|
||||
# Provider: "auto" (probe), "gitea" (also Forgejo), "gitlab", or "github".
|
||||
git_provider: str = os.getenv("GIT_PROVIDER", "auto").strip().lower()
|
||||
# Base URL of the git server, e.g. https://git.example.com / https://gitlab.com
|
||||
# For GitHub leave blank (defaults to api.github.com) and set GIT_PROVIDER=github.
|
||||
git_base_url: str = os.getenv("GIT_BASE_URL", "").strip().rstrip("/")
|
||||
# Personal access token (read-only is enough). Optional for public servers.
|
||||
git_token: str = os.getenv("GIT_TOKEN", "").strip()
|
||||
# Default channel for new-project drops (also settable per-guild via modal).
|
||||
git_drop_channel_id: int | None = _get_int("GIT_DROP_CHANNEL_ID")
|
||||
# Channel for highlighted/featured drops (keyword/star matches).
|
||||
git_highlight_channel_id: int | None = _get_int("GIT_HIGHLIGHT_CHANNEL_ID")
|
||||
# Role to ping on a highlighted drop.
|
||||
git_highlight_role_id: int | None = _get_int("GIT_HIGHLIGHT_ROLE_ID")
|
||||
# How often (seconds) the monitor polls the git server for new projects.
|
||||
git_poll_interval: int = _get_int("GIT_POLL_INTERVAL") or 300
|
||||
# Max new projects to drop per scan cycle (avoids flooding on bursts).
|
||||
git_max_drops_per_cycle: int = _get_int("GIT_MAX_DROPS_PER_CYCLE") or 10
|
||||
|
||||
# ── Paths ────────────────────────────────────────────────
|
||||
data_dir: Path = PROJECT_ROOT / "data"
|
||||
db_path: Path = PROJECT_ROOT / "data" / "reporadar.db"
|
||||
|
||||
# ── Behaviour ────────────────────────────────────────────
|
||||
log_level: str = os.getenv("LOG_LEVEL", "INFO").strip().upper()
|
||||
http_timeout: int = 30 # seconds per request
|
||||
request_retries: int = 3 # transient retry attempts
|
||||
user_agent: str = "RepoRadar/1.0 (+https://github.com/your-org/reporadar)"
|
||||
|
||||
# ── Cyberpunk / hacker colour palette (hex → int) ─────────
|
||||
color_drop: int = 0x8A63FF # neon violet (new project drops)
|
||||
color_highlight: int = 0xE0115F # ruby (featured / highlighted)
|
||||
color_success: int = 0x00FF9C # matrix green
|
||||
color_error: int = 0xFF003C # neon red
|
||||
color_medium: int = 0xFFB300 # amber (unconfigured / neutral)
|
||||
color_info: int = 0x0A84FF # electric blue
|
||||
|
||||
def ensure_dirs(self) -> None:
|
||||
"""Create the data directory if it does not yet exist."""
|
||||
self.data_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
settings = Settings()
|
||||
Reference in New Issue
Block a user