Files
castarr/tools/fetch-crests.py
be-nj 8aa3a4da02
All checks were successful
Build TV app / build (push) Successful in 4m15s
Ship the real club crests in the APK, and fix the CI licence step
Resolving crests from Wikipedia at runtime never produced a visible badge
on the TV and left nothing in the log to debug, so the shield fallback was
all anyone ever saw. They are now downloaded once at build time by
tools/fetch-crests.py into assets/crests (git-ignored, so no trademarked
artwork is committed) and loaded from there — instant, and independent of
the network.

CI: accepting SDK licences by piping "yes" into sdkmanager died of SIGPIPE
(exit 141) under pipefail; the licence hashes are written directly now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 03:31:06 +02:00

55 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Downloads club crests into the APK's assets at build time.
The badges are trademarks: they are fetched into a generated, git-ignored
folder so the repository stays free of them while the app ships with them
and needs no network at runtime.
"""
import json
import os
import re
import sys
import time
import urllib.parse
import urllib.request
OUT = sys.argv[1] if len(sys.argv) > 1 else "app/src/main/assets/crests"
SRC = "app/src/main/java/dev/castarr/tv/data/TeamFilters.kt"
SUMMARY = "https://de.wikipedia.org/api/rest_v1/page/summary/"
UA = {"User-Agent": "Castarr build script (private use)"}
os.makedirs(OUT, exist_ok=True)
kotlin = open(SRC, encoding="utf-8").read()
entries = re.findall(r'club\((.*?)\)\s*,\s*(?://.*)?$', kotlin, re.M | re.S)
clubs = []
for raw in re.findall(r'club\(\s*"([^"]+)",\s*"[^"]*",\s*"([^"]+)"[^\n]*', kotlin):
clubs.append(raw)
# an explicit article = "..." wins over the club name
overrides = dict(re.findall(r'club\(\s*"([^"]+)"[^\n]*article = "([^"]+)"', kotlin))
clubs = [(k, overrides.get(k, n)) for k, n in clubs]
fetched = skipped = failed = 0
for key, full_name in clubs:
target = os.path.join(OUT, f"{key}.png")
if os.path.exists(target) and os.path.getsize(target) > 0:
skipped += 1
continue
try:
url = SUMMARY + urllib.parse.quote(full_name)
with urllib.request.urlopen(urllib.request.Request(url, headers=UA), timeout=20) as r:
thumb = json.load(r).get("thumbnail", {}).get("source")
if not thumb:
raise ValueError("no thumbnail")
with urllib.request.urlopen(urllib.request.Request(thumb, headers=UA), timeout=20) as r:
data = r.read()
with open(target, "wb") as f:
f.write(data)
fetched += 1
except Exception as exc: # noqa: BLE001 - best effort, shield is the fallback
print(f" {key}: {exc}", file=sys.stderr)
failed += 1
# Wikipedia rate-limits bursts; this runs rarely and caches.
time.sleep(1.2)
print(f"crests: {fetched} geladen, {skipped} vorhanden, {failed} fehlgeschlagen")