From 5f6c3a223b40fd600cbb14abc96c2c4f407aae3a Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 14:19:57 +0200 Subject: [PATCH 01/48] transitous: add bruno --- bruno/Gleiswechsel-API/.gitignore | 9 ++++++ .../Gleiswechsel-API/Geocode München HBF.yml | 29 +++++++++++++++++ .../Stoptimes for Station.yml | 32 +++++++++++++++++++ bruno/Gleiswechsel-API/Trip Details.yml | 22 +++++++++++++ .../environments/Transitous API.yml | 6 ++++ bruno/Gleiswechsel-API/opencollection.yml | 10 ++++++ 6 files changed, 108 insertions(+) create mode 100644 bruno/Gleiswechsel-API/.gitignore create mode 100644 bruno/Gleiswechsel-API/Geocode München HBF.yml create mode 100644 bruno/Gleiswechsel-API/Stoptimes for Station.yml create mode 100644 bruno/Gleiswechsel-API/Trip Details.yml create mode 100644 bruno/Gleiswechsel-API/environments/Transitous API.yml create mode 100644 bruno/Gleiswechsel-API/opencollection.yml diff --git a/bruno/Gleiswechsel-API/.gitignore b/bruno/Gleiswechsel-API/.gitignore new file mode 100644 index 0000000..e19311f --- /dev/null +++ b/bruno/Gleiswechsel-API/.gitignore @@ -0,0 +1,9 @@ +# Secrets +.env* + +# Dependencies +node_modules + +# OS files +.DS_Store +Thumbs.db \ No newline at end of file diff --git a/bruno/Gleiswechsel-API/Geocode München HBF.yml b/bruno/Gleiswechsel-API/Geocode München HBF.yml new file mode 100644 index 0000000..865c048 --- /dev/null +++ b/bruno/Gleiswechsel-API/Geocode München HBF.yml @@ -0,0 +1,29 @@ +info: + name: Geocode München HBF + type: http + seq: 1 + +http: + method: GET + url: https://api.transitous.org/api/v1/geocode?text=München Hbf + headers: + - name: User-Agent + value: Gleiswechsel-Discord-Bot + params: + - name: text + value: München Hbf + type: query + auth: inherit + +runtime: + scripts: + - type: after-response + code: |- + const data = res.getBody(); + bru.setEnvVar("stop_id", data[0].id); + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/Gleiswechsel-API/Stoptimes for Station.yml b/bruno/Gleiswechsel-API/Stoptimes for Station.yml new file mode 100644 index 0000000..29a2ef7 --- /dev/null +++ b/bruno/Gleiswechsel-API/Stoptimes for Station.yml @@ -0,0 +1,32 @@ +info: + name: Stoptimes for Station + type: http + seq: 3 + +http: + method: GET + url: https://api.transitous.org/api/v1/stoptimes?stopId={{stop_id}}&n=10 + headers: + - name: User-Agent + value: Gleiswechsel-Discord-Bot + params: + - name: stopId + value: "{{stop_id}}" + type: query + - name: n + value: "10" + type: query + auth: inherit + +runtime: + scripts: + - type: after-response + code: |- + const data = res.getBody(); + bru.setEnvVar("trip_id", data.stopTimes[0].tripId); + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/Gleiswechsel-API/Trip Details.yml b/bruno/Gleiswechsel-API/Trip Details.yml new file mode 100644 index 0000000..1d45b12 --- /dev/null +++ b/bruno/Gleiswechsel-API/Trip Details.yml @@ -0,0 +1,22 @@ +info: + name: Trip Details + type: http + seq: 4 + +http: + method: GET + url: https://api.transitous.org/api/v2/trip?tripId={{trip_id}} + headers: + - name: User-Agent + value: Gleiswechsel-Discord-Bot + params: + - name: tripId + value: "{{trip_id}}" + type: query + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/Gleiswechsel-API/environments/Transitous API.yml b/bruno/Gleiswechsel-API/environments/Transitous API.yml new file mode 100644 index 0000000..0662ac7 --- /dev/null +++ b/bruno/Gleiswechsel-API/environments/Transitous API.yml @@ -0,0 +1,6 @@ +name: Transitous API +variables: + - name: stop_id + value: at-Railway-Current-Reference-Data-2026_de:09162:100:11:11 + - name: trip_id + value: 20260815_11:52_de-DELFI_3338623109 diff --git a/bruno/Gleiswechsel-API/opencollection.yml b/bruno/Gleiswechsel-API/opencollection.yml new file mode 100644 index 0000000..43d1edd --- /dev/null +++ b/bruno/Gleiswechsel-API/opencollection.yml @@ -0,0 +1,10 @@ +opencollection: 1.0.0 + +info: + name: Gleiswechsel-API +bundled: false +extensions: + bruno: + ignore: + - node_modules + - .git From adfa0a0440109319d890c2203f31a731d758aea0 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 17:47:40 +0200 Subject: [PATCH 02/48] transitous: add api functions --- src/api/transitous.py | 120 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/api/transitous.py diff --git a/src/api/transitous.py b/src/api/transitous.py new file mode 100644 index 0000000..d9541e1 --- /dev/null +++ b/src/api/transitous.py @@ -0,0 +1,120 @@ +import json +import requests +import random +from src.utils import logger +from ... import config + +stations = config["stations"] +blacklist = config["blacklist"] +user_agent = config["http"]["user_agent"] + +headers = { + "User-Agent": f"{user_agent}" +} + +endpoint = "https://api.transitous.org" + +def get_stop_id(stop): + req = f"{endpoint}/api/v1/geocode?text={stop}" + + try: + response = requests.get(req, headers=headers) + response.raise_for_status() + data = response.json() + except requests.RequestException as e: + logger(f"An error occured while searching for a connection: {e}") + return None + + if response.status_code == 404: + logger(f"Error finding station '{stop}'") + + for entry in data: + if entry.get("type") != "STOP": + continue + return entry["id"] + +def get_random_connection(stop_id): + max_pages = 5 + cursor = None + count = 20 + + for _ in range(max_pages): + params = f"stopId={stop_id}&n={count}" + if cursor: + params += f"&pageCursor={cursor}" + + req = f"{endpoint}/api/v1/stoptimes?{params}" + + try: + response = requests.get(req, headers=headers) + response.raise_for_status() + data = response.json() + except requests.RequestException as e: + print(e) + return None + + trip_ids = [] + for entry in data.get("stopTimes", []): + trip_id = entry["tripId"] + if entry["mode"] in blacklist: + continue + trip_ids.append(trip_id) + + if len(trip_ids) >= 5: + break + + cursor = data.get("nextPageCursor") + if not cursor: + break + + if not trip_ids: + print("Couldn't find any connection") + return None + + return random.choice(trip_ids) + +def get_trip_details(trip_id): + req = f"{endpoint}/api/v2/trip?tripId={trip_id}" + + try: + response = requests.get(req, headers=headers) + response.raise_for_status + data = response.json() + except requests.RequestException as e: + print("e") + return None + + legs = data["legs"][0] + + trip_from = legs["tripFrom"]["name"] + trip_to = legs["tripTo"]["name"] + start_time = legs["startTime"] + end_time = legs["endTime"] + + trip_details = { + "name": legs["displayName"], + "from": trip_from, + "to": trip_to, + "agency": legs["agencyName"], + "route_color": legs.get("routeColor"), + "duration": legs["duration"], + "start_time": start_time, + "end_time": end_time, + "mode": legs["mode"], + "stops": {} + } + + trip_details["stops"][trip_from] = start_time + for stop in legs["intermediateStops"]: + trip_details["stops"][stop["name"]] = stop["arrival"] + trip_details["stops"][trip_to] = end_time + + return trip_details + +assigned_station = random.choice(stations) +print(assigned_station) + +stop_id = get_stop_id(assigned_station) +trip_id = get_random_connection(stop_id) +print(json.dumps(get_trip_details(trip_id), indent=2, ensure_ascii=False)) + From 826b54334768442e99f1d5d56e1374d951cc7285 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 19:12:30 +0200 Subject: [PATCH 03/48] transitous: basic rename_vc functionality --- main.py | 42 ++++-------- src/api/transitous.py | 28 ++++---- src/dc/handlers.py | 26 ++++++++ src/dc/helpers.py | 15 +++++ src/utils.py | 144 ++---------------------------------------- 5 files changed, 68 insertions(+), 187 deletions(-) create mode 100644 src/dc/handlers.py create mode 100644 src/dc/helpers.py diff --git a/main.py b/main.py index 8fa34e8..1f006b6 100644 --- a/main.py +++ b/main.py @@ -1,40 +1,20 @@ import discord -import random -from discord.ext import tasks -from src.config import config -from src.handlers import rename_vc -from src.commands import setup_commands -from src.embeds import build_error_embed -from src.utils import logger -from src.data.status import discord_status +from src.utils import config, logger +from src.dc.handlers import rename_vc +from src.dc.helpers import validate_channel bot = discord.Bot(intents=discord.Intents.all()) -setup_commands(bot) -@tasks.loop(minutes=5) -async def change_status(): - status = random.choice(discord_status) - await bot.change_presence(activity=discord.Game(name=f"{status} • /info")) - -_bot_initialized = False @bot.event async def on_ready(): - global _bot_initialized - print(f"{bot.user} ist online") - if not change_status.is_running(): - change_status.start() - if not _bot_initialized: - _bot_initialized = True - await rename_vc(bot) - else: - logger("Discord Reconnect, laufende Fahrt bleibt unangetastet") + server_id = config["server"] + server_vc_id = config["vc"] + channel = validate_channel(bot=bot, server_id=server_id, channel_id=server_vc_id) -@bot.event -async def on_application_command_error(ctx, error): - embed = build_error_embed(f"Ein Fehler ist aufgetreten: {error}") - await ctx.respond(embed=embed) + logger(f"{bot.user} ist online") + await rename_vc(bot=bot, voice_channel=channel) -try: - bot.run(config['token']) +try: + bot.run(config["token"]) except: - logger("Fehler beim parsen des token", "fatal") \ No newline at end of file + logger("Feher peim parsen des tokens", "fatal") \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index d9541e1..9908508 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -1,8 +1,8 @@ import json import requests import random -from src.utils import logger -from ... import config + +from src.utils import logger, config stations = config["stations"] blacklist = config["blacklist"] @@ -14,7 +14,8 @@ headers = { endpoint = "https://api.transitous.org" -def get_stop_id(stop): +def get_random_stop_id() -> str: + stop = random.choice(stations) req = f"{endpoint}/api/v1/geocode?text={stop}" try: @@ -22,7 +23,7 @@ def get_stop_id(stop): response.raise_for_status() data = response.json() except requests.RequestException as e: - logger(f"An error occured while searching for a connection: {e}") + logger(f"An error occured while searching for a connection: {e}", "fatal") return None if response.status_code == 404: @@ -33,7 +34,7 @@ def get_stop_id(stop): continue return entry["id"] -def get_random_connection(stop_id): +def get_random_connection(stop_id: str) -> str: max_pages = 5 cursor = None count = 20 @@ -68,12 +69,12 @@ def get_random_connection(stop_id): break if not trip_ids: - print("Couldn't find any connection") + logger("Couldn't find any connection", "fatal") return None return random.choice(trip_ids) -def get_trip_details(trip_id): +def get_trip_details(trip_id: str) -> dict: req = f"{endpoint}/api/v2/trip?tripId={trip_id}" try: @@ -81,18 +82,20 @@ def get_trip_details(trip_id): response.raise_for_status data = response.json() except requests.RequestException as e: - print("e") + logger(f"An error occured while trying to get the route details: {e}", "fatal") return None legs = data["legs"][0] + display_name = legs["displayName"] trip_from = legs["tripFrom"]["name"] trip_to = legs["tripTo"]["name"] start_time = legs["startTime"] end_time = legs["endTime"] trip_details = { - "name": legs["displayName"], + "long_name": f"{display_name} nach {trip_to} von {trip_from}", + "short_name": display_name, "from": trip_from, "to": trip_to, "agency": legs["agencyName"], @@ -111,10 +114,3 @@ def get_trip_details(trip_id): return trip_details -assigned_station = random.choice(stations) -print(assigned_station) - -stop_id = get_stop_id(assigned_station) -trip_id = get_random_connection(stop_id) -print(json.dumps(get_trip_details(trip_id), indent=2, ensure_ascii=False)) - diff --git a/src/dc/handlers.py b/src/dc/handlers.py new file mode 100644 index 0000000..5d750ec --- /dev/null +++ b/src/dc/handlers.py @@ -0,0 +1,26 @@ +import discord +import asyncio + +from src.api import transitous +from src.utils import logger + +_scheduled_task: asyncio.Task | None = None + +async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = False): + if not from_scheduler and _scheduled_task and not _scheduled_task.done(): + _scheduled_task.cancel() + + station_id = transitous.get_random_stop_id() + trip_id = transitous.get_random_connection(station_id) + trip = transitous.get_trip_details(trip_id) + + train_name = trip["long_name"] + + print("-----------------") + logger(f"Umstieg: {train_name}") + logger(f"Betreiber: {trip["agency"]}, Typ: {trip["mode"]}") + logger(f"Sprachkanal wird geändert, wenn nichts passiert bin ich im cooldown (warte einen moment!)") + + await voice_channel.edit(name=train_name) + logger(f"Name geändert!") + diff --git a/src/dc/helpers.py b/src/dc/helpers.py new file mode 100644 index 0000000..c364db3 --- /dev/null +++ b/src/dc/helpers.py @@ -0,0 +1,15 @@ +import discord +from src.utils import logger + +def validate_channel(bot: discord.bot, server_id: int, channel_id: int): + guild = bot.get_guild(server_id) + channel = guild.get_channel(channel_id) + + if guild is None: + logger(f"Es konnte kein Server mit der ID {server_id} gefunden werden", "fatal") + + if not isinstance(channel, discord.VoiceChannel): + logger(f"Es konnte kein VC mit der id {channel_id} gefunden werden", "fatal") + return False + + return channel \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index 1f30067..11d7f2c 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,147 +1,11 @@ -import requests -import random +import json import os -import importlib from datetime import datetime -from src.config import config -import src.data.operators as operators_module -import src.data.emojis as emojis -_operators_mtime = None -dbf = config.get("dbf", "https://dbf.finalrewind.org") +with open("config.json", "r") as file: + config = json.load(file) -def _reload_operators_if_changed(): - global _operators_mtime - - path = operators_module.__file__ - current_mtime = os.path.getmtime(path) - - if _operators_mtime is None: - _operators_mtime = current_mtime - return - - if current_mtime != _operators_mtime: - importlib.reload(operators_module) - _operators_mtime = current_mtime - logger("operators.py wurde automatisch neu geladen (Änderungen erkannt)") - -def random_connection(): - available_stations = config["stations"].copy() - while True: - if not available_stations: - logger("Keine validen Bahnhöfe. Schlag den richtigen Bahnhofsnamen auf {dbf} nach", "fatal") - - station = random.choice(available_stations) - url = f"{dbf}/{station}.json" - blacklist = config.get("blacklist", []) - - try: - response = requests.get(url) - response.raise_for_status() - data = response.json() - except requests.RequestException as e: - logger(f"Fehler beim aussuchen der Verbindung: {e}", "fatal") - return - - if response.status_code == 300: - logger(f"Bahnhof '{station}' konnte nicht gefunden werden ({url})", "error") - available_stations.remove(station) - continue - - departures = [ - d for d in data.get("departures", []) - if d.get("scheduledDeparture") and d.get("destination") != station - and not d.get("train", "").startswith(tuple(blacklist)) - ] - - if not departures: - continue - - if not config['random']: - dep = departures[0] - else: - dep = random.choice(departures) - - return { - "train": dep['train'], - "destination": dep['destination'], - "route": dep['route'], - "departure": dep['scheduledDeparture'], - "via": dep['via'], - "station": station, - "train_number": dep['trainNumber'] - } - -def get_train_info(station, train_ID, train_type): - url = f"{dbf}/z/{train_type}%20{train_ID}/{station}.json" - logger(f"Fetche {url}") - try: - response = requests.get(url) - response.raise_for_status() - data = response.json() - except requests.RequestException as e: - logger(f"ReqestException Fehler: {e}") - return None - - dep = data.get("departure", []) - if not dep: - logger("Kein departure Feld gefunden", "error") - return None - - route_post = dep.get("route_post_diff") - if not route_post: - logger("Kein route_post_diff Feld gefunden", "error") - return None - - arrival_iso = route_post[-1].get("sched_arr") - if not arrival_iso: - logger("Keine Ankunftszeit gefunden", "error") - return None - - return { - "arrival": arrival_iso, - "operators": dep.get("operators"), - } - -def format_via_list(via: list[str]): - if not via: - return "" - if len(via) == 1: - return via[0] - return ", ".join(via[:-1]) + " und " + via[-1] - -def resolve_operator(operators): - if not operators: - return None - for op in operators: - if op in operators_module.OPERATOR_ALIASES or op in operators_module.OPERATORS: - return op - - return operators[0] - -def operator_metadata(operator): - _reload_operators_if_changed() - - if not operator: - return operators_module.OPERATORS["fallback"] - - if operator in operators_module.OPERATOR_ALIASES: - return operators_module.OPERATOR_ALIASES[operator] - - return operators_module.OPERATORS.get(operator, operators_module.OPERATORS["fallback"]) - -def get_channel_formatting(train_type): - formatting = config.get("formatting", "") - train_emoji = "" - - if config.get("emojis", True): - train_emoji = emojis.train_types.get(train_type) - if train_emoji is None: - train_emoji = emojis.emoji_list.get("Fallback", "") - - return f"{train_emoji}{formatting}" - -def logger(msg, log_type="info"): +def logger(msg, log_type="info") -> str: status = log_type.upper() current_time = datetime.now().strftime('%X') print(f"{current_time}: {status}: {msg}") From 8770d03bb6a74d9074aeea00f28a503f3c04ba3b Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 19:48:15 +0200 Subject: [PATCH 04/48] transitous rewrite: channel formatting --- src/api/transitous.py | 10 ++++++---- src/data/emojis.py | 21 +++++---------------- src/dc/handlers.py | 17 +++++++++++------ src/utils.py | 22 +++++++++++++++++++++- 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index 9908508..888e702 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -1,8 +1,7 @@ -import json import requests import random -from src.utils import logger, config +from src.utils import logger, config, get_train_name stations = config["stations"] blacklist = config["blacklist"] @@ -92,9 +91,12 @@ def get_trip_details(trip_id: str) -> dict: trip_to = legs["tripTo"]["name"] start_time = legs["startTime"] end_time = legs["endTime"] + mode = legs["mode"] + train_name = get_train_name(display_name, mode) + trip_details = { - "long_name": f"{display_name} nach {trip_to} von {trip_from}", + "long_name": f"{train_name} nach {trip_to} von {trip_from}", "short_name": display_name, "from": trip_from, "to": trip_to, @@ -103,7 +105,7 @@ def get_trip_details(trip_id: str) -> dict: "duration": legs["duration"], "start_time": start_time, "end_time": end_time, - "mode": legs["mode"], + "mode": mode, "stops": {} } diff --git a/src/data/emojis.py b/src/data/emojis.py index 566116b..79175bb 100644 --- a/src/data/emojis.py +++ b/src/data/emojis.py @@ -1,18 +1,7 @@ emoji_list = { - "Fallback": "🚉", - "Nahverkehr": "🚃", - "Höchstgeschwindigkeit": "🚄", - "Bus": "🚎" -} - -train_types = { # Unvollständig! - "ICE": emoji_list["Höchstgeschwindigkeit"], - "TGV": emoji_list["Höchstgeschwindigkeit"], - - "RE": emoji_list["Nahverkehr"], - "RB": emoji_list["Nahverkehr"], - "ARV": emoji_list["Nahverkehr"], - "BRB": emoji_list["Nahverkehr"], - - "Bus": emoji_list["Bus"] + "Fallback": "💺", + "BUS": "🚎", + "Tram": "🚈", + "REGIONAL_RAIL": "🚊", + "HIGHSPEED_RAIL": "🚅" } \ No newline at end of file diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 5d750ec..b22e348 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -1,8 +1,9 @@ import discord import asyncio +from datetime import datetime from src.api import transitous -from src.utils import logger +from src.utils import logger, channel_formatting _scheduled_task: asyncio.Task | None = None @@ -14,13 +15,17 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals trip_id = transitous.get_random_connection(station_id) trip = transitous.get_trip_details(trip_id) - train_name = trip["long_name"] - + arrival = datetime.fromisoformat(trip["end_time"]) + long_name = trip["long_name"] + print("-----------------") - logger(f"Umstieg: {train_name}") + logger(f"Umstieg: {long_name}, Ankunft: {arrival}") logger(f"Betreiber: {trip["agency"]}, Typ: {trip["mode"]}") - logger(f"Sprachkanal wird geändert, wenn nichts passiert bin ich im cooldown (warte einen moment!)") + logger(f"Versuche Namen zu ändern, wenn nichts passiert bin ich im cooldown... (warte bis zu 10min!)") + + formatting = channel_formatting(trip["mode"]) + await voice_channel.edit(name=f"{formatting}{long_name}") + await voice_channel.set_status(f"Ankunft um {arrival.strftime('%H:%M')}") - await voice_channel.edit(name=train_name) logger(f"Name geändert!") diff --git a/src/utils.py b/src/utils.py index 11d7f2c..640901b 100644 --- a/src/utils.py +++ b/src/utils.py @@ -2,6 +2,8 @@ import json import os from datetime import datetime +from src.data.emojis import emoji_list + with open("config.json", "r") as file: config = json.load(file) @@ -10,4 +12,22 @@ def logger(msg, log_type="info") -> str: current_time = datetime.now().strftime('%X') print(f"{current_time}: {status}: {msg}") if status == "FATAL": - os._exit(1) \ No newline at end of file + os._exit(1) + +def channel_formatting(mode: str) -> str: + formatting = config.get("formatting", "") + + if config.get("emojis", True): + emoji = emoji_list.get(mode) + if emoji is None: + emoji = emoji_list.get("Fallback") + + return f"{emoji}{formatting}" + +def get_train_name(train_name: str, mode: str) -> str: + if train_name.isdigit(): + train = f"{mode.capitalize()} {train_name}" + else: + train = train_name + + return train \ No newline at end of file From f2a686edca46a5b85b87396d221af6e9bf90c15f Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 20:06:04 +0200 Subject: [PATCH 05/48] transitous rewrite: fix tram emoji --- src/data/emojis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/emojis.py b/src/data/emojis.py index 79175bb..11bfe5f 100644 --- a/src/data/emojis.py +++ b/src/data/emojis.py @@ -1,7 +1,7 @@ emoji_list = { "Fallback": "💺", "BUS": "🚎", - "Tram": "🚈", + "TRAM": "🚈", "REGIONAL_RAIL": "🚊", "HIGHSPEED_RAIL": "🚅" } \ No newline at end of file From cf696df5f5986bd90af0a60125f17293dea32500 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 20:06:47 +0200 Subject: [PATCH 06/48] transitous rewrite: remove ID from some german regional trains the API gave a name like RB69 (IDNUMBERS) for RE and RB trains --- src/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils.py b/src/utils.py index 640901b..a714a64 100644 --- a/src/utils.py +++ b/src/utils.py @@ -27,6 +27,8 @@ def channel_formatting(mode: str) -> str: def get_train_name(train_name: str, mode: str) -> str: if train_name.isdigit(): train = f"{mode.capitalize()} {train_name}" + elif "(" in train_name: + train = train_name.split(" (")[0] else: train = train_name From 697a0f62184724676f778fcf78ad1e79ac7b0b9c Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 22:13:58 +0200 Subject: [PATCH 07/48] transitous rewrite: some minor info embed improvements --- main.py | 16 ++++++++++++++- src/api/transitous.py | 47 +++++++++++++++++++++++++++--------------- src/dc/commands.py | 7 +++++++ src/dc/embeds.py | 48 +++++++++++++++++++++++++++++++++++++++++++ src/dc/handlers.py | 9 ++++---- src/dc/helpers.py | 20 ++++++++++++++++-- src/utils.py | 30 ++++++++++++++++++++++++++- 7 files changed, 152 insertions(+), 25 deletions(-) create mode 100644 src/dc/commands.py create mode 100644 src/dc/embeds.py diff --git a/main.py b/main.py index 1f006b6..82acaf6 100644 --- a/main.py +++ b/main.py @@ -2,8 +2,10 @@ import discord from src.utils import config, logger from src.dc.handlers import rename_vc from src.dc.helpers import validate_channel +from src.dc.commands import setup_commands bot = discord.Bot(intents=discord.Intents.all()) +setup_commands(bot=bot) @bot.event async def on_ready(): @@ -17,4 +19,16 @@ async def on_ready(): try: bot.run(config["token"]) except: - logger("Feher peim parsen des tokens", "fatal") \ No newline at end of file + logger("Feher peim parsen des tokens", "fatal") + +''' +TODO +- Only choose connections in the future +- discord reconnection handling +- Automatic transfer +- discord status +- text announcements +- voice announcements +- improved error handling (retry connection) +- Footer Notice Slogangs +''' \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index 888e702..813b791 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -1,7 +1,8 @@ import requests import random +from datetime import datetime -from src.utils import logger, config, get_train_name +from src.utils import logger, config, get_train_name, convert_iso_string stations = config["stations"] blacklist = config["blacklist"] @@ -14,8 +15,8 @@ headers = { endpoint = "https://api.transitous.org" def get_random_stop_id() -> str: - stop = random.choice(stations) - req = f"{endpoint}/api/v1/geocode?text={stop}" + assigned_station = random.choice(stations) + req = f"{endpoint}/api/v1/geocode?text={assigned_station}" try: response = requests.get(req, headers=headers) @@ -26,7 +27,7 @@ def get_random_stop_id() -> str: return None if response.status_code == 404: - logger(f"Error finding station '{stop}'") + logger(f"Error finding station '{assigned_station}'") for entry in data: if entry.get("type") != "STOP": @@ -54,7 +55,8 @@ def get_random_connection(stop_id: str) -> str: return None trip_ids = [] - for entry in data.get("stopTimes", []): + stop_times = data.get("stopTimes", []) + for entry in stop_times: trip_id = entry["tripId"] if entry["mode"] in blacklist: continue @@ -71,9 +73,14 @@ def get_random_connection(stop_id: str) -> str: logger("Couldn't find any connection", "fatal") return None - return random.choice(trip_ids) + trip_id = random.choice(trip_id) + from_station = stop_times[0]["place"]["name"] + return { + "trip_id": random.choice(trip_ids), + "from_station": from_station + } -def get_trip_details(trip_id: str) -> dict: +def get_trip_details(trip_id: str, from_station: str) -> dict: req = f"{endpoint}/api/v2/trip?tripId={trip_id}" try: @@ -88,31 +95,37 @@ def get_trip_details(trip_id: str) -> dict: display_name = legs["displayName"] trip_from = legs["tripFrom"]["name"] - trip_to = legs["tripTo"]["name"] + goes_to = legs["tripTo"]["name"] start_time = legs["startTime"] end_time = legs["endTime"] mode = legs["mode"] + + departure = convert_iso_string(start_time) + arrival = convert_iso_string(end_time) train_name = get_train_name(display_name, mode) - trip_details = { - "long_name": f"{train_name} nach {trip_to} von {trip_from}", + "long_name": f"{train_name} nach {goes_to} von {from_station}", "short_name": display_name, - "from": trip_from, - "to": trip_to, + "from": from_station, + "to": goes_to, "agency": legs["agencyName"], "route_color": legs.get("routeColor"), "duration": legs["duration"], - "start_time": start_time, - "end_time": end_time, + "departure": departure, + "arrival": arrival, "mode": mode, "stops": {} } - trip_details["stops"][trip_from] = start_time + trip_details["stops"][trip_from] = departure for stop in legs["intermediateStops"]: - trip_details["stops"][stop["name"]] = stop["arrival"] - trip_details["stops"][trip_to] = end_time + arrival = convert_iso_string(stop["arrival"]) + trip_details["stops"][stop["name"]] = arrival + if stop.get("name") == from_station: + departure_time = stop["departure"] + trip_details["departure"] = convert_iso_string(departure_time) + trip_details["stops"][goes_to] = arrival return trip_details diff --git a/src/dc/commands.py b/src/dc/commands.py new file mode 100644 index 0000000..339e466 --- /dev/null +++ b/src/dc/commands.py @@ -0,0 +1,7 @@ +import discord +from src.dc.embeds import build_info_embed + +def setup_commands(bot: discord.Bot): + @bot.slash_command(description="Informationen über die aktuelle Fahrt") + async def info(ctx): + await ctx.respond(embed=build_info_embed()) \ No newline at end of file diff --git a/src/dc/embeds.py b/src/dc/embeds.py new file mode 100644 index 0000000..8b1973f --- /dev/null +++ b/src/dc/embeds.py @@ -0,0 +1,48 @@ +import discord +import random + +from src.utils import convert_iso_string, get_operator_metadata +from src.dc.helpers import format_timestamp_to_dc + +def build_embed_footer(mode: str, slogans): + footer_notice = f"Data provided by https://transitous.org • Typ: {mode}" + icon = "https://avatars.githubusercontent.com/u/24960008?s=60&v=4" + + if slogans is not None: + footer_text = f"{random.choice(slogans)} • {footer_notice}" + else: + footer_text = footer_notice + + return { + "text": footer_text, + "icon": icon + } + +def build_info_embed() -> discord.Embed: + from src.dc.handlers import trip + + agency = trip["agency"] + metadata = get_operator_metadata(agency, trip["route_color"]) + departure = format_timestamp_to_dc(trip["departure"]) + arrival = format_timestamp_to_dc(trip["arrival"]) + embed = discord.Embed( + title = trip["long_name"], + description=f"Abfahrt von {trip["from"]} um {departure}. Ankunft um {arrival}", + color = metadata["color"] + ) + + route_lines = [] + for stop_name, stop_arrival in trip["stops"].items(): + if stop_name == trip["from"]: + route_lines.append(f"**• {stop_name} ({stop_arrival} Uhr)**") + else: + route_lines.append(f"• {stop_name} ({stop_arrival} Uhr)") + embed.add_field(name="Route", value="\n".join(route_lines)) + + footer = build_embed_footer(trip["mode"], metadata["slogans"]) + embed.set_footer(text=footer["text"], icon_url=footer["icon"]) + + embed.set_author(name=agency) + embed.set_thumbnail(url=metadata["logo"]) + + return embed \ No newline at end of file diff --git a/src/dc/handlers.py b/src/dc/handlers.py index b22e348..6599691 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -8,14 +8,15 @@ from src.utils import logger, channel_formatting _scheduled_task: asyncio.Task | None = None async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = False): + global trip if not from_scheduler and _scheduled_task and not _scheduled_task.done(): _scheduled_task.cancel() station_id = transitous.get_random_stop_id() - trip_id = transitous.get_random_connection(station_id) - trip = transitous.get_trip_details(trip_id) + connection = transitous.get_random_connection(station_id) + trip = transitous.get_trip_details(connection["trip_id"], connection["from_station"]) - arrival = datetime.fromisoformat(trip["end_time"]) + arrival = trip["arrival"] long_name = trip["long_name"] print("-----------------") @@ -25,7 +26,7 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals formatting = channel_formatting(trip["mode"]) await voice_channel.edit(name=f"{formatting}{long_name}") - await voice_channel.set_status(f"Ankunft um {arrival.strftime('%H:%M')}") + await voice_channel.set_status(f"Ankunft um {arrival}") logger(f"Name geändert!") diff --git a/src/dc/helpers.py b/src/dc/helpers.py index c364db3..cf1c7a8 100644 --- a/src/dc/helpers.py +++ b/src/dc/helpers.py @@ -1,5 +1,6 @@ import discord -from src.utils import logger +from datetime import datetime, timedelta +from src.utils import logger, convert_iso_string def validate_channel(bot: discord.bot, server_id: int, channel_id: int): guild = bot.get_guild(server_id) @@ -12,4 +13,19 @@ def validate_channel(bot: discord.bot, server_id: int, channel_id: int): logger(f"Es konnte kein VC mit der id {channel_id} gefunden werden", "fatal") return False - return channel \ No newline at end of file + return channel + +def format_timestamp_to_dc(timestr): + parsed_time = datetime.strptime(timestr, "%H:%M") + now = datetime.now() + final_datetime = datetime.now().replace( + hour=parsed_time.hour, + minute=parsed_time.minute, + second=0, + microsecond=0 + ) + + if final_datetime <= now: + final_datetime += timedelta(days=1) + + return discord.utils.format_dt(final_datetime, style="t") \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index a714a64..13f2832 100644 --- a/src/utils.py +++ b/src/utils.py @@ -2,8 +2,10 @@ import json import os from datetime import datetime +import src.data.operators as operators from src.data.emojis import emoji_list + with open("config.json", "r") as file: config = json.load(file) @@ -14,6 +16,10 @@ def logger(msg, log_type="info") -> str: if status == "FATAL": os._exit(1) +def convert_iso_string(isostring) -> str: + datetime_isostring = datetime.fromisoformat(isostring) + return datetime_isostring.strftime('%H:%M') + def channel_formatting(mode: str) -> str: formatting = config.get("formatting", "") @@ -32,4 +38,26 @@ def get_train_name(train_name: str, mode: str) -> str: else: train = train_name - return train \ No newline at end of file + return train + +def get_operator_metadata(agency: str, route_color: str) -> dict: + op_data = operators.OPERATOR_ALIASES.get(agency) or operators.OPERATORS.get(agency) or operators.OPERATORS["fallback"] + + logo = op_data.get("logo", operators.OPERATORS["fallback"]["logo"]) + slogans = op_data.get("slogans") + + color = op_data.get("color") + if color is None: + if route_color is not None: + try: + color = int(f"0x{route_color.upper()}") + except ValueError: + color = operators.OPERATORS["fallback"]["color"] + else: + color = operators.OPERATORS["fallback"]["colors"] + + return { + "logo": logo, + "color": color, + "slogans": slogans + } \ No newline at end of file From 46fe9eb61eedb27a6e67383814035d9fb5cf2c15 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 22:55:57 +0200 Subject: [PATCH 08/48] transitous rewrite: bug fixes in the info embed --- .gitignore | 2 + bruno/Gleiswechsel-API/.gitignore | 9 - .../Gleiswechsel-API/Geocode München HBF.yml | 29 - .../Stoptimes for Station.yml | 32 - bruno/Gleiswechsel-API/Trip Details.yml | 22 - .../environments/Transitous API.yml | 6 - bruno/Gleiswechsel-API/opencollection.yml | 10 - main.py | 2 +- src/api/transitous.py | 19 +- src/commands.py | 12 - src/config.py | 4 - src/data/emojis.py | 4 +- src/dc/embeds.py | 2 + src/embeds.py | 109 --- src/handlers.py | 154 ---- src/utils.py | 9 +- wtf.json | 827 ++++++++++++++++++ 17 files changed, 853 insertions(+), 399 deletions(-) delete mode 100644 bruno/Gleiswechsel-API/.gitignore delete mode 100644 bruno/Gleiswechsel-API/Geocode München HBF.yml delete mode 100644 bruno/Gleiswechsel-API/Stoptimes for Station.yml delete mode 100644 bruno/Gleiswechsel-API/Trip Details.yml delete mode 100644 bruno/Gleiswechsel-API/environments/Transitous API.yml delete mode 100644 bruno/Gleiswechsel-API/opencollection.yml delete mode 100644 src/commands.py delete mode 100644 src/config.py delete mode 100644 src/embeds.py delete mode 100644 src/handlers.py create mode 100644 wtf.json diff --git a/.gitignore b/.gitignore index 7d67f13..e337bbc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ __pycache__/ src/data/announcements/* !src/data/announcements/.gitkeep config.json +src/legacy/ +main_legacy.py \ No newline at end of file diff --git a/bruno/Gleiswechsel-API/.gitignore b/bruno/Gleiswechsel-API/.gitignore deleted file mode 100644 index e19311f..0000000 --- a/bruno/Gleiswechsel-API/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Secrets -.env* - -# Dependencies -node_modules - -# OS files -.DS_Store -Thumbs.db \ No newline at end of file diff --git a/bruno/Gleiswechsel-API/Geocode München HBF.yml b/bruno/Gleiswechsel-API/Geocode München HBF.yml deleted file mode 100644 index 865c048..0000000 --- a/bruno/Gleiswechsel-API/Geocode München HBF.yml +++ /dev/null @@ -1,29 +0,0 @@ -info: - name: Geocode München HBF - type: http - seq: 1 - -http: - method: GET - url: https://api.transitous.org/api/v1/geocode?text=München Hbf - headers: - - name: User-Agent - value: Gleiswechsel-Discord-Bot - params: - - name: text - value: München Hbf - type: query - auth: inherit - -runtime: - scripts: - - type: after-response - code: |- - const data = res.getBody(); - bru.setEnvVar("stop_id", data[0].id); - -settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 diff --git a/bruno/Gleiswechsel-API/Stoptimes for Station.yml b/bruno/Gleiswechsel-API/Stoptimes for Station.yml deleted file mode 100644 index 29a2ef7..0000000 --- a/bruno/Gleiswechsel-API/Stoptimes for Station.yml +++ /dev/null @@ -1,32 +0,0 @@ -info: - name: Stoptimes for Station - type: http - seq: 3 - -http: - method: GET - url: https://api.transitous.org/api/v1/stoptimes?stopId={{stop_id}}&n=10 - headers: - - name: User-Agent - value: Gleiswechsel-Discord-Bot - params: - - name: stopId - value: "{{stop_id}}" - type: query - - name: n - value: "10" - type: query - auth: inherit - -runtime: - scripts: - - type: after-response - code: |- - const data = res.getBody(); - bru.setEnvVar("trip_id", data.stopTimes[0].tripId); - -settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 diff --git a/bruno/Gleiswechsel-API/Trip Details.yml b/bruno/Gleiswechsel-API/Trip Details.yml deleted file mode 100644 index 1d45b12..0000000 --- a/bruno/Gleiswechsel-API/Trip Details.yml +++ /dev/null @@ -1,22 +0,0 @@ -info: - name: Trip Details - type: http - seq: 4 - -http: - method: GET - url: https://api.transitous.org/api/v2/trip?tripId={{trip_id}} - headers: - - name: User-Agent - value: Gleiswechsel-Discord-Bot - params: - - name: tripId - value: "{{trip_id}}" - type: query - auth: inherit - -settings: - encodeUrl: true - timeout: 0 - followRedirects: true - maxRedirects: 5 diff --git a/bruno/Gleiswechsel-API/environments/Transitous API.yml b/bruno/Gleiswechsel-API/environments/Transitous API.yml deleted file mode 100644 index 0662ac7..0000000 --- a/bruno/Gleiswechsel-API/environments/Transitous API.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: Transitous API -variables: - - name: stop_id - value: at-Railway-Current-Reference-Data-2026_de:09162:100:11:11 - - name: trip_id - value: 20260815_11:52_de-DELFI_3338623109 diff --git a/bruno/Gleiswechsel-API/opencollection.yml b/bruno/Gleiswechsel-API/opencollection.yml deleted file mode 100644 index 43d1edd..0000000 --- a/bruno/Gleiswechsel-API/opencollection.yml +++ /dev/null @@ -1,10 +0,0 @@ -opencollection: 1.0.0 - -info: - name: Gleiswechsel-API -bundled: false -extensions: - bruno: - ignore: - - node_modules - - .git diff --git a/main.py b/main.py index 82acaf6..2de3078 100644 --- a/main.py +++ b/main.py @@ -30,5 +30,5 @@ TODO - text announcements - voice announcements - improved error handling (retry connection) -- Footer Notice Slogangs +- multi language support ''' \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index 813b791..6abe4a0 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -1,6 +1,6 @@ import requests import random -from datetime import datetime +import json from src.utils import logger, config, get_train_name, convert_iso_string @@ -73,10 +73,15 @@ def get_random_connection(stop_id: str) -> str: logger("Couldn't find any connection", "fatal") return None - trip_id = random.choice(trip_id) - from_station = stop_times[0]["place"]["name"] + trip_id = random.choice(trip_ids) + for trip in stop_times: + if trip.get("tripId") == trip_id: + from_station = trip.get("place").get("name") + break + + print(from_station) return { - "trip_id": random.choice(trip_ids), + "trip_id": trip_id, "from_station": from_station } @@ -85,7 +90,7 @@ def get_trip_details(trip_id: str, from_station: str) -> dict: try: response = requests.get(req, headers=headers) - response.raise_for_status + response.raise_for_status() data = response.json() except requests.RequestException as e: logger(f"An error occured while trying to get the route details: {e}", "fatal") @@ -120,8 +125,8 @@ def get_trip_details(trip_id: str, from_station: str) -> dict: trip_details["stops"][trip_from] = departure for stop in legs["intermediateStops"]: - arrival = convert_iso_string(stop["arrival"]) - trip_details["stops"][stop["name"]] = arrival + stop_arrival = convert_iso_string(stop["arrival"]) + trip_details["stops"][stop["name"]] = stop_arrival if stop.get("name") == from_station: departure_time = stop["departure"] trip_details["departure"] = convert_iso_string(departure_time) diff --git a/src/commands.py b/src/commands.py deleted file mode 100644 index 67298c3..0000000 --- a/src/commands.py +++ /dev/null @@ -1,12 +0,0 @@ -import discord -from discord.ext import commands -from src.embeds import build_info_embed, build_error_embed - -def setup_commands(bot: discord.Bot): - @bot.slash_command(description="Informationen über die aktuelle Fahrt") - async def info(ctx): - embed = build_info_embed() - if embed is None: - await build_error_embed("Noch keine Verbindung gesetzt.") - return - await ctx.respond(embed=embed) diff --git a/src/config.py b/src/config.py deleted file mode 100644 index 45d45c1..0000000 --- a/src/config.py +++ /dev/null @@ -1,4 +0,0 @@ -import json - -with open("config.json", "r") as file: - config = json.load(file) \ No newline at end of file diff --git a/src/data/emojis.py b/src/data/emojis.py index 11bfe5f..22fafcc 100644 --- a/src/data/emojis.py +++ b/src/data/emojis.py @@ -3,5 +3,7 @@ emoji_list = { "BUS": "🚎", "TRAM": "🚈", "REGIONAL_RAIL": "🚊", - "HIGHSPEED_RAIL": "🚅" + "HIGHSPEED_RAIL": "🚅", + "METRO": "🚇", + "SUBWAY": "🚇" } \ No newline at end of file diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 8b1973f..6ffa2ee 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -45,4 +45,6 @@ def build_info_embed() -> discord.Embed: embed.set_author(name=agency) embed.set_thumbnail(url=metadata["logo"]) + color = trip.get("color", "keine farbe :(") + print(color) return embed \ No newline at end of file diff --git a/src/embeds.py b/src/embeds.py deleted file mode 100644 index 2097669..0000000 --- a/src/embeds.py +++ /dev/null @@ -1,109 +0,0 @@ -import random -import discord -from datetime import datetime, timedelta -import src.handlers as handlers -from src.config import config -from src.utils import operator_metadata, format_via_list, resolve_operator, logger - -def format_timestamp(timestr): - parsed_time = datetime.strptime(timestr, "%H:%M") - now = datetime.now() - final_datetime = datetime.now().replace( - hour=parsed_time.hour, - minute=parsed_time.minute, - second=0, - microsecond=0 - ) - - if final_datetime <= now: - final_datetime += timedelta(days=1) - - return discord.utils.format_dt(final_datetime, style="t") - -def format_iso_timestamp(isostr): - parsed_time = discord.utils.parse_time(isostr) - return discord.utils.format_dt(parsed_time, style="t") - -def build_embed_footer(operator_slogans): - dbf = config.get("dbf", "https://dbf.finalrewind.org") - footer_notice = f"Daten großzügig bereitgestellt von {dbf} • Typ: {handlers.train_type}" - footer_text = ( - f"{random.choice(operator_slogans)} • {footer_notice}" - if operator_slogans else - footer_notice - ) - icon = f"{dbf}/static/icons/icon-96x96.png" - return { - "text": footer_text, - "icon": icon - } - -def build_info_embed() -> discord.Embed | None: - conn = handlers.current - info = handlers.train_info - - if handlers.current is None and handlers.train_info is None: - return None - - current_operator = resolve_operator(info["operators"]) - arrival = format_iso_timestamp(info["arrival"]) - departure = format_timestamp(conn['departure']) - - operator_infos = operator_metadata(current_operator) - - embed = discord.Embed( - title=handlers.train_name, - description=f"Abfahrt von {conn['station']} um {departure}. Ankunft um {arrival}", - color=operator_infos["color"] - ) - - if len(conn['via']) > 0: - embed.add_field(name="Über", value=format_via_list(conn['via']), inline=False) - - if operator_infos.get("unknown"): - logger(f"Metadaten für {current_operator} konten in operators.py nicht gefunden werden") - - embed.set_author(name=current_operator) - embed.set_thumbnail(url=operator_infos["logo"]) - - route_lines = [] - for stop in conn['route']: - stop_name = stop["name"] - if stop_name == conn['station']: - route_lines.append(f"• **{stop_name}**") - else: - route_lines.append(f"• {stop_name}") - - embed.add_field(name="Route", value="\n".join(route_lines)) - - footer = build_embed_footer(operator_infos.get("slogan")) - embed.set_footer(text=footer["text"], icon_url=footer["icon"]) - - return embed - -def build_announcement_embed(msg): - current_operator = resolve_operator(handlers.train_info["operators"]) - operator_infos = operator_metadata(current_operator) - - embed = discord.Embed( - title = "Informationen zu Ihrer Fahrt", - description=msg, - color=operator_infos["color"] - ) - - embed.set_author(name=current_operator) - embed.set_thumbnail(url=operator_infos["logo"]) - - footer = build_embed_footer(operator_infos.get("slogan")) - embed.set_footer(text=footer["text"], icon_url=footer["icon"]) - - return embed - -def build_error_embed(errormsg) -> discord.Embed: - embed = discord.Embed( - title="Ein Fehler ist aufgetreten!", - description=errormsg, - color=discord.Colour.red() - ) - - return embed \ No newline at end of file diff --git a/src/handlers.py b/src/handlers.py deleted file mode 100644 index 57a058e..0000000 --- a/src/handlers.py +++ /dev/null @@ -1,154 +0,0 @@ -import discord -from datetime import datetime, timedelta -import asyncio -import random -from pathlib import Path - -from src.config import config -from src.utils import random_connection, get_train_info, get_channel_formatting, logger -from src.embeds import build_announcement_embed, build_info_embed - -current = None -_scheduled_task: asyncio.Task | None = None - -async def announcer(bot, announcement): - voice_channel = bot.get_channel(config["vc"]) - if len(voice_channel.members) > 0: - match announcement: - case "ende": - destination = current['destination'] - embed = build_announcement_embed( - f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für Ihr Vertrauen und auf Wiedersehen.') - if config["voice_announcements"][0]["enabled"]: - await voice_announcer(bot, destination, voice_channel) - case "umstieg": - embed = build_info_embed() - case _: - embed = None - if embed is None: - logger(f"Unbekanntes Announcement: {announcement}") - else: - await voice_channel.send(embed=embed) - else: - logger(f"Announcement {announcement} wird geskipped, keiner da") - return - -async def voice_announcer(bot: discord.Bot, destination, voice_channel): - voice_announcement_config = config["voice_announcements"][0] - voice_stations = voice_announcement_config["stations"] - - if destination in voice_stations: - announcement_for = destination - else: - if voice_stations.get("general", "") == "": - return - announcement_for = "general" - - if voice_stations.values() == list: - sound_file = random.choice(voice_stations.get(announcement_for)) - else: - sound_file = voice_stations.get(announcement_for) - - sound_path = f"src/data/announcements/{sound_file}" - if Path(sound_path).is_file() is False: - logger(f"Konnte Datei {sound_path} nicht finden", "error") - return - - logger(f"VC wird betreten, spiele {sound_path}") - vc = await voice_channel.connect(timeout=15, reconnect=True) - audio_source = discord.FFmpegPCMAudio(sound_path) - - if not vc.is_playing(): - def after_playing(error): - if error: - logger(f"Player error: {error}", "error") - bot.loop.create_task(vc.disconnect()) - logger("VC wird verlassen") - - vc.play(audio_source, after=after_playing) - -async def rename_vc(bot: discord.Bot, from_scheduler: bool = False): - global current, train_name, train_info, train_type, _scheduled_task - - guild = bot.get_guild(int(config["server"])) - if guild is None: - logger(f"Es konnte kein Server mit der ID {config['server']} gefunden werden! Ist der Bot ein Member?", "fatal") - return False - - channel = guild.get_channel(int(config["vc"])) - if not isinstance(channel, discord.VoiceChannel): - logger(f"Es konnte kein VC mit der ID {config['vc']} auf dem Server gefunden werden", "fatal") - return False - - if not from_scheduler and _scheduled_task and not _scheduled_task.done(): - _scheduled_task.cancel() - - attempt = 0 - while True: - if attempt == 20: - logger("Zu viele Fehlversuche. Füge einen anderen Bahnhof hinzu.", "fatal") - return "Es konnte kein Zug gefunden werden." - - attempt += 1 - current = random_connection() - if current == None: - return None - - parts = current['train'].split() - train_type = parts[0] - - if parts[1].isdigit(): - train = current['train'] - train_ID = parts[1] - else: - train = parts[1] - train_ID = current['train_number'] - - station = current['station'] - train_info = get_train_info(station=station, train_ID=train_ID, train_type=train_type) - if train_info and train_info.get('operators') and train_info.get('arrival'): - break - - logger(f"Versuch {attempt}: Fehler bei {current['train']} von {station}, versuche neue Verbindung...") - - train_name = f"{train} nach {current['destination']} von {current['station']}" - logger(f"Vorbereitung auf {train_name} (typ: {train_type})") - arrival = datetime.fromisoformat((train_info["arrival"])) - formatting = get_channel_formatting(train_type) - - - print("-----------------------------------------") - logger(f"Umstieg: {train_name}") - logger(f"Betreiber: {''.join(train_info['operators'])}") - logger(f"Train-Type: {train_type}") - logger(f"Wenn der Name nicht geändert wird bin ich im Cooldown") - await channel.edit(name=f"{formatting}{train_name}") - await channel.set_status(f"Ankunft um {arrival.strftime('%H:%M')}") - logger(f"Name geändert!") - - if config.get("announcements", True): - await announcer(bot, "umstieg") - - _scheduled_task = asyncio.create_task(_schedule_next_umstieg(bot, arrival)) - - return True - -async def _schedule_next_umstieg(bot, arrival): - announcement = config.get("announcements", True) - announcement_countdown = random.randrange(180, 300) # letzte station announcement ist meistens 3-5min vor ankunft - wait_seconds = (arrival - datetime.now()).total_seconds() - if wait_seconds > 0: - remaining = str(timedelta(seconds=wait_seconds)) - logger(f"Nächster Umstieg in {remaining.split('.')[0]} ({arrival.strftime('%H:%M:%S')} Uhr)") - - if announcement and wait_seconds > announcement_countdown: - wait_until_end_announcement = wait_seconds - announcement_countdown - await asyncio.sleep(wait_until_end_announcement) - await announcer(bot, "ende") - await asyncio.sleep(announcement_countdown) - - else: - await asyncio.sleep(wait_seconds) - - logger("Zug angekommen, wähle neue Verbindung...") - await rename_vc(bot, from_scheduler=True) \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index 13f2832..8c82ed4 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,6 +1,6 @@ import json import os -from datetime import datetime +from datetime import datetime, timedelta import src.data.operators as operators from src.data.emojis import emoji_list @@ -17,8 +17,11 @@ def logger(msg, log_type="info") -> str: os._exit(1) def convert_iso_string(isostring) -> str: - datetime_isostring = datetime.fromisoformat(isostring) - return datetime_isostring.strftime('%H:%M') + dt = datetime.fromisoformat(isostring.replace('Z', '+00:00')) + if dt.second >= 30: + dt += timedelta(minutes=1) + + return dt.strftime('%H:%M') def channel_formatting(mode: str) -> str: formatting = config.get("formatting", "") diff --git a/wtf.json b/wtf.json new file mode 100644 index 0000000..089f239 --- /dev/null +++ b/wtf.json @@ -0,0 +1,827 @@ +{ + "duration": 3240, + "startTime": "2026-08-15T20:16:00Z", + "endTime": "2026-08-15T21:10:00Z", + "transfers": 0, + "id": "CqEBCgIxMhIiMjAyNjA4MTVfMjI6MTZfZGUtREVMRklfMzMwNTA4MDkwNhofZGUtREVMRklfZGU6MDIwMDA6MTAwNTY6OjEwMDAxOSH0ona/CsZKQClzRSkhWB0kQDIfZGUtREVMRklfZGU6MDIwMDA6ODAwMDU6OjgwMDA1NDk1e6AVGMZKQEGc/1cdObojQEiAkoPUBlCwqoPUBloDQlVTYAE=", + "legs": [ + { + "mode": "BUS", + "from": { + "name": "Osterbrookplatz", + "stopId": "de-DELFI_de:02000:10056::100019", + "importance": 0.00038864786620251834, + "lat": 53.547202999999996, + "lon": 10.057312999999999, + "level": 0.0, + "tz": "Europe/Berlin", + "departure": "2026-08-15T20:16:00Z", + "scheduledDeparture": "2026-08-15T20:16:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 100017", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + "to": { + "name": "Teufelsbr\u00fcck (F\u00e4hre)", + "stopId": "de-DELFI_de:02000:80005::800054", + "importance": 0.001101788366213441, + "lat": 53.54761, + "lon": 9.863717000000001, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:10:00Z", + "scheduledArrival": "2026-08-15T21:08:00Z", + "scheduledTrack": "5", + "track": "5", + "description": "VHH 800019", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + "duration": 3240, + "startTime": "2026-08-15T20:16:00Z", + "endTime": "2026-08-15T21:10:00Z", + "scheduledStartTime": "2026-08-15T20:16:00Z", + "scheduledEndTime": "2026-08-15T21:08:00Z", + "realTime": true, + "scheduled": true, + "interlineWithPreviousLeg": false, + "headsign": "Teufelsbr\u00fcck (F\u00e4hre)", + "tripFrom": { + "name": "Osterbrookplatz", + "stopId": "de-DELFI_de:02000:10056::100019", + "importance": 0.00038864786620251834, + "lat": 53.547202999999996, + "lon": 10.057312999999999, + "level": 0.0, + "tz": "Europe/Berlin", + "departure": "2026-08-15T20:16:00Z", + "scheduledDeparture": "2026-08-15T20:16:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 100017", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + "tripTo": { + "name": "Teufelsbr\u00fcck (F\u00e4hre)", + "stopId": "de-DELFI_de:02000:80005::800054", + "importance": 0.001101788366213441, + "lat": 53.54761, + "lon": 9.863717000000001, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:10:00Z", + "scheduledArrival": "2026-08-15T21:08:00Z", + "scheduledTrack": "5", + "track": "5", + "description": "VHH 800019", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + "routeId": "de-DELFI_de:hvv:12:_3", + "routeUrl": "", + "directionId": "1", + "routeColor": "ca3d2a", + "routeTextColor": "ffffff", + "routeType": 3, + "agencyName": "Hochbahn Bus", + "agencyUrl": "", + "agencyFareUrl": "", + "agencyId": "15140", + "tripId": "20260815_22:16_de-DELFI_3305080906", + "routeShortName": "12", + "routeLongName": "", + "tripShortName": "1200086", + "displayName": "12", + "cancelled": false, + "source": "de_DELFI.gtfs.zip/stop_times.txt:33330623:33330654", + "intermediateStops": [ + { + "name": "Schadesweg", + "stopId": "de-DELFI_de:02000:10042::100197", + "importance": 0.00038864786620251834, + "lat": 53.547714, + "lon": 10.05187, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:17:00Z", + "departure": "2026-08-15T20:17:00Z", + "scheduledArrival": "2026-08-15T20:17:00Z", + "scheduledDeparture": "2026-08-15T20:17:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 100196", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Luisenweg", + "stopId": "de-DELFI_de:02000:10041::100224", + "importance": 0.00038864786620251834, + "lat": 53.548298, + "lon": 10.046362999999998, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:18:00Z", + "departure": "2026-08-15T20:18:00Z", + "scheduledArrival": "2026-08-15T20:18:00Z", + "scheduledDeparture": "2026-08-15T20:18:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 100195", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Ausschl\u00e4ger Weg (LBV)", + "stopId": "de-DELFI_de:02000:10040::100181", + "importance": 0.001163465902209282, + "lat": 53.547276, + "lon": 10.037443, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:22:00Z", + "departure": "2026-08-15T20:22:00Z", + "scheduledArrival": "2026-08-15T20:20:00Z", + "scheduledDeparture": "2026-08-15T20:20:00Z", + "scheduledTrack": "1", + "track": "1", + "description": "HHA-B 100181", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "S\u00fcderstra\u00dfe", + "stopId": "de-DELFI_de:02000:10039::100172", + "importance": 0.0010683928849175572, + "lat": 53.545147, + "lon": 10.029789000000001, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:22:00Z", + "departure": "2026-08-15T20:22:00Z", + "scheduledArrival": "2026-08-15T20:21:00Z", + "scheduledDeparture": "2026-08-15T20:21:00Z", + "scheduledTrack": "3", + "track": "3", + "description": "HHA-B 100164", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "S Hammerbrook (S\u00fcd)", + "stopId": "de-DELFI_de:02000:10038::100207", + "importance": 0.0006706778658553958, + "lat": 53.54553200000001, + "lon": 10.024811999999999, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:24:00Z", + "departure": "2026-08-15T20:24:00Z", + "scheduledArrival": "2026-08-15T20:22:00Z", + "scheduledDeparture": "2026-08-15T20:22:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "SBAHNS 3921901", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "S Hammerbrook (Nord)", + "stopId": "de-DELFI_de:02000:10060::100030", + "importance": 0.00039489471237175167, + "lat": 53.547832, + "lon": 10.02298, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:25:00Z", + "departure": "2026-08-15T20:25:00Z", + "scheduledArrival": "2026-08-15T20:23:00Z", + "scheduledDeparture": "2026-08-15T20:23:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 100029", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Albertstra\u00dfe", + "stopId": "de-DELFI_000011005802", + "importance": 0.00039489471237175167, + "lat": 53.54898, + "lon": 10.019054, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:26:00Z", + "departure": "2026-08-15T20:26:00Z", + "scheduledArrival": "2026-08-15T20:24:00Z", + "scheduledDeparture": "2026-08-15T20:24:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 100026", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Repsoldstra\u00dfe", + "stopId": "de-DELFI_000011005702", + "importance": 0.00039489471237175167, + "lat": 53.54862, + "lon": 10.013898, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:28:00Z", + "departure": "2026-08-15T20:28:00Z", + "scheduledArrival": "2026-08-15T20:26:00Z", + "scheduledDeparture": "2026-08-15T20:26:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 100020", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "U Steinstra\u00dfe (Deichtorplatz)", + "stopId": "de-DELFI_de:02000:10024::100050", + "importance": 0.0013284930028021336, + "lat": 53.548954, + "lon": 10.006442000000002, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:30:00Z", + "departure": "2026-08-15T20:30:00Z", + "scheduledArrival": "2026-08-15T20:28:00Z", + "scheduledDeparture": "2026-08-15T20:28:00Z", + "scheduledTrack": "3", + "track": "3", + "description": "HHA-B 100033", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "HBF/Spitalerstra\u00dfe", + "stopId": "de-DELFI_de:02000:10011::100133", + "importance": 0.2917599081993103, + "lat": 53.552642999999996, + "lon": 10.005606000000002, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:32:00Z", + "departure": "2026-08-15T20:32:00Z", + "scheduledArrival": "2026-08-15T20:30:00Z", + "scheduledDeparture": "2026-08-15T20:30:00Z", + "scheduledTrack": "1", + "track": "1", + "description": "HHA-B 100133", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "HIGHSPEED_RAIL", + "LONG_DISTANCE", + "COACH", + "NIGHT_RAIL", + "REGIONAL_RAIL", + "SUBURBAN", + "SUBWAY", + "BUS" + ] + }, + { + "name": "Kunsthalle", + "stopId": "de-DELFI_000011103302", + "importance": 0.0003962125920224935, + "lat": 53.555546, + "lon": 10.001356999999999, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:35:00Z", + "departure": "2026-08-15T20:35:00Z", + "scheduledArrival": "2026-08-15T20:33:00Z", + "scheduledDeparture": "2026-08-15T20:33:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 100213", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "U Stephansplatz", + "stopId": "de-DELFI_de:02000:11013:1:110071", + "importance": 0.0023285001516342163, + "lat": 53.558370000000004, + "lon": 9.98852, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:38:00Z", + "departure": "2026-08-15T20:38:00Z", + "scheduledArrival": "2026-08-15T20:36:00Z", + "scheduledDeparture": "2026-08-15T20:36:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 110071", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Johannes-Brahms-Platz", + "stopId": "de-DELFI_de:02000:11009:1:110056", + "importance": 0.0004172989574726671, + "lat": 53.555110000000006, + "lon": 9.978620999999999, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:40:00Z", + "departure": "2026-08-15T20:40:00Z", + "scheduledArrival": "2026-08-15T20:38:00Z", + "scheduledDeparture": "2026-08-15T20:38:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 110056", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Handwerkskammer", + "stopId": "de-DELFI_de:02000:11008::110054", + "importance": 0.0004172989574726671, + "lat": 53.55314, + "lon": 9.976393, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:41:00Z", + "departure": "2026-08-15T20:41:00Z", + "scheduledArrival": "2026-08-15T20:39:00Z", + "scheduledDeparture": "2026-08-15T20:39:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 110053", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Museum f\u00fcr Hamburgische Geschichte", + "stopId": "de-DELFI_de:02000:11007::110052", + "importance": 0.0004172989574726671, + "lat": 53.55146799999999, + "lon": 9.974794000000001, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:42:00Z", + "departure": "2026-08-15T20:42:00Z", + "scheduledArrival": "2026-08-15T20:40:00Z", + "scheduledDeparture": "2026-08-15T20:40:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 110051", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "U St. Pauli", + "stopId": "de-DELFI_de:02000:80017:3:800037", + "importance": 0.0012117273872718215, + "lat": 53.550117, + "lon": 9.969799000000002, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:45:00Z", + "departure": "2026-08-15T20:45:00Z", + "scheduledArrival": "2026-08-15T20:43:00Z", + "scheduledDeparture": "2026-08-15T20:43:00Z", + "scheduledTrack": "3", + "track": "3", + "description": "HHA-B 800037", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Davidstra\u00dfe", + "stopId": "de-DELFI_de:02000:80018:2:800039", + "importance": 0.001252002315595746, + "lat": 53.549583, + "lon": 9.961643, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:48:00Z", + "departure": "2026-08-15T20:48:00Z", + "scheduledArrival": "2026-08-15T20:46:00Z", + "scheduledDeparture": "2026-08-15T20:46:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 800033", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "S Reeperbahn", + "stopId": "de-DELFI_de:02000:80019:2:800041", + "importance": 0.0014315921580418944, + "lat": 53.549746999999996, + "lon": 9.954717, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:52:00Z", + "departure": "2026-08-15T20:52:00Z", + "scheduledArrival": "2026-08-15T20:50:00Z", + "scheduledDeparture": "2026-08-15T20:50:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 800031", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Bl\u00fccherstra\u00dfe", + "stopId": "de-DELFI_de:02000:80107::800356", + "importance": 0.0009377760579809546, + "lat": 53.549186999999996, + "lon": 9.949956, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:53:00Z", + "departure": "2026-08-15T20:53:00Z", + "scheduledArrival": "2026-08-15T20:51:00Z", + "scheduledDeparture": "2026-08-15T20:51:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 800356", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Gro\u00dfe Bergstra\u00dfe", + "stopId": "de-DELFI_de:02000:80023:2:800323", + "importance": 0.0009272329043596983, + "lat": 53.551525, + "lon": 9.946254999999999, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:55:00Z", + "departure": "2026-08-15T20:55:00Z", + "scheduledArrival": "2026-08-15T20:53:00Z", + "scheduledDeparture": "2026-08-15T20:53:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 800323", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Goethestra\u00dfe", + "stopId": "de-DELFI_de:02000:80024::800082", + "importance": 0.0004593530611600727, + "lat": 53.55199399999999, + "lon": 9.940056, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:56:00Z", + "departure": "2026-08-15T20:56:00Z", + "scheduledArrival": "2026-08-15T20:54:00Z", + "scheduledDeparture": "2026-08-15T20:54:00Z", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Bf. Altona", + "stopId": "de-DELFI_de:02000:80026::800091", + "importance": 0.00639944477006793, + "lat": 53.551548, + "lon": 9.934171999999998, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:58:00Z", + "departure": "2026-08-15T20:58:00Z", + "scheduledArrival": "2026-08-15T20:56:00Z", + "scheduledDeparture": "2026-08-15T20:56:00Z", + "scheduledTrack": "5", + "track": "5", + "description": "VHH 800096", + "vertexType": "TRANSIT", + "pickupType": "NOT_ALLOWED", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Bf. Altona", + "stopId": "de-DELFI_de:02000:80026::800094", + "importance": 0.00639944477006793, + "lat": 53.55177, + "lon": 9.934406000000001, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T20:59:00Z", + "departure": "2026-08-15T20:59:00Z", + "scheduledArrival": "2026-08-15T20:57:00Z", + "scheduledDeparture": "2026-08-15T20:57:00Z", + "scheduledTrack": "8", + "track": "8", + "description": "Z 69275700", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NOT_ALLOWED", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Rathaus Altona", + "stopId": "de-DELFI_de:02000:80015::800044", + "importance": 0.0019747898913919926, + "lat": 53.547134, + "lon": 9.936131, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:01:00Z", + "departure": "2026-08-15T21:01:00Z", + "scheduledArrival": "2026-08-15T20:59:00Z", + "scheduledDeparture": "2026-08-15T20:59:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 800205", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Susettestra\u00dfe", + "stopId": "de-DELFI_de:02000:80098::800329", + "importance": 0.00032002496300265193, + "lat": 53.546482, + "lon": 9.924938, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:03:00Z", + "departure": "2026-08-15T21:03:00Z", + "scheduledArrival": "2026-08-15T21:01:00Z", + "scheduledDeparture": "2026-08-15T21:01:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 800328", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Hohenzollernring (S\u00fcd)", + "stopId": "de-DELFI_de:02000:80010::800047", + "importance": 0.00032002496300265193, + "lat": 53.546079999999996, + "lon": 9.915613, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:04:00Z", + "departure": "2026-08-15T21:04:00Z", + "scheduledArrival": "2026-08-15T21:02:00Z", + "scheduledDeparture": "2026-08-15T21:02:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 800026", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Liebermannstra\u00dfe", + "stopId": "de-DELFI_de:02000:80009::800048", + "importance": 0.00032002496300265193, + "lat": 53.54596, + "lon": 9.899587000000002, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:06:00Z", + "departure": "2026-08-15T21:06:00Z", + "scheduledArrival": "2026-08-15T21:04:00Z", + "scheduledDeparture": "2026-08-15T21:04:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "HHA-B 800025", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Halbmondsweg", + "stopId": "de-DELFI_de:02000:80008::800050", + "importance": 0.0005810476723127067, + "lat": 53.546510000000005, + "lon": 9.887433000000001, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:07:00Z", + "departure": "2026-08-15T21:07:00Z", + "scheduledArrival": "2026-08-15T21:05:00Z", + "scheduledDeparture": "2026-08-15T21:05:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 800023", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Zedernweg", + "stopId": "de-DELFI_de:02000:80007::800051", + "importance": 0.0005810476723127067, + "lat": 53.54658, + "lon": 9.88216, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:08:00Z", + "departure": "2026-08-15T21:08:00Z", + "scheduledArrival": "2026-08-15T21:06:00Z", + "scheduledDeparture": "2026-08-15T21:06:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 800022", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + }, + { + "name": "Holztwiete", + "stopId": "de-DELFI_de:02000:89006::800110", + "importance": 0.0005810476723127067, + "lat": 53.547146, + "lon": 9.874039000000002, + "level": 0.0, + "tz": "Europe/Berlin", + "arrival": "2026-08-15T21:09:00Z", + "departure": "2026-08-15T21:09:00Z", + "scheduledArrival": "2026-08-15T21:07:00Z", + "scheduledDeparture": "2026-08-15T21:07:00Z", + "scheduledTrack": "2", + "track": "2", + "description": "VHH 800021", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "BUS" + ] + } + ], + "legGeometry": { + "points": "cfgceBsczdREx@q@tN{@|R_Dbt@q@xNgB~^e@nIM`B_@`DWlDMzBIxCBpCF`E@vEMpFsAtVsCfi@}@jOYpFaDnk@_@zGANCp@WtEa@pH]tJ]xKuArH[rEcA^{@`Ai@zAUjBApBPjBd@|At@dAIhF\\nGeG`iAuBzb@kJxmBUtEeAdTAPq@bOYfGWxHQdFMdG[~RYlZGvRCvFmAhG?tE?rBJfHJ|H\\pPRlNpBhNJpN\\~LNpDf@rL|@hOn@|KRjCh@lHxCp]PnB~Cx[TbClBtQPdBp@zF~@pHdB|LdDnUlAtIpIrh@lJxi@xBlMDZxArIjEdWrB|L|BbMpWjxAxEbWzKxl@|EvWdJxf@dC`N|Gx^bLtm@jAtNdClMj@zCtAfH~BxL~AjIhGz\\PdAlCxNpFvSfA|Fv@fEjCrNrCjOpB~Kf@jC|E~WhA`GtAfHzAlIbDbQfAxIfDrXVtBtA`LjAbGvAtD_BdE}AvCu@fAuAzAsLjIeBlAkYhSsN`KuF|DqA~@wB~AmDjCwG|EgIpFqBxAc_@xWuHnF}a@bZ_DzBqN`KeD~BiHhFgAv@cExCu@j@sHnF_R|MuWtRmGpEgChBwVnQmG`FyBfBaGtEza@d~BrEbW|C~PxFn[pAnG_ObKkChBaFjD}F~DuIbGaBhAuDfClBpKjFhZ`C|M|Kpn@rI|e@bKvk@~@hF^tB~F`\\t@zD\\vBh@zCnC~NtJnh@RlApDtRt@dF~@jHd@dGPvGDhJDfHLbINzHPvHr@jr@BfQGrYM|POfV]fg@Y|a@OxSGdJIvTCdBMzDSnEWxD{@bJsGrCgLImG_DsGcA}HuAkBYeEq@cT_EwLsAqJa@cK@_BHoDf@{Er@u@HkEp@_JzB{Br@aOnEuOxEoJ~CmNrEcA\\w@RmGrAQFuFnAaGvAwPlE_IrCsE~BeAh@_Az@iB~A}EzEyBlBwIfK}KhNsHhKmEpFeV`[qA`BuE|GoDlFcG~IiEdHkCdFk`@~v@qFlMqBvT}KtVgIhQgEdJw@nB{@tB{@vBgCfGsDjJuBbGeIbTkFjPkCtI{DxNyDz[a@`CeAdFeGx[sIhe@gM`s@{D|VcA`GwIxm@{Fvf@m@rFqEla@wCbV[pCaB|MeAxIi@pFi@dGm@xHkIffA}Cpa@sIhmAqB|X_@dFGl@K`BWtJ?hEGlJ?pD?pGZtOLrFt@tWlAz\\nF|dBdBhe@~@tQl@~I|@rJ^pC~A~LlB`M^~BbAlFrCzMxBbLtCtNlEzR`CdKdCtJvB~H`CrHrDxKbEnLvFzNjHhPzk@joApItPlAbCbBrD|AbDdGjIn@dAlDhFvAfB`@f@|GvH~LfJNJfNhK|aAvqApXp]nA|A|JjL~@fAtBbCbM|KxF`FvEtEhGdGp@p@jQfQlWdW|OhNtAjAhJbInYpUpUzPv@f@pGjExIfLpDlHvAvB~BfDdBxAfEn@xE|CdBgOdAmJjAiO~@iLNiBr@{Lh@oLJ_CTuQxCotAtAow@H_LBqDPmPLaIJ{GNsCj@mXFiB_@mQbB{SfD__@|Kq_AvL}aAzJux@zDgLTkBtA_KjAgJDe@nCkUvCwTdBsMlCqQnF__@nCgP^_TzBsPXkCPmDLyDA_MQgCWmAyAdO_AvIiJ~y@{Fj`@cClRmF~b@iC~SUlBgArIsAtKSlB@rO{Jtx@wL|aA}Kp_AgD~^cBzSyDnOoAtQ_@`KKpDKxHGxHOjO?vBIjUE|I_@p`@c@|Rm@|T}Ab^k@zKq@`MQlBcClVsEx_@_@fDeAhKoAjOgBvY{AfU_A`KmAvKm@nFwAnLmAx[KzCKhDE`DMrHA~B^ba@TfYFfF?\\HxILxJJ~JVlWN|Sp@fi@^xRNlHr@zSFbB~JdwBHhBd@rLzKnbCHdBl@fL^fLf@``@@x@?fA@nN]vm@KtQEzLChFCnCChIIdJEnHKbMA~AuAbb@E|@KnDY~G{Cnk@{Ah^QtHS`Is@lYCja@?vALbFXrMTxHp@d\\HlCPbHTdJPpGtBpd@DhBHdCt@bZ\\rM`@fL`AvRjAtR`If~@~AvPPfBT|BxEvg@B`@|AtPMdMPfF\\dEn@rIrB`VtAxPs@jDcA|E{@nDmN`o@aCbCsAr@uA`@sBHgJr@qEM{SL}K`@gZ`@wC_A_Nr@u@Ce@GYI]O]YOg@Sc@U_@W[[S[M[I]?[B]JYPYTUXQ\\Q`@Md@Kf@Gf@Ej@Ch@?j@@T@TDh@Hf@?v@Cn@Cr@Ej@MjBwDzf@{BdZKjAY~D}Ftx@WhEeCn`@s@lOAV_@~PUdTIxJOnRi@vy@SbVu@zh@o@`Ug@pFUjCe@lGi@rHc@d@m@r@R~AHpBCbC_JtnAcCbZ}Cj_@a@zEcAtG_AdG`F|G~AjBjBjBpD~CbDbCnIzE|A~@nPvJ_@|EGxB@`b@P|IZhFZ|DJrDGhSAxCEfb@?r@Qlb@E|NO|@Sp@Y^a@RaGOm@[Si@Oi@I{@DkU?yIB{GHqT?gBJkXBiNHsB`@{Ax@gBvGeMb@eAhBoFPe_@DoAp@_HdRfFrGpArKdA|Rh@vA?jGK`EGtEI|dBM~WD`C?n@?~IXdEJfJL~J?jJ@r@?t\\@zCZ|ARfAb@dAbAx@tAp@hBl@zC`@|L?nTCjIaAjXYpJNpOuF~sAsAn\\k@xUCzIA~LBpHFzEJ|FPfFj@|K`@lHxFhhANrCl@`MNpGEnHOzFwBze@o@tPYtLChIF~OJdHX~NNhHNxYK`Q@nDIhOA~F?hC@pCT`^BzC^lWhCn^pAhRvBtXtA~Tj@bPf@xQV`Rf@nd@b@xOfA~TNzCPfCt@~KdCbXx@lKn@vKl@dPf@dTF`NHpNQ|WAz@KjIYtLSjGYtIe@dMe@rLOjEq@jTg@jT[dQWjNAdACxBmArr@o@x]E|DQtL?lNAvBMzj@KjbAHvKJxFRxIh@nPfAdXTpFdAhWv@nRFjAFpBJdCv@dSlAhYp@tP^vKp@~[n@tXh@hPj@nOnAnU`AfPnCrc@|@vOhBbZdAlPPpCn@bKl@lL^pKRfJD~M?rJEvIM`MEnDKhJCl@QfJc@dJ_@dF]|Da@bEc@tDk@jE}AzJ}D~UyA|Ky@rH_@`G_A`No@zMIdBItBm@dN{Ab_@]|HE|@IhBK|Bq@dOQtDy@tQMzDk@nNu@`Ra@zJkB~X_D|j@m@jK{Bte@UhFm@zL{ElfAmG`uAGxAmApXm@dSKjJ_@v`@@pQDdGGt\\F~JR`PV`LN`Dl@lMt@fK`BxOvCdVVxGFlGBzFYpk@Q|LGhEYfRMbIKhIa@zc@o@lu@EnDO|QQ`RmAhwACtKEnO\\rPRlK@Xx@zT^~JT`O@~@D|KQxMWhIS`F]pGO|A]|Dk@lGa@vEc@|Ee@lI[lGa@t[i@x]InG_Alr@QrKSfQI~XOrb@GnIOxH[xHm@bIi@zFy@lHyB~OiAzIo@xE}AdM_AzIq@tHc@tGQxCk@bKq@vKWxEGlAGfA{@~Oc@fJeAfWiAj^sBlv@}Adl@QlI[|G_@bFy@vHcB|KkHhb@uB~NgBnOcBbScDza@M`BIlAe@hIi@bNUhKMnMB|NNfOXvN`@bNX`H\\hHVjEVlDlAvLnDn[^lDj@bFh@jEdAhInB|MfBjL", + "precision": 6, + "length": 972 + }, + "bikesAllowed": false, + "wheelchairAccessible": "NOT_ACCESSIBLE", + "reservation": "NONE", + "alternatives": [] + } + ] +} \ No newline at end of file From 53358c08b1508a960f1a4a81791122f40a54b31e Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sat, 15 Aug 2026 22:58:32 +0200 Subject: [PATCH 09/48] transitous rewrite: remove wtf.json --- wtf.json | 827 ------------------------------------------------------- 1 file changed, 827 deletions(-) delete mode 100644 wtf.json diff --git a/wtf.json b/wtf.json deleted file mode 100644 index 089f239..0000000 --- a/wtf.json +++ /dev/null @@ -1,827 +0,0 @@ -{ - "duration": 3240, - "startTime": "2026-08-15T20:16:00Z", - "endTime": "2026-08-15T21:10:00Z", - "transfers": 0, - "id": "CqEBCgIxMhIiMjAyNjA4MTVfMjI6MTZfZGUtREVMRklfMzMwNTA4MDkwNhofZGUtREVMRklfZGU6MDIwMDA6MTAwNTY6OjEwMDAxOSH0ona/CsZKQClzRSkhWB0kQDIfZGUtREVMRklfZGU6MDIwMDA6ODAwMDU6OjgwMDA1NDk1e6AVGMZKQEGc/1cdObojQEiAkoPUBlCwqoPUBloDQlVTYAE=", - "legs": [ - { - "mode": "BUS", - "from": { - "name": "Osterbrookplatz", - "stopId": "de-DELFI_de:02000:10056::100019", - "importance": 0.00038864786620251834, - "lat": 53.547202999999996, - "lon": 10.057312999999999, - "level": 0.0, - "tz": "Europe/Berlin", - "departure": "2026-08-15T20:16:00Z", - "scheduledDeparture": "2026-08-15T20:16:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 100017", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - "to": { - "name": "Teufelsbr\u00fcck (F\u00e4hre)", - "stopId": "de-DELFI_de:02000:80005::800054", - "importance": 0.001101788366213441, - "lat": 53.54761, - "lon": 9.863717000000001, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:10:00Z", - "scheduledArrival": "2026-08-15T21:08:00Z", - "scheduledTrack": "5", - "track": "5", - "description": "VHH 800019", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - "duration": 3240, - "startTime": "2026-08-15T20:16:00Z", - "endTime": "2026-08-15T21:10:00Z", - "scheduledStartTime": "2026-08-15T20:16:00Z", - "scheduledEndTime": "2026-08-15T21:08:00Z", - "realTime": true, - "scheduled": true, - "interlineWithPreviousLeg": false, - "headsign": "Teufelsbr\u00fcck (F\u00e4hre)", - "tripFrom": { - "name": "Osterbrookplatz", - "stopId": "de-DELFI_de:02000:10056::100019", - "importance": 0.00038864786620251834, - "lat": 53.547202999999996, - "lon": 10.057312999999999, - "level": 0.0, - "tz": "Europe/Berlin", - "departure": "2026-08-15T20:16:00Z", - "scheduledDeparture": "2026-08-15T20:16:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 100017", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - "tripTo": { - "name": "Teufelsbr\u00fcck (F\u00e4hre)", - "stopId": "de-DELFI_de:02000:80005::800054", - "importance": 0.001101788366213441, - "lat": 53.54761, - "lon": 9.863717000000001, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:10:00Z", - "scheduledArrival": "2026-08-15T21:08:00Z", - "scheduledTrack": "5", - "track": "5", - "description": "VHH 800019", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - "routeId": "de-DELFI_de:hvv:12:_3", - "routeUrl": "", - "directionId": "1", - "routeColor": "ca3d2a", - "routeTextColor": "ffffff", - "routeType": 3, - "agencyName": "Hochbahn Bus", - "agencyUrl": "", - "agencyFareUrl": "", - "agencyId": "15140", - "tripId": "20260815_22:16_de-DELFI_3305080906", - "routeShortName": "12", - "routeLongName": "", - "tripShortName": "1200086", - "displayName": "12", - "cancelled": false, - "source": "de_DELFI.gtfs.zip/stop_times.txt:33330623:33330654", - "intermediateStops": [ - { - "name": "Schadesweg", - "stopId": "de-DELFI_de:02000:10042::100197", - "importance": 0.00038864786620251834, - "lat": 53.547714, - "lon": 10.05187, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:17:00Z", - "departure": "2026-08-15T20:17:00Z", - "scheduledArrival": "2026-08-15T20:17:00Z", - "scheduledDeparture": "2026-08-15T20:17:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 100196", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Luisenweg", - "stopId": "de-DELFI_de:02000:10041::100224", - "importance": 0.00038864786620251834, - "lat": 53.548298, - "lon": 10.046362999999998, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:18:00Z", - "departure": "2026-08-15T20:18:00Z", - "scheduledArrival": "2026-08-15T20:18:00Z", - "scheduledDeparture": "2026-08-15T20:18:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 100195", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Ausschl\u00e4ger Weg (LBV)", - "stopId": "de-DELFI_de:02000:10040::100181", - "importance": 0.001163465902209282, - "lat": 53.547276, - "lon": 10.037443, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:22:00Z", - "departure": "2026-08-15T20:22:00Z", - "scheduledArrival": "2026-08-15T20:20:00Z", - "scheduledDeparture": "2026-08-15T20:20:00Z", - "scheduledTrack": "1", - "track": "1", - "description": "HHA-B 100181", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "S\u00fcderstra\u00dfe", - "stopId": "de-DELFI_de:02000:10039::100172", - "importance": 0.0010683928849175572, - "lat": 53.545147, - "lon": 10.029789000000001, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:22:00Z", - "departure": "2026-08-15T20:22:00Z", - "scheduledArrival": "2026-08-15T20:21:00Z", - "scheduledDeparture": "2026-08-15T20:21:00Z", - "scheduledTrack": "3", - "track": "3", - "description": "HHA-B 100164", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "S Hammerbrook (S\u00fcd)", - "stopId": "de-DELFI_de:02000:10038::100207", - "importance": 0.0006706778658553958, - "lat": 53.54553200000001, - "lon": 10.024811999999999, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:24:00Z", - "departure": "2026-08-15T20:24:00Z", - "scheduledArrival": "2026-08-15T20:22:00Z", - "scheduledDeparture": "2026-08-15T20:22:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "SBAHNS 3921901", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "S Hammerbrook (Nord)", - "stopId": "de-DELFI_de:02000:10060::100030", - "importance": 0.00039489471237175167, - "lat": 53.547832, - "lon": 10.02298, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:25:00Z", - "departure": "2026-08-15T20:25:00Z", - "scheduledArrival": "2026-08-15T20:23:00Z", - "scheduledDeparture": "2026-08-15T20:23:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 100029", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Albertstra\u00dfe", - "stopId": "de-DELFI_000011005802", - "importance": 0.00039489471237175167, - "lat": 53.54898, - "lon": 10.019054, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:26:00Z", - "departure": "2026-08-15T20:26:00Z", - "scheduledArrival": "2026-08-15T20:24:00Z", - "scheduledDeparture": "2026-08-15T20:24:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 100026", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Repsoldstra\u00dfe", - "stopId": "de-DELFI_000011005702", - "importance": 0.00039489471237175167, - "lat": 53.54862, - "lon": 10.013898, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:28:00Z", - "departure": "2026-08-15T20:28:00Z", - "scheduledArrival": "2026-08-15T20:26:00Z", - "scheduledDeparture": "2026-08-15T20:26:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 100020", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "U Steinstra\u00dfe (Deichtorplatz)", - "stopId": "de-DELFI_de:02000:10024::100050", - "importance": 0.0013284930028021336, - "lat": 53.548954, - "lon": 10.006442000000002, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:30:00Z", - "departure": "2026-08-15T20:30:00Z", - "scheduledArrival": "2026-08-15T20:28:00Z", - "scheduledDeparture": "2026-08-15T20:28:00Z", - "scheduledTrack": "3", - "track": "3", - "description": "HHA-B 100033", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "HBF/Spitalerstra\u00dfe", - "stopId": "de-DELFI_de:02000:10011::100133", - "importance": 0.2917599081993103, - "lat": 53.552642999999996, - "lon": 10.005606000000002, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:32:00Z", - "departure": "2026-08-15T20:32:00Z", - "scheduledArrival": "2026-08-15T20:30:00Z", - "scheduledDeparture": "2026-08-15T20:30:00Z", - "scheduledTrack": "1", - "track": "1", - "description": "HHA-B 100133", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "HIGHSPEED_RAIL", - "LONG_DISTANCE", - "COACH", - "NIGHT_RAIL", - "REGIONAL_RAIL", - "SUBURBAN", - "SUBWAY", - "BUS" - ] - }, - { - "name": "Kunsthalle", - "stopId": "de-DELFI_000011103302", - "importance": 0.0003962125920224935, - "lat": 53.555546, - "lon": 10.001356999999999, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:35:00Z", - "departure": "2026-08-15T20:35:00Z", - "scheduledArrival": "2026-08-15T20:33:00Z", - "scheduledDeparture": "2026-08-15T20:33:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 100213", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "U Stephansplatz", - "stopId": "de-DELFI_de:02000:11013:1:110071", - "importance": 0.0023285001516342163, - "lat": 53.558370000000004, - "lon": 9.98852, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:38:00Z", - "departure": "2026-08-15T20:38:00Z", - "scheduledArrival": "2026-08-15T20:36:00Z", - "scheduledDeparture": "2026-08-15T20:36:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 110071", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Johannes-Brahms-Platz", - "stopId": "de-DELFI_de:02000:11009:1:110056", - "importance": 0.0004172989574726671, - "lat": 53.555110000000006, - "lon": 9.978620999999999, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:40:00Z", - "departure": "2026-08-15T20:40:00Z", - "scheduledArrival": "2026-08-15T20:38:00Z", - "scheduledDeparture": "2026-08-15T20:38:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 110056", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Handwerkskammer", - "stopId": "de-DELFI_de:02000:11008::110054", - "importance": 0.0004172989574726671, - "lat": 53.55314, - "lon": 9.976393, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:41:00Z", - "departure": "2026-08-15T20:41:00Z", - "scheduledArrival": "2026-08-15T20:39:00Z", - "scheduledDeparture": "2026-08-15T20:39:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 110053", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Museum f\u00fcr Hamburgische Geschichte", - "stopId": "de-DELFI_de:02000:11007::110052", - "importance": 0.0004172989574726671, - "lat": 53.55146799999999, - "lon": 9.974794000000001, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:42:00Z", - "departure": "2026-08-15T20:42:00Z", - "scheduledArrival": "2026-08-15T20:40:00Z", - "scheduledDeparture": "2026-08-15T20:40:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 110051", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "U St. Pauli", - "stopId": "de-DELFI_de:02000:80017:3:800037", - "importance": 0.0012117273872718215, - "lat": 53.550117, - "lon": 9.969799000000002, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:45:00Z", - "departure": "2026-08-15T20:45:00Z", - "scheduledArrival": "2026-08-15T20:43:00Z", - "scheduledDeparture": "2026-08-15T20:43:00Z", - "scheduledTrack": "3", - "track": "3", - "description": "HHA-B 800037", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Davidstra\u00dfe", - "stopId": "de-DELFI_de:02000:80018:2:800039", - "importance": 0.001252002315595746, - "lat": 53.549583, - "lon": 9.961643, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:48:00Z", - "departure": "2026-08-15T20:48:00Z", - "scheduledArrival": "2026-08-15T20:46:00Z", - "scheduledDeparture": "2026-08-15T20:46:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 800033", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "S Reeperbahn", - "stopId": "de-DELFI_de:02000:80019:2:800041", - "importance": 0.0014315921580418944, - "lat": 53.549746999999996, - "lon": 9.954717, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:52:00Z", - "departure": "2026-08-15T20:52:00Z", - "scheduledArrival": "2026-08-15T20:50:00Z", - "scheduledDeparture": "2026-08-15T20:50:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 800031", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Bl\u00fccherstra\u00dfe", - "stopId": "de-DELFI_de:02000:80107::800356", - "importance": 0.0009377760579809546, - "lat": 53.549186999999996, - "lon": 9.949956, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:53:00Z", - "departure": "2026-08-15T20:53:00Z", - "scheduledArrival": "2026-08-15T20:51:00Z", - "scheduledDeparture": "2026-08-15T20:51:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 800356", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Gro\u00dfe Bergstra\u00dfe", - "stopId": "de-DELFI_de:02000:80023:2:800323", - "importance": 0.0009272329043596983, - "lat": 53.551525, - "lon": 9.946254999999999, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:55:00Z", - "departure": "2026-08-15T20:55:00Z", - "scheduledArrival": "2026-08-15T20:53:00Z", - "scheduledDeparture": "2026-08-15T20:53:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 800323", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Goethestra\u00dfe", - "stopId": "de-DELFI_de:02000:80024::800082", - "importance": 0.0004593530611600727, - "lat": 53.55199399999999, - "lon": 9.940056, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:56:00Z", - "departure": "2026-08-15T20:56:00Z", - "scheduledArrival": "2026-08-15T20:54:00Z", - "scheduledDeparture": "2026-08-15T20:54:00Z", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Bf. Altona", - "stopId": "de-DELFI_de:02000:80026::800091", - "importance": 0.00639944477006793, - "lat": 53.551548, - "lon": 9.934171999999998, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:58:00Z", - "departure": "2026-08-15T20:58:00Z", - "scheduledArrival": "2026-08-15T20:56:00Z", - "scheduledDeparture": "2026-08-15T20:56:00Z", - "scheduledTrack": "5", - "track": "5", - "description": "VHH 800096", - "vertexType": "TRANSIT", - "pickupType": "NOT_ALLOWED", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Bf. Altona", - "stopId": "de-DELFI_de:02000:80026::800094", - "importance": 0.00639944477006793, - "lat": 53.55177, - "lon": 9.934406000000001, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T20:59:00Z", - "departure": "2026-08-15T20:59:00Z", - "scheduledArrival": "2026-08-15T20:57:00Z", - "scheduledDeparture": "2026-08-15T20:57:00Z", - "scheduledTrack": "8", - "track": "8", - "description": "Z 69275700", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NOT_ALLOWED", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Rathaus Altona", - "stopId": "de-DELFI_de:02000:80015::800044", - "importance": 0.0019747898913919926, - "lat": 53.547134, - "lon": 9.936131, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:01:00Z", - "departure": "2026-08-15T21:01:00Z", - "scheduledArrival": "2026-08-15T20:59:00Z", - "scheduledDeparture": "2026-08-15T20:59:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 800205", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Susettestra\u00dfe", - "stopId": "de-DELFI_de:02000:80098::800329", - "importance": 0.00032002496300265193, - "lat": 53.546482, - "lon": 9.924938, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:03:00Z", - "departure": "2026-08-15T21:03:00Z", - "scheduledArrival": "2026-08-15T21:01:00Z", - "scheduledDeparture": "2026-08-15T21:01:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 800328", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Hohenzollernring (S\u00fcd)", - "stopId": "de-DELFI_de:02000:80010::800047", - "importance": 0.00032002496300265193, - "lat": 53.546079999999996, - "lon": 9.915613, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:04:00Z", - "departure": "2026-08-15T21:04:00Z", - "scheduledArrival": "2026-08-15T21:02:00Z", - "scheduledDeparture": "2026-08-15T21:02:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 800026", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Liebermannstra\u00dfe", - "stopId": "de-DELFI_de:02000:80009::800048", - "importance": 0.00032002496300265193, - "lat": 53.54596, - "lon": 9.899587000000002, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:06:00Z", - "departure": "2026-08-15T21:06:00Z", - "scheduledArrival": "2026-08-15T21:04:00Z", - "scheduledDeparture": "2026-08-15T21:04:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "HHA-B 800025", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Halbmondsweg", - "stopId": "de-DELFI_de:02000:80008::800050", - "importance": 0.0005810476723127067, - "lat": 53.546510000000005, - "lon": 9.887433000000001, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:07:00Z", - "departure": "2026-08-15T21:07:00Z", - "scheduledArrival": "2026-08-15T21:05:00Z", - "scheduledDeparture": "2026-08-15T21:05:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 800023", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Zedernweg", - "stopId": "de-DELFI_de:02000:80007::800051", - "importance": 0.0005810476723127067, - "lat": 53.54658, - "lon": 9.88216, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:08:00Z", - "departure": "2026-08-15T21:08:00Z", - "scheduledArrival": "2026-08-15T21:06:00Z", - "scheduledDeparture": "2026-08-15T21:06:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 800022", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - }, - { - "name": "Holztwiete", - "stopId": "de-DELFI_de:02000:89006::800110", - "importance": 0.0005810476723127067, - "lat": 53.547146, - "lon": 9.874039000000002, - "level": 0.0, - "tz": "Europe/Berlin", - "arrival": "2026-08-15T21:09:00Z", - "departure": "2026-08-15T21:09:00Z", - "scheduledArrival": "2026-08-15T21:07:00Z", - "scheduledDeparture": "2026-08-15T21:07:00Z", - "scheduledTrack": "2", - "track": "2", - "description": "VHH 800021", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "BUS" - ] - } - ], - "legGeometry": { - "points": "cfgceBsczdREx@q@tN{@|R_Dbt@q@xNgB~^e@nIM`B_@`DWlDMzBIxCBpCF`E@vEMpFsAtVsCfi@}@jOYpFaDnk@_@zGANCp@WtEa@pH]tJ]xKuArH[rEcA^{@`Ai@zAUjBApBPjBd@|At@dAIhF\\nGeG`iAuBzb@kJxmBUtEeAdTAPq@bOYfGWxHQdFMdG[~RYlZGvRCvFmAhG?tE?rBJfHJ|H\\pPRlNpBhNJpN\\~LNpDf@rL|@hOn@|KRjCh@lHxCp]PnB~Cx[TbClBtQPdBp@zF~@pHdB|LdDnUlAtIpIrh@lJxi@xBlMDZxArIjEdWrB|L|BbMpWjxAxEbWzKxl@|EvWdJxf@dC`N|Gx^bLtm@jAtNdClMj@zCtAfH~BxL~AjIhGz\\PdAlCxNpFvSfA|Fv@fEjCrNrCjOpB~Kf@jC|E~WhA`GtAfHzAlIbDbQfAxIfDrXVtBtA`LjAbGvAtD_BdE}AvCu@fAuAzAsLjIeBlAkYhSsN`KuF|DqA~@wB~AmDjCwG|EgIpFqBxAc_@xWuHnF}a@bZ_DzBqN`KeD~BiHhFgAv@cExCu@j@sHnF_R|MuWtRmGpEgChBwVnQmG`FyBfBaGtEza@d~BrEbW|C~PxFn[pAnG_ObKkChBaFjD}F~DuIbGaBhAuDfClBpKjFhZ`C|M|Kpn@rI|e@bKvk@~@hF^tB~F`\\t@zD\\vBh@zCnC~NtJnh@RlApDtRt@dF~@jHd@dGPvGDhJDfHLbINzHPvHr@jr@BfQGrYM|POfV]fg@Y|a@OxSGdJIvTCdBMzDSnEWxD{@bJsGrCgLImG_DsGcA}HuAkBYeEq@cT_EwLsAqJa@cK@_BHoDf@{Er@u@HkEp@_JzB{Br@aOnEuOxEoJ~CmNrEcA\\w@RmGrAQFuFnAaGvAwPlE_IrCsE~BeAh@_Az@iB~A}EzEyBlBwIfK}KhNsHhKmEpFeV`[qA`BuE|GoDlFcG~IiEdHkCdFk`@~v@qFlMqBvT}KtVgIhQgEdJw@nB{@tB{@vBgCfGsDjJuBbGeIbTkFjPkCtI{DxNyDz[a@`CeAdFeGx[sIhe@gM`s@{D|VcA`GwIxm@{Fvf@m@rFqEla@wCbV[pCaB|MeAxIi@pFi@dGm@xHkIffA}Cpa@sIhmAqB|X_@dFGl@K`BWtJ?hEGlJ?pD?pGZtOLrFt@tWlAz\\nF|dBdBhe@~@tQl@~I|@rJ^pC~A~LlB`M^~BbAlFrCzMxBbLtCtNlEzR`CdKdCtJvB~H`CrHrDxKbEnLvFzNjHhPzk@joApItPlAbCbBrD|AbDdGjIn@dAlDhFvAfB`@f@|GvH~LfJNJfNhK|aAvqApXp]nA|A|JjL~@fAtBbCbM|KxF`FvEtEhGdGp@p@jQfQlWdW|OhNtAjAhJbInYpUpUzPv@f@pGjExIfLpDlHvAvB~BfDdBxAfEn@xE|CdBgOdAmJjAiO~@iLNiBr@{Lh@oLJ_CTuQxCotAtAow@H_LBqDPmPLaIJ{GNsCj@mXFiB_@mQbB{SfD__@|Kq_AvL}aAzJux@zDgLTkBtA_KjAgJDe@nCkUvCwTdBsMlCqQnF__@nCgP^_TzBsPXkCPmDLyDA_MQgCWmAyAdO_AvIiJ~y@{Fj`@cClRmF~b@iC~SUlBgArIsAtKSlB@rO{Jtx@wL|aA}Kp_AgD~^cBzSyDnOoAtQ_@`KKpDKxHGxHOjO?vBIjUE|I_@p`@c@|Rm@|T}Ab^k@zKq@`MQlBcClVsEx_@_@fDeAhKoAjOgBvY{AfU_A`KmAvKm@nFwAnLmAx[KzCKhDE`DMrHA~B^ba@TfYFfF?\\HxILxJJ~JVlWN|Sp@fi@^xRNlHr@zSFbB~JdwBHhBd@rLzKnbCHdBl@fL^fLf@``@@x@?fA@nN]vm@KtQEzLChFCnCChIIdJEnHKbMA~AuAbb@E|@KnDY~G{Cnk@{Ah^QtHS`Is@lYCja@?vALbFXrMTxHp@d\\HlCPbHTdJPpGtBpd@DhBHdCt@bZ\\rM`@fL`AvRjAtR`If~@~AvPPfBT|BxEvg@B`@|AtPMdMPfF\\dEn@rIrB`VtAxPs@jDcA|E{@nDmN`o@aCbCsAr@uA`@sBHgJr@qEM{SL}K`@gZ`@wC_A_Nr@u@Ce@GYI]O]YOg@Sc@U_@W[[S[M[I]?[B]JYPYTUXQ\\Q`@Md@Kf@Gf@Ej@Ch@?j@@T@TDh@Hf@?v@Cn@Cr@Ej@MjBwDzf@{BdZKjAY~D}Ftx@WhEeCn`@s@lOAV_@~PUdTIxJOnRi@vy@SbVu@zh@o@`Ug@pFUjCe@lGi@rHc@d@m@r@R~AHpBCbC_JtnAcCbZ}Cj_@a@zEcAtG_AdG`F|G~AjBjBjBpD~CbDbCnIzE|A~@nPvJ_@|EGxB@`b@P|IZhFZ|DJrDGhSAxCEfb@?r@Qlb@E|NO|@Sp@Y^a@RaGOm@[Si@Oi@I{@DkU?yIB{GHqT?gBJkXBiNHsB`@{Ax@gBvGeMb@eAhBoFPe_@DoAp@_HdRfFrGpArKdA|Rh@vA?jGK`EGtEI|dBM~WD`C?n@?~IXdEJfJL~J?jJ@r@?t\\@zCZ|ARfAb@dAbAx@tAp@hBl@zC`@|L?nTCjIaAjXYpJNpOuF~sAsAn\\k@xUCzIA~LBpHFzEJ|FPfFj@|K`@lHxFhhANrCl@`MNpGEnHOzFwBze@o@tPYtLChIF~OJdHX~NNhHNxYK`Q@nDIhOA~F?hC@pCT`^BzC^lWhCn^pAhRvBtXtA~Tj@bPf@xQV`Rf@nd@b@xOfA~TNzCPfCt@~KdCbXx@lKn@vKl@dPf@dTF`NHpNQ|WAz@KjIYtLSjGYtIe@dMe@rLOjEq@jTg@jT[dQWjNAdACxBmArr@o@x]E|DQtL?lNAvBMzj@KjbAHvKJxFRxIh@nPfAdXTpFdAhWv@nRFjAFpBJdCv@dSlAhYp@tP^vKp@~[n@tXh@hPj@nOnAnU`AfPnCrc@|@vOhBbZdAlPPpCn@bKl@lL^pKRfJD~M?rJEvIM`MEnDKhJCl@QfJc@dJ_@dF]|Da@bEc@tDk@jE}AzJ}D~UyA|Ky@rH_@`G_A`No@zMIdBItBm@dN{Ab_@]|HE|@IhBK|Bq@dOQtDy@tQMzDk@nNu@`Ra@zJkB~X_D|j@m@jK{Bte@UhFm@zL{ElfAmG`uAGxAmApXm@dSKjJ_@v`@@pQDdGGt\\F~JR`PV`LN`Dl@lMt@fK`BxOvCdVVxGFlGBzFYpk@Q|LGhEYfRMbIKhIa@zc@o@lu@EnDO|QQ`RmAhwACtKEnO\\rPRlK@Xx@zT^~JT`O@~@D|KQxMWhIS`F]pGO|A]|Dk@lGa@vEc@|Ee@lI[lGa@t[i@x]InG_Alr@QrKSfQI~XOrb@GnIOxH[xHm@bIi@zFy@lHyB~OiAzIo@xE}AdM_AzIq@tHc@tGQxCk@bKq@vKWxEGlAGfA{@~Oc@fJeAfWiAj^sBlv@}Adl@QlI[|G_@bFy@vHcB|KkHhb@uB~NgBnOcBbScDza@M`BIlAe@hIi@bNUhKMnMB|NNfOXvN`@bNX`H\\hHVjEVlDlAvLnDn[^lDj@bFh@jEdAhInB|MfBjL", - "precision": 6, - "length": 972 - }, - "bikesAllowed": false, - "wheelchairAccessible": "NOT_ACCESSIBLE", - "reservation": "NONE", - "alternatives": [] - } - ] -} \ No newline at end of file From f3d9a25f9505abfd404e264c040db2aa0a21e935 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:43:38 +0200 Subject: [PATCH 10/48] transitous rewrite: make sure to only use connections in the future --- main.py | 19 +++++++---- src/api/transitous.py | 73 +++++++++++++++++++++++++------------------ src/data/operators.py | 2 +- src/dc/handlers.py | 34 ++++++++++++++------ src/utils.py | 13 +++++++- 5 files changed, 93 insertions(+), 48 deletions(-) diff --git a/main.py b/main.py index 2de3078..0121fc8 100644 --- a/main.py +++ b/main.py @@ -6,15 +6,22 @@ from src.dc.commands import setup_commands bot = discord.Bot(intents=discord.Intents.all()) setup_commands(bot=bot) +_bot_initialized = False @bot.event async def on_ready(): - server_id = config["server"] - server_vc_id = config["vc"] - channel = validate_channel(bot=bot, server_id=server_id, channel_id=server_vc_id) + global _bot_initialized logger(f"{bot.user} ist online") - await rename_vc(bot=bot, voice_channel=channel) + + if not _bot_initialized: + _bot_initialized = True + server_id = config["server"] + server_vc_id = config["vc"] + channel = validate_channel(bot=bot, server_id=server_id, channel_id=server_vc_id) + await rename_vc(bot, voice_channel=channel) + else: + logger("Reconnected to discord gateway, this wont disturb your current ride") try: bot.run(config["token"]) @@ -23,12 +30,12 @@ except: ''' TODO -- Only choose connections in the future -- discord reconnection handling +- 1024 embed limit - Automatic transfer - discord status - text announcements - voice announcements - improved error handling (retry connection) - multi language support +- random = False ''' \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index 6abe4a0..b9f2567 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -1,6 +1,7 @@ import requests import random import json +from datetime import datetime, timezone from src.utils import logger, config, get_train_name, convert_iso_string @@ -35,55 +36,65 @@ def get_random_stop_id() -> str: return entry["id"] def get_random_connection(stop_id: str) -> str: - max_pages = 5 + now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + print(f"Aktuelle Zeit für Query: {now}") cursor = None - count = 20 + max_pages = 5 + min_results = 5 + trip_ids = [] + all_stop_times = [] for _ in range(max_pages): - params = f"stopId={stop_id}&n={count}" + params = { + "stopId": stop_id, + "n": 20, + "time": now, + } if cursor: - params += f"&pageCursor={cursor}" + params["pageCursor"] = cursor - req = f"{endpoint}/api/v1/stoptimes?{params}" - - try: - response = requests.get(req, headers=headers) - response.raise_for_status() - data = response.json() - except requests.RequestException as e: - print(e) - return None - - trip_ids = [] - stop_times = data.get("stopTimes", []) - for entry in stop_times: - trip_id = entry["tripId"] - if entry["mode"] in blacklist: - continue - trip_ids.append(trip_id) - - if len(trip_ids) >= 5: + try: + response = requests.get(f"{endpoint}/api/v5/stoptimes", params=params, headers=headers) + response.raise_for_status() + data = response.json() + except requests.RequestException as e: + print(e) break + + stop_times = data.get("stopTimes", []) + all_stop_times.extend(stop_times) + for entry in stop_times: + dep = entry.get("place", {}).get("departure") or entry.get("place", {}).get("arrival") + print(f"{entry.get('mode')}: {convert_iso_string(dep)}") + trip_id = entry["tripId"] + if entry["mode"] in blacklist: + continue + trip_ids.append(entry["tripId"]) + + if len(trip_ids) >= min_results: + break + cursor = data.get("nextPageCursor") if not cursor: break - if not trip_ids: + if not trip_ids: logger("Couldn't find any connection", "fatal") return None - + trip_id = random.choice(trip_ids) - for trip in stop_times: - if trip.get("tripId") == trip_id: - from_station = trip.get("place").get("name") + + from_station = None + for entry in all_stop_times: + if entry.get("tripId") == trip_id: + from_station = entry.get("place", {}).get("name") break - print(from_station) return { "trip_id": trip_id, "from_station": from_station - } + } def get_trip_details(trip_id: str, from_station: str) -> dict: req = f"{endpoint}/api/v2/trip?tripId={trip_id}" @@ -108,7 +119,7 @@ def get_trip_details(trip_id: str, from_station: str) -> dict: departure = convert_iso_string(start_time) arrival = convert_iso_string(end_time) train_name = get_train_name(display_name, mode) - + trip_details = { "long_name": f"{train_name} nach {goes_to} von {from_station}", "short_name": display_name, diff --git a/src/data/operators.py b/src/data/operators.py index 2b9ccfa..e301893 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -38,7 +38,7 @@ OPERATORS = { "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/ODEG-Logo_Neu.svg/960px-ODEG-Logo_Neu.svg.png", "color": 0x00745C }, - "Nederlandse Spoorwegen": { + "NS": { "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3d/Logo_NS.svg/960px-Logo_NS.svg.png", "color": 0X00337F, "slogan": ["Goed op weg", "Welkom in de trein van morgen", "Veilig, Vlug, Voordelig", "we haben een serious probleem", "Neuken in de keuken"] diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 6599691..c7f0b53 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -1,26 +1,22 @@ import discord import asyncio -from datetime import datetime +from datetime import datetime, timedelta, date -from src.api import transitous -from src.utils import logger, channel_formatting +from src.utils import logger, channel_formatting, choose_connection _scheduled_task: asyncio.Task | None = None async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = False): - global trip + global trip, _scheduled_task if not from_scheduler and _scheduled_task and not _scheduled_task.done(): _scheduled_task.cancel() - station_id = transitous.get_random_stop_id() - connection = transitous.get_random_connection(station_id) - trip = transitous.get_trip_details(connection["trip_id"], connection["from_station"]) - + trip = choose_connection() arrival = trip["arrival"] long_name = trip["long_name"] print("-----------------") - logger(f"Umstieg: {long_name}, Ankunft: {arrival}") + logger(f"Umstieg: {long_name}, Ankunft: {arrival} Uhr") logger(f"Betreiber: {trip["agency"]}, Typ: {trip["mode"]}") logger(f"Versuche Namen zu ändern, wenn nichts passiert bin ich im cooldown... (warte bis zu 10min!)") @@ -30,3 +26,23 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals logger(f"Name geändert!") + _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, arrival)) + +async def _schedule_next_transfer(bot, arrival): + now = datetime.now() + parsed_time = datetime.strptime(arrival, "%H:%M").time() + arrival_dt = datetime.combine(date.today(), parsed_time) + + if arrival_dt < now: + arrival_dt += timedelta(days=1) + + wait_seconds = (arrival_dt - now).total_seconds() + if wait_seconds > 0: + remaining = str(timedelta(seconds=wait_seconds)) + logger(f"Nächster Umstieg in {remaining.split('.')[0]} ({arrival} Uhr)") + + await asyncio.sleep(wait_seconds) + + logger("Zug angekommen, wähle neue Verbindung") + await rename_vc(bot, from_scheduler=True) + diff --git a/src/utils.py b/src/utils.py index 8c82ed4..3c00290 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,11 +1,11 @@ import json import os from datetime import datetime, timedelta +from zoneinfo import ZoneInfo import src.data.operators as operators from src.data.emojis import emoji_list - with open("config.json", "r") as file: config = json.load(file) @@ -16,8 +16,19 @@ def logger(msg, log_type="info") -> str: if status == "FATAL": os._exit(1) +def choose_connection() -> dict: + from src.api import transitous + station_id = transitous.get_random_stop_id() + connection = transitous.get_random_connection(station_id) + trip = transitous.get_trip_details(connection["trip_id"], connection["from_station"]) + + return trip + def convert_iso_string(isostring) -> str: + timezone = config.get("timezone", "Europe/Berlin") dt = datetime.fromisoformat(isostring.replace('Z', '+00:00')) + dt = dt.astimezone(ZoneInfo(timezone)) + if dt.second >= 30: dt += timedelta(minutes=1) From 1892c734cd264417aa11fc2bc64ede2066e6f863 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 11:00:31 +0200 Subject: [PATCH 11/48] transitous rewrite: fix params string --- main.py | 2 +- src/api/transitous.py | 8 ++++---- src/data/emojis.py | 1 + src/data/operators.py | 6 ++++-- src/utils.py | 21 +++++++++++++++++++++ 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/main.py b/main.py index 0121fc8..e76d5c8 100644 --- a/main.py +++ b/main.py @@ -31,7 +31,7 @@ except: ''' TODO - 1024 embed limit -- Automatic transfer +- automatic reload of operators - discord status - text announcements - voice announcements diff --git a/src/api/transitous.py b/src/api/transitous.py index b9f2567..68ef964 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -17,10 +17,10 @@ endpoint = "https://api.transitous.org" def get_random_stop_id() -> str: assigned_station = random.choice(stations) - req = f"{endpoint}/api/v1/geocode?text={assigned_station}" + req = f"{endpoint}/api/v1/geocode" try: - response = requests.get(req, headers=headers) + response = requests.get(req, params={"text": assigned_station}, headers=headers) response.raise_for_status() data = response.json() except requests.RequestException as e: @@ -97,10 +97,10 @@ def get_random_connection(stop_id: str) -> str: } def get_trip_details(trip_id: str, from_station: str) -> dict: - req = f"{endpoint}/api/v2/trip?tripId={trip_id}" + req = f"{endpoint}/api/v2/trip" try: - response = requests.get(req, headers=headers) + response = requests.get(req, params={"tripId": trip_id}, headers=headers) response.raise_for_status() data = response.json() except requests.RequestException as e: diff --git a/src/data/emojis.py b/src/data/emojis.py index 22fafcc..4238dfe 100644 --- a/src/data/emojis.py +++ b/src/data/emojis.py @@ -1,6 +1,7 @@ emoji_list = { "Fallback": "💺", "BUS": "🚎", + "COACH": "🚎", "TRAM": "🚈", "REGIONAL_RAIL": "🚊", "HIGHSPEED_RAIL": "🚅", diff --git a/src/data/operators.py b/src/data/operators.py index e301893..098e98b 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -109,10 +109,12 @@ OPERATOR_ALIASES = { "DB Regio AG Bayern": OPERATORS["db_bayern"], "DB Fernverkehr AG": OPERATORS["db_allgemein"], "DB Regio AG NRW": OPERATORS["db_allgemein"], - "DB Regio AG Nord": OPERATORS["db_allgemein"], "DB Regio AG Südost": OPERATORS["db_allgemein"], "DB Regio AG Nordost": OPERATORS["db_allgemein"], "DB Regio AG Mitte": OPERATORS["db_allgemein"], "SBB GmbH": OPERATORS["SBB"], "Schweizerische Bundesbahnen SBB": OPERATORS["SBB"], -} \ No newline at end of file +} + + + diff --git a/src/utils.py b/src/utils.py index 3c00290..3ea006f 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,11 +1,14 @@ import json import os +import importlib from datetime import datetime, timedelta from zoneinfo import ZoneInfo import src.data.operators as operators from src.data.emojis import emoji_list +_operator_mtime = None + with open("config.json", "r") as file: config = json.load(file) @@ -54,7 +57,25 @@ def get_train_name(train_name: str, mode: str) -> str: return train +def _reload_operators_if_changed(): + global _operator_mtime + + path = operators.__file__ + current_mtime = os.path.getmtime(path) + + if _operator_mtime is None: + _operator_mtime = current_mtime + return + + if current_mtime != _operator_mtime: + importlib.reload(operators) + _operator_mtime = current_mtime + logger("operators.py wurde automatisch neu geladen (Änderungen erkannt)") + + def get_operator_metadata(agency: str, route_color: str) -> dict: + _reload_operators_if_changed() + op_data = operators.OPERATOR_ALIASES.get(agency) or operators.OPERATORS.get(agency) or operators.OPERATORS["fallback"] logo = op_data.get("logo", operators.OPERATORS["fallback"]["logo"]) From 1b0b10dc4587ccf696bbaefd64e77ec27a5cd95c Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:11:05 +0200 Subject: [PATCH 12/48] transitous rewrite: validate connections --- main.py | 3 +- src/api/transitous.py | 54 ++++++++++++++++-------- src/data/assets/transitous-logo.license | 2 + src/data/assets/transitous-logo.png | Bin 0 -> 1351 bytes src/dc/handlers.py | 22 +++++++--- src/utils.py | 25 ++++++++--- 6 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 src/data/assets/transitous-logo.license create mode 100644 src/data/assets/transitous-logo.png diff --git a/main.py b/main.py index e76d5c8..812affc 100644 --- a/main.py +++ b/main.py @@ -31,11 +31,10 @@ except: ''' TODO - 1024 embed limit -- automatic reload of operators - discord status - text announcements - voice announcements - improved error handling (retry connection) - multi language support -- random = False +- README ''' \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index 68ef964..fcf67af 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -1,9 +1,9 @@ import requests import random import json -from datetime import datetime, timezone +from datetime import datetime, timezone, timedelta -from src.utils import logger, config, get_train_name, convert_iso_string +from src.utils import logger, config, get_train_name, convert_iso_string, validate_connection stations = config["stations"] blacklist = config["blacklist"] @@ -15,8 +15,9 @@ headers = { endpoint = "https://api.transitous.org" -def get_random_stop_id() -> str: +def get_random_stop_id() -> str | None: assigned_station = random.choice(stations) + logger(f"Station: {assigned_station}") req = f"{endpoint}/api/v1/geocode" try: @@ -24,18 +25,30 @@ def get_random_stop_id() -> str: response.raise_for_status() data = response.json() except requests.RequestException as e: - logger(f"An error occured while searching for a connection: {e}", "fatal") + logger(f"An error occured while searching for a connection: {e}", "error") return None if response.status_code == 404: - logger(f"Error finding station '{assigned_station}'") + logger(f"Error finding station '{assigned_station}'", "error") + return None + id = [] for entry in data: if entry.get("type") != "STOP": continue - return entry["id"] + entry_id = entry.get("id", None) + id.append(entry_id) -def get_random_connection(stop_id: str) -> str: + if id is None: + logger(f"Failed to grab ID from '{assigned_station}'", "error") + return None + + return random.choice(id) + +def get_random_connection(stop_id: str) -> str | None: + if stop_id is None: + return None + now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") print(f"Aktuelle Zeit für Query: {now}") cursor = None @@ -58,15 +71,13 @@ def get_random_connection(stop_id: str) -> str: response.raise_for_status() data = response.json() except requests.RequestException as e: - print(e) + logger(e, "Error") break stop_times = data.get("stopTimes", []) all_stop_times.extend(stop_times) for entry in stop_times: - dep = entry.get("place", {}).get("departure") or entry.get("place", {}).get("arrival") - print(f"{entry.get('mode')}: {convert_iso_string(dep)}") trip_id = entry["tripId"] if entry["mode"] in blacklist: continue @@ -80,7 +91,7 @@ def get_random_connection(stop_id: str) -> str: break if not trip_ids: - logger("Couldn't find any connection", "fatal") + logger("Couldn't find any connection", "error") return None trip_id = random.choice(trip_ids) @@ -96,28 +107,36 @@ def get_random_connection(stop_id: str) -> str: "from_station": from_station } -def get_trip_details(trip_id: str, from_station: str) -> dict: +def get_trip_details(random_connection: dict | None) -> dict | None: + if random_connection is None: + return None + req = f"{endpoint}/api/v2/trip" try: - response = requests.get(req, params={"tripId": trip_id}, headers=headers) + response = requests.get(req, params={"tripId": random_connection["trip_id"]}, headers=headers) response.raise_for_status() data = response.json() except requests.RequestException as e: - logger(f"An error occured while trying to get the route details: {e}", "fatal") + logger(f"An error occured while trying to get the route details: {e}", "error") return None legs = data["legs"][0] - + end_time = legs["endTime"] + from_station = random_connection["from_station"] display_name = legs["displayName"] trip_from = legs["tripFrom"]["name"] goes_to = legs["tripTo"]["name"] start_time = legs["startTime"] - end_time = legs["endTime"] mode = legs["mode"] - departure = convert_iso_string(start_time) + is_valid = validate_connection(start_time, end_time) + if not is_valid: + return None + arrival = convert_iso_string(end_time) + departure = convert_iso_string(start_time) + train_name = get_train_name(display_name, mode) trip_details = { @@ -143,5 +162,6 @@ def get_trip_details(trip_id: str, from_station: str) -> dict: trip_details["departure"] = convert_iso_string(departure_time) trip_details["stops"][goes_to] = arrival + logger(json.dumps(trip_details, indent=4, ensure_ascii=False)) return trip_details diff --git a/src/data/assets/transitous-logo.license b/src/data/assets/transitous-logo.license new file mode 100644 index 0000000..4b5c5bb --- /dev/null +++ b/src/data/assets/transitous-logo.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2024 Mathis Brüchert +SPDX-License-Identifier: CC-BY-SA-4.0 \ No newline at end of file diff --git a/src/data/assets/transitous-logo.png b/src/data/assets/transitous-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0a351c549c68f4c1ccaee8c320b7c3eca1e2077a GIT binary patch literal 1351 zcmV-N1-SZ&P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91AfN*P1ONa40RR91AOHXW0IY^$^8f$@u}MThR9Fe^SA9$zMHGLtdv^=h z`@ZrSL_F#zglI0LX&XcJG!hlHL~KH8YOJ;zP1Rsx8vc+*qp4C2QAx2)Q%N?-) zg&n(s-tIUUH>T3?KZ<#IIxjMV?GHWC!*Ps`BmKx|?F%8cRs+b~S!c8u z?7fsp8a(5qoqGk16j-v00Esc36Y6wP?Q;kgVmMr+I#z; zbubAGj?8}`{7T4p5T@?F`qlP;wh|!NaI~a+|FAjr86YHp5Ujm-`0{>&VIQ~2s0dh{ z^JPn}5h7eZR|1v=Gq%UP1spU-aqxOY6ErHdc$ZWv{}jthsr-W8^6ALrxI8Eave zLC~ve*Th&-cPXu9GSt((Q9LAD;X=9uC$BxI>djKfSy}w&fx=v7I%fDkYKC>F1j5=% z5OeP>Mn^DW&Z(rBNf9jpJvG=e(U{BpiUP>lIA)`sROdv2-EEy&MMqAiztYmy74i>{ zLe1e;__8JSIZz-sW`-b_Jw1zZt^|ofUP^DxnzC?tRDoZ8P`_6Ghvui27NxQBe{Vx)15OK)oA~-|uH70Efe&^!N8G4Gj(d zNdSm86A-C$DZ5MRCUK^|AvYVHPxRLcLy3oDS=G+HUCw3SKmkAV6SD zc3UhK#pQBoa?XO+l!26#6e7zqM#{}st7{Hfc-Z#mtmJ0alE zcAG65v)xZOAWzP+R8s)lf-Bt;T0apgNgI?q2;KUb1>+xhp8u;!Kp1)-Hdnk{JSA1{>5L64DGtHvg^DzX9-OxF=8G-+=%C002ov JPDHLkV1j5QUF84( literal 0 HcmV?d00001 diff --git a/src/dc/handlers.py b/src/dc/handlers.py index c7f0b53..4ce76c8 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -11,24 +11,36 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals if not from_scheduler and _scheduled_task and not _scheduled_task.done(): _scheduled_task.cancel() + attempt = 0 + max_attempt = 10 trip = choose_connection() + while trip is None and attempt < max_attempt: + attempt += 1 + logger(f"Attempt {attempt}: Failed to select route, retrying...", "error") + trip = choose_connection() + + if trip is None: + logger(f"Failed to select route after {max_attempt} attempts", "fatal") + return False + arrival = trip["arrival"] long_name = trip["long_name"] + mode = trip["mode"] print("-----------------") logger(f"Umstieg: {long_name}, Ankunft: {arrival} Uhr") - logger(f"Betreiber: {trip["agency"]}, Typ: {trip["mode"]}") + logger(f"Betreiber: {trip["agency"]}, Typ: {mode}") logger(f"Versuche Namen zu ändern, wenn nichts passiert bin ich im cooldown... (warte bis zu 10min!)") - formatting = channel_formatting(trip["mode"]) + formatting = channel_formatting(mode) await voice_channel.edit(name=f"{formatting}{long_name}") await voice_channel.set_status(f"Ankunft um {arrival}") logger(f"Name geändert!") - _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, arrival)) + _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, arrival, voice_channel)) -async def _schedule_next_transfer(bot, arrival): +async def _schedule_next_transfer(bot, arrival, voice_channel): now = datetime.now() parsed_time = datetime.strptime(arrival, "%H:%M").time() arrival_dt = datetime.combine(date.today(), parsed_time) @@ -44,5 +56,5 @@ async def _schedule_next_transfer(bot, arrival): await asyncio.sleep(wait_seconds) logger("Zug angekommen, wähle neue Verbindung") - await rename_vc(bot, from_scheduler=True) + await rename_vc(bot, voice_channel, from_scheduler=True) diff --git a/src/utils.py b/src/utils.py index 3ea006f..34f6265 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,7 +1,7 @@ import json import os import importlib -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from zoneinfo import ZoneInfo import src.data.operators as operators @@ -19,14 +19,30 @@ def logger(msg, log_type="info") -> str: if status == "FATAL": os._exit(1) -def choose_connection() -> dict: +def choose_connection() -> dict | None: from src.api import transitous station_id = transitous.get_random_stop_id() connection = transitous.get_random_connection(station_id) - trip = transitous.get_trip_details(connection["trip_id"], connection["from_station"]) + trip = transitous.get_trip_details(connection) return trip +def validate_connection(start_time: str, end_time: str) -> bool: + now = datetime.now(timezone.utc) + start_dt = datetime.fromisoformat(start_time.replace("Z", "+00:00")) + end_dt = datetime.fromisoformat(end_time.replace("Z", "+00:00")) + max_wait_time = config.get("max_wait_time", 6) + + if end_dt < now: + logger(f"Verbindung liegt bereits in der Vergangenheit: {start_dt}", "error") + return False + + if start_dt > now + timedelta(hours=max_wait_time): + logger(f"Verbindung liegt zu weit in der Zukunft: {start_dt}", "error") + return False + + return True + def convert_iso_string(isostring) -> str: timezone = config.get("timezone", "Europe/Berlin") dt = datetime.fromisoformat(isostring.replace('Z', '+00:00')) @@ -34,7 +50,6 @@ def convert_iso_string(isostring) -> str: if dt.second >= 30: dt += timedelta(minutes=1) - return dt.strftime('%H:%M') def channel_formatting(mode: str) -> str: @@ -75,7 +90,7 @@ def _reload_operators_if_changed(): def get_operator_metadata(agency: str, route_color: str) -> dict: _reload_operators_if_changed() - + op_data = operators.OPERATOR_ALIASES.get(agency) or operators.OPERATORS.get(agency) or operators.OPERATORS["fallback"] logo = op_data.get("logo", operators.OPERATORS["fallback"]["logo"]) From 5a2d0bf8d6d4135eb72ae8934d92cebfe69d16dd Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 14:04:55 +0200 Subject: [PATCH 13/48] transitous rewrite: bug fixes don't know anymore :( --- .gitignore | 3 ++- src/api/transitous.py | 32 +++++++++++++++++++++----------- src/data/operators.py | 1 + src/dc/embeds.py | 2 -- src/dc/handlers.py | 2 +- src/utils.py | 10 ++++++---- 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index e337bbc..c61264a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ src/data/announcements/* !src/data/announcements/.gitkeep config.json src/legacy/ -main_legacy.py \ No newline at end of file +main_legacy.py +data.json \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index fcf67af..9f41c5c 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -1,7 +1,7 @@ import requests import random import json -from datetime import datetime, timezone, timedelta +from datetime import datetime, timezone from src.utils import logger, config, get_train_name, convert_iso_string, validate_connection @@ -32,18 +32,18 @@ def get_random_stop_id() -> str | None: logger(f"Error finding station '{assigned_station}'", "error") return None - id = [] + id = None for entry in data: if entry.get("type") != "STOP": continue - entry_id = entry.get("id", None) - id.append(entry_id) + id = entry.get("id", None) + break if id is None: logger(f"Failed to grab ID from '{assigned_station}'", "error") return None - - return random.choice(id) + + return id def get_random_connection(stop_id: str) -> str | None: if stop_id is None: @@ -81,7 +81,9 @@ def get_random_connection(stop_id: str) -> str | None: trip_id = entry["tripId"] if entry["mode"] in blacklist: continue - trip_ids.append(entry["tripId"]) + else: + print(entry["mode"]) + trip_ids.append(entry["tripId"]) if len(trip_ids) >= min_results: break @@ -125,8 +127,8 @@ def get_trip_details(random_connection: dict | None) -> dict | None: end_time = legs["endTime"] from_station = random_connection["from_station"] display_name = legs["displayName"] - trip_from = legs["tripFrom"]["name"] - goes_to = legs["tripTo"]["name"] + trip_from = legs["from"]["name"] + goes_to = legs["to"]["name"] start_time = legs["startTime"] mode = legs["mode"] @@ -138,9 +140,13 @@ def get_trip_details(random_connection: dict | None) -> dict | None: departure = convert_iso_string(start_time) train_name = get_train_name(display_name, mode) - + if trip_from == from_station: + long_name = f"{train_name} nach {goes_to} von {trip_from}" + else: + long_name = f"{train_name} nach {goes_to} von {trip_from}, über {from_station}" + trip_details = { - "long_name": f"{train_name} nach {goes_to} von {from_station}", + "long_name": long_name, "short_name": display_name, "from": from_station, "to": goes_to, @@ -154,6 +160,7 @@ def get_trip_details(random_connection: dict | None) -> dict | None: } trip_details["stops"][trip_from] = departure + print(trip_from) for stop in legs["intermediateStops"]: stop_arrival = convert_iso_string(stop["arrival"]) trip_details["stops"][stop["name"]] = stop_arrival @@ -162,6 +169,9 @@ def get_trip_details(random_connection: dict | None) -> dict | None: trip_details["departure"] = convert_iso_string(departure_time) trip_details["stops"][goes_to] = arrival + with open('data.json', 'w') as f: + json.dump(data, f, indent=4, ensure_ascii=False) + logger(json.dumps(trip_details, indent=4, ensure_ascii=False)) return trip_details diff --git a/src/data/operators.py b/src/data/operators.py index 098e98b..6dc3a9f 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -112,6 +112,7 @@ OPERATOR_ALIASES = { "DB Regio AG Südost": OPERATORS["db_allgemein"], "DB Regio AG Nordost": OPERATORS["db_allgemein"], "DB Regio AG Mitte": OPERATORS["db_allgemein"], + "NS International": OPERATORS["NS"], "SBB GmbH": OPERATORS["SBB"], "Schweizerische Bundesbahnen SBB": OPERATORS["SBB"], } diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 6ffa2ee..8b1973f 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -45,6 +45,4 @@ def build_info_embed() -> discord.Embed: embed.set_author(name=agency) embed.set_thumbnail(url=metadata["logo"]) - color = trip.get("color", "keine farbe :(") - print(color) return embed \ No newline at end of file diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 4ce76c8..3607904 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -28,7 +28,7 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals mode = trip["mode"] print("-----------------") - logger(f"Umstieg: {long_name}, Ankunft: {arrival} Uhr") + logger(f"Umstieg: {long_name}; Ankunft: {arrival} Uhr") logger(f"Betreiber: {trip["agency"]}, Typ: {mode}") logger(f"Versuche Namen zu ändern, wenn nichts passiert bin ich im cooldown... (warte bis zu 10min!)") diff --git a/src/utils.py b/src/utils.py index 34f6265..ab3ba51 100644 --- a/src/utils.py +++ b/src/utils.py @@ -30,6 +30,7 @@ def choose_connection() -> dict | None: def validate_connection(start_time: str, end_time: str) -> bool: now = datetime.now(timezone.utc) start_dt = datetime.fromisoformat(start_time.replace("Z", "+00:00")) + print(start_dt) end_dt = datetime.fromisoformat(end_time.replace("Z", "+00:00")) max_wait_time = config.get("max_wait_time", 6) @@ -94,18 +95,19 @@ def get_operator_metadata(agency: str, route_color: str) -> dict: op_data = operators.OPERATOR_ALIASES.get(agency) or operators.OPERATORS.get(agency) or operators.OPERATORS["fallback"] logo = op_data.get("logo", operators.OPERATORS["fallback"]["logo"]) - slogans = op_data.get("slogans") + slogans = op_data.get("slogan") color = op_data.get("color") if color is None: if route_color is not None: try: - color = int(f"0x{route_color.upper()}") + color = int(route_color, 16) except ValueError: color = operators.OPERATORS["fallback"]["color"] + else: + logger(f"Managed to get color from API: {color}") else: - color = operators.OPERATORS["fallback"]["colors"] - + color = operators.OPERATORS["fallback"]["color"] return { "logo": logo, "color": color, From a4d9cb36f0a6c439e11bbb286a0a833645b9e256 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 14:23:56 +0200 Subject: [PATCH 14/48] transitous rewrite: fix color from API --- src/api/transitous.py | 19 +++++++++---------- src/dc/embeds.py | 4 ++-- src/utils.py | 6 +++--- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index 9f41c5c..687a00d 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -17,7 +17,6 @@ endpoint = "https://api.transitous.org" def get_random_stop_id() -> str | None: assigned_station = random.choice(stations) - logger(f"Station: {assigned_station}") req = f"{endpoint}/api/v1/geocode" try: @@ -50,7 +49,6 @@ def get_random_connection(stop_id: str) -> str | None: return None now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") - print(f"Aktuelle Zeit für Query: {now}") cursor = None max_pages = 5 min_results = 5 @@ -82,7 +80,6 @@ def get_random_connection(stop_id: str) -> str | None: if entry["mode"] in blacklist: continue else: - print(entry["mode"]) trip_ids.append(entry["tripId"]) if len(trip_ids) >= min_results: @@ -104,6 +101,7 @@ def get_random_connection(stop_id: str) -> str | None: from_station = entry.get("place", {}).get("name") break + logger(f"Station: {from_station}") return { "trip_id": trip_id, "from_station": from_station @@ -127,7 +125,7 @@ def get_trip_details(random_connection: dict | None) -> dict | None: end_time = legs["endTime"] from_station = random_connection["from_station"] display_name = legs["displayName"] - trip_from = legs["from"]["name"] + train_from = legs["from"]["name"] goes_to = legs["to"]["name"] start_time = legs["startTime"] mode = legs["mode"] @@ -140,15 +138,16 @@ def get_trip_details(random_connection: dict | None) -> dict | None: departure = convert_iso_string(start_time) train_name = get_train_name(display_name, mode) - if trip_from == from_station: - long_name = f"{train_name} nach {goes_to} von {trip_from}" + if train_from == from_station: + long_name = f"{train_name} nach {goes_to} von {train_from}" else: - long_name = f"{train_name} nach {goes_to} von {trip_from}, über {from_station}" + long_name = f"{train_name} nach {goes_to} über {from_station}" trip_details = { "long_name": long_name, "short_name": display_name, - "from": from_station, + "station": from_station, + "from": train_from, "to": goes_to, "agency": legs["agencyName"], "route_color": legs.get("routeColor"), @@ -159,8 +158,8 @@ def get_trip_details(random_connection: dict | None) -> dict | None: "stops": {} } - trip_details["stops"][trip_from] = departure - print(trip_from) + trip_details["stops"][train_from] = departure + for stop in legs["intermediateStops"]: stop_arrival = convert_iso_string(stop["arrival"]) trip_details["stops"][stop["name"]] = stop_arrival diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 8b1973f..ae3ece3 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -27,13 +27,13 @@ def build_info_embed() -> discord.Embed: arrival = format_timestamp_to_dc(trip["arrival"]) embed = discord.Embed( title = trip["long_name"], - description=f"Abfahrt von {trip["from"]} um {departure}. Ankunft um {arrival}", + description=f"Abfahrt von {trip["station"]} um {departure}. Ankunft um {arrival}", color = metadata["color"] ) route_lines = [] for stop_name, stop_arrival in trip["stops"].items(): - if stop_name == trip["from"]: + if stop_name == trip["station"]: route_lines.append(f"**• {stop_name} ({stop_arrival} Uhr)**") else: route_lines.append(f"• {stop_name} ({stop_arrival} Uhr)") diff --git a/src/utils.py b/src/utils.py index ab3ba51..9fc05e3 100644 --- a/src/utils.py +++ b/src/utils.py @@ -30,7 +30,6 @@ def choose_connection() -> dict | None: def validate_connection(start_time: str, end_time: str) -> bool: now = datetime.now(timezone.utc) start_dt = datetime.fromisoformat(start_time.replace("Z", "+00:00")) - print(start_dt) end_dt = datetime.fromisoformat(end_time.replace("Z", "+00:00")) max_wait_time = config.get("max_wait_time", 6) @@ -98,14 +97,15 @@ def get_operator_metadata(agency: str, route_color: str) -> dict: slogans = op_data.get("slogan") color = op_data.get("color") - if color is None: + if color is None or color == 0xFFFFFF: if route_color is not None: try: color = int(route_color, 16) + print(color) except ValueError: color = operators.OPERATORS["fallback"]["color"] else: - logger(f"Managed to get color from API: {color}") + logger(f"Managed to get color from API, edit src/data/operators.py if you don't like it") else: color = operators.OPERATORS["fallback"]["color"] return { From 10e1ea8adeeebc423aec6d8d9bec3b0afddc9105 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 14:50:11 +0200 Subject: [PATCH 15/48] transitous rewrite: minimal route length --- src/api/transitous.py | 13 +++++++------ src/utils.py | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index 687a00d..14b14a7 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -130,10 +130,6 @@ def get_trip_details(random_connection: dict | None) -> dict | None: start_time = legs["startTime"] mode = legs["mode"] - is_valid = validate_connection(start_time, end_time) - if not is_valid: - return None - arrival = convert_iso_string(end_time) departure = convert_iso_string(start_time) @@ -159,15 +155,20 @@ def get_trip_details(random_connection: dict | None) -> dict | None: } trip_details["stops"][train_from] = departure - + departure_time = start_time + for stop in legs["intermediateStops"]: stop_arrival = convert_iso_string(stop["arrival"]) - trip_details["stops"][stop["name"]] = stop_arrival + trip_details["stops"][stop["name"]] = stop_arrival # not sure if that actually works but im too tired to question it if stop.get("name") == from_station: departure_time = stop["departure"] trip_details["departure"] = convert_iso_string(departure_time) trip_details["stops"][goes_to] = arrival + valid = validate_connection(start_time, end_time, departure_time) + if not valid: + return None + with open('data.json', 'w') as f: json.dump(data, f, indent=4, ensure_ascii=False) diff --git a/src/utils.py b/src/utils.py index 9fc05e3..b03de69 100644 --- a/src/utils.py +++ b/src/utils.py @@ -27,20 +27,27 @@ def choose_connection() -> dict | None: return trip -def validate_connection(start_time: str, end_time: str) -> bool: +def validate_connection(start_time: str, end_time: str, station_departure: str) -> bool: now = datetime.now(timezone.utc) - start_dt = datetime.fromisoformat(start_time.replace("Z", "+00:00")) + end_dt = datetime.fromisoformat(end_time.replace("Z", "+00:00")) - max_wait_time = config.get("max_wait_time", 6) - if end_dt < now: logger(f"Verbindung liegt bereits in der Vergangenheit: {start_dt}", "error") return False + max_wait_time = config.get("max_wait_time", 6) + start_dt = datetime.fromisoformat(start_time.replace("Z", "+00:00")) if start_dt > now + timedelta(hours=max_wait_time): logger(f"Verbindung liegt zu weit in der Zukunft: {start_dt}", "error") return False - + + station_departure_dt = datetime.fromisoformat(station_departure.replace("Z", "+00:00")) + trip_duration = (end_dt - station_departure_dt).total_seconds() + min_duration = config.get("min_duration", 600) + if trip_duration < min_duration: + logger(f"Verbindung ist zu kurz: Nur {trip_duration} Sekunden lang ({min_duration} gewollt)") + return False + return True def convert_iso_string(isostring) -> str: From 4598dcdc080a6ac4a821dd5fe754d9d20af38596 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 14:51:28 +0200 Subject: [PATCH 16/48] transitous rewrite: add logo license --- .../{transitous-logo.license => transitous-logo.png.license} | 0 src/dc/embeds.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/data/assets/{transitous-logo.license => transitous-logo.png.license} (100%) diff --git a/src/data/assets/transitous-logo.license b/src/data/assets/transitous-logo.png.license similarity index 100% rename from src/data/assets/transitous-logo.license rename to src/data/assets/transitous-logo.png.license diff --git a/src/dc/embeds.py b/src/dc/embeds.py index ae3ece3..b2b4db7 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -5,7 +5,7 @@ from src.utils import convert_iso_string, get_operator_metadata from src.dc.helpers import format_timestamp_to_dc def build_embed_footer(mode: str, slogans): - footer_notice = f"Data provided by https://transitous.org • Typ: {mode}" + footer_notice = f"Data provided by https://transitous.org • mode: {mode}" icon = "https://avatars.githubusercontent.com/u/24960008?s=60&v=4" if slogans is not None: From 1b0546ff4d6deb7f70e5a92cf5c263c0fb8f1872 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 15:20:07 +0200 Subject: [PATCH 17/48] transitous rewrite: add max_duration --- src/dc/handlers.py | 2 +- src/utils.py | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 3607904..d0b89c6 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -12,7 +12,7 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals _scheduled_task.cancel() attempt = 0 - max_attempt = 10 + max_attempt = 15 trip = choose_connection() while trip is None and attempt < max_attempt: attempt += 1 diff --git a/src/utils.py b/src/utils.py index b03de69..cfbeb7f 100644 --- a/src/utils.py +++ b/src/utils.py @@ -43,10 +43,20 @@ def validate_connection(start_time: str, end_time: str, station_departure: str) station_departure_dt = datetime.fromisoformat(station_departure.replace("Z", "+00:00")) trip_duration = (end_dt - station_departure_dt).total_seconds() + trip_duration_minutes = str(timedelta(seconds=trip_duration)) + min_duration = config.get("min_duration", 600) - if trip_duration < min_duration: - logger(f"Verbindung ist zu kurz: Nur {trip_duration} Sekunden lang ({min_duration} gewollt)") + min_duration_seconds = min_duration * 60 + if trip_duration < min_duration_seconds: + logger(f"Verbindung ist mit {trip_duration_minutes} zu kurz (mindestens {min_duration} Minuten gewollt)", "error") return False + + max_duration = config.get("max_duration", "") + if max_duration: + max_duration_seconds = max_duration * 60 + if max_duration_seconds < trip_duration: + logger(f"Verbindung ist mit {trip_duration_minutes} zu lang (höchstens {max_duration} Minuten gewollt)", "error") + return False return True @@ -104,7 +114,7 @@ def get_operator_metadata(agency: str, route_color: str) -> dict: slogans = op_data.get("slogan") color = op_data.get("color") - if color is None or color == 0xFFFFFF: + if color is None or color == operators.OPERATORS["fallback"]["color"]: if route_color is not None: try: color = int(route_color, 16) From a75b12ea319586f733ffb6672f6d45934e0f0662 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 15:59:08 +0200 Subject: [PATCH 18/48] transitous rewrite: via --- src/api/transitous.py | 2 +- src/data/emojis.py | 1 + src/data/operators.py | 6 ++++++ src/dc/embeds.py | 12 +++++++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index 14b14a7..09f1855 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -92,7 +92,7 @@ def get_random_connection(stop_id: str) -> str | None: if not trip_ids: logger("Couldn't find any connection", "error") return None - + print(trip_ids) trip_id = random.choice(trip_ids) from_station = None diff --git a/src/data/emojis.py b/src/data/emojis.py index 4238dfe..f5f8827 100644 --- a/src/data/emojis.py +++ b/src/data/emojis.py @@ -5,6 +5,7 @@ emoji_list = { "TRAM": "🚈", "REGIONAL_RAIL": "🚊", "HIGHSPEED_RAIL": "🚅", + "LONG_DISTANCE": "🚅", "METRO": "🚇", "SUBWAY": "🚇" } \ No newline at end of file diff --git a/src/data/operators.py b/src/data/operators.py index 6dc3a9f..5a09541 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -98,6 +98,10 @@ OPERATORS = { "enno": { "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Enno_logo.svg/960px-Enno_logo.svg.png", "color": 0x88216F + }, + "DSB": { + "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/87/DSB_company_logo.svg/960px-DSB_company_logo.svg.png", + "color": 0xB22B32 } } @@ -111,10 +115,12 @@ OPERATOR_ALIASES = { "DB Regio AG NRW": OPERATORS["db_allgemein"], "DB Regio AG Südost": OPERATORS["db_allgemein"], "DB Regio AG Nordost": OPERATORS["db_allgemein"], + "DB Regio AG Nord": OPERATORS["db_allgemein"], "DB Regio AG Mitte": OPERATORS["db_allgemein"], "NS International": OPERATORS["NS"], "SBB GmbH": OPERATORS["SBB"], "Schweizerische Bundesbahnen SBB": OPERATORS["SBB"], + "Dänische Staatsbahnen": OPERATORS["DSB"] } diff --git a/src/dc/embeds.py b/src/dc/embeds.py index b2b4db7..854388a 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -31,8 +31,18 @@ def build_info_embed() -> discord.Embed: color = metadata["color"] ) + stops = trip["stops"] + + if len(stops) > 2: + count = min(3, len(stops)) + random_stops = random.sample(list(stops), k=count) + + via = ", ".join(random_stops[:-1]) + " und " + random_stops[-1] + embed.add_field(name="Über", value=via, inline=False) + + route_lines = [] - for stop_name, stop_arrival in trip["stops"].items(): + for stop_name, stop_arrival in stops.items(): if stop_name == trip["station"]: route_lines.append(f"**• {stop_name} ({stop_arrival} Uhr)**") else: From c563062b9a90253765bffbd59022961d648976b1 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 17:22:50 +0200 Subject: [PATCH 19/48] transitous rewrite: announcements --- main.py | 1 - src/dc/embeds.py | 21 +++++++++++++++- src/dc/handlers.py | 63 +++++++++++++++++++++++++++++++++++++++++++--- src/dc/helpers.py | 2 +- src/utils.py | 28 ++++++++++++++++++++- 5 files changed, 107 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index 812affc..b11792c 100644 --- a/main.py +++ b/main.py @@ -34,7 +34,6 @@ TODO - discord status - text announcements - voice announcements -- improved error handling (retry connection) - multi language support - README ''' \ No newline at end of file diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 854388a..0e1f11b 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -55,4 +55,23 @@ def build_info_embed() -> discord.Embed: embed.set_author(name=agency) embed.set_thumbnail(url=metadata["logo"]) - return embed \ No newline at end of file + return embed + +def build_announcement_embed(msg): + from src.dc.handlers import trip + agency = trip["agency"] + metadata = get_operator_metadata(agency, trip["route_color"]) + + embed = discord.Embed( + title = "Informationen zu ihrer Fahrt", + description=msg, + color=metadata["color"] + ) + + embed.set_author(name=agency) + embed.set_thumbnail(url=metadata["logo"]) + + footer = build_embed_footer(trip["mode"], metadata.get("slogan")) + embed.set_footer(text=footer["text"], icon_url=footer["icon"]) + + return embed diff --git a/src/dc/handlers.py b/src/dc/handlers.py index d0b89c6..bcfbb7a 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -1,8 +1,9 @@ import discord import asyncio +import random from datetime import datetime, timedelta, date -from src.utils import logger, channel_formatting, choose_connection +from src.utils import logger, channel_formatting, choose_connection, config, get_sound_path _scheduled_task: asyncio.Task | None = None @@ -38,9 +39,12 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals logger(f"Name geändert!") - _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, arrival, voice_channel)) + await announcer(bot, "umstieg", voice_channel) -async def _schedule_next_transfer(bot, arrival, voice_channel): + _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, arrival, voice_channel, trip["to"])) + + +async def _schedule_next_transfer(bot: discord.Bot, arrival, voice_channel: discord.VoiceChannel, destination: str): now = datetime.now() parsed_time = datetime.strptime(arrival, "%H:%M").time() arrival_dt = datetime.combine(date.today(), parsed_time) @@ -49,12 +53,63 @@ async def _schedule_next_transfer(bot, arrival, voice_channel): arrival_dt += timedelta(days=1) wait_seconds = (arrival_dt - now).total_seconds() +# announcement_countdown = random.randrange(180, 300) + announcement_countdown = 3 if wait_seconds > 0: remaining = str(timedelta(seconds=wait_seconds)) logger(f"Nächster Umstieg in {remaining.split('.')[0]} ({arrival} Uhr)") - await asyncio.sleep(wait_seconds) + if wait_seconds > announcement_countdown: + wait_until_end_announcement = wait_seconds - announcement_countdown +# await asyncio.sleep(wait_until_end_announcement) + await asyncio.sleep(5) + await announcer(bot, "ende", voice_channel, destination) + await asyncio.sleep(announcement_countdown) + else: + await asyncio.sleep(wait_seconds) logger("Zug angekommen, wähle neue Verbindung") await rename_vc(bot, voice_channel, from_scheduler=True) +async def announcer(bot: discord.Bot, announcement: str, voice_channel: discord.VoiceChannel, destination = None): + from src.dc.embeds import build_info_embed, build_announcement_embed + + announcements_enabled = config.get("announcements", True) + voice_announcement_enabled = config["voice_announcements"][0]["enabled"] + + if announcements_enabled: + if len(voice_channel.members) > 0: + match announcement: + case "ende": + embed = build_announcement_embed( + f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für ihr Vertrauen und auf Wiedersehen.') + if voice_announcement_enabled: + await voice_announcer(bot, destination, voice_channel) + case "umstieg": + embed = build_info_embed() + case _: + logger(f"Unbekanntes Announcements: {announcement}") + embed = None + if embed: + await voice_channel.send(embed=embed) + else: + logger(f"Announcement {announcement} wird geskipped, keiner da") + return + +async def voice_announcer(bot: discord.bot, destination: str, voice_channel: discord.VoiceChannel): + sound_path = get_sound_path(destination=destination) + if sound_path is None: + return + + logger(f"VC wird betreten, spiele {sound_path}") + vc = await voice_channel.connect(timeout=15, reconnect=True) + audio_source = discord.FFmpegPCMAudio(sound_path) + + if not vc.is_playing(): + def after_playing(error): + if error: + logger(f"Player error: {error}", "error") + bot.loop.create_task(vc.disconnect()) + logger("VC wird verlassen") + + vc.play(audio_source, after=after_playing) \ No newline at end of file diff --git a/src/dc/helpers.py b/src/dc/helpers.py index cf1c7a8..23ee76f 100644 --- a/src/dc/helpers.py +++ b/src/dc/helpers.py @@ -1,6 +1,6 @@ import discord from datetime import datetime, timedelta -from src.utils import logger, convert_iso_string +from src.utils import logger def validate_channel(bot: discord.bot, server_id: int, channel_id: int): guild = bot.get_guild(server_id) diff --git a/src/utils.py b/src/utils.py index cfbeb7f..ed07d3a 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,6 +1,8 @@ import json import os import importlib +import random +from pathlib import Path from datetime import datetime, timedelta, timezone from zoneinfo import ZoneInfo @@ -129,4 +131,28 @@ def get_operator_metadata(agency: str, route_color: str) -> dict: "logo": logo, "color": color, "slogans": slogans - } \ No newline at end of file + } + +def get_sound_path(destination) -> str | None: + voice_announcement_config = config["voice_announcements"][0] + voice_stations = voice_announcement_config["stations"] + + if destination in voice_stations: + announcement_for = destination + else: + general_config = voice_stations.get("general", "") + if general_config == "": + return None + announcement_for = "general" + + if voice_stations.values() == list: + sound_file = random.choice(voice_stations.get(announcement_for)) + else: + sound_file = voice_stations.get(announcement_for) + + sound_path = f"src/data/announcements/{sound_file}" + if Path(sound_path).is_file() is False: + logger(f"Konnte Datei {sound_path} nicht finden", "error") + return None + + return sound_path \ No newline at end of file From 2ec38c18740a2c9a39208cd0fe3ef18efa9d8ba9 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 17:33:18 +0200 Subject: [PATCH 20/48] transitous rewrite: announcer improvements --- src/dc/handlers.py | 18 ++++++++++-------- src/utils.py | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/dc/handlers.py b/src/dc/handlers.py index bcfbb7a..fa318cc 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -39,7 +39,7 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals logger(f"Name geändert!") - await announcer(bot, "umstieg", voice_channel) + await announcer("umstieg", voice_channel) _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, arrival, voice_channel, trip["to"])) @@ -53,7 +53,7 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival, voice_channel: disc arrival_dt += timedelta(days=1) wait_seconds = (arrival_dt - now).total_seconds() -# announcement_countdown = random.randrange(180, 300) + announcement_countdown = random.randrange(180, 300) announcement_countdown = 3 if wait_seconds > 0: remaining = str(timedelta(seconds=wait_seconds)) @@ -61,9 +61,9 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival, voice_channel: disc if wait_seconds > announcement_countdown: wait_until_end_announcement = wait_seconds - announcement_countdown -# await asyncio.sleep(wait_until_end_announcement) + await asyncio.sleep(wait_until_end_announcement) await asyncio.sleep(5) - await announcer(bot, "ende", voice_channel, destination) + await announcer("ende", voice_channel, destination) await asyncio.sleep(announcement_countdown) else: await asyncio.sleep(wait_seconds) @@ -71,7 +71,7 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival, voice_channel: disc logger("Zug angekommen, wähle neue Verbindung") await rename_vc(bot, voice_channel, from_scheduler=True) -async def announcer(bot: discord.Bot, announcement: str, voice_channel: discord.VoiceChannel, destination = None): +async def announcer(announcement: str, voice_channel: discord.VoiceChannel, destination = None): from src.dc.embeds import build_info_embed, build_announcement_embed announcements_enabled = config.get("announcements", True) @@ -84,7 +84,7 @@ async def announcer(bot: discord.Bot, announcement: str, voice_channel: discord. embed = build_announcement_embed( f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für ihr Vertrauen und auf Wiedersehen.') if voice_announcement_enabled: - await voice_announcer(bot, destination, voice_channel) + await voice_announcer(destination, voice_channel) case "umstieg": embed = build_info_embed() case _: @@ -96,7 +96,7 @@ async def announcer(bot: discord.Bot, announcement: str, voice_channel: discord. logger(f"Announcement {announcement} wird geskipped, keiner da") return -async def voice_announcer(bot: discord.bot, destination: str, voice_channel: discord.VoiceChannel): +async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel): sound_path = get_sound_path(destination=destination) if sound_path is None: return @@ -105,11 +105,13 @@ async def voice_announcer(bot: discord.bot, destination: str, voice_channel: dis vc = await voice_channel.connect(timeout=15, reconnect=True) audio_source = discord.FFmpegPCMAudio(sound_path) + loop = asyncio.get_running_loop() + if not vc.is_playing(): def after_playing(error): if error: logger(f"Player error: {error}", "error") - bot.loop.create_task(vc.disconnect()) + loop.create_task(vc.disconnect()) logger("VC wird verlassen") vc.play(audio_source, after=after_playing) \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index ed07d3a..216621e 100644 --- a/src/utils.py +++ b/src/utils.py @@ -141,7 +141,7 @@ def get_sound_path(destination) -> str | None: announcement_for = destination else: general_config = voice_stations.get("general", "") - if general_config == "": + if not general_config: return None announcement_for = "general" From cdceeb4e44658341cc652ffe1de36dbd9b8766b3 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 17:46:46 +0200 Subject: [PATCH 21/48] transitous rewrite: fix default duration values --- src/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.py b/src/utils.py index 216621e..65cb083 100644 --- a/src/utils.py +++ b/src/utils.py @@ -47,7 +47,7 @@ def validate_connection(start_time: str, end_time: str, station_departure: str) trip_duration = (end_dt - station_departure_dt).total_seconds() trip_duration_minutes = str(timedelta(seconds=trip_duration)) - min_duration = config.get("min_duration", 600) + min_duration = config.get("min_duration", 10) min_duration_seconds = min_duration * 60 if trip_duration < min_duration_seconds: logger(f"Verbindung ist mit {trip_duration_minutes} zu kurz (mindestens {min_duration} Minuten gewollt)", "error") From ca3f93f4cd3ffd9ca9617f92915d179bd1b56231 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 18:05:31 +0200 Subject: [PATCH 22/48] transitous rewrite: split /info embed if more than 1024 characters --- src/api/transitous.py | 1 - src/dc/embeds.py | 24 +++++++++++++++--------- src/utils.py | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index 09f1855..f8c168f 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -92,7 +92,6 @@ def get_random_connection(stop_id: str) -> str | None: if not trip_ids: logger("Couldn't find any connection", "error") return None - print(trip_ids) trip_id = random.choice(trip_ids) from_station = None diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 0e1f11b..e317a84 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -1,12 +1,12 @@ import discord import random -from src.utils import convert_iso_string, get_operator_metadata +from src.utils import get_operator_metadata from src.dc.helpers import format_timestamp_to_dc def build_embed_footer(mode: str, slogans): footer_notice = f"Data provided by https://transitous.org • mode: {mode}" - icon = "https://avatars.githubusercontent.com/u/24960008?s=60&v=4" + icon = "https://raw.githubusercontent.com/kaaninchen/Gleiswechsel/refs/heads/main/src/data/assets/transitous-logo.png" if slogans is not None: footer_text = f"{random.choice(slogans)} • {footer_notice}" @@ -40,14 +40,20 @@ def build_info_embed() -> discord.Embed: via = ", ".join(random_stops[:-1]) + " und " + random_stops[-1] embed.add_field(name="Über", value=via, inline=False) + field_lines, field_length, part = [], 0, 1 - route_lines = [] - for stop_name, stop_arrival in stops.items(): - if stop_name == trip["station"]: - route_lines.append(f"**• {stop_name} ({stop_arrival} Uhr)**") - else: - route_lines.append(f"• {stop_name} ({stop_arrival} Uhr)") - embed.add_field(name="Route", value="\n".join(route_lines)) + for name, stop_arrival in stops.items(): + line = f"**• {name} ({stop_arrival} Uhr)**" if name == trip["station"] else f"• {name} ({stop_arrival} Uhr)" + + if field_length + len(line) + 1 > 1024: + embed.add_field(name="Route" if part == 1 else "Route (Fortsetzung)", value="\n".join(field_lines), inline=True) + field_lines, field_length, part = [], 0, part + 1 + + field_lines.append(line) + field_length += len(line) + 1 + + if field_lines: + embed.add_field(name="Route" if part == 1 else "Route (Fortsetzung)", value="\n".join(field_lines), inline=True) footer = build_embed_footer(trip["mode"], metadata["slogans"]) embed.set_footer(text=footer["text"], icon_url=footer["icon"]) diff --git a/src/utils.py b/src/utils.py index 65cb083..448c5d2 100644 --- a/src/utils.py +++ b/src/utils.py @@ -124,7 +124,7 @@ def get_operator_metadata(agency: str, route_color: str) -> dict: except ValueError: color = operators.OPERATORS["fallback"]["color"] else: - logger(f"Managed to get color from API, edit src/data/operators.py if you don't like it") + logger(f"Managed to get color from API, add agency to src/data/operators.py if you don't like it") else: color = operators.OPERATORS["fallback"]["color"] return { From ff8c2f55db4b65b7cc958d66cd7c23103994987a Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:12:20 +0200 Subject: [PATCH 23/48] transitous rewrite: improved station selection --- main.py | 4 +--- src/api/transitous.py | 27 +++++++++++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/main.py b/main.py index b11792c..2161cd4 100644 --- a/main.py +++ b/main.py @@ -30,10 +30,8 @@ except: ''' TODO -- 1024 embed limit - discord status -- text announcements -- voice announcements +- config cleanup - multi language support - README ''' \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index f8c168f..ed75d21 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -27,22 +27,30 @@ def get_random_stop_id() -> str | None: logger(f"An error occured while searching for a connection: {e}", "error") return None - if response.status_code == 404: - logger(f"Error finding station '{assigned_station}'", "error") - return None - - id = None + stop_ids = {} for entry in data: if entry.get("type") != "STOP": continue - id = entry.get("id", None) - break - if id is None: + stop_name = entry.get("name") + stop_id = entry.get("id", None) + stop_ids[stop_id] = stop_name + + if stop_name == assigned_station: + stop_ids.clear() + stop_ids[stop_id] = stop_name + break + + + if stop_ids is None: logger(f"Failed to grab ID from '{assigned_station}'", "error") return None - return id + stop_ids_list = list(stop_ids.keys()) + stops_string = ", ".join(stop_ids.values()) + logger(f"Availabe stations: {stops_string}") + chosen_stop_id = random.choice(stop_ids_list) + return chosen_stop_id def get_random_connection(stop_id: str) -> str | None: if stop_id is None: @@ -100,7 +108,6 @@ def get_random_connection(stop_id: str) -> str | None: from_station = entry.get("place", {}).get("name") break - logger(f"Station: {from_station}") return { "trip_id": trip_id, "from_station": from_station From 66289e8572796ebf9d61d7640ed65333d500e530 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 19:43:53 +0200 Subject: [PATCH 24/48] transitous rewrite: next_stop functionality --- src/dc/embeds.py | 18 +++++++++++++----- src/utils.py | 25 +++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/dc/embeds.py b/src/dc/embeds.py index e317a84..3cf5a9d 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -1,7 +1,7 @@ import discord import random -from src.utils import get_operator_metadata +from src.utils import get_operator_metadata, get_next_station from src.dc.helpers import format_timestamp_to_dc def build_embed_footer(mode: str, slogans): @@ -25,6 +25,8 @@ def build_info_embed() -> discord.Embed: metadata = get_operator_metadata(agency, trip["route_color"]) departure = format_timestamp_to_dc(trip["departure"]) arrival = format_timestamp_to_dc(trip["arrival"]) + next_stop = get_next_station(trip["stops"]) + embed = discord.Embed( title = trip["long_name"], description=f"Abfahrt von {trip["station"]} um {departure}. Ankunft um {arrival}", @@ -37,23 +39,29 @@ def build_info_embed() -> discord.Embed: count = min(3, len(stops)) random_stops = random.sample(list(stops), k=count) - via = ", ".join(random_stops[:-1]) + " und " + random_stops[-1] + via = ", ".join(random_stops[:-1]) + " und " + random_stops[-1] + ". Nächster Halt: " + next_stop["name"] embed.add_field(name="Über", value=via, inline=False) field_lines, field_length, part = [], 0, 1 for name, stop_arrival in stops.items(): - line = f"**• {name} ({stop_arrival} Uhr)**" if name == trip["station"] else f"• {name} ({stop_arrival} Uhr)" + if name == next_stop["name"]: + line = f"**• {name} ({stop_arrival} Uhr)**" + else: + line = f"• {name} ({stop_arrival} Uhr)" if field_length + len(line) + 1 > 1024: - embed.add_field(name="Route" if part == 1 else "Route (Fortsetzung)", value="\n".join(field_lines), inline=True) + route_page_name = "Route" + if part != 1: + route_page_name += " (Fortsetzung)" + embed.add_field(name=route_page_name, value="\n".join(field_lines), inline=False) field_lines, field_length, part = [], 0, part + 1 field_lines.append(line) field_length += len(line) + 1 if field_lines: - embed.add_field(name="Route" if part == 1 else "Route (Fortsetzung)", value="\n".join(field_lines), inline=True) + embed.add_field(name="Route" if part == 1 else "Route (Fortsetzung)", value="\n".join(field_lines), inline=False) footer = build_embed_footer(trip["mode"], metadata["slogans"]) embed.set_footer(text=footer["text"], icon_url=footer["icon"]) diff --git a/src/utils.py b/src/utils.py index 448c5d2..46f0491 100644 --- a/src/utils.py +++ b/src/utils.py @@ -3,7 +3,7 @@ import os import importlib import random from pathlib import Path -from datetime import datetime, timedelta, timezone +from datetime import datetime, timedelta, timezone, date from zoneinfo import ZoneInfo import src.data.operators as operators @@ -155,4 +155,25 @@ def get_sound_path(destination) -> str | None: logger(f"Konnte Datei {sound_path} nicht finden", "error") return None - return sound_path \ No newline at end of file + return sound_path + +def get_next_station(stops: dict) -> dict | None: + now = datetime.now() + today = datetime.today() + day_offset = 0 + previous_time = None + + for name, arrival_str in stops.items(): + arrival_time = datetime.strptime(arrival_str, "%H:%M").time() + + if previous_time is not None and arrival_time < previous_time: + day_offset += 1 + + arrival_dt = datetime.combine(today + timedelta(days=day_offset), arrival_time) + previous_time = arrival_time + + if arrival_dt >= now: + return {"name": name, "arrival": arrival_str} + + return None + \ No newline at end of file From 41e185a211dbafb18d48fb830e36df8d965928cd Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 20:18:16 +0200 Subject: [PATCH 25/48] transitous rewrite: code cleanup --- src/dc/embeds.py | 38 ++++++++++++-------------------------- src/utils.py | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 3cf5a9d..495d78b 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -1,7 +1,7 @@ import discord import random -from src.utils import get_operator_metadata, get_next_station +from src.utils import get_operator_metadata, get_next_station, format_via_list, format_stop_list from src.dc.helpers import format_timestamp_to_dc def build_embed_footer(mode: str, slogans): @@ -25,7 +25,6 @@ def build_info_embed() -> discord.Embed: metadata = get_operator_metadata(agency, trip["route_color"]) departure = format_timestamp_to_dc(trip["departure"]) arrival = format_timestamp_to_dc(trip["arrival"]) - next_stop = get_next_station(trip["stops"]) embed = discord.Embed( title = trip["long_name"], @@ -35,33 +34,20 @@ def build_info_embed() -> discord.Embed: stops = trip["stops"] - if len(stops) > 2: - count = min(3, len(stops)) - random_stops = random.sample(list(stops), k=count) + next_stop = get_next_station(trip["stops"]) + next_stop_station = next_stop["name"] - via = ", ".join(random_stops[:-1]) + " und " + random_stops[-1] + ". Nächster Halt: " + next_stop["name"] + via = format_via_list(stops) + + if via: + via += f". Nächster Halt: **{next_stop_station}**" embed.add_field(name="Über", value=via, inline=False) + else: + embed.add_field(name="Nächster Halt", value=next_stop_station, inline=False) - field_lines, field_length, part = [], 0, 1 - - for name, stop_arrival in stops.items(): - if name == next_stop["name"]: - line = f"**• {name} ({stop_arrival} Uhr)**" - else: - line = f"• {name} ({stop_arrival} Uhr)" - - if field_length + len(line) + 1 > 1024: - route_page_name = "Route" - if part != 1: - route_page_name += " (Fortsetzung)" - embed.add_field(name=route_page_name, value="\n".join(field_lines), inline=False) - field_lines, field_length, part = [], 0, part + 1 - - field_lines.append(line) - field_length += len(line) + 1 - - if field_lines: - embed.add_field(name="Route" if part == 1 else "Route (Fortsetzung)", value="\n".join(field_lines), inline=False) + route_fields = format_stop_list(stops, next_stop_station) + for field_name, field_value in route_fields: + embed.add_field(name=field_name, value=field_value, inline=False) footer = build_embed_footer(trip["mode"], metadata["slogans"]) embed.set_footer(text=footer["text"], icon_url=footer["icon"]) diff --git a/src/utils.py b/src/utils.py index 46f0491..ea0989b 100644 --- a/src/utils.py +++ b/src/utils.py @@ -176,4 +176,35 @@ def get_next_station(stops: dict) -> dict | None: return {"name": name, "arrival": arrival_str} return None - \ No newline at end of file + +def format_via_list(stops: dict) -> str: + if len(stops) > 2: + count = min(3, len(stops)) + random_stops = random.sample(list(stops), k=count) + via = f"{', '.join(random_stops[:-1])} und {random_stops[-1]}" + return via + return None + +def format_stop_list(stops: dict, next_stop: str) -> list[tuple[str, str]]: + fields = [] + field_lines, field_length, part = [], 0, 1 + + for name, stop_arrival in stops.items(): + if name == next_stop: + line = f"**• {name} ({stop_arrival} Uhr)**" + else: + line = f"• {name} ({stop_arrival} Uhr)" + + if field_length + len(line) + 1 > 1024: + route_page_name = "Route" if part == 1 else "Route (Fortsetzung)" + fields.append((route_page_name, "\n".join(field_lines))) + field_lines, field_length, part = [], 0, part + 1 + + field_lines.append(line) + field_length += len(line) + 1 + + if field_lines: + route_page_name = "Route" if part == 1 else "Route (Fortsetzung)" + fields.append((route_page_name, "\n".join(field_lines))) + + return fields \ No newline at end of file From 8e9fa7c2f27e6113ad258733d76341304302e6f4 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 20:49:31 +0200 Subject: [PATCH 26/48] transitous rewrite: refactor config --- config.json.example | 39 +++++++++++++++++++---------- main.py | 10 ++++---- src/api/transitous.py | 9 ++++--- src/config.py | 58 +++++++++++++++++++++++++++++++++++++++++++ src/dc/handlers.py | 8 +++--- src/dc/helpers.py | 3 ++- src/utils.py | 25 ++++++++----------- 7 files changed, 111 insertions(+), 41 deletions(-) create mode 100644 src/config.py diff --git a/config.json.example b/config.json.example index c7401f8..9c7767e 100644 --- a/config.json.example +++ b/config.json.example @@ -1,20 +1,33 @@ { + "discord": { "token": "", - "stations": ["Hamburg Hbf", "München Hbf", "Köln Hbf", "Amsterdam Centraal"], - "dbf": "https://dbf.finalrewind.org", - "server": , + "server": , "vc": , - "random": true, - "emojis": true, "formatting": "┇", - "announcements": true, - "voice_announcements: [ - { - "enabled": false, - "stations": { - "general": "" - } + "emojis": true + }, + "connections": { + "stations": [ + "" + ], + "blacklist": [], + "min_duration": 5, + "max_duration": null, + "max_wait_time": 6, + "timezone": "Europe/Berlin" + }, + "announcements": { + "enabled": true, + "voice": [ + { + "enabled": false, + "stations": { + "general": "general.aac", } + } ] - "blacklist": [] + }, + "http": { + "user_agent": "Gleiswechsel-Discord-Bot" + } } \ No newline at end of file diff --git a/main.py b/main.py index 2161cd4..53b8c97 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,6 @@ import discord -from src.utils import config, logger +from src.utils import logger +from src.config import config from src.dc.handlers import rename_vc from src.dc.helpers import validate_channel from src.dc.commands import setup_commands @@ -16,22 +17,21 @@ async def on_ready(): if not _bot_initialized: _bot_initialized = True - server_id = config["server"] - server_vc_id = config["vc"] + server_id = config.discord.server + server_vc_id = config.discord.vc channel = validate_channel(bot=bot, server_id=server_id, channel_id=server_vc_id) await rename_vc(bot, voice_channel=channel) else: logger("Reconnected to discord gateway, this wont disturb your current ride") try: - bot.run(config["token"]) + bot.run(config.discord.token) except: logger("Feher peim parsen des tokens", "fatal") ''' TODO - discord status -- config cleanup - multi language support - README ''' \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index ed75d21..0f26fe0 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -3,11 +3,12 @@ import random import json from datetime import datetime, timezone -from src.utils import logger, config, get_train_name, convert_iso_string, validate_connection +from src.utils import logger, get_train_name, convert_iso_string, validate_connection +from src.config import config -stations = config["stations"] -blacklist = config["blacklist"] -user_agent = config["http"]["user_agent"] +stations = config.connections.stations +blacklist = config.connections.blacklist +user_agent = config.http.user_agent headers = { "User-Agent": f"{user_agent}" diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..160486c --- /dev/null +++ b/src/config.py @@ -0,0 +1,58 @@ +import json +import os +from dataclasses import dataclass, field +from typing import Optional + +@dataclass +class DiscordConfig: + token: str + server: int + vc: int + formatting: str + emojis: bool + +@dataclass +class ConnectionsConfig: + stations: list[str] + blacklist: list[str] + min_duration: int + max_wait_time: int + timezone: str + max_duration: Optional[int] = None + +@dataclass +class VoiceAnnouncementConfig: + enabled: bool + stations: dict[str, str] + +@dataclass +class AnnouncementConfig: + enabled: bool + voice: list[VoiceAnnouncementConfig] + +@dataclass +class HttpConfig: + user_agent: str + +@dataclass +class Config: + discord: DiscordConfig + connections: ConnectionsConfig + announcements: AnnouncementConfig + http: HttpConfig + +def _load_config() -> Config: + with open("config.json", "r") as file: + raw = json.load(file) + + return Config( + discord=DiscordConfig(**raw["discord"]), + connections=ConnectionsConfig(**raw["connections"]), + announcements=AnnouncementConfig( + enabled=raw["announcements"]["enabled"], + voice=[VoiceAnnouncementConfig(**v) for v in raw["announcements"]["voice"]], + ), + http=HttpConfig(**raw["http"]), + ) + +config = _load_config() \ No newline at end of file diff --git a/src/dc/handlers.py b/src/dc/handlers.py index fa318cc..c2c00c9 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -3,7 +3,8 @@ import asyncio import random from datetime import datetime, timedelta, date -from src.utils import logger, channel_formatting, choose_connection, config, get_sound_path +from src.utils import logger, channel_formatting, choose_connection, get_sound_path +from src.config import config _scheduled_task: asyncio.Task | None = None @@ -62,7 +63,6 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival, voice_channel: disc if wait_seconds > announcement_countdown: wait_until_end_announcement = wait_seconds - announcement_countdown await asyncio.sleep(wait_until_end_announcement) - await asyncio.sleep(5) await announcer("ende", voice_channel, destination) await asyncio.sleep(announcement_countdown) else: @@ -74,8 +74,8 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival, voice_channel: disc async def announcer(announcement: str, voice_channel: discord.VoiceChannel, destination = None): from src.dc.embeds import build_info_embed, build_announcement_embed - announcements_enabled = config.get("announcements", True) - voice_announcement_enabled = config["voice_announcements"][0]["enabled"] + announcements_enabled = config.announcements.enabled + voice_announcement_enabled = config.announcements.voice[0].enabled if announcements_enabled: if len(voice_channel.members) > 0: diff --git a/src/dc/helpers.py b/src/dc/helpers.py index 23ee76f..3efc8e8 100644 --- a/src/dc/helpers.py +++ b/src/dc/helpers.py @@ -4,11 +4,12 @@ from src.utils import logger def validate_channel(bot: discord.bot, server_id: int, channel_id: int): guild = bot.get_guild(server_id) - channel = guild.get_channel(channel_id) if guild is None: logger(f"Es konnte kein Server mit der ID {server_id} gefunden werden", "fatal") + return False + channel = guild.get_channel(channel_id) if not isinstance(channel, discord.VoiceChannel): logger(f"Es konnte kein VC mit der id {channel_id} gefunden werden", "fatal") return False diff --git a/src/utils.py b/src/utils.py index ea0989b..2b48988 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,9 +1,9 @@ -import json import os import importlib import random from pathlib import Path -from datetime import datetime, timedelta, timezone, date +from datetime import datetime, timedelta, timezone +from src.config import config from zoneinfo import ZoneInfo import src.data.operators as operators @@ -11,8 +11,6 @@ from src.data.emojis import emoji_list _operator_mtime = None -with open("config.json", "r") as file: - config = json.load(file) def logger(msg, log_type="info") -> str: status = log_type.upper() @@ -37,7 +35,7 @@ def validate_connection(start_time: str, end_time: str, station_departure: str) logger(f"Verbindung liegt bereits in der Vergangenheit: {start_dt}", "error") return False - max_wait_time = config.get("max_wait_time", 6) + max_wait_time = config.connections.max_wait_time start_dt = datetime.fromisoformat(start_time.replace("Z", "+00:00")) if start_dt > now + timedelta(hours=max_wait_time): logger(f"Verbindung liegt zu weit in der Zukunft: {start_dt}", "error") @@ -47,13 +45,13 @@ def validate_connection(start_time: str, end_time: str, station_departure: str) trip_duration = (end_dt - station_departure_dt).total_seconds() trip_duration_minutes = str(timedelta(seconds=trip_duration)) - min_duration = config.get("min_duration", 10) + min_duration = config.connections.min_duration min_duration_seconds = min_duration * 60 if trip_duration < min_duration_seconds: logger(f"Verbindung ist mit {trip_duration_minutes} zu kurz (mindestens {min_duration} Minuten gewollt)", "error") return False - max_duration = config.get("max_duration", "") + max_duration = config.connections.max_duration if max_duration: max_duration_seconds = max_duration * 60 if max_duration_seconds < trip_duration: @@ -63,7 +61,7 @@ def validate_connection(start_time: str, end_time: str, station_departure: str) return True def convert_iso_string(isostring) -> str: - timezone = config.get("timezone", "Europe/Berlin") + timezone = config.connections.timezone dt = datetime.fromisoformat(isostring.replace('Z', '+00:00')) dt = dt.astimezone(ZoneInfo(timezone)) @@ -72,9 +70,9 @@ def convert_iso_string(isostring) -> str: return dt.strftime('%H:%M') def channel_formatting(mode: str) -> str: - formatting = config.get("formatting", "") + formatting = config.discord.formatting - if config.get("emojis", True): + if config.discord.formatting: emoji = emoji_list.get(mode) if emoji is None: emoji = emoji_list.get("Fallback") @@ -134,14 +132,13 @@ def get_operator_metadata(agency: str, route_color: str) -> dict: } def get_sound_path(destination) -> str | None: - voice_announcement_config = config["voice_announcements"][0] - voice_stations = voice_announcement_config["stations"] + voice_stations = config.announcements.voice[0].stations if destination in voice_stations: announcement_for = destination else: - general_config = voice_stations.get("general", "") - if not general_config: + general_sound_enabled = voice_stations.get("general", "") + if not general_sound_enabled: return None announcement_for = "general" From 36a1db06475d64be0f84d6d8e09ee5e441c81c85 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 23:15:38 +0200 Subject: [PATCH 27/48] transitous rewrite: add check_stations() function --- .gitignore | 4 +- data.json | 698 ++++++++++++++++++++++++++++++++++++++++++ main.py | 8 + src/api/transitous.py | 79 ++++- src/data/operators.py | 4 + src/dc/embeds.py | 14 +- src/utils.py | 2 +- 7 files changed, 796 insertions(+), 13 deletions(-) create mode 100644 data.json diff --git a/.gitignore b/.gitignore index c61264a..1a291fb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,4 @@ __pycache__/ src/data/announcements/* !src/data/announcements/.gitkeep config.json -src/legacy/ -main_legacy.py -data.json \ No newline at end of file +stations.json \ No newline at end of file diff --git a/data.json b/data.json new file mode 100644 index 0000000..a68ed54 --- /dev/null +++ b/data.json @@ -0,0 +1,698 @@ +{ + "duration": 1440, + "startTime": "2026-08-16T21:25:00Z", + "endTime": "2026-08-16T21:49:00Z", + "transfers": 0, + "id": "CogBCgI1NBIiMjAyNjA4MTZfMjM6MjVfbmwtT3Blbk9WXzM3Njc3ODE5OBoRbmwtT3Blbk9WXzM5ODA3NDch/ilVouwlSkAp147iHHX0E0AyEW5sLU9wZW5PVl8zOTc5OTIwOZRIopdRMEpAQcGxZ89lmhNASKzViNQGUMzgiNQGWgZTVUJXQVlgAQ==", + "legs": [ + { + "mode": "SUBWAY", + "from": { + "name": "Amsterdam, Gein", + "stopId": "nl-OpenOV_3980747", + "parentId": "nl-OpenOV_NL:S:30009530", + "importance": 0.018040798604488373, + "lat": 52.296284, + "lon": 4.988728000000001, + "level": 0.0, + "tz": "Europe/Brussels", + "departure": "2026-08-16T21:25:00Z", + "scheduledDeparture": "2026-08-16T21:25:00Z", + "scheduledTrack": "1", + "track": "1", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NOT_ALLOWED", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", + "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" + } + ], + "modes": [ + "SUBWAY", + "BUS" + ] + }, + "to": { + "name": "Amsterdam, Centraal Station", + "stopId": "nl-OpenOV_3979920", + "parentId": "nl-OpenOV_NL:S:30009500", + "importance": 0.17953550815582275, + "lat": 52.377489999999995, + "lon": 4.900779000000001, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:49:00Z", + "scheduledArrival": "2026-08-16T21:49:00Z", + "vertexType": "TRANSIT", + "pickupType": "NOT_ALLOWED", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Neem M52 naar Zuid voor RAI en de richting Isolatorweg. Details: gvb.nl/zomermetro|-- Take M52 to Zuid for RAI and the direction Isolatorweg", + "descriptionText": "Neem M52 naar Zuid voor RAI en de richting Isolatorweg. Details: gvb.nl/zomermetro|-- Take M52 to Zuid for RAI and the direction Isolatorweg. Details: gvb.nl/summermetro" + } + ], + "modes": [ + "HIGHSPEED_RAIL", + "LONG_DISTANCE", + "NIGHT_RAIL", + "REGIONAL_RAIL", + "SUBWAY", + "TRAM", + "BUS", + "FERRY" + ] + }, + "duration": 1440, + "startTime": "2026-08-16T21:25:00Z", + "endTime": "2026-08-16T21:49:00Z", + "scheduledStartTime": "2026-08-16T21:25:00Z", + "scheduledEndTime": "2026-08-16T21:49:00Z", + "realTime": true, + "scheduled": true, + "interlineWithPreviousLeg": false, + "headsign": "Centraal Station", + "tripFrom": { + "name": "Amsterdam, Gein", + "stopId": "nl-OpenOV_3980747", + "parentId": "nl-OpenOV_NL:S:30009530", + "importance": 0.018040798604488373, + "lat": 52.296284, + "lon": 4.988728000000001, + "level": 0.0, + "tz": "Europe/Brussels", + "departure": "2026-08-16T21:25:00Z", + "scheduledDeparture": "2026-08-16T21:25:00Z", + "scheduledTrack": "1", + "track": "1", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NOT_ALLOWED", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", + "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" + } + ], + "modes": [ + "SUBWAY", + "BUS" + ] + }, + "tripTo": { + "name": "Amsterdam, Centraal Station", + "stopId": "nl-OpenOV_3979920", + "parentId": "nl-OpenOV_NL:S:30009500", + "importance": 0.17953550815582275, + "lat": 52.377489999999995, + "lon": 4.900779000000001, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:49:00Z", + "scheduledArrival": "2026-08-16T21:49:00Z", + "vertexType": "TRANSIT", + "pickupType": "NOT_ALLOWED", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Neem M52 naar Zuid voor RAI en de richting Isolatorweg. Details: gvb.nl/zomermetro|-- Take M52 to Zuid for RAI and the direction Isolatorweg", + "descriptionText": "Neem M52 naar Zuid voor RAI en de richting Isolatorweg. Details: gvb.nl/zomermetro|-- Take M52 to Zuid for RAI and the direction Isolatorweg. Details: gvb.nl/summermetro" + } + ], + "modes": [ + "HIGHSPEED_RAIL", + "LONG_DISTANCE", + "NIGHT_RAIL", + "REGIONAL_RAIL", + "SUBWAY", + "TRAM", + "BUS", + "FERRY" + ] + }, + "routeId": "nl-OpenOV_152364", + "routeUrl": "", + "directionId": "0", + "routeColor": "fff200", + "routeTextColor": "000000", + "routeType": 1, + "agencyName": "GVB", + "agencyUrl": "http://www.gvb.nl/klantenservice", + "agencyFareUrl": "", + "agencyId": "GVB", + "tripId": "20260816_23:25_nl-OpenOV_376778198", + "routeShortName": "54", + "routeLongName": "Lijn 54", + "tripShortName": "", + "displayName": "54", + "cancelled": false, + "source": "nl_OpenOV.gtfs.zip/stop_times.txt:1582071:1582085", + "intermediateStops": [ + { + "name": "Amsterdam, Reigersbos", + "stopId": "nl-OpenOV_3979741", + "parentId": "nl-OpenOV_NL:S:30009528", + "importance": 0.018029676750302315, + "lat": 52.29557400000001, + "lon": 4.973636000000001, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:26:00Z", + "departure": "2026-08-16T21:27:00Z", + "scheduledArrival": "2026-08-16T21:26:00Z", + "scheduledDeparture": "2026-08-16T21:27:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", + "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" + } + ], + "modes": [ + "SUBWAY", + "BUS" + ] + }, + { + "name": "Amsterdam, Station Holendrecht", + "stopId": "nl-OpenOV_3981303", + "parentId": "nl-OpenOV_NL:S:30009526", + "importance": 0.026576673611998558, + "lat": 52.29839300000001, + "lon": 4.959859000000001, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:28:00Z", + "departure": "2026-08-16T21:29:00Z", + "scheduledArrival": "2026-08-16T21:28:00Z", + "scheduledDeparture": "2026-08-16T21:29:00Z", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", + "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" + } + ], + "modes": [ + "REGIONAL_RAIL", + "SUBWAY", + "BUS" + ] + }, + { + "name": "Amsterdam, Bullewijk", + "stopId": "nl-OpenOV_3981144", + "parentId": "nl-OpenOV_NL:S:30009524", + "importance": 0.017878592014312744, + "lat": 52.30693, + "lon": 4.952079, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:30:00Z", + "departure": "2026-08-16T21:31:00Z", + "scheduledArrival": "2026-08-16T21:30:00Z", + "scheduledDeparture": "2026-08-16T21:31:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", + "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" + } + ], + "modes": [ + "SUBWAY" + ] + }, + { + "name": "Amsterdam, Station Bijlmer ArenA", + "stopId": "nl-OpenOV_3980962", + "parentId": "nl-OpenOV_NL:S:30009522", + "importance": 0.04671318084001541, + "lat": 52.31261, + "lon": 4.946935, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:32:00Z", + "departure": "2026-08-16T21:32:00Z", + "scheduledArrival": "2026-08-16T21:32:00Z", + "scheduledDeparture": "2026-08-16T21:32:00Z", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Neem NS-treinen naar Zuid of stap op Spaklerweg over voor Overamstel. Details: gvb.nl/zomermetro --|Take NS trains to Zuid or change at Spak", + "descriptionText": "Neem NS-treinen naar Zuid of stap op Spaklerweg over voor Overamstel. Details: gvb.nl/zomermetro --|Take NS trains to Zuid or change at Spaklerweg for Overamstel. Details: gvb.nl/summermetro" + } + ], + "modes": [ + "LONG_DISTANCE", + "COACH", + "NIGHT_RAIL", + "REGIONAL_RAIL", + "SUBWAY", + "BUS" + ] + }, + { + "name": "Amsterdam, Strandvliet", + "stopId": "nl-OpenOV_3981329", + "parentId": "nl-OpenOV_NL:S:30009520", + "importance": 0.017878592014312744, + "lat": 52.31868399999999, + "lon": 4.941375000000001, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:33:00Z", + "departure": "2026-08-16T21:34:00Z", + "scheduledArrival": "2026-08-16T21:33:00Z", + "scheduledDeparture": "2026-08-16T21:34:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Stap op Spaklerweg over voor Overamstel of op Amstel voor RAI. Details: gvb.nl/zomermetro –|Change at Spaklerweg for Overamstel or at Amstel", + "descriptionText": "Stap op Spaklerweg over voor Overamstel of op Amstel voor RAI. Details: gvb.nl/zomermetro –|Change at Spaklerweg for Overamstel or at Amstel for RAI. Details: gvb.nl/summermetro" + } + ], + "modes": [ + "SUBWAY" + ] + }, + { + "name": "Duivendrecht, Station Duivendrecht", + "stopId": "nl-OpenOV_3979812", + "parentId": "nl-OpenOV_NL:S:30009551", + "importance": 0.018022045493125916, + "lat": 52.323895, + "lon": 4.936262000000002, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:35:00Z", + "departure": "2026-08-16T21:35:00Z", + "scheduledArrival": "2026-08-16T21:35:00Z", + "scheduledDeparture": "2026-08-16T21:35:00Z", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-09T15:42:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-09T15:42:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Neem NS-treinen naar Zuid of stap op Spaklerweg over voor Overamstel. Details: gvb.nl/zomermetro --|Take NS trains to Zuid or change at Spak", + "descriptionText": "Neem NS-treinen naar Zuid of stap op Spaklerweg over voor Overamstel. Details: gvb.nl/zomermetro --|Take NS trains to Zuid or change at Spaklerweg for Overamstel. Details: gvb.nl/summermetro" + } + ], + "modes": [ + "SUBWAY", + "BUS" + ] + }, + { + "name": "Amsterdam, Van der Madeweg", + "stopId": "nl-OpenOV_3981387", + "parentId": "nl-OpenOV_NL:S:30009516", + "importance": 0.0271453857421875, + "lat": 52.329903, + "lon": 4.930333000000001, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:36:00Z", + "departure": "2026-08-16T21:37:00Z", + "scheduledArrival": "2026-08-16T21:36:00Z", + "scheduledDeparture": "2026-08-16T21:37:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Stap op Spaklerweg over voor Overamstel of op Amstel voor RAI. Details: gvb.nl/zomermetro –|Change at Spaklerweg for Overamstel or at Amstel", + "descriptionText": "Stap op Spaklerweg over voor Overamstel of op Amstel voor RAI. Details: gvb.nl/zomermetro –|Change at Spaklerweg for Overamstel or at Amstel for RAI. Details: gvb.nl/summermetro" + } + ], + "modes": [ + "SUBWAY", + "BUS" + ] + }, + { + "name": "Amsterdam, Spaklerweg", + "stopId": "nl-OpenOV_3980158", + "parentId": "nl-OpenOV_NL:S:30009518", + "importance": 0.02681240625679493, + "lat": 52.340239999999994, + "lon": 4.92107, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:39:00Z", + "departure": "2026-08-16T21:39:00Z", + "scheduledArrival": "2026-08-16T21:39:00Z", + "scheduledDeparture": "2026-08-16T21:39:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "SUBWAY", + "BUS" + ] + }, + { + "name": "Amsterdam, Amstelstation", + "stopId": "nl-OpenOV_3980520", + "parentId": "nl-OpenOV_NL:S:30009514", + "importance": 0.052102621644735336, + "lat": 52.346489999999996, + "lon": 4.9175699999999996, + "level": 0.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:40:00Z", + "departure": "2026-08-16T21:41:00Z", + "scheduledArrival": "2026-08-16T21:40:00Z", + "scheduledDeparture": "2026-08-16T21:41:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "alerts": [ + { + "communicationPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "impactPeriod": [ + { + "start": "2026-07-04T04:00:00Z", + "end": "2026-08-16T23:00:00Z" + } + ], + "cause": "UNKNOWN_CAUSE", + "effect": "UNKNOWN_EFFECT", + "headerText": "Neem tram 23 voor RAI of bus 78 voor Overamstel. Details: gvb.nl/zomermetro. --|Take tram 23 for RAI or bus 78 for Overamstel. Details: gvb.nl/summermetro", + "descriptionText": "Neem tram 23 voor RAI of bus 78 voor Overamstel. Details: gvb.nl/zomermetro. --|Take tram 23 for RAI or bus 78 for Overamstel. Details: gvb.nl/summermetro" + } + ], + "modes": [ + "REGIONAL_RAIL", + "SUBWAY", + "TRAM", + "BUS" + ] + }, + { + "name": "Amsterdam, Wibautstraat", + "stopId": "nl-OpenOV_3980265", + "parentId": "nl-OpenOV_NL:S:30009512", + "importance": 0.027183683589100838, + "lat": 52.354332, + "lon": 4.9121879999999996, + "level": -2.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:42:00Z", + "departure": "2026-08-16T21:43:00Z", + "scheduledArrival": "2026-08-16T21:42:00Z", + "scheduledDeparture": "2026-08-16T21:43:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "SUBWAY", + "TRAM", + "BUS" + ] + }, + { + "name": "Amsterdam, Weesperplein", + "stopId": "nl-OpenOV_3981336", + "parentId": "nl-OpenOV_NL:S:30009510", + "importance": 0.02798701450228691, + "lat": 52.361236999999996, + "lon": 4.907945, + "level": -2.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:44:00Z", + "departure": "2026-08-16T21:45:00Z", + "scheduledArrival": "2026-08-16T21:44:00Z", + "scheduledDeparture": "2026-08-16T21:45:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "SUBWAY", + "TRAM", + "BUS" + ] + }, + { + "name": "Amsterdam, Waterlooplein", + "stopId": "nl-OpenOV_3980640", + "parentId": "nl-OpenOV_NL:S:30009508", + "importance": 0.027206193655729294, + "lat": 52.366985, + "lon": 4.9031400000000005, + "level": -2.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:46:00Z", + "departure": "2026-08-16T21:46:00Z", + "scheduledArrival": "2026-08-16T21:46:00Z", + "scheduledDeparture": "2026-08-16T21:46:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "SUBWAY", + "TRAM", + "BUS" + ] + }, + { + "name": "Amsterdam, Nieuwmarkt", + "stopId": "nl-OpenOV_3981245", + "parentId": "nl-OpenOV_NL:S:30009502", + "importance": 0.02679653838276863, + "lat": 52.371914, + "lon": 4.901427000000001, + "level": -2.0, + "tz": "Europe/Brussels", + "arrival": "2026-08-16T21:47:00Z", + "departure": "2026-08-16T21:47:00Z", + "scheduledArrival": "2026-08-16T21:47:00Z", + "scheduledDeparture": "2026-08-16T21:47:00Z", + "scheduledTrack": "2", + "track": "2", + "vertexType": "TRANSIT", + "pickupType": "NORMAL", + "dropoffType": "NORMAL", + "cancelled": false, + "modes": [ + "SUBWAY" + ] + } + ], + "legGeometry": { + "points": "wd|vbBornoHN??fGFxa@?hQOzU?jFwBhF}ApDVhFLhg@^bi@LnDM|UBno@?bIKj[?vATxl@NpNFz`@D~j@?z`@?f]Fpd@Vl[?dGLjQVdGL|Jb@hQHlE\\rMnAxVb@|Id@jFzAlZhAtLv@vLjAvL?ZbAvLf@fGfBbSjAtL~Ib~@rClZvAjPd@lEdH|t@tCf\\`C`Tr@zJd@hFdA`IpBhQxBhQjEpX|AvLpCpXjCtWbGpn@zHnz@fBdR|A`TjAbSd@tWVvLWtM[`T_@|JmAhQaBhRcClP_DjQsEbT_DzKoD|JkD~J{E|J}BnE_DfG_DjFkBtBkFfHeFhGiGhGqHjG{OzLee@t\\{PvN_SnQW?eAz@cj@xf@g@\\aAz@a@ZgAz@e@z@u@\\qHfHap@nj@u@z@kAx@O\\e@?qCrCse@bc@_SrP_IdIiXbVeJdI}OxMsAxAaRpPmBxAq@x@q@z@yIdIkGjFeOxMuJbJ}Az@kCrCg@\\sAvA{HjGgGhGO?wXbV{FlFoWfU_d@h`@s`@p]oUjSsOzMoCrCkAx@_DrCeEpDmGfHmh@|e@sAx@kAz@sAvAyAxA{p@lk@u@z@q@z@gEpDsDrCkCrCw`@r\\{JbJqk@vg@qBxAil@pi@yBvBce@db@wAz@mBvA]z@u@\\e@x@u@\\cAz@}OvNwDpDaf@db@sAxAaCtBcTnQS\\}XfUqHjG{BtBaAz@u@x@oCvBkFnEwGfHw`@p]gb@l_@wX`Wu@\\iAvAkBxAgAz@wAvAqRlRgYdVyNvN_DrC?\\K?{FnEgSrPO?cj@|e@oDnDsBxAgm@ri@yAvAuJfI{f@bc@iBtBiAz@u@\\iBtBccA~}@wL`Kcj@th@wVbW_UfT_VdVwAvAgAz@eXxYoCtCyBrCW?k@x@u@z@{FhGkBrCeSjSmGhGuNtO{L~KqLbJoCtBeKbJkK`K_}@lcAW\\cAz@cAvA}@z@sAvAsj@hm@}h@th@wIbJwFjFuWt[}O~KcP`L_DrC{@x@w@z@_DrCcAz@cAz@kAx@gAxAsEpDU\\{AvAgc@l_@iUlSce@ha@_IdImBtByFnEea@r]e@z@wAx@kM|LaCtByBtBsCvBkCtByNzMa@Z}BvBuJdIs`@r]sj@|e@kiC`~Bos@hn@sfAxaA_\\~XoUlR{PzMcVnRyLfIqBz@iCxAqGpDeU|M}bAxj@eA\\{Az@ac@pSwBvAsEvBwDrCcIrDwBxAiA\\_DxAyIrDgOjG_MvCuNpEyUvDgJvCkGxAkNhHcj@fXk_Adf@gJnFiZvOkKnFyBz@ya@pSWZ}^rRyQ|LyIjG_M~Kkl@nk@sb@fb@wVfUaP~L}P~KwMlGuOdJqVhIwSpFcWfJgLpEwLnFgOjHga@nSsFtCs{@lc@eS~LaR~KkdA`i@ia@pSihA~i@c`@nScJpEgGrDcV`Li}@df@uOhIwf@dXsWzNwDxA_MnFmQjHufBxz@oLnFea@fWuJjGiGlFmFlF_DpDmDpDqCnDeEjGeEhG_ItNsY|o@sMvYgZzp@yF|KuE|KkF|KwG|KyDhGyBrC{FfHaHfHmLbKkHnE}FtCoDxAeExAeE|@iBz@mFz@eJ|@_Nb@oG@{JsA_DYeIuAiLgE_TyI_o@aY_NcGkCuAoAy@sEoC_HiEsDqCsIaHoJyJyBoCeEiFcMgPu^kc@qL{IqM_H}S_HkKqAqMsAaNDgSxCoHxAcMtDsR~LkHfHsCpDiBtBaAvBY?sAtBqEfHcCrCuE~Ja@z@oGvM_DdI_IdTkVnt@wBqC", + "precision": 6, + "length": 430 + }, + "bikesAllowed": true, + "wheelchairAccessible": "NOT_ACCESSIBLE", + "reservation": "NONE", + "alternatives": [] + } + ] +} \ No newline at end of file diff --git a/main.py b/main.py index 53b8c97..c03a2e9 100644 --- a/main.py +++ b/main.py @@ -1,14 +1,22 @@ import discord +import sys + from src.utils import logger from src.config import config from src.dc.handlers import rename_vc from src.dc.helpers import validate_channel from src.dc.commands import setup_commands +from src.api.transitous import check_stations bot = discord.Bot(intents=discord.Intents.all()) setup_commands(bot=bot) _bot_initialized = False +if len(sys.argv) > 1: + if sys.argv[1] == "stations": + check_stations() + sys.exit(0) + @bot.event async def on_ready(): global _bot_initialized diff --git a/src/api/transitous.py b/src/api/transitous.py index 0f26fe0..5a26c09 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -16,6 +16,77 @@ headers = { endpoint = "https://api.transitous.org" +def check_stations(): + all_stations_output = {} + minimal_overview = { + "stations": {} + } + + for station in stations: + req = f"{endpoint}/api/v1/geocode" + + try: + response = requests.get(req, params={"text": station}, headers=headers) + response.raise_for_status() + data = response.json() + except requests.RequestException as e: + logger(f"An error occured while checking for station {station}: {e}") + continue + + stops_dict = {} + aliases_list = [] + exact_match = False + + for entry in data: + if entry.get("type") != "STOP": + continue + + station_id = entry.get("id") + stop_name = entry.get("name") + coords = f"{entry.get("lat")}, {entry.get("lon")}" + modes = entry.get("modes") + + stop_details = { + "tz": entry.get("tz"), + "country": entry.get("country"), + "coords": coords, + "modes": modes, + "id": station_id, + } + + if stop_name: + stops_dict[stop_name] = stop_details + aliases_list.append(stop_name) + + if stop_name == station: + if not exact_match: + logger(f"Exact match found! {station} is an assigned station! Bot would use that station directly") + exact_match = True + + if not stops_dict: + logger("Failed to grab ID from 'search_name'", "error") + continue + + all_stations_output[station] = { + "associated": stops_dict + } + + minimal_overview["stations"][station] = aliases_list + + logger(json.dumps(minimal_overview, indent=4, ensure_ascii=False)) + + + print(f"\nIf you want, I can save a more detailed version directly as a json file to disk.") + print("The json would provide informations like coords, country and transport modes that are from every specific associated station.") + prompt = input("This would help you to identify the associated stations more accurately (y/n): ") + if prompt == "y" or prompt == "yes": + with open('stations.json', 'w') as f: + json.dump(all_stations_output, f, indent=4, ensure_ascii=False) + logger("stations.json generated") + else: + logger("okay :(") + + def get_random_stop_id() -> str | None: assigned_station = random.choice(stations) req = f"{endpoint}/api/v1/geocode" @@ -42,14 +113,15 @@ def get_random_stop_id() -> str | None: stop_ids[stop_id] = stop_name break - if stop_ids is None: logger(f"Failed to grab ID from '{assigned_station}'", "error") return None stop_ids_list = list(stop_ids.keys()) stops_string = ", ".join(stop_ids.values()) - logger(f"Availabe stations: {stops_string}") + if len(stop_ids_list) > 1: + logger(f"Station '{assigned_station}' not found, choosing random from available: {stops_string}") + logger(f"No station associated as '{assigned_station}', choosing random from available") chosen_stop_id = random.choice(stop_ids_list) return chosen_stop_id @@ -176,9 +248,6 @@ def get_trip_details(random_connection: dict | None) -> dict | None: if not valid: return None - with open('data.json', 'w') as f: - json.dump(data, f, indent=4, ensure_ascii=False) - logger(json.dumps(trip_details, indent=4, ensure_ascii=False)) return trip_details diff --git a/src/data/operators.py b/src/data/operators.py index 5a09541..4b9aaf7 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -102,6 +102,10 @@ OPERATORS = { "DSB": { "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/87/DSB_company_logo.svg/960px-DSB_company_logo.svg.png", "color": 0xB22B32 + }, + "Vr": { + "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Vr_Logo.png/330px-Vr_Logo.png", + "color": 0x00B451 } } diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 495d78b..2a4860e 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -35,16 +35,22 @@ def build_info_embed() -> discord.Embed: stops = trip["stops"] next_stop = get_next_station(trip["stops"]) - next_stop_station = next_stop["name"] + next_stop_text = "" + next_stop_station = None + if next_stop: + print("next_stop") + next_stop_station = next_stop.get("name") + next_stop_text = f". Nächster Halt: **{next_stop_station}**" via = format_via_list(stops) if via: - via += f". Nächster Halt: **{next_stop_station}**" + via += next_stop_text embed.add_field(name="Über", value=via, inline=False) else: - embed.add_field(name="Nächster Halt", value=next_stop_station, inline=False) - + if next_stop: + embed.add_field(name="Nächster Halt", value=next_stop_station, inline=False) + route_fields = format_stop_list(stops, next_stop_station) for field_name, field_value in route_fields: embed.add_field(name=field_name, value=field_value, inline=False) diff --git a/src/utils.py b/src/utils.py index 2b48988..3614210 100644 --- a/src/utils.py +++ b/src/utils.py @@ -182,7 +182,7 @@ def format_via_list(stops: dict) -> str: return via return None -def format_stop_list(stops: dict, next_stop: str) -> list[tuple[str, str]]: +def format_stop_list(stops: dict, next_stop: str | None) -> list[tuple[str, str]]: fields = [] field_lines, field_length, part = [], 0, 1 From 27f8ef2cbc16d34dacf9b0a2da76963e4f4d9003 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Sun, 16 Aug 2026 23:29:03 +0200 Subject: [PATCH 28/48] transitous rewrite: /info improvements --- src/data/operators.py | 3 ++- src/dc/embeds.py | 10 +++------- src/utils.py | 5 ++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/data/operators.py b/src/data/operators.py index 4b9aaf7..68119cb 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -124,7 +124,8 @@ OPERATOR_ALIASES = { "NS International": OPERATORS["NS"], "SBB GmbH": OPERATORS["SBB"], "Schweizerische Bundesbahnen SBB": OPERATORS["SBB"], - "Dänische Staatsbahnen": OPERATORS["DSB"] + "Dänische Staatsbahnen": OPERATORS["DSB"], + "VR": OPERATORS["Vr"] } diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 2a4860e..2f9a070 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -35,21 +35,17 @@ def build_info_embed() -> discord.Embed: stops = trip["stops"] next_stop = get_next_station(trip["stops"]) - next_stop_text = "" + print(f"next_stop: {next_stop}") next_stop_station = None if next_stop: - print("next_stop") next_stop_station = next_stop.get("name") - next_stop_text = f". Nächster Halt: **{next_stop_station}**" via = format_via_list(stops) if via: - via += next_stop_text embed.add_field(name="Über", value=via, inline=False) - else: - if next_stop: - embed.add_field(name="Nächster Halt", value=next_stop_station, inline=False) + if next_stop: + embed.add_field(name="Nächster Halt", value=f"__{next_stop_station}__", inline=False) route_fields = format_stop_list(stops, next_stop_station) for field_name, field_value in route_fields: diff --git a/src/utils.py b/src/utils.py index 3614210..e8611d2 100644 --- a/src/utils.py +++ b/src/utils.py @@ -80,7 +80,7 @@ def channel_formatting(mode: str) -> str: return f"{emoji}{formatting}" def get_train_name(train_name: str, mode: str) -> str: - if train_name.isdigit(): + if mode == "BUS" or mode == "TRAM": train = f"{mode.capitalize()} {train_name}" elif "(" in train_name: train = train_name.split(" (")[0] @@ -118,7 +118,6 @@ def get_operator_metadata(agency: str, route_color: str) -> dict: if route_color is not None: try: color = int(route_color, 16) - print(color) except ValueError: color = operators.OPERATORS["fallback"]["color"] else: @@ -188,7 +187,7 @@ def format_stop_list(stops: dict, next_stop: str | None) -> list[tuple[str, str] for name, stop_arrival in stops.items(): if name == next_stop: - line = f"**• {name} ({stop_arrival} Uhr)**" + line = f"• __{name} ({stop_arrival} Uhr__)" else: line = f"• {name} ({stop_arrival} Uhr)" From 59af14e6ff2ef86a60229bd01db49061b70836a5 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 12:49:35 +0200 Subject: [PATCH 29/48] transitous rewrite: next_stop improvements --- data.json | 698 ------------------------------------------ src/api/transitous.py | 34 +- src/config.py | 2 +- src/data/operators.py | 1 + src/dc/embeds.py | 3 +- src/utils.py | 48 ++- 6 files changed, 39 insertions(+), 747 deletions(-) delete mode 100644 data.json diff --git a/data.json b/data.json deleted file mode 100644 index a68ed54..0000000 --- a/data.json +++ /dev/null @@ -1,698 +0,0 @@ -{ - "duration": 1440, - "startTime": "2026-08-16T21:25:00Z", - "endTime": "2026-08-16T21:49:00Z", - "transfers": 0, - "id": "CogBCgI1NBIiMjAyNjA4MTZfMjM6MjVfbmwtT3Blbk9WXzM3Njc3ODE5OBoRbmwtT3Blbk9WXzM5ODA3NDch/ilVouwlSkAp147iHHX0E0AyEW5sLU9wZW5PVl8zOTc5OTIwOZRIopdRMEpAQcGxZ89lmhNASKzViNQGUMzgiNQGWgZTVUJXQVlgAQ==", - "legs": [ - { - "mode": "SUBWAY", - "from": { - "name": "Amsterdam, Gein", - "stopId": "nl-OpenOV_3980747", - "parentId": "nl-OpenOV_NL:S:30009530", - "importance": 0.018040798604488373, - "lat": 52.296284, - "lon": 4.988728000000001, - "level": 0.0, - "tz": "Europe/Brussels", - "departure": "2026-08-16T21:25:00Z", - "scheduledDeparture": "2026-08-16T21:25:00Z", - "scheduledTrack": "1", - "track": "1", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NOT_ALLOWED", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", - "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" - } - ], - "modes": [ - "SUBWAY", - "BUS" - ] - }, - "to": { - "name": "Amsterdam, Centraal Station", - "stopId": "nl-OpenOV_3979920", - "parentId": "nl-OpenOV_NL:S:30009500", - "importance": 0.17953550815582275, - "lat": 52.377489999999995, - "lon": 4.900779000000001, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:49:00Z", - "scheduledArrival": "2026-08-16T21:49:00Z", - "vertexType": "TRANSIT", - "pickupType": "NOT_ALLOWED", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Neem M52 naar Zuid voor RAI en de richting Isolatorweg. Details: gvb.nl/zomermetro|-- Take M52 to Zuid for RAI and the direction Isolatorweg", - "descriptionText": "Neem M52 naar Zuid voor RAI en de richting Isolatorweg. Details: gvb.nl/zomermetro|-- Take M52 to Zuid for RAI and the direction Isolatorweg. Details: gvb.nl/summermetro" - } - ], - "modes": [ - "HIGHSPEED_RAIL", - "LONG_DISTANCE", - "NIGHT_RAIL", - "REGIONAL_RAIL", - "SUBWAY", - "TRAM", - "BUS", - "FERRY" - ] - }, - "duration": 1440, - "startTime": "2026-08-16T21:25:00Z", - "endTime": "2026-08-16T21:49:00Z", - "scheduledStartTime": "2026-08-16T21:25:00Z", - "scheduledEndTime": "2026-08-16T21:49:00Z", - "realTime": true, - "scheduled": true, - "interlineWithPreviousLeg": false, - "headsign": "Centraal Station", - "tripFrom": { - "name": "Amsterdam, Gein", - "stopId": "nl-OpenOV_3980747", - "parentId": "nl-OpenOV_NL:S:30009530", - "importance": 0.018040798604488373, - "lat": 52.296284, - "lon": 4.988728000000001, - "level": 0.0, - "tz": "Europe/Brussels", - "departure": "2026-08-16T21:25:00Z", - "scheduledDeparture": "2026-08-16T21:25:00Z", - "scheduledTrack": "1", - "track": "1", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NOT_ALLOWED", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", - "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" - } - ], - "modes": [ - "SUBWAY", - "BUS" - ] - }, - "tripTo": { - "name": "Amsterdam, Centraal Station", - "stopId": "nl-OpenOV_3979920", - "parentId": "nl-OpenOV_NL:S:30009500", - "importance": 0.17953550815582275, - "lat": 52.377489999999995, - "lon": 4.900779000000001, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:49:00Z", - "scheduledArrival": "2026-08-16T21:49:00Z", - "vertexType": "TRANSIT", - "pickupType": "NOT_ALLOWED", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Neem M52 naar Zuid voor RAI en de richting Isolatorweg. Details: gvb.nl/zomermetro|-- Take M52 to Zuid for RAI and the direction Isolatorweg", - "descriptionText": "Neem M52 naar Zuid voor RAI en de richting Isolatorweg. Details: gvb.nl/zomermetro|-- Take M52 to Zuid for RAI and the direction Isolatorweg. Details: gvb.nl/summermetro" - } - ], - "modes": [ - "HIGHSPEED_RAIL", - "LONG_DISTANCE", - "NIGHT_RAIL", - "REGIONAL_RAIL", - "SUBWAY", - "TRAM", - "BUS", - "FERRY" - ] - }, - "routeId": "nl-OpenOV_152364", - "routeUrl": "", - "directionId": "0", - "routeColor": "fff200", - "routeTextColor": "000000", - "routeType": 1, - "agencyName": "GVB", - "agencyUrl": "http://www.gvb.nl/klantenservice", - "agencyFareUrl": "", - "agencyId": "GVB", - "tripId": "20260816_23:25_nl-OpenOV_376778198", - "routeShortName": "54", - "routeLongName": "Lijn 54", - "tripShortName": "", - "displayName": "54", - "cancelled": false, - "source": "nl_OpenOV.gtfs.zip/stop_times.txt:1582071:1582085", - "intermediateStops": [ - { - "name": "Amsterdam, Reigersbos", - "stopId": "nl-OpenOV_3979741", - "parentId": "nl-OpenOV_NL:S:30009528", - "importance": 0.018029676750302315, - "lat": 52.29557400000001, - "lon": 4.973636000000001, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:26:00Z", - "departure": "2026-08-16T21:27:00Z", - "scheduledArrival": "2026-08-16T21:26:00Z", - "scheduledDeparture": "2026-08-16T21:27:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", - "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" - } - ], - "modes": [ - "SUBWAY", - "BUS" - ] - }, - { - "name": "Amsterdam, Station Holendrecht", - "stopId": "nl-OpenOV_3981303", - "parentId": "nl-OpenOV_NL:S:30009526", - "importance": 0.026576673611998558, - "lat": 52.29839300000001, - "lon": 4.959859000000001, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:28:00Z", - "departure": "2026-08-16T21:29:00Z", - "scheduledArrival": "2026-08-16T21:28:00Z", - "scheduledDeparture": "2026-08-16T21:29:00Z", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", - "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" - } - ], - "modes": [ - "REGIONAL_RAIL", - "SUBWAY", - "BUS" - ] - }, - { - "name": "Amsterdam, Bullewijk", - "stopId": "nl-OpenOV_3981144", - "parentId": "nl-OpenOV_NL:S:30009524", - "importance": 0.017878592014312744, - "lat": 52.30693, - "lon": 4.952079, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:30:00Z", - "departure": "2026-08-16T21:31:00Z", - "scheduledArrival": "2026-08-16T21:30:00Z", - "scheduledDeparture": "2026-08-16T21:31:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS train", - "descriptionText": "Stap op Bijlmer ArenA over op NS-treinen naar Zuid of op Spaklerweg voor Overamstel. Details: gvb.nl --|Change at Bijlmer ArenA for NS trains to Zuid or at Spaklerweg for Overamstel. Details: gvb.nl" - } - ], - "modes": [ - "SUBWAY" - ] - }, - { - "name": "Amsterdam, Station Bijlmer ArenA", - "stopId": "nl-OpenOV_3980962", - "parentId": "nl-OpenOV_NL:S:30009522", - "importance": 0.04671318084001541, - "lat": 52.31261, - "lon": 4.946935, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:32:00Z", - "departure": "2026-08-16T21:32:00Z", - "scheduledArrival": "2026-08-16T21:32:00Z", - "scheduledDeparture": "2026-08-16T21:32:00Z", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Neem NS-treinen naar Zuid of stap op Spaklerweg over voor Overamstel. Details: gvb.nl/zomermetro --|Take NS trains to Zuid or change at Spak", - "descriptionText": "Neem NS-treinen naar Zuid of stap op Spaklerweg over voor Overamstel. Details: gvb.nl/zomermetro --|Take NS trains to Zuid or change at Spaklerweg for Overamstel. Details: gvb.nl/summermetro" - } - ], - "modes": [ - "LONG_DISTANCE", - "COACH", - "NIGHT_RAIL", - "REGIONAL_RAIL", - "SUBWAY", - "BUS" - ] - }, - { - "name": "Amsterdam, Strandvliet", - "stopId": "nl-OpenOV_3981329", - "parentId": "nl-OpenOV_NL:S:30009520", - "importance": 0.017878592014312744, - "lat": 52.31868399999999, - "lon": 4.941375000000001, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:33:00Z", - "departure": "2026-08-16T21:34:00Z", - "scheduledArrival": "2026-08-16T21:33:00Z", - "scheduledDeparture": "2026-08-16T21:34:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Stap op Spaklerweg over voor Overamstel of op Amstel voor RAI. Details: gvb.nl/zomermetro –|Change at Spaklerweg for Overamstel or at Amstel", - "descriptionText": "Stap op Spaklerweg over voor Overamstel of op Amstel voor RAI. Details: gvb.nl/zomermetro –|Change at Spaklerweg for Overamstel or at Amstel for RAI. Details: gvb.nl/summermetro" - } - ], - "modes": [ - "SUBWAY" - ] - }, - { - "name": "Duivendrecht, Station Duivendrecht", - "stopId": "nl-OpenOV_3979812", - "parentId": "nl-OpenOV_NL:S:30009551", - "importance": 0.018022045493125916, - "lat": 52.323895, - "lon": 4.936262000000002, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:35:00Z", - "departure": "2026-08-16T21:35:00Z", - "scheduledArrival": "2026-08-16T21:35:00Z", - "scheduledDeparture": "2026-08-16T21:35:00Z", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-09T15:42:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-09T15:42:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Neem NS-treinen naar Zuid of stap op Spaklerweg over voor Overamstel. Details: gvb.nl/zomermetro --|Take NS trains to Zuid or change at Spak", - "descriptionText": "Neem NS-treinen naar Zuid of stap op Spaklerweg over voor Overamstel. Details: gvb.nl/zomermetro --|Take NS trains to Zuid or change at Spaklerweg for Overamstel. Details: gvb.nl/summermetro" - } - ], - "modes": [ - "SUBWAY", - "BUS" - ] - }, - { - "name": "Amsterdam, Van der Madeweg", - "stopId": "nl-OpenOV_3981387", - "parentId": "nl-OpenOV_NL:S:30009516", - "importance": 0.0271453857421875, - "lat": 52.329903, - "lon": 4.930333000000001, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:36:00Z", - "departure": "2026-08-16T21:37:00Z", - "scheduledArrival": "2026-08-16T21:36:00Z", - "scheduledDeparture": "2026-08-16T21:37:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Stap op Spaklerweg over voor Overamstel of op Amstel voor RAI. Details: gvb.nl/zomermetro –|Change at Spaklerweg for Overamstel or at Amstel", - "descriptionText": "Stap op Spaklerweg over voor Overamstel of op Amstel voor RAI. Details: gvb.nl/zomermetro –|Change at Spaklerweg for Overamstel or at Amstel for RAI. Details: gvb.nl/summermetro" - } - ], - "modes": [ - "SUBWAY", - "BUS" - ] - }, - { - "name": "Amsterdam, Spaklerweg", - "stopId": "nl-OpenOV_3980158", - "parentId": "nl-OpenOV_NL:S:30009518", - "importance": 0.02681240625679493, - "lat": 52.340239999999994, - "lon": 4.92107, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:39:00Z", - "departure": "2026-08-16T21:39:00Z", - "scheduledArrival": "2026-08-16T21:39:00Z", - "scheduledDeparture": "2026-08-16T21:39:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "SUBWAY", - "BUS" - ] - }, - { - "name": "Amsterdam, Amstelstation", - "stopId": "nl-OpenOV_3980520", - "parentId": "nl-OpenOV_NL:S:30009514", - "importance": 0.052102621644735336, - "lat": 52.346489999999996, - "lon": 4.9175699999999996, - "level": 0.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:40:00Z", - "departure": "2026-08-16T21:41:00Z", - "scheduledArrival": "2026-08-16T21:40:00Z", - "scheduledDeparture": "2026-08-16T21:41:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "alerts": [ - { - "communicationPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "impactPeriod": [ - { - "start": "2026-07-04T04:00:00Z", - "end": "2026-08-16T23:00:00Z" - } - ], - "cause": "UNKNOWN_CAUSE", - "effect": "UNKNOWN_EFFECT", - "headerText": "Neem tram 23 voor RAI of bus 78 voor Overamstel. Details: gvb.nl/zomermetro. --|Take tram 23 for RAI or bus 78 for Overamstel. Details: gvb.nl/summermetro", - "descriptionText": "Neem tram 23 voor RAI of bus 78 voor Overamstel. Details: gvb.nl/zomermetro. --|Take tram 23 for RAI or bus 78 for Overamstel. Details: gvb.nl/summermetro" - } - ], - "modes": [ - "REGIONAL_RAIL", - "SUBWAY", - "TRAM", - "BUS" - ] - }, - { - "name": "Amsterdam, Wibautstraat", - "stopId": "nl-OpenOV_3980265", - "parentId": "nl-OpenOV_NL:S:30009512", - "importance": 0.027183683589100838, - "lat": 52.354332, - "lon": 4.9121879999999996, - "level": -2.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:42:00Z", - "departure": "2026-08-16T21:43:00Z", - "scheduledArrival": "2026-08-16T21:42:00Z", - "scheduledDeparture": "2026-08-16T21:43:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "SUBWAY", - "TRAM", - "BUS" - ] - }, - { - "name": "Amsterdam, Weesperplein", - "stopId": "nl-OpenOV_3981336", - "parentId": "nl-OpenOV_NL:S:30009510", - "importance": 0.02798701450228691, - "lat": 52.361236999999996, - "lon": 4.907945, - "level": -2.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:44:00Z", - "departure": "2026-08-16T21:45:00Z", - "scheduledArrival": "2026-08-16T21:44:00Z", - "scheduledDeparture": "2026-08-16T21:45:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "SUBWAY", - "TRAM", - "BUS" - ] - }, - { - "name": "Amsterdam, Waterlooplein", - "stopId": "nl-OpenOV_3980640", - "parentId": "nl-OpenOV_NL:S:30009508", - "importance": 0.027206193655729294, - "lat": 52.366985, - "lon": 4.9031400000000005, - "level": -2.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:46:00Z", - "departure": "2026-08-16T21:46:00Z", - "scheduledArrival": "2026-08-16T21:46:00Z", - "scheduledDeparture": "2026-08-16T21:46:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "SUBWAY", - "TRAM", - "BUS" - ] - }, - { - "name": "Amsterdam, Nieuwmarkt", - "stopId": "nl-OpenOV_3981245", - "parentId": "nl-OpenOV_NL:S:30009502", - "importance": 0.02679653838276863, - "lat": 52.371914, - "lon": 4.901427000000001, - "level": -2.0, - "tz": "Europe/Brussels", - "arrival": "2026-08-16T21:47:00Z", - "departure": "2026-08-16T21:47:00Z", - "scheduledArrival": "2026-08-16T21:47:00Z", - "scheduledDeparture": "2026-08-16T21:47:00Z", - "scheduledTrack": "2", - "track": "2", - "vertexType": "TRANSIT", - "pickupType": "NORMAL", - "dropoffType": "NORMAL", - "cancelled": false, - "modes": [ - "SUBWAY" - ] - } - ], - "legGeometry": { - "points": "wd|vbBornoHN??fGFxa@?hQOzU?jFwBhF}ApDVhFLhg@^bi@LnDM|UBno@?bIKj[?vATxl@NpNFz`@D~j@?z`@?f]Fpd@Vl[?dGLjQVdGL|Jb@hQHlE\\rMnAxVb@|Id@jFzAlZhAtLv@vLjAvL?ZbAvLf@fGfBbSjAtL~Ib~@rClZvAjPd@lEdH|t@tCf\\`C`Tr@zJd@hFdA`IpBhQxBhQjEpX|AvLpCpXjCtWbGpn@zHnz@fBdR|A`TjAbSd@tWVvLWtM[`T_@|JmAhQaBhRcClP_DjQsEbT_DzKoD|JkD~J{E|J}BnE_DfG_DjFkBtBkFfHeFhGiGhGqHjG{OzLee@t\\{PvN_SnQW?eAz@cj@xf@g@\\aAz@a@ZgAz@e@z@u@\\qHfHap@nj@u@z@kAx@O\\e@?qCrCse@bc@_SrP_IdIiXbVeJdI}OxMsAxAaRpPmBxAq@x@q@z@yIdIkGjFeOxMuJbJ}Az@kCrCg@\\sAvA{HjGgGhGO?wXbV{FlFoWfU_d@h`@s`@p]oUjSsOzMoCrCkAx@_DrCeEpDmGfHmh@|e@sAx@kAz@sAvAyAxA{p@lk@u@z@q@z@gEpDsDrCkCrCw`@r\\{JbJqk@vg@qBxAil@pi@yBvBce@db@wAz@mBvA]z@u@\\e@x@u@\\cAz@}OvNwDpDaf@db@sAxAaCtBcTnQS\\}XfUqHjG{BtBaAz@u@x@oCvBkFnEwGfHw`@p]gb@l_@wX`Wu@\\iAvAkBxAgAz@wAvAqRlRgYdVyNvN_DrC?\\K?{FnEgSrPO?cj@|e@oDnDsBxAgm@ri@yAvAuJfI{f@bc@iBtBiAz@u@\\iBtBccA~}@wL`Kcj@th@wVbW_UfT_VdVwAvAgAz@eXxYoCtCyBrCW?k@x@u@z@{FhGkBrCeSjSmGhGuNtO{L~KqLbJoCtBeKbJkK`K_}@lcAW\\cAz@cAvA}@z@sAvAsj@hm@}h@th@wIbJwFjFuWt[}O~KcP`L_DrC{@x@w@z@_DrCcAz@cAz@kAx@gAxAsEpDU\\{AvAgc@l_@iUlSce@ha@_IdImBtByFnEea@r]e@z@wAx@kM|LaCtByBtBsCvBkCtByNzMa@Z}BvBuJdIs`@r]sj@|e@kiC`~Bos@hn@sfAxaA_\\~XoUlR{PzMcVnRyLfIqBz@iCxAqGpDeU|M}bAxj@eA\\{Az@ac@pSwBvAsEvBwDrCcIrDwBxAiA\\_DxAyIrDgOjG_MvCuNpEyUvDgJvCkGxAkNhHcj@fXk_Adf@gJnFiZvOkKnFyBz@ya@pSWZ}^rRyQ|LyIjG_M~Kkl@nk@sb@fb@wVfUaP~L}P~KwMlGuOdJqVhIwSpFcWfJgLpEwLnFgOjHga@nSsFtCs{@lc@eS~LaR~KkdA`i@ia@pSihA~i@c`@nScJpEgGrDcV`Li}@df@uOhIwf@dXsWzNwDxA_MnFmQjHufBxz@oLnFea@fWuJjGiGlFmFlF_DpDmDpDqCnDeEjGeEhG_ItNsY|o@sMvYgZzp@yF|KuE|KkF|KwG|KyDhGyBrC{FfHaHfHmLbKkHnE}FtCoDxAeExAeE|@iBz@mFz@eJ|@_Nb@oG@{JsA_DYeIuAiLgE_TyI_o@aY_NcGkCuAoAy@sEoC_HiEsDqCsIaHoJyJyBoCeEiFcMgPu^kc@qL{IqM_H}S_HkKqAqMsAaNDgSxCoHxAcMtDsR~LkHfHsCpDiBtBaAvBY?sAtBqEfHcCrCuE~Ja@z@oGvM_DdI_IdTkVnt@wBqC", - "precision": 6, - "length": 430 - }, - "bikesAllowed": true, - "wheelchairAccessible": "NOT_ACCESSIBLE", - "reservation": "NONE", - "alternatives": [] - } - ] -} \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index 5a26c09..b255557 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -3,7 +3,7 @@ import random import json from datetime import datetime, timezone -from src.utils import logger, get_train_name, convert_iso_string, validate_connection +from src.utils import logger, get_train_name, validate_connection, parse_iso from src.config import config stations = config.connections.stations @@ -120,8 +120,8 @@ def get_random_stop_id() -> str | None: stop_ids_list = list(stop_ids.keys()) stops_string = ", ".join(stop_ids.values()) if len(stop_ids_list) > 1: - logger(f"Station '{assigned_station}' not found, choosing random from available: {stops_string}") - logger(f"No station associated as '{assigned_station}', choosing random from available") + logger(f"No station associated as '{assigned_station}', choosing random from similar named stations:") + logger({stops_string}) chosen_stop_id = random.choice(stop_ids_list) return chosen_stop_id @@ -209,8 +209,8 @@ def get_trip_details(random_connection: dict | None) -> dict | None: start_time = legs["startTime"] mode = legs["mode"] - arrival = convert_iso_string(end_time) - departure = convert_iso_string(start_time) + arrival_dt = parse_iso(end_time) + departure_dt = parse_iso(start_time) train_name = get_train_name(display_name, mode) if train_from == from_station: @@ -227,27 +227,27 @@ def get_trip_details(random_connection: dict | None) -> dict | None: "agency": legs["agencyName"], "route_color": legs.get("routeColor"), "duration": legs["duration"], - "departure": departure, - "arrival": arrival, + "departure": departure_dt.strftime("%H:%M"), + "arrival": arrival_dt.strftime("%H:%M"), "mode": mode, "stops": {} } - trip_details["stops"][train_from] = departure - departure_time = start_time + trip_details["stops"][train_from] = departure_dt + departure_time_iso = start_time for stop in legs["intermediateStops"]: - stop_arrival = convert_iso_string(stop["arrival"]) - trip_details["stops"][stop["name"]] = stop_arrival # not sure if that actually works but im too tired to question it + stop_arrival_dt = parse_iso(stop["arrival"]) + trip_details["stops"][stop["name"]] = stop_arrival_dt if stop.get("name") == from_station: - departure_time = stop["departure"] - trip_details["departure"] = convert_iso_string(departure_time) - trip_details["stops"][goes_to] = arrival + departure_time_iso = stop["departure"] + trip_details["departure"] = parse_iso(departure_time_iso).strftime("%H:%M") - valid = validate_connection(start_time, end_time, departure_time) + trip_details["stops"][goes_to] = arrival_dt + + valid = validate_connection(start_time, end_time, departure_time_iso) if not valid: return None - - logger(json.dumps(trip_details, indent=4, ensure_ascii=False)) + return trip_details diff --git a/src/config.py b/src/config.py index 160486c..33957b9 100644 --- a/src/config.py +++ b/src/config.py @@ -44,7 +44,7 @@ class Config: def _load_config() -> Config: with open("config.json", "r") as file: raw = json.load(file) - + return Config( discord=DiscordConfig(**raw["discord"]), connections=ConnectionsConfig(**raw["connections"]), diff --git a/src/data/operators.py b/src/data/operators.py index 68119cb..a3bd292 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -110,6 +110,7 @@ OPERATORS = { } OPERATOR_ALIASES = { + "Arverio BAyern GmbH": OPERATORS["Arverio Bayern"], "DB Regio AG Baden-Württemberg": OPERATORS["db_bawü"], "DB Regio Stuttgart GmbH": OPERATORS["db_bawü"], "Arverio Baden-Württemberg": OPERATORS["db_bawü"], diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 2f9a070..a383f58 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -34,8 +34,7 @@ def build_info_embed() -> discord.Embed: stops = trip["stops"] - next_stop = get_next_station(trip["stops"]) - print(f"next_stop: {next_stop}") + next_stop = get_next_station(trip["stops"], trip["from"]) next_stop_station = None if next_stop: next_stop_station = next_stop.get("name") diff --git a/src/utils.py b/src/utils.py index e8611d2..2c42df2 100644 --- a/src/utils.py +++ b/src/utils.py @@ -10,7 +10,7 @@ import src.data.operators as operators from src.data.emojis import emoji_list _operator_mtime = None - +LOCAL_TZ = ZoneInfo(config.connections.timezone) def logger(msg, log_type="info") -> str: status = log_type.upper() @@ -60,14 +60,9 @@ def validate_connection(start_time: str, end_time: str, station_departure: str) return True -def convert_iso_string(isostring) -> str: - timezone = config.connections.timezone - dt = datetime.fromisoformat(isostring.replace('Z', '+00:00')) - dt = dt.astimezone(ZoneInfo(timezone)) - - if dt.second >= 30: - dt += timedelta(minutes=1) - return dt.strftime('%H:%M') +def parse_iso(iso_str: str) -> datetime: + dt = datetime.fromisoformat(iso_str.replace("Z", "+00:00")) + return dt.astimezone(LOCAL_TZ) def channel_formatting(mode: str) -> str: formatting = config.discord.formatting @@ -80,7 +75,7 @@ def channel_formatting(mode: str) -> str: return f"{emoji}{formatting}" def get_train_name(train_name: str, mode: str) -> str: - if mode == "BUS" or mode == "TRAM": + if mode == "BUS" or mode == "TRAM" or train_name.isdigit(): train = f"{mode.capitalize()} {train_name}" elif "(" in train_name: train = train_name.split(" (")[0] @@ -153,24 +148,19 @@ def get_sound_path(destination) -> str | None: return sound_path -def get_next_station(stops: dict) -> dict | None: - now = datetime.now() - today = datetime.today() - day_offset = 0 - previous_time = None - - for name, arrival_str in stops.items(): - arrival_time = datetime.strptime(arrival_str, "%H:%M").time() - - if previous_time is not None and arrival_time < previous_time: - day_offset += 1 - - arrival_dt = datetime.combine(today + timedelta(days=day_offset), arrival_time) - previous_time = arrival_time - +def get_next_station(stops: dict, train_from :str) -> dict | None: + now = datetime.now(LOCAL_TZ) + print(train_from) + for name, arrival_dt in stops.items(): if arrival_dt >= now: - return {"name": name, "arrival": arrival_str} - + if name == train_from: + return None + else: + return { + "name": name, + "arrival": arrival_dt.strftime("%H:%M") + } + return None def format_via_list(stops: dict) -> str: @@ -187,9 +177,9 @@ def format_stop_list(stops: dict, next_stop: str | None) -> list[tuple[str, str] for name, stop_arrival in stops.items(): if name == next_stop: - line = f"• __{name} ({stop_arrival} Uhr__)" + line = f"• __{name}__ ({stop_arrival.strftime("%H:%M")} Uhr)" else: - line = f"• {name} ({stop_arrival} Uhr)" + line = f"• {name} ({stop_arrival.strftime("%H:%M")} Uhr)" if field_length + len(line) + 1 > 1024: route_page_name = "Route" if part == 1 else "Route (Fortsetzung)" From 21146fff862361ba0c8abfc813b72503332faa78 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 14:08:08 +0200 Subject: [PATCH 30/48] transitous rewrite: fix transfer --- src/api/transitous.py | 1 + src/dc/handlers.py | 19 +++++++------------ src/utils.py | 1 - 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index b255557..e124988 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -229,6 +229,7 @@ def get_trip_details(random_connection: dict | None) -> dict | None: "duration": legs["duration"], "departure": departure_dt.strftime("%H:%M"), "arrival": arrival_dt.strftime("%H:%M"), + "arrival_dt": arrival_dt, "mode": mode, "stops": {} } diff --git a/src/dc/handlers.py b/src/dc/handlers.py index c2c00c9..a4052f6 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -3,7 +3,7 @@ import asyncio import random from datetime import datetime, timedelta, date -from src.utils import logger, channel_formatting, choose_connection, get_sound_path +from src.utils import logger, channel_formatting, choose_connection, get_sound_path, LOCAL_TZ from src.config import config _scheduled_task: asyncio.Task | None = None @@ -42,23 +42,18 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals await announcer("umstieg", voice_channel) - _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, arrival, voice_channel, trip["to"])) + _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, trip["arrival_dt"], voice_channel, trip["to"])) -async def _schedule_next_transfer(bot: discord.Bot, arrival, voice_channel: discord.VoiceChannel, destination: str): - now = datetime.now() - parsed_time = datetime.strptime(arrival, "%H:%M").time() - arrival_dt = datetime.combine(date.today(), parsed_time) - - if arrival_dt < now: - arrival_dt += timedelta(days=1) +async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_channel: discord.VoiceChannel, destination: str): + now = datetime.now(LOCAL_TZ) wait_seconds = (arrival_dt - now).total_seconds() announcement_countdown = random.randrange(180, 300) - announcement_countdown = 3 + if wait_seconds > 0: remaining = str(timedelta(seconds=wait_seconds)) - logger(f"Nächster Umstieg in {remaining.split('.')[0]} ({arrival} Uhr)") + logger(f"Nächster Umstieg in {remaining.split('.')[0]} ({arrival_dt.strftime('%H:%M')} Uhr)") if wait_seconds > announcement_countdown: wait_until_end_announcement = wait_seconds - announcement_countdown @@ -73,7 +68,7 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival, voice_channel: disc async def announcer(announcement: str, voice_channel: discord.VoiceChannel, destination = None): from src.dc.embeds import build_info_embed, build_announcement_embed - + now = datetime.now() announcements_enabled = config.announcements.enabled voice_announcement_enabled = config.announcements.voice[0].enabled diff --git a/src/utils.py b/src/utils.py index 2c42df2..f0ab591 100644 --- a/src/utils.py +++ b/src/utils.py @@ -150,7 +150,6 @@ def get_sound_path(destination) -> str | None: def get_next_station(stops: dict, train_from :str) -> dict | None: now = datetime.now(LOCAL_TZ) - print(train_from) for name, arrival_dt in stops.items(): if arrival_dt >= now: if name == train_from: From 842c944faa2596db3dfca5a6eee5a22fc5584a19 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 15:33:14 +0200 Subject: [PATCH 31/48] transitous rewrite: improved via --- src/api/transitous.py | 25 ++++++++++++++++++++----- src/data/operators.py | 4 ++++ src/dc/embeds.py | 1 + src/dc/handlers.py | 1 - src/utils.py | 35 +++++++++++++++++++++++++++++------ 5 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index e124988..986684b 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -232,23 +232,38 @@ def get_trip_details(random_connection: dict | None) -> dict | None: "arrival_dt": arrival_dt, "mode": mode, "stops": {} - } + } - trip_details["stops"][train_from] = departure_dt + train_from_importance = legs["from"]["importance"] + trip_details["stops"][train_from] = { + "arrival": departure_dt, + "importance": train_from_importance + } + departure_time_iso = start_time for stop in legs["intermediateStops"]: stop_arrival_dt = parse_iso(stop["arrival"]) - trip_details["stops"][stop["name"]] = stop_arrival_dt + stop_importance = stop["importance"] + stop_details = { + "arrival": stop_arrival_dt, + "importance": stop_importance + } + trip_details["stops"][stop["name"]] = stop_details if stop.get("name") == from_station: departure_time_iso = stop["departure"] trip_details["departure"] = parse_iso(departure_time_iso).strftime("%H:%M") - trip_details["stops"][goes_to] = arrival_dt + train_to_importance = legs["to"]["importance"] + trip_details["stops"][goes_to] = { + "arrival": arrival_dt, + "importance": train_to_importance + } valid = validate_connection(start_time, end_time, departure_time_iso) if not valid: return None - + + logger(json.dumps(trip_details, indent=4, ensure_ascii=False, default=str)) return trip_details diff --git a/src/data/operators.py b/src/data/operators.py index a3bd292..a187f78 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -106,6 +106,10 @@ OPERATORS = { "Vr": { "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Vr_Logo.png/330px-Vr_Logo.png", "color": 0x00B451 + }, + "GVB": { + "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/GVB_Amsterdam_Logo_001.svg/1280px-GVB_Amsterdam_Logo_001.svg.png", + "color": 0x2B62AF } } diff --git a/src/dc/embeds.py b/src/dc/embeds.py index a383f58..610c229 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -18,6 +18,7 @@ def build_embed_footer(mode: str, slogans): "icon": icon } + def build_info_embed() -> discord.Embed: from src.dc.handlers import trip diff --git a/src/dc/handlers.py b/src/dc/handlers.py index a4052f6..c7a502c 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -18,7 +18,6 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals trip = choose_connection() while trip is None and attempt < max_attempt: attempt += 1 - logger(f"Attempt {attempt}: Failed to select route, retrying...", "error") trip = choose_connection() if trip is None: diff --git a/src/utils.py b/src/utils.py index f0ab591..5b7146b 100644 --- a/src/utils.py +++ b/src/utils.py @@ -150,7 +150,8 @@ def get_sound_path(destination) -> str | None: def get_next_station(stops: dict, train_from :str) -> dict | None: now = datetime.now(LOCAL_TZ) - for name, arrival_dt in stops.items(): + for name, info in stops.items(): + arrival_dt = info["arrival"] if arrival_dt >= now: if name == train_from: return None @@ -164,20 +165,42 @@ def get_next_station(stops: dict, train_from :str) -> dict | None: def format_via_list(stops: dict) -> str: if len(stops) > 2: - count = min(3, len(stops)) - random_stops = random.sample(list(stops), k=count) - via = f"{', '.join(random_stops[:-1])} und {random_stops[-1]}" + stations = list(stops.keys()) + trip_from = stations[0] + trip_to = stations[-1] + + important_stops = sort_stations_by_importance(stops)[:3] + if trip_from in important_stops: + important_stops.remove(trip_from) + if trip_to in important_stops: + important_stops.remove(trip_to) + + via = f"{', '.join(important_stops[:-1])} und {important_stops[-1]}" return via return None +def sort_stations_by_importance(stops: dict) -> list: + sorted_stations_dict = dict( + sorted( + [(name, info["importance"]) for name, info in stops.items()], + key=lambda x: x[1], + reverse=True) + ) + + sorted_stations = list(sorted_stations_dict.keys()) + return sorted_stations + def format_stop_list(stops: dict, next_stop: str | None) -> list[tuple[str, str]]: fields = [] field_lines, field_length, part = [], 0, 1 - for name, stop_arrival in stops.items(): + for name, info in stops.items(): if name == next_stop: + stop_arrival = info["arrival"] + print(stop_arrival) line = f"• __{name}__ ({stop_arrival.strftime("%H:%M")} Uhr)" else: + stop_arrival = info["arrival"] line = f"• {name} ({stop_arrival.strftime("%H:%M")} Uhr)" if field_length + len(line) + 1 > 1024: @@ -192,4 +215,4 @@ def format_stop_list(stops: dict, next_stop: str | None) -> list[tuple[str, str] route_page_name = "Route" if part == 1 else "Route (Fortsetzung)" fields.append((route_page_name, "\n".join(field_lines))) - return fields \ No newline at end of file + return fields From f990a55da9880ef28c8e4a5fac320f17c647f898 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 15:52:12 +0200 Subject: [PATCH 32/48] transitous rewrite: minor cleanup --- src/api/transitous.py | 1 - src/dc/handlers.py | 1 - src/utils.py | 6 ++---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index 986684b..5b2315f 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -264,6 +264,5 @@ def get_trip_details(random_connection: dict | None) -> dict | None: if not valid: return None - logger(json.dumps(trip_details, indent=4, ensure_ascii=False, default=str)) return trip_details diff --git a/src/dc/handlers.py b/src/dc/handlers.py index c7a502c..2d41f12 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -67,7 +67,6 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_ async def announcer(announcement: str, voice_channel: discord.VoiceChannel, destination = None): from src.dc.embeds import build_info_embed, build_announcement_embed - now = datetime.now() announcements_enabled = config.announcements.enabled voice_announcement_enabled = config.announcements.voice[0].enabled diff --git a/src/utils.py b/src/utils.py index 5b7146b..b76a217 100644 --- a/src/utils.py +++ b/src/utils.py @@ -66,8 +66,9 @@ def parse_iso(iso_str: str) -> datetime: def channel_formatting(mode: str) -> str: formatting = config.discord.formatting + emoji = "" - if config.discord.formatting: + if config.discord.emojis: emoji = emoji_list.get(mode) if emoji is None: emoji = emoji_list.get("Fallback") @@ -115,8 +116,6 @@ def get_operator_metadata(agency: str, route_color: str) -> dict: color = int(route_color, 16) except ValueError: color = operators.OPERATORS["fallback"]["color"] - else: - logger(f"Managed to get color from API, add agency to src/data/operators.py if you don't like it") else: color = operators.OPERATORS["fallback"]["color"] return { @@ -197,7 +196,6 @@ def format_stop_list(stops: dict, next_stop: str | None) -> list[tuple[str, str] for name, info in stops.items(): if name == next_stop: stop_arrival = info["arrival"] - print(stop_arrival) line = f"• __{name}__ ({stop_arrival.strftime("%H:%M")} Uhr)" else: stop_arrival = info["arrival"] From 60d4936ddafa93f672356116fa185570f144d5b5 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:14:43 +0200 Subject: [PATCH 33/48] transitous rewrite: only send announcement embed when no voice announcement --- src/api/transitous.py | 4 +- src/data/operators.py | 2 +- src/dc/embeds.py | 4 +- src/dc/handlers.py | 101 ++++++++++++++++++++++-------------------- src/utils.py | 13 +++--- 5 files changed, 66 insertions(+), 58 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index 5b2315f..b84247d 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -120,8 +120,8 @@ def get_random_stop_id() -> str | None: stop_ids_list = list(stop_ids.keys()) stops_string = ", ".join(stop_ids.values()) if len(stop_ids_list) > 1: - logger(f"No station associated as '{assigned_station}', choosing random from similar named stations:") - logger({stops_string}) + logger(f"No station associated as '{assigned_station}', choosing random from similar named station") + logger(f"Run `python run main.py stations` to get exact station names") chosen_stop_id = random.choice(stop_ids_list) return chosen_stop_id diff --git a/src/data/operators.py b/src/data/operators.py index a187f78..bf927dd 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -108,7 +108,7 @@ OPERATORS = { "color": 0x00B451 }, "GVB": { - "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a3/GVB_Amsterdam_Logo_001.svg/1280px-GVB_Amsterdam_Logo_001.svg.png", + "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/BSicon_LOGO_GVB.svg/960px-BSicon_LOGO_GVB.svg.png", "color": 0x2B62AF } } diff --git a/src/dc/embeds.py b/src/dc/embeds.py index 610c229..f99430f 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -23,7 +23,7 @@ def build_info_embed() -> discord.Embed: from src.dc.handlers import trip agency = trip["agency"] - metadata = get_operator_metadata(agency, trip["route_color"]) + metadata = get_operator_metadata(agency, trip["route_color"], trip["mode"]) departure = format_timestamp_to_dc(trip["departure"]) arrival = format_timestamp_to_dc(trip["arrival"]) @@ -62,7 +62,7 @@ def build_info_embed() -> discord.Embed: def build_announcement_embed(msg): from src.dc.handlers import trip agency = trip["agency"] - metadata = get_operator_metadata(agency, trip["route_color"]) + metadata = get_operator_metadata(agency, trip["route_color"], trip["mode"]) embed = discord.Embed( title = "Informationen zu ihrer Fahrt", diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 2d41f12..3717aa0 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -3,7 +3,7 @@ import asyncio import random from datetime import datetime, timedelta, date -from src.utils import logger, channel_formatting, choose_connection, get_sound_path, LOCAL_TZ +from src.utils import logger, channel_formatting, choose_connection, get_sound_path, LOCAL_TZ, get_next_station from src.config import config _scheduled_task: asyncio.Task | None = None @@ -43,7 +43,56 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, trip["arrival_dt"], voice_channel, trip["to"])) - +async def announcer(announcement: str, voice_channel: discord.VoiceChannel, destination = None): + from src.dc.embeds import build_info_embed, build_announcement_embed + announcements_enabled = config.announcements.enabled + voice_announcement_enabled = config.announcements.voice[0].enabled + + if announcements_enabled: + if len(voice_channel.members) > 0: + match announcement: + case "ende": + if voice_announcement_enabled: + announcement_status = await voice_announcer(destination, voice_channel) + if announcement_status: + return + embed = build_announcement_embed( + f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für ihr Vertrauen und auf Wiedersehen.') + case "umstieg": + embed = build_info_embed() + case _: + logger(f"Unbekanntes Announcements: {announcement}") + embed = None + + if embed: + await voice_channel.send(embed=embed) + + else: + logger(f"Announcement {announcement} wird geskipped, keiner da") + return + +async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel) -> bool: + sound_path = get_sound_path(destination=destination) + if sound_path is None: + return False + + logger(f"VC wird betreten, spiele {sound_path}") + vc = await voice_channel.connect(timeout=15, reconnect=True) + audio_source = discord.FFmpegPCMAudio(sound_path) + + loop = asyncio.get_running_loop() + + if not vc.is_playing(): + def after_playing(error): + if error: + logger(f"Player error: {error}", "error") + loop.create_task(vc.disconnect()) + logger("VC wird verlassen") + + vc.play(audio_source, after=after_playing) + return True + + async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_channel: discord.VoiceChannel, destination: str): now = datetime.now(LOCAL_TZ) @@ -62,49 +111,5 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_ else: await asyncio.sleep(wait_seconds) - logger("Zug angekommen, wähle neue Verbindung") - await rename_vc(bot, voice_channel, from_scheduler=True) - -async def announcer(announcement: str, voice_channel: discord.VoiceChannel, destination = None): - from src.dc.embeds import build_info_embed, build_announcement_embed - announcements_enabled = config.announcements.enabled - voice_announcement_enabled = config.announcements.voice[0].enabled - - if announcements_enabled: - if len(voice_channel.members) > 0: - match announcement: - case "ende": - embed = build_announcement_embed( - f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für ihr Vertrauen und auf Wiedersehen.') - if voice_announcement_enabled: - await voice_announcer(destination, voice_channel) - case "umstieg": - embed = build_info_embed() - case _: - logger(f"Unbekanntes Announcements: {announcement}") - embed = None - if embed: - await voice_channel.send(embed=embed) - else: - logger(f"Announcement {announcement} wird geskipped, keiner da") - return - -async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel): - sound_path = get_sound_path(destination=destination) - if sound_path is None: - return - - logger(f"VC wird betreten, spiele {sound_path}") - vc = await voice_channel.connect(timeout=15, reconnect=True) - audio_source = discord.FFmpegPCMAudio(sound_path) - - loop = asyncio.get_running_loop() - - if not vc.is_playing(): - def after_playing(error): - if error: - logger(f"Player error: {error}", "error") - loop.create_task(vc.disconnect()) - logger("VC wird verlassen") - - vc.play(audio_source, after=after_playing) \ No newline at end of file + logger("Zug angekommen, wähle neue Verbindung") + await rename_vc(bot, voice_channel, from_scheduler=True) \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index b76a217..2fd5f37 100644 --- a/src/utils.py +++ b/src/utils.py @@ -76,7 +76,7 @@ def channel_formatting(mode: str) -> str: return f"{emoji}{formatting}" def get_train_name(train_name: str, mode: str) -> str: - if mode == "BUS" or mode == "TRAM" or train_name.isdigit(): + if train_name.isdigit(): train = f"{mode.capitalize()} {train_name}" elif "(" in train_name: train = train_name.split(" (")[0] @@ -101,7 +101,7 @@ def _reload_operators_if_changed(): logger("operators.py wurde automatisch neu geladen (Änderungen erkannt)") -def get_operator_metadata(agency: str, route_color: str) -> dict: +def get_operator_metadata(agency: str, route_color: str, mode: str) -> dict: _reload_operators_if_changed() op_data = operators.OPERATOR_ALIASES.get(agency) or operators.OPERATORS.get(agency) or operators.OPERATORS["fallback"] @@ -147,7 +147,7 @@ def get_sound_path(destination) -> str | None: return sound_path -def get_next_station(stops: dict, train_from :str) -> dict | None: +def get_next_station(stops: dict, train_from: str) -> dict | None: now = datetime.now(LOCAL_TZ) for name, info in stops.items(): arrival_dt = info["arrival"] @@ -157,7 +157,7 @@ def get_next_station(stops: dict, train_from :str) -> dict | None: else: return { "name": name, - "arrival": arrival_dt.strftime("%H:%M") + "arrival": arrival_dt } return None @@ -174,7 +174,10 @@ def format_via_list(stops: dict) -> str: if trip_to in important_stops: important_stops.remove(trip_to) - via = f"{', '.join(important_stops[:-1])} und {important_stops[-1]}" + if len(important_stops) > 1: + via = f"{', '.join(important_stops[:-1])} und {important_stops[-1]}" + else: + via = important_stops[0] return via return None From 9cd1f54258a42d5bdcfb84171b384b0e6db9b89c Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 18:29:06 +0200 Subject: [PATCH 34/48] transitous rewrite: fix validate_connection --- src/api/transitous.py | 12 ++++-------- src/data/operators.py | 2 +- src/dc/handlers.py | 1 - src/utils.py | 8 ++++---- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/api/transitous.py b/src/api/transitous.py index b84247d..a27e525 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -110,6 +110,7 @@ def get_random_stop_id() -> str | None: if stop_name == assigned_station: stop_ids.clear() + logger(f"Exact match found! Using {stop_name}") stop_ids[stop_id] = stop_name break @@ -118,11 +119,11 @@ def get_random_stop_id() -> str | None: return None stop_ids_list = list(stop_ids.keys()) - stops_string = ", ".join(stop_ids.values()) if len(stop_ids_list) > 1: logger(f"No station associated as '{assigned_station}', choosing random from similar named station") logger(f"Run `python run main.py stations` to get exact station names") - chosen_stop_id = random.choice(stop_ids_list) + chosen_stop_id, chosen_station = random.choice(list(stop_ids.items())) + logger(f"Assigned Station: {chosen_station}") return chosen_stop_id def get_random_connection(stop_id: str) -> str | None: @@ -199,6 +200,7 @@ def get_trip_details(random_connection: dict | None) -> dict | None: except requests.RequestException as e: logger(f"An error occured while trying to get the route details: {e}", "error") return None + legs = data["legs"][0] end_time = legs["endTime"] @@ -254,12 +256,6 @@ def get_trip_details(random_connection: dict | None) -> dict | None: departure_time_iso = stop["departure"] trip_details["departure"] = parse_iso(departure_time_iso).strftime("%H:%M") - train_to_importance = legs["to"]["importance"] - trip_details["stops"][goes_to] = { - "arrival": arrival_dt, - "importance": train_to_importance - } - valid = validate_connection(start_time, end_time, departure_time_iso) if not valid: return None diff --git a/src/data/operators.py b/src/data/operators.py index bf927dd..dec5cfe 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -114,7 +114,7 @@ OPERATORS = { } OPERATOR_ALIASES = { - "Arverio BAyern GmbH": OPERATORS["Arverio Bayern"], + "Arverio Bayern GmbH": OPERATORS["Arverio Bayern"], "DB Regio AG Baden-Württemberg": OPERATORS["db_bawü"], "DB Regio Stuttgart GmbH": OPERATORS["db_bawü"], "Arverio Baden-Württemberg": OPERATORS["db_bawü"], diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 3717aa0..40c69fd 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -92,7 +92,6 @@ async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel) vc.play(audio_source, after=after_playing) return True - async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_channel: discord.VoiceChannel, destination: str): now = datetime.now(LOCAL_TZ) diff --git a/src/utils.py b/src/utils.py index 2fd5f37..000cbe0 100644 --- a/src/utils.py +++ b/src/utils.py @@ -27,8 +27,9 @@ def choose_connection() -> dict | None: return trip -def validate_connection(start_time: str, end_time: str, station_departure: str) -> bool: +def validate_connection(start_time: str, end_time: str, departure_time_iso: str) -> bool: now = datetime.now(timezone.utc) + start_dt = datetime.fromisoformat(start_time.replace("Z", "+00:00")) end_dt = datetime.fromisoformat(end_time.replace("Z", "+00:00")) if end_dt < now: @@ -36,13 +37,12 @@ def validate_connection(start_time: str, end_time: str, station_departure: str) return False max_wait_time = config.connections.max_wait_time - start_dt = datetime.fromisoformat(start_time.replace("Z", "+00:00")) if start_dt > now + timedelta(hours=max_wait_time): logger(f"Verbindung liegt zu weit in der Zukunft: {start_dt}", "error") return False - station_departure_dt = datetime.fromisoformat(station_departure.replace("Z", "+00:00")) - trip_duration = (end_dt - station_departure_dt).total_seconds() + departure_time_iso_dt = datetime.fromisoformat(departure_time_iso.replace("Z", "+00:00")) + trip_duration = (end_dt - departure_time_iso_dt).total_seconds() trip_duration_minutes = str(timedelta(seconds=trip_duration)) min_duration = config.connections.min_duration From d4971ab95b88411e9a7fa8aad6daacc5d1d2ebfe Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:35:04 +0200 Subject: [PATCH 35/48] transitous rewrite: retry on roundtrip connections --- README.md | 174 ------------------------------------------ main.py | 5 +- src/api/transitous.py | 4 + 3 files changed, 5 insertions(+), 178 deletions(-) diff --git a/README.md b/README.md index 193c43d..fd7da6e 100644 --- a/README.md +++ b/README.md @@ -1,175 +1 @@ # Gleiswechsel -Gleiswechel ist ein Discord Bot, welcher einen Sprachkanal zu einer real-existierenden, aktuell befahrenden Zugverbindung umbenennt. Diesen Namen behält der Kanal so lange, wie die Verbindung in echt dauert. - -![Beispiel Kanal](.github/preview_kanal.png) - -Der Bot stellt außerdem den `/info` Befehl dar, welcher einem weitere Informationen zur Verbindung zurückgibt - -![Beispiel info](.github/preview_info.png) - -## Setup -```sh -git clone https://github.com/kaaninchen/Gleiswechsel.git - -# Mit Python -python -m venv venv -source venv/bin/activate -pip install -r requirements.txt - -# Mit uv -uv venv venv -source venv/bin/activate -uv pip install -r requirements.txt - -``` - -### Config - -`$ cp config.json.example config.json` -```jsonc -{ - "token": "", // Token des Bots - "stations": [ "Berlin Hbf", "Hamburg Hbf", "München Hbf", "Amsterdam Centraal"], // Bahnhöfe, von denen die Anzeigetafelns gelesen werden. Namen kann man auf https://dbf.finalrewind.org/ nachschlagen. - "dbf": "https://dbf.finalrewind.org", // Die DBF Instanz. Normalerweise müsste man hier nichts ändern - "server": , // Discord Server ID - "vc": , // Server VC ID - "random": true, // Random Zug aus der Anzeigetafel (true) oder erster Zug, der angezeigt wird (false) - "emojis": true, // Emoji Namen beim Channel-Namen (true) oder nicht (false), - "formatting": "┇", // VC Name. Davor steht der Emoji, danach der Zug. - "announcemenents": true, // Announcements zur aktuellen Zugreise im VC-Kanal ja (true) oder nein (false) - "voice_announcements": [ // siehe weitere config erklärungen in der README, benötigt extra setup - { - "enabled": false, - "stations": { - "general": "" - } - } - ], - "blacklist": [] // Blacklist für bestimmte Zug-Typen -} - -``` - -
-weitere Config Erklärungen - -#### dbf: -Falls, aus irgendwelchem Gründen, man nicht die [offizielle DBF Instanz](https://dbf.finalrewind.org) nutzen möchte, hat man die Möglichkeiten seine eigene zu hosten. Instruction dazu gibts auf dem [zuständigen Repo](https://github.com/derf/db-fakedisplay). Dafür kann man das Feld in der config mit der eigenen URL austauschen. - -#### random: -Bei kleineren Bahnhöfen stehen an den Anzeigetafeln öfters die Züge lange vor Abfahrt da, weil sonst der Bahnhof leer steht. Dadurch wird auch der Name des VC sehr lange gleich bleiben. -Sollte man `random = false` setzen, würde immer der erste Zug an der Anzeigetafel genommen werden, welcher auch der wäre welcher am frühesten losfährt. Wenn man viele Bahnhöfe hat besteht darin keine Gefahr. - -Wenn man nur einen Bahnhof hat ist es stark empfohlen random zu nutzen. Sonst könnte der Bot bei unvollständigen Einträgen in einer Schleife immer wieder vergeblich den selben unvollständigen Zug probieren. - -#### announcements: -Der Bot kann während der Zugreise Ankündigungen in den Textkanal vom Sprachkanal schicken. Das würde er aber auch nur machen wenn sich dort mindestens eine Person aufhält. Aktuelle Announcements: -- 3-5 Min vor Umstieg gibt es eine Ankündigung dafür -- Info Embed bei Umstieg -- voice_announcements - -#### voice_announcements: -⚠️ Announcements muss aktiviert sein - -Der Bot kann 3-5 Min vor Umstieg den VC joinen und eine Audiodatei abspielen. Dafür braucht der Bot ffmpeg. - -```sh -$ sudo apt install ffmpeg # Debian/Ubuntu - -$ brew install ffmpeg # macOS (brew) -``` - -##### Voice_announcements config: - -```json - "voice_announcements": [ - { - "enabled": true, - "stations": { - "general": "general.aac", - "Hannover": "hannover.aac" - } - } - ], -``` - -Audiodateien werden in [src/data/announcements](src/data/announcements) platziert. In der Config wird der Name der Station (z.B. Hannover) zu dem Namen der Audiodatei (z.B. hannover.aac) zugewiesen. Die Audiodatei braucht keinen Path. - -Der Eintrag `general` meint die allgemeine Audiodatei, welche bei jeder Endstation (mit Ausnahme der zugewiesenen) spielt. Sollte man nur Audios bei zugewiesenen Endstationen abspielen wollen kann man `general` leerlassen, der bot skipped das ganze dann: - -```json -"stations": { - "general": "" -} -``` - -Es gibt außerdem die Möglichkeit, mehrere Audiodateien zu einer Endstation durch Listen zuzuweisen. Der Bot sucht sich dann jedes mal wenn er den vc joined eine davon aus. - -```json -"stations": { - "general": ["general_1.aac", "general_2.aac"] -} -``` - -#### blacklist: -Die Blacklist ist dafür gedacht, ganze Zugtypen zu ignorieren. Beispielsweise möchte man, dass der Bot keine ICE's, keine NightJets und keine European Sleepers auswählt, da diese sehr lange Strecken fahren und der VC somit lange unverändert bleibt: -```json -{ - "blacklist": [ - "ICE", - "NJ", - "ES" - ] -} -``` - -Die Namen der einzelnen Zugtypen kann im Footer von `/info` oder im Terminal log erfahren. - -#### src/data -Es kann vorkommen, dass während dem `/info` Befehl das Logo und die Farbe des Bahnuntermehns fehlt. - -![Beispiel für fehlende Daten](.github/info_fehlende_daten.png) - -Die zugehörigen Daten lassen sich innerhalb [src/data/operators.py](src/data/operators.py) ergänzen. Der Aufbau dabei sollte selbsterklärend sein, dennoch habe ich eine kleine Beschreibung in die Datei hinzugefügt. Bei Änderungen sind PR's willkommen. - -Emojis für die Formattierung werden dynamisch anhand des Zugtypens gepulled. Dabei wird zwischen Nahverkehr und Fernverkehr unterschieden. Bei einem Zugtyp, welcher zu keiner der Kategorie assigned ist, wird ein Fallback Emoji eingesetzt. Sollte man einen Zugtypen hinzufügen wollen oder die Emojis ändern/deaktivieren wollen ist dies in [src/data/emojis.py](src/data/emojis.py) möglich. Die Namen der einzelnen Zugtypen kann im Footer von `/info` oder im Terminal log erfahren. - -Den Status, den sich der Bot alle 5 Minuten random auswählt, kann man in [src/data/status.py](src/data/status.py) anpassen. - -
- -### Running - -```sh -# Python -python main.py -# ODER -python3 main.py - -# uv -uv run main.py -``` - -## Bekannte Bugs -#### Stuttgart in Berlin -Ich weiß nicht ganz wieso, aber die API vertauscht manchmal die S-Bahn von Berlin mit der S-Bahn von Stuttgart. Es scheint eher ein API-Issue zu sein, weswegen ich da leider mit dem Bot nicht viel ändern kann. -Der Bug führt dazu, dass bei manchen S-Bahn Verbindungen `DB Regio AG S-Bahn Stuttgart` als Betreiber der Berlin S-Bahn angezeigt wird. Außerdem gibt die API dem Bot die Ankunftszeiten einer S-Bahn Verbindung von Stuttgart wieder, während die Route von der aus Berlin stammt (Die Route und die Ankunftszeiten werden von zwei verschiedenen Endpoints gepulled: Route: `{dbf}/Berlin%20Hbf.json`, Ankunftszeit: `{dbf}/z/S%20{ID}/Berlin Hbf.json`). -Falls das einem zu sehr stört kann man S-Bahns auf die Blacklist packen. - -```json -{ - "blacklist": [ - "S " - ] -} - -``` - -#### Nahreisezug -Der Bot empfängt durch die dbf API ein Operator Field, wo der Betreiber des Züges angezeigt wird. Dadurch kann im `/info` Embed das Logo durch [src/data/operators.py](src/data/operators.py) zugewiesen werden. Manchmal schmeißt die API aber als Operator "Nahreisezug" aus. - -![Beispiel für Nahreisezug](.github/info_nahreisezug.png) - -Wenn mehrere Betreiber angezeigt werden (bspw `["SBB", "Nahreisezug"]`) versucht der Bot immer, den Embed den bekannten Betreiber (in dem Fall SBB) zuzuweisen. Sollte allerdings nur Nahreisezug angezeigt werden, kann damit nicht gearbeitet werden, wodurch die Fallback Metadaten genutzt werden. - -Die Fallback Metadaten können in [src/data/operators.py](src/data/operators.py) angepasst werden. \ No newline at end of file diff --git a/main.py b/main.py index c03a2e9..c1c1f6f 100644 --- a/main.py +++ b/main.py @@ -21,16 +21,13 @@ if len(sys.argv) > 1: async def on_ready(): global _bot_initialized - logger(f"{bot.user} ist online") - if not _bot_initialized: + logger(f"{bot.user} ist online") _bot_initialized = True server_id = config.discord.server server_vc_id = config.discord.vc channel = validate_channel(bot=bot, server_id=server_id, channel_id=server_vc_id) await rename_vc(bot, voice_channel=channel) - else: - logger("Reconnected to discord gateway, this wont disturb your current ride") try: bot.run(config.discord.token) diff --git a/src/api/transitous.py b/src/api/transitous.py index a27e525..fc02f51 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -211,6 +211,10 @@ def get_trip_details(random_connection: dict | None) -> dict | None: start_time = legs["startTime"] mode = legs["mode"] + if goes_to == train_from: + logger(f"Bot doesn't know what to do with round trips, I'll have to implement this some day", "error") + return None # TODO actually handel this + arrival_dt = parse_iso(end_time) departure_dt = parse_iso(start_time) From bbc2be89e9972088ecb69bfcc4b7ca65f21adb07 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:45:37 +0200 Subject: [PATCH 36/48] transitous rewrite: rewrite all logs into english --- main.py | 4 ++-- src/dc/handlers.py | 30 +++++++++++++----------------- src/dc/helpers.py | 4 ++-- src/utils.py | 12 +++++------- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/main.py b/main.py index c1c1f6f..d18445b 100644 --- a/main.py +++ b/main.py @@ -22,7 +22,7 @@ async def on_ready(): global _bot_initialized if not _bot_initialized: - logger(f"{bot.user} ist online") + logger(f"{bot.user} is online") _bot_initialized = True server_id = config.discord.server server_vc_id = config.discord.vc @@ -32,7 +32,7 @@ async def on_ready(): try: bot.run(config.discord.token) except: - logger("Feher peim parsen des tokens", "fatal") + logger("An error occured while parsing the token", "fatal") ''' TODO diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 40c69fd..93eddeb 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -29,17 +29,17 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals mode = trip["mode"] print("-----------------") - logger(f"Umstieg: {long_name}; Ankunft: {arrival} Uhr") - logger(f"Betreiber: {trip["agency"]}, Typ: {mode}") - logger(f"Versuche Namen zu ändern, wenn nichts passiert bin ich im cooldown... (warte bis zu 10min!)") + logger(f"Transfer: {long_name}; Arrival: {arrival}") + logger(f"Agency: {trip["agency"]}, mode: {mode}") + logger(f"Trying to change channel name. Discord put the bot into a cooldown if nothing happens... (automatically resolves after up to 10min)") formatting = channel_formatting(mode) await voice_channel.edit(name=f"{formatting}{long_name}") await voice_channel.set_status(f"Ankunft um {arrival}") - logger(f"Name geändert!") + logger(f"Updated channel name!") - await announcer("umstieg", voice_channel) + await announcer("transfer", voice_channel) _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, trip["arrival_dt"], voice_channel, trip["to"])) @@ -51,32 +51,28 @@ async def announcer(announcement: str, voice_channel: discord.VoiceChannel, dest if announcements_enabled: if len(voice_channel.members) > 0: match announcement: - case "ende": + case "end_of_connection": if voice_announcement_enabled: announcement_status = await voice_announcer(destination, voice_channel) if announcement_status: return embed = build_announcement_embed( f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für ihr Vertrauen und auf Wiedersehen.') - case "umstieg": + case "transfer": embed = build_info_embed() case _: - logger(f"Unbekanntes Announcements: {announcement}") + logger(f"Unknown announcement: {announcement}") embed = None if embed: await voice_channel.send(embed=embed) - else: - logger(f"Announcement {announcement} wird geskipped, keiner da") - return - async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel) -> bool: sound_path = get_sound_path(destination=destination) if sound_path is None: return False - logger(f"VC wird betreten, spiele {sound_path}") + logger(f"Joining vc, playing {sound_path}") vc = await voice_channel.connect(timeout=15, reconnect=True) audio_source = discord.FFmpegPCMAudio(sound_path) @@ -87,7 +83,7 @@ async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel) if error: logger(f"Player error: {error}", "error") loop.create_task(vc.disconnect()) - logger("VC wird verlassen") + logger("Leaving vc") vc.play(audio_source, after=after_playing) return True @@ -100,15 +96,15 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_ if wait_seconds > 0: remaining = str(timedelta(seconds=wait_seconds)) - logger(f"Nächster Umstieg in {remaining.split('.')[0]} ({arrival_dt.strftime('%H:%M')} Uhr)") + logger(f"Nexxt transfer in {remaining.split('.')[0]} ({arrival_dt.strftime('%H:%M')} Uhr)") if wait_seconds > announcement_countdown: wait_until_end_announcement = wait_seconds - announcement_countdown await asyncio.sleep(wait_until_end_announcement) - await announcer("ende", voice_channel, destination) + await announcer("end_of_connection", voice_channel, destination) await asyncio.sleep(announcement_countdown) else: await asyncio.sleep(wait_seconds) - logger("Zug angekommen, wähle neue Verbindung") + logger("Train arrived, searching for a new connection....") await rename_vc(bot, voice_channel, from_scheduler=True) \ No newline at end of file diff --git a/src/dc/helpers.py b/src/dc/helpers.py index 3efc8e8..e8b3568 100644 --- a/src/dc/helpers.py +++ b/src/dc/helpers.py @@ -6,12 +6,12 @@ def validate_channel(bot: discord.bot, server_id: int, channel_id: int): guild = bot.get_guild(server_id) if guild is None: - logger(f"Es konnte kein Server mit der ID {server_id} gefunden werden", "fatal") + logger(f"Couldn't find server with ID '{server_id}', is the bot invited?", "fatal") return False channel = guild.get_channel(channel_id) if not isinstance(channel, discord.VoiceChannel): - logger(f"Es konnte kein VC mit der id {channel_id} gefunden werden", "fatal") + logger(f"Couldn't find vc with '{channel_id}'", "fatal") return False return channel diff --git a/src/utils.py b/src/utils.py index 000cbe0..26d96b0 100644 --- a/src/utils.py +++ b/src/utils.py @@ -33,12 +33,12 @@ def validate_connection(start_time: str, end_time: str, departure_time_iso: str) end_dt = datetime.fromisoformat(end_time.replace("Z", "+00:00")) if end_dt < now: - logger(f"Verbindung liegt bereits in der Vergangenheit: {start_dt}", "error") + logger(f"Connection is from the past: {start_dt}", "error") return False max_wait_time = config.connections.max_wait_time if start_dt > now + timedelta(hours=max_wait_time): - logger(f"Verbindung liegt zu weit in der Zukunft: {start_dt}", "error") + logger(f"Connection is way too far in the future: {start_dt} (max_wait_time: {max_wait_time}h)", "error") return False departure_time_iso_dt = datetime.fromisoformat(departure_time_iso.replace("Z", "+00:00")) @@ -48,14 +48,14 @@ def validate_connection(start_time: str, end_time: str, departure_time_iso: str) min_duration = config.connections.min_duration min_duration_seconds = min_duration * 60 if trip_duration < min_duration_seconds: - logger(f"Verbindung ist mit {trip_duration_minutes} zu kurz (mindestens {min_duration} Minuten gewollt)", "error") + logger(f"Connection is with {trip_duration_minutes} minutes too short (configured to {min_duration} minutes or more)", "error") return False max_duration = config.connections.max_duration if max_duration: max_duration_seconds = max_duration * 60 if max_duration_seconds < trip_duration: - logger(f"Verbindung ist mit {trip_duration_minutes} zu lang (höchstens {max_duration} Minuten gewollt)", "error") + logger(f"Connection is with {trip_duration_minutes} too long (configured to {max_duration} minutes at most)", "error") return False return True @@ -98,8 +98,6 @@ def _reload_operators_if_changed(): if current_mtime != _operator_mtime: importlib.reload(operators) _operator_mtime = current_mtime - logger("operators.py wurde automatisch neu geladen (Änderungen erkannt)") - def get_operator_metadata(agency: str, route_color: str, mode: str) -> dict: _reload_operators_if_changed() @@ -142,7 +140,7 @@ def get_sound_path(destination) -> str | None: sound_path = f"src/data/announcements/{sound_file}" if Path(sound_path).is_file() is False: - logger(f"Konnte Datei {sound_path} nicht finden", "error") + logger(f"Couldn't find {sound_path}", "error") return None return sound_path From a6e15f5cd6f81ca899b7b89a0d3f26378332ca6b Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:04:47 +0200 Subject: [PATCH 37/48] transitous rewrite: multiple languages support --- config.json.example | 1 + requirements.txt | 3 +- src/api/transitous.py | 7 +++-- src/config.py | 2 +- src/data/locales/de.yaml | 17 +++++++++++ src/data/locales/en.yaml | 17 +++++++++++ src/dc/embeds.py | 18 +++++++----- src/dc/handlers.py | 11 ++++---- src/lang/language_models.py | 56 +++++++++++++++++++++++++++++++++++++ src/lang/locales.py | 34 ++++++++++++++++++++++ src/utils.py | 4 +-- 11 files changed, 152 insertions(+), 18 deletions(-) create mode 100644 src/data/locales/de.yaml create mode 100644 src/data/locales/en.yaml create mode 100644 src/lang/language_models.py create mode 100644 src/lang/locales.py diff --git a/config.json.example b/config.json.example index 9c7767e..c5f9041 100644 --- a/config.json.example +++ b/config.json.example @@ -3,6 +3,7 @@ "token": "", "server": , "vc": , + "lang": "de" "formatting": "┇", "emojis": true }, diff --git a/requirements.txt b/requirements.txt index d49c13c..56144ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,6 +13,7 @@ numpy==2.5.1 pandas==3.0.3 propcache==0.5.2 py-cord==2.8.0 +pyyaml==6.0.3 pycparser==3.0 pynacl==1.6.2 python-dateutil==2.9.0.post0 @@ -20,4 +21,4 @@ requests==2.34.2 six==1.17.0 typing-extensions==4.16.0 urllib3==2.7.0 -yarl==1.24.2 +yarl==1.24.2 \ No newline at end of file diff --git a/src/api/transitous.py b/src/api/transitous.py index fc02f51..06cc738 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -5,9 +5,12 @@ from datetime import datetime, timezone from src.utils import logger, get_train_name, validate_connection, parse_iso from src.config import config +from src.lang.locales import lang + stations = config.connections.stations blacklist = config.connections.blacklist +long_name_lang = lang.channel.long_name user_agent = config.http.user_agent headers = { @@ -220,9 +223,9 @@ def get_trip_details(random_connection: dict | None) -> dict | None: train_name = get_train_name(display_name, mode) if train_from == from_station: - long_name = f"{train_name} nach {goes_to} von {train_from}" + long_name = long_name_lang.train_from() else: - long_name = f"{train_name} nach {goes_to} über {from_station}" + long_name = long_name_lang.train_via() trip_details = { "long_name": long_name, diff --git a/src/config.py b/src/config.py index 33957b9..b6071e1 100644 --- a/src/config.py +++ b/src/config.py @@ -1,5 +1,4 @@ import json -import os from dataclasses import dataclass, field from typing import Optional @@ -8,6 +7,7 @@ class DiscordConfig: token: str server: int vc: int + lang: str formatting: str emojis: bool diff --git a/src/data/locales/de.yaml b/src/data/locales/de.yaml new file mode 100644 index 0000000..4fe234c --- /dev/null +++ b/src/data/locales/de.yaml @@ -0,0 +1,17 @@ +channel: + status: "Ankunft um {arrival}" + long_name: + train_from: "{train_name} nach {goes_to} von {train_from}" + train_via: "{train_name} nach {goes_to} über {from_station}" +embeds: + footer: + notice: "Daten großzügig bereitgestellt von https://transitous.org" + info: + description: "Abfahrt von {station} um {departure}. Ankunft um {arrival}" + via: "Über" + "via_and": "und" + "next_stop": "Nächster Halt" + announcement: + title: "Informationen zu ihrer Fahrt" + "end_of_connection": + message: "Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Unsere Reise endet dort\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für ihr Vertrauen und auf Wiedersehen." diff --git a/src/data/locales/en.yaml b/src/data/locales/en.yaml new file mode 100644 index 0000000..4373207 --- /dev/null +++ b/src/data/locales/en.yaml @@ -0,0 +1,17 @@ +channel: + status: "Ankunft um {arrival}" + long_name: + train_from: "{train_name} to {goes_to} from {train_from}" + train_via: "{train_name} to {goes_to} via {from_station}" +embeds: + footer: + notice: "Data provided by https://transitous.org" + info: + description: "Departure from {station} at {departure}. Arrival by {arrival}" + via: "via" + "via_and": "and" + "next_stop": "Next stop" + announcement: + title: "Information about your trip" + "end_of_connection": + message: "Dear Passengers,\nwe will be arriving at {destination} in a few minutes. Our journey ends there.\n\nWe wish you a pleasant onward journey.\n\nThank you for your patronage, and goodbye." diff --git a/src/dc/embeds.py b/src/dc/embeds.py index f99430f..c203343 100644 --- a/src/dc/embeds.py +++ b/src/dc/embeds.py @@ -3,9 +3,12 @@ import random from src.utils import get_operator_metadata, get_next_station, format_via_list, format_stop_list from src.dc.helpers import format_timestamp_to_dc +from src.lang.locales import lang + +lang_embed = lang.embeds def build_embed_footer(mode: str, slogans): - footer_notice = f"Data provided by https://transitous.org • mode: {mode}" + footer_notice = f"{lang.embeds.footer.notice()} • mode: {mode}" icon = "https://raw.githubusercontent.com/kaaninchen/Gleiswechsel/refs/heads/main/src/data/assets/transitous-logo.png" if slogans is not None: @@ -22,14 +25,15 @@ def build_embed_footer(mode: str, slogans): def build_info_embed() -> discord.Embed: from src.dc.handlers import trip + station = trip["station"] agency = trip["agency"] metadata = get_operator_metadata(agency, trip["route_color"], trip["mode"]) departure = format_timestamp_to_dc(trip["departure"]) arrival = format_timestamp_to_dc(trip["arrival"]) - + embed = discord.Embed( title = trip["long_name"], - description=f"Abfahrt von {trip["station"]} um {departure}. Ankunft um {arrival}", + description=lang_embed.info.description(), color = metadata["color"] ) @@ -40,12 +44,12 @@ def build_info_embed() -> discord.Embed: if next_stop: next_stop_station = next_stop.get("name") - via = format_via_list(stops) + via = format_via_list(stops, lang_embed.info.via_and()) if via: - embed.add_field(name="Über", value=via, inline=False) + embed.add_field(name=lang_embed.info.via(), value=via, inline=False) if next_stop: - embed.add_field(name="Nächster Halt", value=f"__{next_stop_station}__", inline=False) + embed.add_field(name=lang_embed.info.next_stop(), value=f"__{next_stop_station}__", inline=False) route_fields = format_stop_list(stops, next_stop_station) for field_name, field_value in route_fields: @@ -65,7 +69,7 @@ def build_announcement_embed(msg): metadata = get_operator_metadata(agency, trip["route_color"], trip["mode"]) embed = discord.Embed( - title = "Informationen zu ihrer Fahrt", + title = lang_embed.announcement.title(), description=msg, color=metadata["color"] ) diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 93eddeb..8a5bbb0 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -1,12 +1,14 @@ import discord import asyncio import random -from datetime import datetime, timedelta, date +from datetime import datetime, timedelta from src.utils import logger, channel_formatting, choose_connection, get_sound_path, LOCAL_TZ, get_next_station from src.config import config +from src.lang.locales import lang _scheduled_task: asyncio.Task | None = None +channel_lang = lang.channel async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = False): global trip, _scheduled_task @@ -35,7 +37,7 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals formatting = channel_formatting(mode) await voice_channel.edit(name=f"{formatting}{long_name}") - await voice_channel.set_status(f"Ankunft um {arrival}") + await voice_channel.set_status(channel_lang.status()) logger(f"Updated channel name!") @@ -56,8 +58,7 @@ async def announcer(announcement: str, voice_channel: discord.VoiceChannel, dest announcement_status = await voice_announcer(destination, voice_channel) if announcement_status: return - embed = build_announcement_embed( - f'Sehr geehrte Fahrgäste,\nIn wenigen Minuten erreichen wir {destination}. Dieser Zug endet dort.\n\nWir wünschen Ihnen eine angenehme Weiterreise.\n\nVielen Dank für ihr Vertrauen und auf Wiedersehen.') + embed = build_announcement_embed(lang.embeds.announcement.end_of_connection.message()) case "transfer": embed = build_info_embed() case _: @@ -96,7 +97,7 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_ if wait_seconds > 0: remaining = str(timedelta(seconds=wait_seconds)) - logger(f"Nexxt transfer in {remaining.split('.')[0]} ({arrival_dt.strftime('%H:%M')} Uhr)") + logger(f"Next transfer in {remaining.split('.')[0]} ({arrival_dt.strftime('%H:%M')} Uhr)") if wait_seconds > announcement_countdown: wait_until_end_announcement = wait_seconds - announcement_countdown diff --git a/src/lang/language_models.py b/src/lang/language_models.py new file mode 100644 index 0000000..e99a54b --- /dev/null +++ b/src/lang/language_models.py @@ -0,0 +1,56 @@ +# generated by datamodel-codegen: +# filename: de.yaml +# timestamp: 2026-08-17T18:44:37+00:00 + +from __future__ import annotations + +from dataclasses import dataclass + + +@dataclass +class LongName: + train_from: str + train_via: str + + +@dataclass +class Channel: + status: str + long_name: LongName + + +@dataclass +class Footer: + notice: str + + +@dataclass +class Info: + description: str + via: str + via_and: str + next_stop: str + + +@dataclass +class EndOfConnection: + message: str + + +@dataclass +class Announcement: + title: str + end_of_connection: EndOfConnection + + +@dataclass +class Embeds: + footer: Footer + info: Info + announcement: Announcement + + +@dataclass +class Model: + channel: Channel + embeds: Embeds diff --git a/src/lang/locales.py b/src/lang/locales.py new file mode 100644 index 0000000..586594d --- /dev/null +++ b/src/lang/locales.py @@ -0,0 +1,34 @@ +import yaml +import sys + +from src.utils import logger +from src.config import config +from src.lang.language_models import Model + +class AutoFormatStr(str): + def __call__(self): + frame = sys._getframe(1) + context = {**frame.f_globals, **frame.f_locals} + return self.format(**context) + +class LanguageObject: + def __init__(self, dictionary: dict): + for key, value in dictionary.items(): + if isinstance(value, dict): + setattr(self, key, LanguageObject(value)) + elif isinstance(value, str): + setattr(self, key, AutoFormatStr(value)) + else: + setattr(self, key, value) + +def load_language(lang_code): + path = f"src/data/locales/{lang_code}.yaml" + + try: + with open(path, "r", encoding="utf-8") as file: + data = yaml.safe_load(file) + return LanguageObject(data) + except Exception as e: + logger(f"Failed loading language file: {e}", "FATAL") + +lang: Model = load_language(config.discord.lang) \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index 26d96b0..ef58390 100644 --- a/src/utils.py +++ b/src/utils.py @@ -160,7 +160,7 @@ def get_next_station(stops: dict, train_from: str) -> dict | None: return None -def format_via_list(stops: dict) -> str: +def format_via_list(stops: dict, via_and: str) -> str: if len(stops) > 2: stations = list(stops.keys()) trip_from = stations[0] @@ -173,7 +173,7 @@ def format_via_list(stops: dict) -> str: important_stops.remove(trip_to) if len(important_stops) > 1: - via = f"{', '.join(important_stops[:-1])} und {important_stops[-1]}" + via = f"{', '.join(important_stops[:-1])} {via_and} {important_stops[-1]}" else: via = important_stops[0] return via From ee51e8578680f5bb02157d684ccb19e60cdd4cc0 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 00:21:58 +0200 Subject: [PATCH 38/48] transitous rewrite: set vc status to next_station --- config.json.example | 6 ++++-- src/api/transitous.py | 4 ++-- src/data/locales/de.yaml | 1 - src/data/locales/en.yaml | 1 - src/data/operators.py | 6 ++++++ src/lang/language_models.py | 1 - src/utils.py | 1 - 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/config.json.example b/config.json.example index c5f9041..171972a 100644 --- a/config.json.example +++ b/config.json.example @@ -3,13 +3,15 @@ "token": "", "server": , "vc": , - "lang": "de" + "lang": "de", "formatting": "┇", "emojis": true }, "connections": { "stations": [ - "" + "Berlin Hauptbahnhof", + "Amsterdam", + "Helsinki" ], "blacklist": [], "min_duration": 5, diff --git a/src/api/transitous.py b/src/api/transitous.py index 06cc738..c69c5b3 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -123,7 +123,7 @@ def get_random_stop_id() -> str | None: stop_ids_list = list(stop_ids.keys()) if len(stop_ids_list) > 1: - logger(f"No station associated as '{assigned_station}', choosing random from similar named station") + logger(f"No station associated as '{assigned_station}', choosing random from similar named stations") logger(f"Run `python run main.py stations` to get exact station names") chosen_stop_id, chosen_station = random.choice(list(stop_ids.items())) logger(f"Assigned Station: {chosen_station}") @@ -235,8 +235,8 @@ def get_trip_details(random_connection: dict | None) -> dict | None: "to": goes_to, "agency": legs["agencyName"], "route_color": legs.get("routeColor"), - "duration": legs["duration"], "departure": departure_dt.strftime("%H:%M"), + "departure_dt": departure_dt, "arrival": arrival_dt.strftime("%H:%M"), "arrival_dt": arrival_dt, "mode": mode, diff --git a/src/data/locales/de.yaml b/src/data/locales/de.yaml index 4fe234c..a19afeb 100644 --- a/src/data/locales/de.yaml +++ b/src/data/locales/de.yaml @@ -1,5 +1,4 @@ channel: - status: "Ankunft um {arrival}" long_name: train_from: "{train_name} nach {goes_to} von {train_from}" train_via: "{train_name} nach {goes_to} über {from_station}" diff --git a/src/data/locales/en.yaml b/src/data/locales/en.yaml index 4373207..2e8adcb 100644 --- a/src/data/locales/en.yaml +++ b/src/data/locales/en.yaml @@ -1,5 +1,4 @@ channel: - status: "Ankunft um {arrival}" long_name: train_from: "{train_name} to {goes_to} from {train_from}" train_via: "{train_name} to {goes_to} via {from_station}" diff --git a/src/data/operators.py b/src/data/operators.py index dec5cfe..5818f2b 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -110,9 +110,15 @@ OPERATORS = { "GVB": { "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/BSicon_LOGO_GVB.svg/960px-BSicon_LOGO_GVB.svg.png", "color": 0x2B62AF + }, + "Berliner Verkehrsbetriebe": { + "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/BVG_Logo_07.2021.svg/960px-BVG_Logo_07.2021.svg.png", + "color": 0xEFD13C } } + + OPERATOR_ALIASES = { "Arverio Bayern GmbH": OPERATORS["Arverio Bayern"], "DB Regio AG Baden-Württemberg": OPERATORS["db_bawü"], diff --git a/src/lang/language_models.py b/src/lang/language_models.py index e99a54b..08cd1a7 100644 --- a/src/lang/language_models.py +++ b/src/lang/language_models.py @@ -15,7 +15,6 @@ class LongName: @dataclass class Channel: - status: str long_name: LongName diff --git a/src/utils.py b/src/utils.py index ef58390..f353d21 100644 --- a/src/utils.py +++ b/src/utils.py @@ -157,7 +157,6 @@ def get_next_station(stops: dict, train_from: str) -> dict | None: "name": name, "arrival": arrival_dt } - return None def format_via_list(stops: dict, via_and: str) -> str: From b608656bc7d9f3713f77d113a1926abbddfaa952 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 00:24:02 +0200 Subject: [PATCH 39/48] transitous rewrite: forgot to commit them --- main.py | 3 +++ src/dc/handlers.py | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index d18445b..367963a 100644 --- a/main.py +++ b/main.py @@ -24,6 +24,9 @@ async def on_ready(): if not _bot_initialized: logger(f"{bot.user} is online") _bot_initialized = True + + bot.change_presence(activity=discord.Game(name="tschu tschu! • /info")) + server_id = config.discord.server server_vc_id = config.discord.vc channel = validate_channel(bot=bot, server_id=server_id, channel_id=server_vc_id) diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 8a5bbb0..e4b88b6 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -8,6 +8,7 @@ from src.config import config from src.lang.locales import lang _scheduled_task: asyncio.Task | None = None +_next_stop_task: asyncio.Task | None = None channel_lang = lang.channel async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = False): @@ -33,16 +34,19 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals print("-----------------") logger(f"Transfer: {long_name}; Arrival: {arrival}") logger(f"Agency: {trip["agency"]}, mode: {mode}") - logger(f"Trying to change channel name. Discord put the bot into a cooldown if nothing happens... (automatically resolves after up to 10min)") + logger(f"Trying to change channel name. If nothing happens, then the bot is in cooldown... (automatically resolves after up to 10min)") formatting = channel_formatting(mode) await voice_channel.edit(name=f"{formatting}{long_name}") await voice_channel.set_status(channel_lang.status()) + start_next_stop_updates(bot, voice_channel) + logger(f"Updated channel name!") await announcer("transfer", voice_channel) + _scheduled_task = asyncio.create_task(_schedule_next_transfer(bot, trip["arrival_dt"], voice_channel, trip["to"])) async def announcer(announcement: str, voice_channel: discord.VoiceChannel, destination = None): @@ -108,4 +112,42 @@ async def _schedule_next_transfer(bot: discord.Bot, arrival_dt: datetime, voice_ await asyncio.sleep(wait_seconds) logger("Train arrived, searching for a new connection....") - await rename_vc(bot, voice_channel, from_scheduler=True) \ No newline at end of file + await rename_vc(bot, voice_channel, from_scheduler=True) + +async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChannel): + global trip + try: + if trip is None: + return + + now = datetime.now(LOCAL_TZ) + departure_dt = trip["departure_dt"] + + if departure_dt > now: + await bot.change_presence(activity=discord.Game(name="tschu tschu! • /info")) + wait_seconds = (departure_dt - now).total_seconds() + print(f"Waiting for {wait_seconds} seconds") + await asyncio.sleep(wait_seconds) + + while True: + next_stop = get_next_station(trip["stops"], trip["from"]) + + if next_stop is None: + return + + presence_text = f"{lang.embeds.info.next_stop()}: {next_stop["name"]}" + await voice_channel.set_status(presence_text) + wait_seconds = (next_stop["arrival"] - datetime.now(LOCAL_TZ)).total_seconds() + if wait_seconds > 0: + await asyncio.sleep(wait_seconds) + + except asyncio.CancelledError: + raise + +def start_next_stop_updates(bot: discord.bot, voice_channel: discord.VoiceChannel): + global _next_stop_task + + if _next_stop_task is not None and not _next_stop_task.done(): + _next_stop_task.cancel() + + _next_stop_task = asyncio.create_task(_update_next_loop(bot, voice_channel)) \ No newline at end of file From 5886c747fec6fff3629bb83e2936c8a3f5d47a06 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 11:41:15 +0200 Subject: [PATCH 40/48] transitous rewrite: voice_announcements on stops --- config.json.example | 4 +++- main.py | 2 +- src/config.py | 3 ++- src/dc/handlers.py | 26 ++++++++++++++++++-------- src/utils.py | 12 ++++++++---- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/config.json.example b/config.json.example index 171972a..55612f7 100644 --- a/config.json.example +++ b/config.json.example @@ -24,8 +24,10 @@ "voice": [ { "enabled": false, - "stations": { + "end_stations": { "general": "general.aac", + }, + "stops": { } } ] diff --git a/main.py b/main.py index 367963a..305f751 100644 --- a/main.py +++ b/main.py @@ -25,7 +25,7 @@ async def on_ready(): logger(f"{bot.user} is online") _bot_initialized = True - bot.change_presence(activity=discord.Game(name="tschu tschu! • /info")) + await bot.change_presence(activity=discord.Game(name="tschu tschu! • /info")) server_id = config.discord.server server_vc_id = config.discord.vc diff --git a/src/config.py b/src/config.py index b6071e1..956e6d3 100644 --- a/src/config.py +++ b/src/config.py @@ -23,7 +23,8 @@ class ConnectionsConfig: @dataclass class VoiceAnnouncementConfig: enabled: bool - stations: dict[str, str] + end_stations: dict[str, str] + stops: dict[str, str] @dataclass class AnnouncementConfig: diff --git a/src/dc/handlers.py b/src/dc/handlers.py index e4b88b6..bd743c9 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -38,7 +38,6 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals formatting = channel_formatting(mode) await voice_channel.edit(name=f"{formatting}{long_name}") - await voice_channel.set_status(channel_lang.status()) start_next_stop_updates(bot, voice_channel) @@ -72,15 +71,22 @@ async def announcer(announcement: str, voice_channel: discord.VoiceChannel, dest if embed: await voice_channel.send(embed=embed) -async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel) -> bool: - sound_path = get_sound_path(destination=destination) +async def voice_announcer(destination: str, voice_channel: discord.VoiceChannel, type_announcement: str) -> bool: + sound_path = get_sound_path(destination=destination, type_announcement=type_announcement) if sound_path is None: return False + + if voice_channel.guild.voice_client: + logger(f"Already in vc, skipping this announcement to be safe") + return False logger(f"Joining vc, playing {sound_path}") - vc = await voice_channel.connect(timeout=15, reconnect=True) + + connect_task = asyncio.create_task(voice_channel.connect(timeout=15, reconnect=True)) audio_source = discord.FFmpegPCMAudio(sound_path) + vc = await connect_task + loop = asyncio.get_running_loop() if not vc.is_playing(): @@ -124,9 +130,7 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne departure_dt = trip["departure_dt"] if departure_dt > now: - await bot.change_presence(activity=discord.Game(name="tschu tschu! • /info")) wait_seconds = (departure_dt - now).total_seconds() - print(f"Waiting for {wait_seconds} seconds") await asyncio.sleep(wait_seconds) while True: @@ -135,13 +139,19 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne if next_stop is None: return - presence_text = f"{lang.embeds.info.next_stop()}: {next_stop["name"]}" - await voice_channel.set_status(presence_text) + next_stop_str = next_stop["name"] + + status_text = f"{lang.embeds.info.next_stop()}: {next_stop_str}" + await voice_channel.set_status(status_text, reason="Next stop status") + + await voice_announcer(next_stop_str, voice_channel, type_announcement="stops") + wait_seconds = (next_stop["arrival"] - datetime.now(LOCAL_TZ)).total_seconds() if wait_seconds > 0: await asyncio.sleep(wait_seconds) except asyncio.CancelledError: + await voice_channel.set_status(None) raise def start_next_stop_updates(bot: discord.bot, voice_channel: discord.VoiceChannel): diff --git a/src/utils.py b/src/utils.py index f353d21..7274576 100644 --- a/src/utils.py +++ b/src/utils.py @@ -122,9 +122,12 @@ def get_operator_metadata(agency: str, route_color: str, mode: str) -> dict: "slogans": slogans } -def get_sound_path(destination) -> str | None: - voice_stations = config.announcements.voice[0].stations - +def get_sound_path(destination, type_announcement: str) -> str | None: + if type_announcement == "end_stations": + voice_stations = config.announcements.voice[0].end_stations + elif type_announcement == "stops": + voice_stations = config.announcements.voice[0].stops + if destination in voice_stations: announcement_for = destination else: @@ -156,7 +159,8 @@ def get_next_station(stops: dict, train_from: str) -> dict | None: return { "name": name, "arrival": arrival_dt - } + } + return None def format_via_list(stops: dict, via_and: str) -> str: From 4a73ec6ef2e7628df1b85e85fb0ba2bb459ba8ca Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:24:08 +0200 Subject: [PATCH 41/48] transitous rewrite: update README --- .github/end_of_trip_announcement.png | Bin 0 -> 34067 bytes .github/info_fehlende_daten.png | Bin 146951 -> 0 bytes .github/info_nahreisezug.png | Bin 53902 -> 0 bytes .github/preview_info.png | Bin 108287 -> 64650 bytes .github/preview_kanal.png | Bin 112478 -> 10915 bytes .github/voice_announcements_visualized.png | Bin 0 -> 74343 bytes README.md | 249 +++++++++++++++++++++ config.json.example | 5 +- src/api/transitous.py | 6 + src/config.py | 2 +- src/data/operators.py | 24 +- src/data/status.py | 16 -- src/dc/handlers.py | 6 +- src/utils.py | 7 +- 14 files changed, 273 insertions(+), 42 deletions(-) create mode 100644 .github/end_of_trip_announcement.png delete mode 100644 .github/info_fehlende_daten.png delete mode 100644 .github/info_nahreisezug.png create mode 100644 .github/voice_announcements_visualized.png delete mode 100644 src/data/status.py diff --git a/.github/end_of_trip_announcement.png b/.github/end_of_trip_announcement.png new file mode 100644 index 0000000000000000000000000000000000000000..346df794282872c62e449f77938b5a888561f86c GIT binary patch literal 34067 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 diff --git a/.github/info_nahreisezug.png b/.github/info_nahreisezug.png deleted file mode 100644 index 4b5c2a88f1bed10da10a55b7cb1b421799e398df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53902 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 z zJ8~kHmDgVJGC1XT-IWnHW-PLdM4<1vs`zj*7p(kQsDjL~x7gBJmR)?wk&us@tCvPT zT2uopQUVOwsi}={Qd;qBvf&C%t0#|I3v9D&G{a~J%N|TRII3ShRTr{m)rg>L*0oH6 zbDuE4UOb{80@ismbobwIH+Z_Qk5x>IC@BmxrWA$h=qxNVj%o6=f*fFsyzFAjvDwF> z@jP~Nk?T^wr`>(7!@UaWmFBs~bgxuHb9zrF^K>JIl9LnOM>PZ7i!Eq|SGl_LcIAdm znh!f&w3X%$TgM3w9RO{oM|hq=$pQ-CxkA(8tB-rnNV`ooGgMEUwFrHi1WQI<>wAV( zaoV@yp`I=F-Pf~5oSn4o=gKfKDW2cygaU2 zWkZ&F1$z>V;TP@2_vLJs@+&N$;-Fg6Ls7fm6$2vCgwcj*g_18KzU~qp42QNWO_L!h zrZ5n2M~8@#m)SK(?bGDM<}+AVG2MFW<${?yhZ54xXHzf_d|wCoOh$f)5sqGxEF=rw zg5q!GhM8Gs%f2hRv%uwWwbz0|Q9XnKy2)13shQ;hTAcRPxZJw|SE0||6IFtS)b3#t zjM@710dRQUi?bxh`f)6K7lXm)xB_Q??daX`Ec*nRaOws#e}iQrWqw2}(IdOeQYNoyH`uR71;w zW2r?ND~#%xZ?B6OL!H zS7}kw+hS1!M|(!Q(#9?*#D3xgG|y`^Ny&(!cnm3=64mM(;kf4;8W_?D5PzRGI!-Ad zNJte-6W_-UExK_GwQzi8I$Ys2O51s6Yv_J5Ua?`3ma&S^m&KWosF!&U4HrG0;U~Dc z8O2u`Khyt0vnoveI1@u#r-{eq@zAeWBR9o}TU0uf1}=}2v(`h^stpK)!d`&bfge*) ze^b4Q=v)=Cc~QRD@~b$3G?&jQAOouw{)(IvF_lrpuhB2#?}OQ%&`E873d7GaD8+#u z3g;T%gBvYWL~b=g8E$OG>4*8-kSk24*GJdS9#hZ53rc=Q)0^ly6LF_-xl{*1ea zkFcuEhs!Z`gew-f zW~e)EAZq1^HMi`ki3ysqEy=NJaCaf+P}@F#fijkM9*=9%gW-|vUUA(G&y<1_rEnY1 z);kQ=z1Cc08xDRv?7hc!fvNrs1z;-mJZ+>|b!&T^3t8$2@aVhDa%qp;pvdlO!%WFX zasep#?_r*lnCGzJf0ydG-acYq(`j|LkQz!+2gOmckl#rhiC$)0Qd;X4kW`y;f4R2# zHa+n0>~otvUv#!cU#L3dAa*s*ZK&NmFyy}(jD+HWjAIkQZ)xn2>*KdQJ{E8_!8Zn_ zRP^7amuW(Q3`_r4m06$VRRcdbi#7DrQ3P*xXJx3BGTMm!+;&{uK~?J#J~EGquPySI zx;S+I9=da#BjYMTw@`^W`Udt~=lY&uS8`(!#a~oY{$PJPX-H_ppakXxzWVUzK_Nz6 zgZ2K(A81Vd+)~eK(tRB<9azl7+&|TBb>+2g248x)<5VM{^a$ZCqG&B5Vh2%%eXC6H zd_%>~)T4&_b*CJtp<*sb@~mWH(>1EkceI5Uo!Gb=>6gnOI0uK`_H;!)Z{0Jk`cZ`7 z6gKFlM+x^QK=mwNxk0BV=|64!Apu6h|?bPLZFiN{l3U02a3iI`b%(S)(@C{qqcnb8;f5w?+} z6aqWF;mOp54L<{9Hz9wMEL}AG4M36fY_oKlyKTufyy9aOJU-{wz^jMPDx z;f7$?7}!9VeQHTq9x7c7h=|qBA@w_-`V#yemM@ZAxE$B`pKNd%{z8%Nm9sAYrxhf2 zIU5RWYMGN7+o5(1hiG+=!@nj4J@%Qlm4q&uf zaaSzSae%Hsez?p_^acc@akd98c$r^j1SxPhF@M%L)Gr%?Mk%UeN-AYLb5qq5=(@=`EOFt@_|Lh|;1I0fW8DE0e* zqVrko;RCs8J?k9HLzi6&S#tlzY`@Eqvqp~BmNnN{kvx)8#r5@ur*$vx{xBLpY$M8L zEcNLE>9N0#DU5{+$R4X+8-KpM)M4KdULNOq9l=L$>dE{UIVNGlOym3Q{k?66B1SwI zM(|JDwsFBpPF}8c)-fPYHWyzmSm^e!B#$_sf?STdp_|jck{V%#6JNL`C4Cv*>!TqN zg~UgZo0KHu=LdWdZZ=j$x}<0o4L$gfYpn%Br4h{hNnxQ@Y!a77_}7mwSi^G3r$eMP zd4Yn8kyw-Ic!Pv5IS@(0xw#%h4D+(5cV^QVNBDI(91u*_>r`UD`;y5Vj-4pA`j^@l zsrI`jHop%=bxa!6FuR2?zTyw%DYQj$kC4~;kFjo+zr|`&&jVhiWm)D$VeCBR=3J1} z=Oax!Nw4)S?QAKO)D=yMoc*^*6?l!Jn@^Vda8j_GnucITPJT(h-k*H>Wjo|hRH@@d z`jydmHg#aX%$Fv!EZ4(k-$d*|X^+WFUR!Z~W+;bZ!k`8GJkB#>2ey-Bs>ygO!Kh4O zR=x=_H4mk=eHr5^F3^N0nwwRxn)y~O2(X9M;2x5Y$f6|>K)Aeza)!dl$&Etd_3c`4 zcfKbq`ez%t!d0r8_U8EpZv?*iD@Mp?M45@s-~IN@YaS5#_3G4}b68*IJfipvkhs zMs51L^C_)4-aPa(zXWLA2T_+QF`u;st*D9gvE+kCWFckh4VUvGKF6jYgQYBx?Z;mU zd)B$fToK>2i8;s2)VE-ot7n1FHoZcZQI^P-Kd)j#yppc4)bxAA|M*BCOJ@0;B?Z1- z<@M4ut8^YRUJc-W49k1C!O^PSzTZZ!M@P_e&GWYM#_+kj#{eLp65OR;{PqzOFwW%d z%|V)p4=Ap^*QC>0NH=E3_?XK&dI|MenrW#UCiDO<_a7mmvzA-ldaK1%J2qIRNw3py z49@6#ONR;3^r{G-#n6Z6eAUXuJrx($^5(j#KD%6Ua_O-;_$Pd0n$>}C<({|P1cr%D zS-GmFR?qjn+NM?7!F*@q&Wb*1jC60m<0SIFasZdbjjW}yrf`%hg75=^5e4>2so0{d zJ!O}JCv734hC)co>{_YZBD4xx`FG?^E$+WOeC3rtHsoTTHvdvr(1=+8LzdJpH7YOQ z+n58Aos7SzKOWq9%X!9=bd6QdR&3nP+711lE%POmcg(5|<=mCKy(3pFJ}NC1L}>Ua zp%7!-9j#A-qc~ew>LV2WaiX>jF9rq0vZ`J28lgn{CJoVr-1IhzKy(tHkxA5Z8cX;)HA3uw3yMpO8U0zre!iBT713 zYayBYx ?O}=#OUb(5s(&DBd!h{Q+d980w?AnkPheqV7l(Ek){*!ZoQi0`Kt7PRJ zlERGt&bp}i`&O~W1FSVf6+K}n!Vy7uQyl&uN>~TGN?l?uChq`juex~byKs#h=XDzw z1&%Lbs~Jn2(HeI;COKBGUhN^TPaAI^=GYb~Q{bvrpzffhfQ1Extgjx*typovLsZD{ zy%?rW7*>-dwR}>8`z{-~B|?Fi=YQK)w4M3mMjQQ_F@0s8bnxes+KiBdXSLR-;2G?1 zgwgQ6Lj3sp;`lRC${bu4x>oGpKKrB^uZiZBC=ABK0vSQ1Q@m3&i};t}UtQNmhR6fW zz3V4Lx*v}!;%r<$cE7#)rjP4iW2LU3Od<7MokUUJCEpzQ?p2y%5wA%u=;aO*{^+4( z7}rTK_)b+;-qniSiyeX>-sitb+YB^~Nzicf|JLc5?wxbLzfW(RI55cknWmdx>!+Y% z5aPM*v2N-QjG#&v_@jy`1#lr*j^%1Ee9==6EO^DsAnsY`I0VCk1ZQDc<(i1y8liaz z2y5>Q5RrOXF@zOVkx2WX?)6(`eer64v|LYYwxnVNE-3^@!{{bI_6q3!6%S_MEnA_F&keb)!J?v7kl~TFmyvrBB*n^`>=n}S|H$Myy##IJ}__+E1jw_#Sz5b!mni?X}ztxLG zj&_Dpv((u22lrV44O_|`)}|cY%c01=LR78eyzHeX#d?$5#CXwT!ygTp2>X;uz97@8 z!Zi>PP@};!+);%{al5M5Oq$BR$|NwQR&nz+l03!mlryoCZMc<}__`!#5EwGPa95|- za#p`uiY<61u3@`cS;RA;foc#;Ha5~w9s9LF7t)E6_S&Xv6?hf;xdNBJ$S%mNWb%|{ zvsO;tK15#@oQj3V6dXiC!#>NFs^4Nkn$4)fiffrAOGywjZZUGO{Bw(l0wCP&#~w$L zvQ#1(i%5x(@reCM`yaO7t=Sg5b`o4^^n<(b zAI6-zUl!$H2^ir-bGE#EHv44=SoKdl!$ZvygwFWg2rn?O-ugPU=Gt+6`>rM$!VNIS zW~1qI8_C3hCXIgK`?>q%`IaUc$l&t>x7y8%we}}Mf8kbi+rbc|B*DYNWR~IO!6(4n zpj~J6P29rGdlS)J;wEwBtbcYp}MYS|0t}8rA#*ySS z6SqWc4jp%@H)U#ff|Hn`7=wr7;mAh{kahAB5m?=b!ffXhCu#P^IEOxP$(q7*l2r35#f{LbmBl9epefy6{ymlP->II0m1ZDLfS>|KyBtJM7 zVWdCL8OqP+XU#Qzv#Qt5ml~6KroBM@B^dK59fNftwE$rOu_7QlT%Y*YjHQ2(-M~?% z5WCpkXFzf-H$Gy+py9+2=i|O#J{xP&&}8LvP2daj$+7#8eTO>$0hg0?5L&PxBbJfW zhP8f1bFe*B7?s(^gIX%ym*jW%r#Z-7pW93oW{N7c&1m7 z1eQ5nu}Y2|C(Ln6u>{ektMmB=k+qF|rD4ca*eYSCJ16Pn$wyQX?uKaE&_s&X--%EU z`TLCexDZKa$tc->INc<`@&fj&8JyLUv9Hkq2<>gLq>Gb9W_uWA;yB#SYIX;9m;~G+ineDL%Wu=3ssDS>8=f#dQRtiwSpy9S2&6zX7w-z8I%(qjRnY z$#)~ANN>!Yw`)2Z>ulg^ZtlIKY=o5`>3c+aU?HdI6eetj*$Bmal`OoP3s~BUtNBrg z2KBKQJteI?D{ZvQJJ+QH%}Ie@;L0m{Ki*STMur(5DtGfDK$8rfy&g&`8s7BRDW%jM zR{dy(nJAqW=@5P4?FDtLl7~SF;sJFmmUjv$SN!C^N0RAf-L0ufyS@a>NT^a)F%{Y` zRWDX0-n6;xXLYCCJOW>}MkU)+|N8w^gA?y9jPB0BBv@Z?jx@#jxcEMP+OkTtO6C%T z4CwH!!wgn!%Lty%y?L8O{|x0f#%2Gw`~75hmTPS^Pr=K&;s z5enovp6QLn-!=Iqx~2MhkHQ3jG$(Wtz#a@-mfEhP~j?|t@HC>`=-pv-8i6w0Ju!u zeb%wRvKqM_}=qjXlXS|7f;;My!~Li>Av`V?ENzWNgAl)}>6)D|8Q> z%4pQQs%FLd2IAs%49bNaKgj5m+a7W^rEVAgdCa9#g=iT)LM*0cvGIJp)>MBKsb@#4 zTXn9?kQ-vo;Y1@IkCl$&Aw**@DQNsc>hh?#I0C`Zq#qoL!h836Oi}ifWlt%!ALQ!B zE?9q>l7~$1^?E^XI2_sVJcT@zWMumQu)j;0U zW5sgCcIq@{E8c?&ZVH|w%3JiCPo>q1y$PD)$Iw(SMIkGc3i)snX? z5XhG5PRlQ!Mejz2XRm4={SzHnjc}T&+U^?80%fA}EQ};JK6>g|;_XqHdJcQDPAPbB z4pi)l$iHX3c9qloT1zlMs}}mGnB7G|fuFWmwHmSXzCVT=8+RQ4*;#6d)QzdwD&*Sc z)WNO~DdTnV8VE$h`B{)Xp92iUBbzx;xfrB6Z{HCY26ktLYNe$4_Pm7i&kvQTkhvSs78fuD13BdgrZlv6%ULkj5C?=b_g8w+!w^D! zk!^qJs&70xR=PSlF1@(fGO!IYZVzA1jV=Y=kMP1K1M;ID%n*QsPpkRUw%A#UUP)y! z8pp?SFutQhgtfeQ0Suh>$6;tj#k-kpN@KWfc-NuR7+}v7SIUd=@vv8wMf<~s?Am4} zg21bs=UKzKy^0&JNvemNl*HJ5Qo<H z5yW2h*VETz8n=V$FKV>FBdcJ%*5CSd6bQ?vKmMU~1<9Izr@-RUt{~PL3u?g86<4jz zf5T5_E}ddlF&h;q9Ci__`HuRI;;ZI7MS?>8;<_4ry21I?0&BCxI!wi->->+ra!Ecy z8!xGx1o2SBB^#Jep5?a`stFR=h)8sEMd~jA`>UI5OGV3z^X`!}!6UPBM8y=_uW-py zoaWSrxI&G|0kU6beDFNAE1CuM)vtrJ2M`c+j3-w}p(Gqn?+0jo?SGjmSf2oY@xnxY zRocH^6t}ghrd(F-t*C57Cfn{2Bx`r|$2ZiZJ-D_r%SYLSaaoYR1TX8T8d5+(tq?d; zvqTKE#>-^a#<9j*(6Gj!No9lRS=st~gZ=7ePSoau1<9DkJ8`h*(70VzQC*xJzAAGV zdS+!EB34A0718Xcbce$8-Y3OhY^$So9+VdNg{!72MMv6by?881#w}!9^5P;rS0!Km zDaxI|=HT{47>U-{LJ|N4)8ok3q=k5gJlioc941~C7fle;c~8XaB3v%Tqg$>}L*!m= zkcm}0R3xmcR;&Huf@H?V!3Xb<2j1EIz7Sjl{m~~)R)vSdm+m@BDW3Mr$*D@Z{H0HF)BvjewyX%b7JX8Yl(#cY%??VT-cK zFY~9*|v%}KF9JGXoXr)LsG%gOSs6;OB&yyT|4oq#)Et}2n>Lvp9 z4s#|lAN@&-F^%K=ozSu(*1&DfN)2ieEclB;3Pg%WmVc>fp1_PgZOcfBoyY+&R_m-O zQ&>f>P}6^x^vy|>N1{U8pF_zHUv zzF>~EV*M3z8(y=6_7Q~%_UHNSKb27t;xH1M5eJ@C9{Ohtv$`lTd=`|db6rd(VU{ew z;4+&k+30xncT>9XX=Rqp;%&kTd+(Ul?qT7Qv~H z(ewy6{Zo0T|F9TuKs{|}=E^_@93M%+Z2La!&@Xsiof?t@)bpr4yHlDQXk!V?!Qwq@ zH|ry4B#82IvomNeLMe6?d6c=^9`1eKIfOLEC7&?jOiK%4z6a?MT%TONgEME{`nof) zr~rBpW_0!%VgH9JXBtWsBoU6r1E6%q7guv59Tu02Zt&DaHD>SgtTj%dltYW62BDz1 zCsKQma)`o%G?dx6XY63luE45il`X zYETX-s5Zbz&6EBe@1Dq%MFN;|*9P4FF*c582OlzM_`DT*p`)ev?M9Sw}hTrMnP>MMY0)zR9Y>G~iTrnEPY|Bk)wO8r(Il zc)?XYH9cqkqdn76*sc5BZ%r%TmEO-<{(rpvWmr|+_dO275v02tq@`QBq$CCD?vf7a zlI}(+0V$R4ZcswHOC+Vc!~Z(>NB#a@Jg=YY@{L@u&pvyvHP@VDj5#JI8pn)F`!7=x z7ZOy;M??CLsB)rroB5NmbFLL{Wk%mRj`6QopdFU1Mbg8&!3}@d{PPBDC0C|(9g;48 z+~&B`^Hfb@zMV&Yw_G^eCvg`nTPZfS^%JWY0YXIdzKhv+xJ5gz#Kirn_{(=ZE-o%6 zsYN5jCUCsHw}&t0F-OFkE_y}(*c~7>V=tZ)FL2I3RbiyciGt*{q6Y;DZrazji6Jf~ zA9Sv{X<0$L7O5`b9%C!OXnLGMoUHZOY6_lP>Y7+V;NxxT4YDzI%jclUWV88 z)2FAKH4gv%+SaD)A>UM$y`yRcAa@blcg)ILFA_-{T3!NLYIP?u{rbFSLTMrYd&QK7 z3C;_Z32)rpCwx7i4Ro72iC(#^uDI3v5(@3V@ZKbh7#a+f3ApX?wPG+fYed4K8vu># z_Jg5Ku_H6o75vnrlxw)8p6fJ3qJAxUZdOW2u2*aM}Bi<)chos{8(YKWCQtKGetnV8borCg_ChV!Qs~=V2DB zseoA4ez-sMADpkXr5*;I+KH&d+_J;Z)}qg2rD#e_-cAE>U4(XS?#srnk8x#B%zMM= zltl(0tp0b$VUakKE{AxUcN5wDKq}DLmsf7-j^=y=@O$RleZIxeZyOIMifaVP>G?>7 z7-iraA6G5dH}`|5N5f??gh znn;yp&}?nTi6p{Yl;v(CC1+CS5XDj#Phj9NX3+J{TqiF2oxKOJe$A?J5^rxqu4BHOr`Zo9wceSgmPF3~!i>CMih8~{+YjHkb6@TEZ*H`iy|omh2V40tg;G3_VQq9 zBN#_%^!<$UI_R{nUyBd_7%T9(t7`1`^J%JPueAFCNh=-{@(OkHHebSP2pHy= zSy>Y^?3)-({O$Mv0kn7^oJx>A<1)fkT4-)wlRTMiGKsv z*HA>Q>x6=-)3#hO2}mxqpk1u*pE>32f00X%j8xVHYRi2Gjo&3D7FcqWD6TQxO`E;c zm@cXvUjv*nt|=8VF4F5vVpB=%8~lXxUwTP~qSk60fsJ8YiaYysd!f#n{ut@_hEsuO zrwq~iw#aT#Cw$BNkq2*$B3V6T4c+B-sN{Z z3mjJyjf@kyDIU!uWzT6Z;6G?sOAaqlciBfp;#?QLAS@}I8J_(o}hIT<>xK_kYIz79_omON(D0erGPU~<{)6q2@JFqS1`0t$fK=&@;@7s*|Bfx zW=4+1j7J>DqJbBpAQNzB59#pM)wG^2c|V1NJyC0`*|`%aNF`h2fxw}C*!~;#LJ262 zGD79q6_0Kfy>X{m>KB>2!!TxA28L*#6Q79OpK-x;4dK?Rw_0i;Ud-D%$W2CA-kdLt zwJ`y8Zb@QE0+a#Vrs0;Wi}L}FBe2bJC4#w&47S7qi033CKBA4M!-B5`&+M+nJPaFV z@>_pD+$In0TjLWhs=ihm9>|vrL+8cl0J>iMg!O*<56M8_v$$GNamUW>sBZmBfY9f$ zo<#%o_QO?udsflG$M}>Uvfa7rB9ZDj`w2D@eh7yf#Zlg>GH6tb`yMCceZhQReArCh z!!S0XB&a{`%FB>^2UYmMe{r5n!Af6gU5(KT<8(UxkFrhk*6oN`?JHmFPR zXD|+YR1l8NbJMiH{dL6*2j_;xhV7T33xa!_y4l$VCe?d8`GI7d;hpv8`Po! z0g=Bqnam6VSqqM1=`jN;PcB-|lm4P#U(a8@nN3YuqDGg{J5mFhibppI`<9n682E1R zTRAHd0!JNhyPAO_z_z5I**uQ?f(n5^VP%XH*zGi~T?i^dJr*d&!t65QJbyntn!c5y z-}EzlvwyxRb1>T0Dng=3_@0Wa=d)y3EN=_L$ihnJ+mFiSbq13eTh}1^hkbYMoJRU(s z&bIyFHm!Yw`uj`Qo;8`F>zI^9X8`w+f~lNSSAFQ#V?GkqDeuRziwg}`&%EQbWh$%J zTj|)Qua8M(P&Uv-2n2ue_0=xQ4LU6s`EC4QukhIURKy}nJaqjSwEi_+vI+RtHGYV{ zy*}NNA*Fi^*SVvU#EmEXNcc>j1USF&csMFPm;V}@%dNCB5p{%u3v^o$~Wz1J!^e)eLx(6!YUQD9%I}I zcrY*qJ}Z-;Q$~r4V`EtZ>tkGrgx@*;`ra{0OeB@Xu(0&X=?0bwUyJWS3^4))74`kW za5X+0MR)yjx-mYQ4u<%gee?cax6b=!_=!r}4XkK66tk1{c*wK6BkJU6U)fU{!h8!b!5KybnsB_2n3#cNyCq4!*0br#n8$UfsYTT+i3Qwg4Yi)Xw`lxKaZ%FD3&j6?_r(~sGrCfW8W zH2Q^E40-6X*pvtFhSFjs37D53w$kTZ1mnck=PkRPmOsL{2!b9GXqL=Um5HmXDrTbB z_YdB`8pF8xb9=)U3IxRECL{`bWAi%aaqOnQwuamWc|aD?#7%lCrK0eq^+IdjMO&i* zFPu+5w}PkHB#BH}atcte)~-Vurlj2$o#?Aq#F;$~uYK>&XDm8xfZNz}jRS47E#Ul8 zo!ty4fk;KEf5ad0Ek7|Pz0EQu)1Z9mhtH|ol@GA=;$rqjl+X6o*-JqR{%|NK)x{UM z#v|8#-DwF^&%i;hWkyMWhZIBZ<$eF-_x*=a6xcV2BgpvDY%v&tksrDQR>a_35MoRU z&ZTX?-CMmk8vjb5@t#?)p+jU`s3ird&{;?KUCYak^N7Tr!8uOF0K9i0^3bM_|R zfxf0_%%iT8WAuT<0{PGT-&Mv?Zu;pdba~(PFk$Q9xNLMApjl+uX^gyDV-Js(7_t`aSB1OXkDdPZZdpkX{U( z6f2Sekv5-zx9y*Yf4-y6&k}GeW3@(&)4UT$H-IS!2>NPrw&*f4Cqt~d1E)IV5^jXo zA*%cut%qCZy2(XJV4H^8-}UsZ6(-zHaH?f|Lj{GX=pi%KHV@v+Eo^;=_hE#(SSDmFB_=dboW=D@C?G2KydYT)OZ*TBAcU~oNkKuJ8cU5<_Zq2P0 zr6v5F-%oIpWgwJl#%sWzegu80?-C$eYC@nMjkfOMz1H_Rmf9TbPX0xcPWifi>7vkz z!%3ay487yh8<^{4$YtW2ok{AAc~;KLh*8r`_a_y78_kvEdB>jL!m%WwvWPIMUoM|k z#%ZZkoU(E;W!BGg1pDE0X}47;LA1jSNTyLKo+ud&5#I0|THfzQpcO}mJ&ue-E*0gb zJNz=B&)Vr?>mBzjEl#=R#_nxb*f7!o1uoXPW6()%Mlz1Vh-J2C==+~e5k^nT%i$u8 zv>TtLfc&^dT3b`IoY-9T?Q>8`cKIy!^kE{BuxLFVhMIycX~o4y(n$tt9lz#Gg)J4^ z!NMJmuy2*{u~rdS#Z@pI6L?|n?dy+3<967hyZSWTkMHRKbweDb{?HK>#pP6C%`>IB zxA-*!I#Zo3CiMmusd8zCL6611>UbP<3JajWwM*uO&Et{7(P#ZeNfYJ0@0TC=`lJ

!EEdN^(nY(`M(xcpWKr&3 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�k@SD_K>E#v*!D^{YmF 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 diff --git a/.github/preview_kanal.png b/.github/preview_kanal.png index ef9a539738073ebd60919c8f8ffb2237e74207be..139f5ac7ab7c3c334c9f69481aa416a093c9765b 100644 GIT binary patch literal 10915 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 bz&W(1&9+3K^Hvqn#ZO)3zH+gm1@eCYzn!pA diff --git a/.github/voice_announcements_visualized.png b/.github/voice_announcements_visualized.png new file mode 100644 index 0000000000000000000000000000000000000000..6d875560e749f91cfe7004e80bcffd66fa4d9108 GIT binary patch literal 74343 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%0A$l?JFW2GVOiyB;tbqcLB9X14e?P`k+L+N*VSI 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%0ASdo#A3Td!)cTWWX@4;l>1Yv`N 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index fd7da6e..8f93038 100644 --- a/README.md +++ b/README.md @@ -1 +1,250 @@ # Gleiswechsel +Gleiswechsel [ˈɡlaɪsvɛksəl] (german for "platform change") is a selfhostable discord bot which regularly changes the name of a voice chat to a real public transport connection. The channel will keep the name until the connection arrived at its last stop, after that it will automatically select a new one. + +![Example Channel](.github/preview_kanal.png) + +## Features +- [International support](https://transitous.org/sources/) for both countries and cities +- Support for various types of transportations, including but not limited to Subways, Busses, Funiculars, Trams and Trains +- Multi language support (+ option to easily add more languages) +- Announcements, including the option to join the voice chat and play an audio file while arriving at a specific station +- Highly customizable +- pretty `/info` embed with some details about your current ride + +![Example info](.github/preview_info.png) + +## Setup +Follow [this guide](https://guide.pycord.dev/getting-started/creating-your-first-bot) to create your discord bot up until you have a token. + +Make sure that you have [Python](https://www.python.org/) installed! + +Download the repo (either with git or by clicking the big "Code" button at the start on this page, downloading the zip and extracting it) and run: + +```sh +# Create a virtual environment so that the bot won't cluster your system with dependencies +python -m venv venv + +# Activate your venv, you should have gotten instructions after running the first command, e.g.: +source venv/bin/activate + +# Install the required dependencies +pip install -r requirements.txt +``` + +Next, you should configure the bot to your liking + +## Config +Even if it seems a bit tedious, I highly recommend going through the entire config and checking if there's something that you would like to customize. + +I added an [example config](config.json.example): +```json +{ + "discord": { + "token": "", + "server": , + "vc": , + "lang": "de", + "formatting": "┇", + "emojis": true + }, + "connections": { + "stations": [ + "" + ], + "blacklist": [], + "min_duration": 5, + "max_duration": null, + "max_wait_time": 6, + "timezone": "Europe/Berlin" + }, + "announcements": { + "enabled": true, + "voice": [ + { + "enabled": false, + "stations": { + "general": "general.aac", + } + } + ] + }, + "http": { + "user_agent": "Gleiswechsel-Discord-Bot" + } +} +``` + +You have to rename `config.json.example` to `config.json` and fill out the essential fields so that the bot is usable. + +### Explanations + +#### discord + +- `"token"` is for the discord bot token. You should have copied it earlier + +- `"server"` and `"vc"` are the ID's for the server and the voice chat that the bot should use. Follow [this guide](https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID) to get them. + +- `"lang"` is for the language that the bot should use within discord. The relevant language files are located in [src/data/locales/](src/data/locales). Current available languages are english ("en") and german ("de"). Feel free to add your language if you miss it! + +- `"formatting"` and `"emojis"` are for the channel name. Set `emojis` to `False` and `"formatting"` to `null` if you just want the connection as the channel's name without any decor. + +#### connections + +##### stations +You can add your desired stations that the bot should search connections from there. The bot will choose one of the stations at random. + +The bot will also search for similar named stations if it couldn't find an exact match to your input. This is really handy if you'd just like to ride around in a city with various stations. For example, if you just input "Amsterdam" as a station, the bot would randomly choose one of these stations: + +```json +"Amsterdam": [ + "Amsterdam Zuid", + "Amsterdam RAI", + "Amsterdam Amstel", + "Amsterdam, Gein", + "Amsterdam Centraal", + "Amsterdam, Noord", + "Amsterdam, Rokin", + "Amsterdam Lelylaan", + "Amsterdam Sloterdijk" +] +``` + +The bot will also warn you if it couldn't find a station with the exact name as your input: + +``` +22:44:46: INFO: No station associated as 'Amsterdam', choosing random from similar named stations +``` + +but you can safely ignore this warning if you're fine with it. + +If not, I've created a tool which would help you to get the exact station name. You can use the tool by running + +```sh +$ python run main.py stations +``` + +Example output: +```json +22:47:56: INFO: Exact match found! London is an assigned station! Bot would use that station directly +22:48:33: INFO: { + "stations": { + "Amsterdam": [ + "Amsterdam Zuid", + "Amsterdam RAI", + "Amsterdam Amstel", + "Amsterdam, Gein", + "Amsterdam Centraal", + "Amsterdam, Noord", + "Amsterdam, Rokin", + "Amsterdam Lelylaan", + "Amsterdam Sloterdijk" + ], + "Berlin": [ + "Berlin Hbf", + "Berlin ZOB", + "Berlin Ostbf", + "Berlin-Spandau", + "Berlin Südkreuz", + "U Rudow (Berlin)", + "S Buch (Berlin)", + "U Hönow (Berlin)" + ] + } +} +``` + +The tool will also ask if it should save a .json file with more informations for every similar station. If you're unsure about what which station is, then it can be really helpful! It would give you data like which types of transports arrive at every similar station, in which country they are and also their coordinates. + +If you choose to generate the json, then you'll find the file as `stations.json` in the same directory as `main.py` + +##### blacklist +You can blacklist specific types of transport, the bot would then skip them while selecting a connection. You can get the type either in your console (mode) +```sh +22:44:47: INFO: Agency: GVB, mode: TRAM +``` +or in the `/info` embed. + +I highly recommend keeping `"OTHER"` blacklisted, if the API doesn't know what that is then we probably shouldn't use it. Also, it would probably a good idea to keep `"RIDE_SHARING"` blacklisted as they have weird timetables + +##### min_duration, max_duration, max_wait_time, timezone + +- `min_duration` is the minimal duration of the connection in minutes. It is HIGHLY recommended to set it to atleast 10, as discord only allows to change the name of a voice chat twice every 10 minutes. + +- `max_duration` is the maximun duration of the connection in minutes. Set to `null` to disable + +- `max_wait_time` is the maximun wait time for a connection in hours. Don't set that one too low, as the bot may have some issues finding a suitable connection at night, or at stations that aren't frequently used. Set to `null` to disable + +- `timezone` is timezone in the IANA timezone format. You can [look it up here](https://www.addevent.com/c/documentation/tools/time-zone-lookup) + +##### announcements +The bot can send a text announcement in the voice chat at the start/end of a trip. +At the end of a trip, it would send this embed: +![end_of_trip](.github/end_of_trip_announcement.png) + +It will also send the `/info` embed at the start of a new connection with informations about your new trip. + +To reduce spam, the bot will only send announcements if someone is in the voice chat + +##### voice +⚠️ Requires `announcements` to be set to enabled + +The bot can join the voice chat, play an audio file, and leave at various points of your trip. You have to have [FFmpeg](https://www.ffmpeg.org/) installed for this to work. + +Place the audio file of your desired station in [src/data/announcements](src/data/announcements/). Then, define the stations name with the name of the audio file in either `end_stations` or `stops`. The path will be autocompleted to [src/data/announcements](src/data/announcements/). The station name has to be EXACT, if you're unsure then [get the name through the helper script](#stations) + +`end_stations` is for audio files that should play at the end of your trip, and `stops` is for audio files that should play while the train is passing through your desired station. If you set the name of a station to `general`, then the bot will always play that file before the trip ends/a new stop has been reached. + +I'm hoping that I didn't explain this too complicated. Here's an example to visualize this: + +![example_files](.github/voice_announcements_visualized.png) + +```json + "announcements": { + "enabled": true, + "voice": [ + { + "enabled": true, + "end_stations": { + "general": "general.aac", + "Hannover Hbf": "hannover.aac" + }, + "stops": { + "Amsterdam, Noorderpark": "noorderpark.aac" + } + } + ] + }, +``` + +#### http + +- `"user_agent"`: The user agent of the bot for the API. If you don't know what that is, then you shouldn't have to change that. Even if you do, you still probably don't have to + +## Running +After you've set everything up, you're ready to start the bot! + +```sh +$ python run main.py +``` + +## src/data +[src/data](src/data/) contains a few files/directories which may be interesting to customize. + +### [emojis.py](src/data/emojis.py) +if `emojis` is enabled in the config, the bot will use that file to determine the right emoji for the voice chats name according to the current mode. You can add missing modes there or customize the emojis + +### [operators.py](src/data/operators.py) +Metadata for the `/info` embed. You can assign an agency a logo, color and (optionally) some slogans. The agency name is visible in the console log and the `/info` embed. + +If multiple agencys should use the same metadata, take a look at OPERATOR_ALIASES. + +You don't have to restart the bot after editing this file. + +### [locales/](src/data/locales/) +Covered in [locales](#locales) + +### [announcements/](src/data/announcements/) +Covered in [voice announcements](#voice) + +### [announcements](src/data/announcements/) +Assets (such as images) which the bot uses. You shouldn't have to change anything there \ No newline at end of file diff --git a/config.json.example b/config.json.example index 55612f7..02675aa 100644 --- a/config.json.example +++ b/config.json.example @@ -13,7 +13,10 @@ "Amsterdam", "Helsinki" ], - "blacklist": [], + "blacklist": [ + "OTHER", + "RIDE_SHARING" + ], "min_duration": 5, "max_duration": null, "max_wait_time": 6, diff --git a/src/api/transitous.py b/src/api/transitous.py index c69c5b3..37f48ea 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -263,6 +263,12 @@ def get_trip_details(random_connection: dict | None) -> dict | None: departure_time_iso = stop["departure"] trip_details["departure"] = parse_iso(departure_time_iso).strftime("%H:%M") + train_to_importance = legs["to"]["importance"] + trip_details["stops"][goes_to] = { + "arrival": arrival_dt, + "importance": train_to_importance + } + valid = validate_connection(start_time, end_time, departure_time_iso) if not valid: return None diff --git a/src/config.py b/src/config.py index 956e6d3..c08d1c1 100644 --- a/src/config.py +++ b/src/config.py @@ -16,8 +16,8 @@ class ConnectionsConfig: stations: list[str] blacklist: list[str] min_duration: int - max_wait_time: int timezone: str + max_wait_time: Optional[int] = None max_duration: Optional[int] = None @dataclass diff --git a/src/data/operators.py b/src/data/operators.py index 5818f2b..df87c8f 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -1,22 +1,5 @@ -'''' -Die Datei gibt dem Embed zugehörige Metadaten der Zugbetreiber. Identifiziert wird dabei durch die genauen Namen der Unternehmen. -Diese werden sowohl im /info Embed als auch in der Konsole angezeigt. - -| Feld | Optional | Wert | Beschreibung | -|---------|----------|-------|-----------------------------------------------------------------------| -| Unknown | Ja | Bool | Eigentlich nur für fallback relevant, sollte man weglassen | -| Logo | Nein | URL | Das Logo in der Ecke des Embeds. Am besten PNG, SVG geht leider nicht | -| Color | Nein | HEX | HEX Color Code des Streifen vom Embed, muss mit 0x anfangen | -| Slogan | Ja | Liste | Zufälliger Text aus der Liste im Footer | - -Sollte es dazu kommen, dass mehrere Anbieter die selben Metadaten nutzen sollen, kann man einen Eintrag für alle in OPERATORS setzen und -die zugehörigen Anbieternamen in OPERATOR_ALIASES auf den Eintrag lenken lassen. db_bawü ist dafür ein gutes Beispiel. - -Nachdem diese Datei editiert wurde muss der Bot nicht neugestartet werden. -''' OPERATORS = { "fallback": { - "unknown": True, "logo": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQCVeC5E0mNNBKyQftQaFMzxIVkbDvEnSzWv07h_c8PdA&s=10", "color": 0xFFFFFF }, @@ -114,6 +97,10 @@ OPERATORS = { "Berliner Verkehrsbetriebe": { "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/BVG_Logo_07.2021.svg/960px-BVG_Logo_07.2021.svg.png", "color": 0xEFD13C + }, + "Flixbus": { + "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Flixbus_201x_logo.svg/1280px-Flixbus_201x_logo.svg.png", + "color": 0x8CD541 } } @@ -136,7 +123,8 @@ OPERATOR_ALIASES = { "SBB GmbH": OPERATORS["SBB"], "Schweizerische Bundesbahnen SBB": OPERATORS["SBB"], "Dänische Staatsbahnen": OPERATORS["DSB"], - "VR": OPERATORS["Vr"] + "VR": OPERATORS["Vr"], + "FlixBus-gb": OPERATORS["Flixbus"] } diff --git a/src/data/status.py b/src/data/status.py deleted file mode 100644 index 375fc40..0000000 --- a/src/data/status.py +++ /dev/null @@ -1,16 +0,0 @@ -discord_status = [ - "Tschu-Tschu!", - "Heute ca. 15 Minuten später", - "Heute ohne Halt in Hamburg-Altona", - "Störung an der Weiche", - "Heute ohne Bordbistro", - "SEV ist eingerichtet", - "Gleiswechsel!", - "Zug entgleist :(", - "Die Bundespolizei ist informiert", - "Dieser Zug endet hier", - "Außerplanmäßiger Halt in Oberhausen Hbf", - "Verspätung aus vorheriger Fahrt", - "Der Zug hat keine Bremsen", - "Heute ohne Klimatisierung", -] \ No newline at end of file diff --git a/src/dc/handlers.py b/src/dc/handlers.py index bd743c9..e1c97c8 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -34,10 +34,11 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals print("-----------------") logger(f"Transfer: {long_name}; Arrival: {arrival}") logger(f"Agency: {trip["agency"]}, mode: {mode}") - logger(f"Trying to change channel name. If nothing happens, then the bot is in cooldown... (automatically resolves after up to 10min)") + logger(f"Trying to change the channels name. If nothing happens, then the bot is in cooldown... (automatically resolves after up to 10min)") formatting = channel_formatting(mode) await voice_channel.edit(name=f"{formatting}{long_name}") + await voice_channel.set_status(None) start_next_stop_updates(bot, voice_channel) @@ -58,7 +59,7 @@ async def announcer(announcement: str, voice_channel: discord.VoiceChannel, dest match announcement: case "end_of_connection": if voice_announcement_enabled: - announcement_status = await voice_announcer(destination, voice_channel) + announcement_status = await voice_announcer(destination, voice_channel, "end_stations") if announcement_status: return embed = build_announcement_embed(lang.embeds.announcement.end_of_connection.message()) @@ -151,7 +152,6 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne await asyncio.sleep(wait_seconds) except asyncio.CancelledError: - await voice_channel.set_status(None) raise def start_next_stop_updates(bot: discord.bot, voice_channel: discord.VoiceChannel): diff --git a/src/utils.py b/src/utils.py index 7274576..9588df2 100644 --- a/src/utils.py +++ b/src/utils.py @@ -37,9 +37,10 @@ def validate_connection(start_time: str, end_time: str, departure_time_iso: str) return False max_wait_time = config.connections.max_wait_time - if start_dt > now + timedelta(hours=max_wait_time): - logger(f"Connection is way too far in the future: {start_dt} (max_wait_time: {max_wait_time}h)", "error") - return False + if max_wait_time: + if start_dt > now + timedelta(hours=max_wait_time): + logger(f"Connection is way too far in the future: {start_dt} (max_wait_time: {max_wait_time}h)", "error") + return False departure_time_iso_dt = datetime.fromisoformat(departure_time_iso.replace("Z", "+00:00")) trip_duration = (end_dt - departure_time_iso_dt).total_seconds() From 000492f3200d0de7012f56f51d63d1b5aaaaae62 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:25:47 +0200 Subject: [PATCH 42/48] transitous rewrite: update example config in README --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8f93038..8c1a906 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,14 @@ I added an [example config](config.json.example): }, "connections": { "stations": [ - "" + "Berlin Hauptbahnhof", + "Amsterdam", + "Helsinki" + ], + "blacklist": [ + "OTHER", + "RIDE_SHARING" ], - "blacklist": [], "min_duration": 5, "max_duration": null, "max_wait_time": 6, @@ -62,8 +67,10 @@ I added an [example config](config.json.example): "voice": [ { "enabled": false, - "stations": { + "end_stations": { "general": "general.aac", + }, + "stops": { } } ] From 9f566a5bf35fc162dbcba1750888f1efdd59fe84 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:26:35 +0200 Subject: [PATCH 43/48] transitous rewrite: change json to sh in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c1a906..855ea3e 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ $ python run main.py stations ``` Example output: -```json +```sh 22:47:56: INFO: Exact match found! London is an assigned station! Bot would use that station directly 22:48:33: INFO: { "stations": { From 260ab043f41680aa9ad80ed95d04d383337dbe09 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:27:01 +0200 Subject: [PATCH 44/48] transitous rewrite: fix image in README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 855ea3e..b994e92 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ I highly recommend keeping `"OTHER"` blacklisted, if the API doesn't know what t ##### announcements The bot can send a text announcement in the voice chat at the start/end of a trip. At the end of a trip, it would send this embed: + ![end_of_trip](.github/end_of_trip_announcement.png) It will also send the `/info` embed at the start of a new connection with informations about your new trip. From a6342ca0390816439808d7c1bb8033c7229d31b6 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 13:39:00 +0200 Subject: [PATCH 45/48] transitous rewrite: fix next_stop --- src/dc/handlers.py | 5 ++++- src/utils.py | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/dc/handlers.py b/src/dc/handlers.py index e1c97c8..6e9febd 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -127,12 +127,14 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne if trip is None: return + ''' now = datetime.now(LOCAL_TZ) departure_dt = trip["departure_dt"] - + if departure_dt > now: wait_seconds = (departure_dt - now).total_seconds() await asyncio.sleep(wait_seconds) + ''' while True: next_stop = get_next_station(trip["stops"], trip["from"]) @@ -141,6 +143,7 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne return next_stop_str = next_stop["name"] + print(next_stop_str) status_text = f"{lang.embeds.info.next_stop()}: {next_stop_str}" await voice_channel.set_status(status_text, reason="Next stop status") diff --git a/src/utils.py b/src/utils.py index 9588df2..b317dc2 100644 --- a/src/utils.py +++ b/src/utils.py @@ -154,6 +154,11 @@ def get_next_station(stops: dict, train_from: str) -> dict | None: for name, info in stops.items(): arrival_dt = info["arrival"] if arrival_dt >= now: + return { + "name": name, + "arrival": arrival_dt + } + ''' if name == train_from: return None else: @@ -161,7 +166,7 @@ def get_next_station(stops: dict, train_from: str) -> dict | None: "name": name, "arrival": arrival_dt } - +''' return None def format_via_list(stops: dict, via_and: str) -> str: From 729f3509242441a6503c7bf110bac8e844f7f275 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:14:10 +0200 Subject: [PATCH 46/48] transitous rewrite: add IDs --- README.md | 6 ++++++ config.json.example | 1 + src/api/transitous.py | 28 ++++++++++++++++++++++++---- src/config.py | 1 + src/data/emojis.py | 3 ++- src/data/operators.py | 4 ++++ src/dc/handlers.py | 3 +-- 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b994e92..84a2af8 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ I added an [example config](config.json.example): "Amsterdam", "Helsinki" ], + "IDs": [], "blacklist": [ "OTHER", "RIDE_SHARING" @@ -164,6 +165,11 @@ The tool will also ask if it should save a .json file with more informations for If you choose to generate the json, then you'll find the file as `stations.json` in the same directory as `main.py` +##### IDs +For every station inside of the `stations.json` you'll find an ID. You can add that ID to `"IDs"` to really specify that you would like to use THAT station, and not a different one. + +This is especially useful if you want to add a station whose name isn't unique and also used by other stations. The bot would falsely use the first station with the same name and consider it an exact match, even if you wanted a different one. This won't happen with the ID, as every ID is uniquely assigned to only one station. + ##### blacklist You can blacklist specific types of transport, the bot would then skip them while selecting a connection. You can get the type either in your console (mode) ```sh diff --git a/config.json.example b/config.json.example index 02675aa..40d0a41 100644 --- a/config.json.example +++ b/config.json.example @@ -13,6 +13,7 @@ "Amsterdam", "Helsinki" ], + "IDs: [] "blacklist": [ "OTHER", "RIDE_SHARING" diff --git a/src/api/transitous.py b/src/api/transitous.py index 37f48ea..6b78aa1 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -8,7 +8,8 @@ from src.config import config from src.lang.locales import lang -stations = config.connections.stations +station_names = config.connections.stations +station_IDs = config.connections.IDs blacklist = config.connections.blacklist long_name_lang = lang.channel.long_name user_agent = config.http.user_agent @@ -25,7 +26,7 @@ def check_stations(): "stations": {} } - for station in stations: + for station in station_names: req = f"{endpoint}/api/v1/geocode" try: @@ -91,7 +92,26 @@ def check_stations(): def get_random_stop_id() -> str | None: - assigned_station = random.choice(stations) + stations = {} + + if len(station_names) > 0: + for entry in station_names: + if entry != "": + stations[entry] = "name" + + if len(station_IDs) > 0: + for entry in station_IDs: + if entry != "": + stations[entry] = "ID" + + if not stations: + logger("Both stations and IDs are empty...", "FATAL") + + assigned_station = random.choice(list(stations.keys())) + + if stations[assigned_station] == "ID": + return assigned_station + req = f"{endpoint}/api/v1/geocode" try: @@ -175,7 +195,7 @@ def get_random_connection(stop_id: str) -> str | None: break if not trip_ids: - logger("Couldn't find any connection", "error") + logger("Couldn't find any connections", "error") return None trip_id = random.choice(trip_ids) diff --git a/src/config.py b/src/config.py index c08d1c1..cae1cf1 100644 --- a/src/config.py +++ b/src/config.py @@ -14,6 +14,7 @@ class DiscordConfig: @dataclass class ConnectionsConfig: stations: list[str] + IDs: list[str] blacklist: list[str] min_duration: int timezone: str diff --git a/src/data/emojis.py b/src/data/emojis.py index f5f8827..f1f27f2 100644 --- a/src/data/emojis.py +++ b/src/data/emojis.py @@ -7,5 +7,6 @@ emoji_list = { "HIGHSPEED_RAIL": "🚅", "LONG_DISTANCE": "🚅", "METRO": "🚇", - "SUBWAY": "🚇" + "SUBWAY": "🚇", + "FERRY": "🚢" } \ No newline at end of file diff --git a/src/data/operators.py b/src/data/operators.py index df87c8f..33c8d10 100644 --- a/src/data/operators.py +++ b/src/data/operators.py @@ -101,6 +101,10 @@ OPERATORS = { "Flixbus": { "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Flixbus_201x_logo.svg/1280px-Flixbus_201x_logo.svg.png", "color": 0x8CD541 + }, + "Tallink Grupp AS": { + "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Tallink_logo.svg/330px-Tallink_logo.svg.png", + "color": 0x225197 } } diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 6e9febd..8bc41c3 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -130,7 +130,7 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne ''' now = datetime.now(LOCAL_TZ) departure_dt = trip["departure_dt"] - + if departure_dt > now: wait_seconds = (departure_dt - now).total_seconds() await asyncio.sleep(wait_seconds) @@ -143,7 +143,6 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne return next_stop_str = next_stop["name"] - print(next_stop_str) status_text = f"{lang.embeds.info.next_stop()}: {next_stop_str}" await voice_channel.set_status(status_text, reason="Next stop status") From 3dcf1e86263d55f75bdf6d0f6725a29aef51719b Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:27:47 +0200 Subject: [PATCH 47/48] transitous rewrite: only show next_stop if its actually stop and not the beginn of the route --- src/dc/handlers.py | 4 +--- src/utils.py | 7 +------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/dc/handlers.py b/src/dc/handlers.py index 8bc41c3..0b5450e 100644 --- a/src/dc/handlers.py +++ b/src/dc/handlers.py @@ -127,14 +127,12 @@ async def _update_next_loop(bot: discord.Bot, voice_channel: discord.VoiceChanne if trip is None: return - ''' now = datetime.now(LOCAL_TZ) departure_dt = trip["departure_dt"] if departure_dt > now: - wait_seconds = (departure_dt - now).total_seconds() + wait_seconds = (departure_dt - now).total_seconds() + 10 await asyncio.sleep(wait_seconds) - ''' while True: next_stop = get_next_station(trip["stops"], trip["from"]) diff --git a/src/utils.py b/src/utils.py index b317dc2..9588df2 100644 --- a/src/utils.py +++ b/src/utils.py @@ -154,11 +154,6 @@ def get_next_station(stops: dict, train_from: str) -> dict | None: for name, info in stops.items(): arrival_dt = info["arrival"] if arrival_dt >= now: - return { - "name": name, - "arrival": arrival_dt - } - ''' if name == train_from: return None else: @@ -166,7 +161,7 @@ def get_next_station(stops: dict, train_from: str) -> dict | None: "name": name, "arrival": arrival_dt } -''' + return None def format_via_list(stops: dict, via_and: str) -> str: From 637a1f19a0536949c292154cff97896e33069fa5 Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:36:59 +0200 Subject: [PATCH 48/48] transitous rewrite: set default min_duration to 10 --- README.md | 4 ++-- config.json.example | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 84a2af8..0ea6261 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,9 @@ I added an [example config](config.json.example): "OTHER", "RIDE_SHARING" ], - "min_duration": 5, + "min_duration": 10, "max_duration": null, - "max_wait_time": 6, + "max_wait_time": null, "timezone": "Europe/Berlin" }, "announcements": { diff --git a/config.json.example b/config.json.example index 40d0a41..3243519 100644 --- a/config.json.example +++ b/config.json.example @@ -18,9 +18,9 @@ "OTHER", "RIDE_SHARING" ], - "min_duration": 5, + "min_duration": 10, "max_duration": null, - "max_wait_time": 6, + "max_wait_time": null, "timezone": "Europe/Berlin" }, "announcements": {

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 V+?v3p8wLKkbyGv3RL(r~{{uK6`Dy?F diff --git a/.github/preview_info.png b/.github/preview_info.png index 47b964428db5a84f2b0dda47c648794190dbe60b..23307902d7846b608912c9e9ee154c0cc9d326d7 100644 GIT binary patch literal 64650 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 z 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