From 8b1046d238e7c378622c579a34af3a6413848aed Mon Sep 17 00:00:00 2001 From: Franziska Kunsmann Date: Fri, 5 Jan 2024 10:32:53 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 1 + importer.py | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 .gitignore create mode 100644 importer.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..224b094 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +state.json diff --git a/importer.py b/importer.py new file mode 100644 index 0000000..4ceea4f --- /dev/null +++ b/importer.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 + +import json +import logging +from datetime import datetime, timezone +from sys import exit + +from requests import Session + +TRAEWELLING_API_TOKEN = "" +TRAEWELLING_USER = "" + +TRAVELYNX_API_TOKEN = "" + +IMPORT_UNTIL = "2021-06-28" + +# ------------------------------------------------------------------- + +logging.basicConfig(level=logging.INFO) +l = logging.getLogger(__name__) +s = Session() +s.headers = { + "Accept": "application/json", +} + +# get all checkins from traewelling +url = f"https://traewelling.de/api/v1/user/{TRAEWELLING_USER}/statuses" +checkins = [] +while url is not None: + try: + l.info(f"requesting statuses from {url}") + r = s.get( + url, + headers={ + "X-CRSF-TOKEN": "", + "Authorization": f"Bearer {TRAEWELLING_API_TOKEN}", + }, + ) + r.raise_for_status() + result_json = r.json() + checkins.extend(result_json.get("data", [])) + url = result_json.get("links", {}).get("next") + except Exception: + l.exception(f"error while getting data from {url}") + if not checkins: + # only exit if we have had no checkins at all + exit(1) + +try: + with open("state.json") as f: + processed_checkins = json.load(f)["checkins"] +except FileNotFoundError: + processed_checkins = [] + +time_limit = datetime.strptime(IMPORT_UNTIL, "%Y-%m-%d").astimezone(timezone.utc) +for checkin in sorted(checkins, key=lambda c: c["createdAt"]): + try: + l.info(f"processing checkin {checkin['id']} created at {checkin['createdAt']}") + created = datetime.fromisoformat(checkin["createdAt"]) + if created >= time_limit: + l.warning("SKIP: newer than IMPORT_UNTIL") + continue + if checkin["id"] in processed_checkins: + l.warning("SKIP: already processed") + continue + train_type = checkin["train"]["lineName"].split(" ")[0] + comment = [f"Import from Traewelling, ID {checkin['id']}"] + if checkin["body"]: + comment.extend(["", checkin["body"]]) + if checkin["event"]: + comment.extend(["", checkin["event"]["name"], checkin["event"]["url"]]) + travelynx_data = { + "token": TRAVELYNX_API_TOKEN, + "dryRun": False, + "lax": True, + "cancelled": False, + "train": { + "type": train_type, + "line": None, + "no": checkin["train"]["number"], + }, + "fromStation": { + "name": checkin["train"]["origin"]["rilIdentifier"] + or checkin["train"]["origin"]["name"], + "scheduledTime": int( + datetime.fromisoformat( + checkin["train"]["origin"]["departurePlanned"] + or checkin["train"]["origin"]["departure"] + ).timestamp() + ), + "realTime": int( + datetime.fromisoformat( + checkin["train"]["origin"]["departureReal"] + ).timestamp() + ) + if checkin["train"]["origin"]["departureReal"] + else None, + }, + "toStation": { + "name": checkin["train"]["destination"]["rilIdentifier"] + or checkin["train"]["destination"]["name"], + "scheduledTime": int( + datetime.fromisoformat( + checkin["train"]["destination"]["departurePlanned"] + or checkin["train"]["destination"]["departure"] + ).timestamp() + ), + "realTime": int( + datetime.fromisoformat( + checkin["train"]["destination"]["departureReal"] + ).timestamp() + ) + if checkin["train"]["destination"]["departureReal"] + else None, + }, + # "intermediateStops": [], + "comment": "\n".join(comment), + } + l.debug(json.dumps(travelynx_data)) + r = s.post( + "https://travelynx.franzi.business/api/v1/import", json=travelynx_data + ) + l.debug(r.text) + r.raise_for_status() + result = r.json() + if result["success"]: + l.info("added to travelynx") + processed_checkins.append(checkin["id"]) + else: + l.error(f"failed with error: {result['error']}") + l.error(travelynx_data) + except Exception: + l.exception("error occured!") + break + +print(processed_checkins) +with open("state.json", "w") as f: + json.dump({"checkins": processed_checkins}, f)