diff --git a/trainpulse/config.py b/trainpulse/config.py index 595014a..d98ae39 100644 --- a/trainpulse/config.py +++ b/trainpulse/config.py @@ -77,6 +77,7 @@ SOURCES = { }, "at_wl": { # Wiener Linien (Tram, U-Bahn, Badner Bahn), CC BY 4.0 "country": "at", + "check_hours": 24, # Server nennt kein Datum: 1x täglich laden (~100 MB) und Inhalt vergleichen "gtfs_url": "http://www.wienerlinien.at/ogd_realtime/doku/ogd/gtfs/gtfs.zip", "rt_url": "", "rt_key": "", "needs_key": False, "rt_interval": 60, }, diff --git a/trainpulse/prepare.py b/trainpulse/prepare.py index 1cbb936..0768a57 100644 --- a/trainpulse/prepare.py +++ b/trainpulse/prepare.py @@ -8,6 +8,7 @@ und macht für eine Quelle nichts, solange dort kein neuer Fahrplan veröffentli """ import argparse import csv +import hashlib import datetime as dt import io import json @@ -69,14 +70,15 @@ def download(url: str, dest: Path) -> None: def remote_id(src: str, url: str) -> tuple[str, str | None]: - """Kennung der aktuell veröffentlichten Datei, ohne sie herunterzuladen: (Name, Datum JJJJMMTT oder None).""" + """Kennung der aktuell veröffentlichten Datei, ohne sie herunterzuladen: (Name, Datum JJJJMMTT oder None). + Name None: der Server sagt nichts (Wiener Linien) – dann entscheidet der Inhalt nach dem Download.""" if src == "ch": return latest_gtfs_name(url), None r = httpx.head(url, follow_redirects=True, timeout=60, headers={"User-Agent": C.USER_AGENT}) r.raise_for_status() lm = r.headers.get("last-modified") if not lm: - raise RuntimeError(f"{url}: kein Last-Modified-Header") + return None, dt.date.today().strftime("%Y%m%d") date = dt.datetime.strptime(lm, "%a, %d %b %Y %H:%M:%S GMT").strftime("%Y%m%d") return f"{src}-{lm}", date @@ -347,12 +349,18 @@ def prepare(source: str, state: dict, zip_path: Path | None = None, force: bool state[source + "@checked"] = time.time() url = gtfs_url(source) name, version = remote_id(source, url) - if f"{name} #{FORMAT}" == state.get(source) and not force: + if name and f"{name} #{FORMAT}" == state.get(source) and not force: log.info("[%s] Kein neuer Fahrplan (%s)", source, name) return zip_path = work / "gtfs.zip" - log.info("[%s] Lade Fahrplan %s", source, name) + log.info("[%s] Lade Fahrplan %s", source, name or "(ohne Datum vom Server)") download(url, zip_path) + if not name: # ohne Datum vom Server: am Inhalt erkennen, ob es Neues gibt + with open(zip_path, "rb") as f: + name = f"{source}-{hashlib.file_digest(f, 'sha256').hexdigest()[:16]}" + if f"{name} #{FORMAT}" == state.get(source) and not force: + log.info("[%s] Kein neuer Fahrplan (gleicher Inhalt)", source) + return t = time.time() version = version or zip_path.stem # (nach dem Glätten hiesse die Datei sonst "normalized")