Files
jail-launcher/jlauncher/config.py
T
JailDesigner e0a93a9c28 Estil targeta tipus web a les files + tema seleccionable (system/clar/fosc)
UI:
- Files amb estil de targeta: icona arrodonida, títol gran, subtítol atenuat i
  'pills' amb estat, versió, data de llançament, jugadors, autor i topics. Els
  pills envolten amb un FlowLayout nou quan no caben.
- Submenú Opcions > Tema amb Sistema/Clar/Fosc; persisteix a settings.json
  (theme) i s'aplica a l'instant. El watcher del SO només actua en mode Sistema.

Dades:
- GameMeta guarda topics i created_at, llegits de la resposta de Gitea que ja
  demanàvem (gratis, auto-sincronitzats).
- games.toml: camps opcionals players i author per joc (la resta surt de Gitea).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:13:32 +02:00

84 lines
2.6 KiB
Python

"""Carga de games.toml → objetos Game con valores derivados."""
from __future__ import annotations
import tomllib
from dataclasses import dataclass, field
from pathlib import Path
from urllib.parse import urlparse
DEFAULT_VERSION_CMD = "git describe --tags --always"
DEFAULT_ICON_REL = "release/icons/icon.png"
@dataclass
class Game:
id: str
name: str
clone_url: str
run_cmd: str
build_cmd: str = ""
version_cmd: str = DEFAULT_VERSION_CMD
info_url: str = ""
icon_rel: str = DEFAULT_ICON_REL
players: str = "" # texto manual para el pill de jugadores (Gitea no lo tiene)
author: str = "" # texto manual para el pill de autor
def __post_init__(self) -> None:
if not self.info_url:
self.info_url = derive_info_url(self.clone_url)
@dataclass
class Config:
data_dir: str = "jlauncher_data"
games: list[Game] = field(default_factory=list)
def derive_info_url(clone_url: str) -> str:
"""De una URL de clone Gitea deriva la URL de la API REST del repo.
https://host/org/repo.git -> https://host/api/v1/repos/org/repo
"""
parsed = urlparse(clone_url)
path = parsed.path.strip("/")
if path.endswith(".git"):
path = path[: -len(".git")]
parts = [p for p in path.split("/") if p]
if len(parts) < 2 or not parsed.scheme or not parsed.netloc:
return ""
owner, repo = parts[-2], parts[-1]
return f"{parsed.scheme}://{parsed.netloc}/api/v1/repos/{owner}/{repo}"
def load_config(path: Path) -> Config:
with open(path, "rb") as fh:
raw = tomllib.load(fh)
games: list[Game] = []
for entry in raw.get("game", []):
missing = [k for k in ("id", "name", "clone_url", "run_cmd") if not entry.get(k)]
if missing:
raise ValueError(
f"Juego con campos obligatorios faltantes {missing}: {entry!r}"
)
games.append(
Game(
id=entry["id"],
name=entry["name"],
clone_url=entry["clone_url"],
run_cmd=entry["run_cmd"],
build_cmd=entry.get("build_cmd", ""),
version_cmd=entry.get("version_cmd") or DEFAULT_VERSION_CMD,
info_url=entry.get("info_url", ""),
icon_rel=entry.get("icon_rel") or DEFAULT_ICON_REL,
players=entry.get("players", ""),
author=entry.get("author", ""),
)
)
if not games:
raise ValueError("games.toml no define ningún [[game]]")
return Config(data_dir=raw.get("data_dir", "jlauncher_data"), games=games)