"""Logos der Homelab-Dienste von selfh.st/icons laden (CC BY 4.0) — seit 25.09.2026. Holt für jede Referenz in WUNSCH das SVG nach frontend/public/logos/.svg und schreibt die Liste der vorhandenen Namen nach frontend/src/lib/logos-liste.ts (die Oberfläche fragt dort nach, ob es ein Logo gibt). Wo das Standard-Logo auf dem dunklen Grund verschwände, steht es in HELL: dann kommt die helle Variante der Sammlung. Die Liste HELL ist am 25.09.2026 gemessen worden (jedes Logo auf den Kachelgrund gezeichnet, Anteil sichtbarer Pixel). Neue Dienste: Referenz aus https://selfh.st/icons in WUNSCH eintragen (ggf. auch in HELL) und laufen lassen: python frontend/scripts/logos_laden.py Ohne Netz nach cdn.jsdelivr.net geht es nicht; die Oberfläche lädt Logos nie aus dem Netz, nur aus diesem Ordner. """ import sys import urllib.request from pathlib import Path REPO = Path(__file__).resolve().parents[2] ZIEL = REPO / "frontend" / "public" / "logos" LISTE = REPO / "frontend" / "src" / "lib" / "logos-liste.ts" BASIS = "https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/" WUNSCH = """ actual-budget adguard-home affine alpine-linux ansible appflowy apprise arcane audiobookshelf authelia authentik baserow bazarr beszel bitwarden bookstack borgmatic caddy calibre-web changedetection checkmk claude cloudflare cockpit comfyui crafty-controller crowdsec debian deluge docker dockge docmost dozzle draw-io duplicati elasticsearch element emby esphome excalidraw firefly-iii flatnotes forgejo freshrss frigate gatus gitea github gitlab glance glances go2rtc gotify grafana grocy harbor headscale healthchecks hedgedoc heimdall hermes-agent homarr home-assistant homebridge homepage immich immich-kiosk influxdb it-tools jellyfin jellyseerr jenkins jitsi-meet joplin kavita keycloak kopia komga komodo kubernetes librenms librespeed lidarr linkding linux linux-containers-lxc linuxserver-io llama-cpp loki logseq mariadb matomo matrix mattermost mealie minecraft miniflux minio mongodb mosquitto n8n navidrome netbird netdata nextcloud nginx nginx-proxy-manager nocodb node-red ntfy nzbget obsidian ollama onlyoffice open-webui openai openmediavault openwrt opnsense outline overseerr paperless-ngx penpot pfsense photoprism pi-hole pingvin-share piwigo planka plausible plex portainer postgresql privatebin prometheus prowlarr proxmox proxmox-helper-scripts pterodactyl qbittorrent qnap rabbitmq radarr rancher rclone readarr redis rocket-chat rustdesk sabnzbd scrutiny scrypted seafile searxng semaphore sonarr speedtest-tracker stirling-pdf syncthing synology tailscale tautulli telegram traefik transmission ubuntu umami unraid uptime-kuma vaultwarden vikunja wallabag watchtower webmin wekan wiki-js wireguard woodpecker-ci wordpress zabbix zigbee2mqtt """.split() # noqa: SIM905 — die lange Namensliste liest sich als Text besser # Auf dunklem Grund zu dunkel → helle Variante der Sammlung. HELL = set(""" affine borgmatic cockpit crafty-controller debian docmost frigate github go2rtc healthchecks heimdall hermes-agent homebridge influxdb logseq matrix mattermost miniflux minio node-red openai outline penpot pfsense portainer radarr scrutiny semaphore tailscale umami vaultwarden wallabag wireguard """.split()) # noqa: SIM905 def laden(ref: str) -> bytes: name = f"{ref}-light.svg" if ref in HELL else f"{ref}.svg" with urllib.request.urlopen(BASIS + name, timeout=30) as antwort: return antwort.read() def main() -> int: ZIEL.mkdir(parents=True, exist_ok=True) fehlt = [] for ref in dict.fromkeys(WUNSCH): try: (ZIEL / f"{ref}.svg").write_bytes(laden(ref)) except Exception as exc: # ein fehlendes Logo ist kein Beinbruch: dann bleibt das Symbol fehlt.append(f"{ref} ({exc})") vorhanden = sorted(p.stem for p in ZIEL.glob("*.svg")) zeilen = "\n".join(f' "{r}",' for r in vorhanden) LISTE.write_bytes(( "// Erzeugt von frontend/scripts/logos_laden.py: die Logos unter /logos/.svg (selfh.st/icons, CC BY 4.0).\n" "// Nicht von Hand pflegen — neue Logos mit demselben Skript holen.\n" f"export const LOGOS: ReadonlySet = new Set([\n{zeilen}\n])\n").encode()) print(f"{len(vorhanden)} Logos in {ZIEL}") if fehlt: print("nicht geladen:", ", ".join(fehlt)) return 0 if __name__ == "__main__": sys.exit(main())