111 lines
4.3 KiB
Python
111 lines
4.3 KiB
Python
"""Eksterne tjenester: geoip, static-assets-version, random-proxy status, Matomo, DiscoPanel."""
|
|
import httpx
|
|
|
|
import cache
|
|
from config import (ASSETS_VERSION_URL, DISCO_API_TOKEN, DISCO_BASE_URL, GEOIP_DB,
|
|
MATOMO_BASE, MATOMO_SITE, MATOMO_TOKEN, RP_API_KEY, RP_BASE_URL)
|
|
|
|
_geoip_reader = None
|
|
|
|
|
|
def geoip_country(ip):
|
|
global _geoip_reader
|
|
try:
|
|
if _geoip_reader is None:
|
|
import maxminddb
|
|
_geoip_reader = maxminddb.open_database(GEOIP_DB)
|
|
rec = _geoip_reader.get(ip) or {}
|
|
c = rec.get("country") or {}
|
|
iso = c.get("iso_code") or ""
|
|
name = (c.get("names") or {}).get("en") or ""
|
|
flag = "".join(chr(0x1F1E6 + ord(ch) - 65) for ch in iso) if len(iso) == 2 and iso.isalpha() else ""
|
|
return {"iso": iso, "name": name, "flag": flag}
|
|
except Exception:
|
|
return {"iso": "", "name": "", "flag": ""}
|
|
|
|
|
|
async def assets_version():
|
|
try:
|
|
async with httpx.AsyncClient(timeout=6) as c:
|
|
r = await c.get(ASSETS_VERSION_URL)
|
|
return r.text.strip()[:40]
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
async def rp_status():
|
|
if not RP_API_KEY:
|
|
return {"error": "ingen RP_API_KEY konfigureret"}
|
|
try:
|
|
async with httpx.AsyncClient(timeout=6) as c:
|
|
r = await c.get(RP_BASE_URL + "/status", headers={"X-WEIRCON-RANDOM-IP": RP_API_KEY})
|
|
d = r.json()
|
|
for p in d.get("proxies", []):
|
|
p["geo"] = geoip_country(p.get("egress_ip") or "")
|
|
rot = d.get("rotation") or {}
|
|
if rot.get("next_egress_ip"):
|
|
rot["geo"] = geoip_country(rot["next_egress_ip"])
|
|
d["inflight_total"] = sum(int(p.get("inflight") or 0) for p in d.get("proxies", []))
|
|
return d
|
|
except Exception as exc:
|
|
return {"error": str(exc)[:200]}
|
|
|
|
|
|
_MC_STATUS = { # DiscoPanel ServerStatus → (dansk label, css-klasse)
|
|
"SERVER_STATUS_RUNNING": ("Kører", "run"),
|
|
"SERVER_STATUS_STARTING": ("Starter…", "warn"),
|
|
"SERVER_STATUS_RESTARTING": ("Genstarter…", "warn"),
|
|
"SERVER_STATUS_CREATING": ("Oprettes…", "warn"),
|
|
"SERVER_STATUS_STOPPING": ("Stopper…", "warn"),
|
|
"SERVER_STATUS_STOPPED": ("Stoppet", "off"),
|
|
"SERVER_STATUS_ERROR": ("Fejl", "err"),
|
|
"SERVER_STATUS_UNHEALTHY": ("Usund", "err"),
|
|
}
|
|
|
|
|
|
async def minecraft_servers():
|
|
"""Serverliste fra DiscoPanel (CT 137, Connect-RPC). None = ikke konfigureret/utilgængelig."""
|
|
if not DISCO_API_TOKEN:
|
|
return None
|
|
hit = cache.get("mc:servers")
|
|
if hit is not None:
|
|
return hit
|
|
try:
|
|
async with httpx.AsyncClient(timeout=6) as c:
|
|
r = await c.post(f"{DISCO_BASE_URL}/discopanel.v1.ServerService/ListServers",
|
|
json={}, headers={"Authorization": f"Bearer {DISCO_API_TOKEN}",
|
|
"Content-Type": "application/json"})
|
|
r.raise_for_status()
|
|
data = r.json()
|
|
servers = []
|
|
for s in data.get("servers", []):
|
|
label, css = _MC_STATUS.get(s.get("status"), ("Ukendt", "off"))
|
|
servers.append({
|
|
"name": s.get("name") or "?",
|
|
"status": label, "css": css,
|
|
"online": s.get("status") == "SERVER_STATUS_RUNNING",
|
|
"players": int(s.get("playersOnline") or 0),
|
|
"max_players": int(s.get("maxPlayers") or 0),
|
|
"version": s.get("serverVersion") or s.get("mcVersion") or ""})
|
|
servers.sort(key=lambda x: (not x["online"], x["name"].lower()))
|
|
cache.put("mc:servers", servers, 15)
|
|
return servers
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
async def matomo_summary():
|
|
if not MATOMO_TOKEN:
|
|
return None
|
|
params = {"module": "API", "method": "VisitsSummary.get", "idSite": MATOMO_SITE,
|
|
"period": "day", "date": "last7", "format": "JSON", "token_auth": MATOMO_TOKEN}
|
|
try:
|
|
async with httpx.AsyncClient(timeout=10) as c:
|
|
r = await c.get(f"{MATOMO_BASE}/index.php", params=params)
|
|
data = r.json()
|
|
days = list(data.values()) if isinstance(data, dict) else []
|
|
return {"visits_7d": sum(int(d.get("nb_visits", 0) or 0) for d in days if isinstance(d, dict)),
|
|
"actions_7d": sum(int(d.get("nb_actions", 0) or 0) for d in days if isinstance(d, dict))}
|
|
except Exception:
|
|
return None
|