All checks were successful
Build TV app / build (push) Successful in 2m49s
Fetching 56 images on every run earned nothing but rate limits, and the CI artefact is a test build that does not need the badges — the shield fallback covers it. The resolved image URLs are cached in tools/crest-sources.json, which is plain text and safe to commit, so a local run needs one request per club instead of two and can resume after a rate limit. The artwork itself stays out of the repository. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
68 lines
2.6 KiB
Python
68 lines
2.6 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"
|
|
URLS = "tools/crest-sources.json"
|
|
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)
|
|
# Image URLs are plain text and safe to commit; the artwork itself is not.
|
|
sources = {}
|
|
if os.path.exists(URLS):
|
|
sources = json.load(open(URLS, encoding="utf-8"))
|
|
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:
|
|
thumb = sources.get(key)
|
|
if not thumb:
|
|
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")
|
|
sources[key] = thumb.split("?")[0]
|
|
thumb = sources[key]
|
|
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)
|
|
|
|
with open(URLS, "w", encoding="utf-8") as f:
|
|
json.dump(dict(sorted(sources.items())), f, indent=2, ensure_ascii=False)
|
|
f.write("\n")
|
|
|
|
print(f"crests: {fetched} geladen, {skipped} vorhanden, {failed} fehlgeschlagen")
|