85 lines
4.1 KiB
Python
Executable File
85 lines
4.1 KiB
Python
Executable File
"""
|
|
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()
|