From d8cfe7b0d7ee3661cd39bed6e3533a4127e9d4ba Mon Sep 17 00:00:00 2001 From: Kaaninchen <124433727+kaaninchen@users.noreply.github.com> Date: Fri, 17 Jul 2026 22:17:59 +0200 Subject: [PATCH] =?UTF-8?q?Zeitschleife=20anhand=20von=20Echtzeit=20Ankunf?= =?UTF-8?q?tsuhrzeit=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ein recht großer commit. Mit dabei ist ein logger, erweiterte Informationen zu den Zügen und eine Zeitschleife, welche sich anhand der echtzeit ankunftsdaten des Zuges richtet. Der Commit benötigt auf jeden fall testing --- src/embeds.py | 21 ++++++++++++++++---- src/handlers.py | 53 ++++++++++++++++++++++++++++++++++++++----------- src/utils.py | 27 +++++++++++++++++++++++-- 3 files changed, 83 insertions(+), 18 deletions(-) diff --git a/src/embeds.py b/src/embeds.py index 6fd21cf..5dee192 100644 --- a/src/embeds.py +++ b/src/embeds.py @@ -1,29 +1,42 @@ import random import discord -from datetime import datetime +from datetime import datetime, timedelta import src.handlers as handlers -from src.utils import operator_infos, format_via_list +from src.utils import operator_infos, format_via_list, 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_info_embed() -> discord.Embed | None: if handlers.current is None: return None conn = handlers.current + info = handlers.train_info + + arrival = format_iso_timestamp(info["arrival"]) + departure = format_timestamp(conn['departure']) operator = operator_infos(conn["train"]) embed = discord.Embed( title=handlers.train_name, - description=f"Abfahrt von {conn['station']} um {format_timestamp(conn['departure'])}", + description=f"Abfahrt von {conn['station']} um {departure}. Ankunft um {arrival}", color=operator["color"] ) @@ -32,7 +45,7 @@ def build_info_embed() -> discord.Embed | None: if operator["name"] == "Unbekannter Anbieter": anbieter = conn['train'].split()[0] - print(f"INFO: Unbekannter Anbieter für Typ {anbieter}") + logger(f"INFO: Unbekannter Anbieter für Typ {anbieter}") operator_name = f"{operator['name']} (Typ: {anbieter})" else: operator_name = operator["name"] diff --git a/src/handlers.py b/src/handlers.py index a48924b..152af06 100644 --- a/src/handlers.py +++ b/src/handlers.py @@ -1,35 +1,64 @@ import discord -import time +from datetime import datetime, timedelta +import asyncio from src.config import config -from src.utils import random_connection +from src.utils import random_connection, get_train_info, logger current = None +_scheduled_task: asyncio.Task | None = None -async def rename_vc(bot: discord.Bot) -> bool: - global current, train_name +async def rename_vc(bot: discord.Bot, scheduled = False) -> bool: + global current, train_name, train_info, _scheduled_task guild = bot.get_guild(int(config["server"])) if guild is None: - print(f"Es konnte kein Server mit der ID {config['server']} gefunden werden! Ist der Bot ein Member?") + logger(f"Es konnte kein Server mit der ID {config['server']} gefunden werden! Ist der Bot ein Member?") return False channel = guild.get_channel(int(config["vc"])) if not isinstance(channel, discord.VoiceChannel): - print(f"Es konnte kein VC mit der ID {config['vc']} auf dem Server gefunden werden") + logger(f"Es konnte kein VC mit der ID {config['vc']} auf dem Server gefunden werden") return False current = random_connection() train_type = current['train'].split()[0] - if train_type in ("IC", "ICE", "NJ"): + if train_type in ("IC", "ICE", "NJ", "ES"): train = current['train'] + train_ID = current['train'].split()[1] else: train = current['train'].split()[1] + train_ID = current['train_number'] + + train_info = get_train_info(station=current['station'], train_ID=train_ID, train_type=train_type) train_name = f"{train} nach {current['destination']}" + if not scheduled and _scheduled_task and not _scheduled_task.done(): + _scheduled_task.cancel() + + if train_info: + _scheduled_task = asyncio.create_task(_schedule_next_umstieg(bot, train_info["arrival"])) + print("-----------------------------------------") - current_time = time.strftime('%X') - print(f"{current_time}: Umstieg: {train_name} (Typ {train_type}) von {current['station']}") - print(f"{current_time}: Wenn hier keine Nachricht mehr kommt bin ich im Cooldown") + logger(f"Umstieg: {train_name} (Typ {train_type}) von {current['station']}") + logger(f"Wenn der Name nicht geändert wird bin ich im Cooldown") await channel.edit(name=f"{config['formatting']}{train_name}",) - print(f"{current_time}: Name geändert!") - return True \ No newline at end of file + logger(f"Name geändert!") + + return True + +async def _schedule_next_umstieg(bot, arrival_iso): + try: + arrival = datetime.fromisoformat(arrival_iso) +# wait_seconds = (arrival - datetime.now()).total_seconds() + wait_seconds = 30 + + if wait_seconds > 0: + remaining = str(timedelta(seconds=wait_seconds)) + logger(f"In {remaining} gehts weiter!...") + await asyncio.sleep(wait_seconds) + logger("Zug angekommen, wähle neue Verbindung...") + await rename_vc(bot, scheduled=True) + + except asyncio.CancelledError: + logger("Geplanter Umstieg wurde abgebrochen (manueller /umstieg dazwischen oder CTRL + C)") + raise \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index bd75bfc..c855356 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,5 +1,6 @@ import requests import random +from datetime import datetime from src.config import config from src.data.operators import OPERATORS @@ -30,7 +31,8 @@ def random_connection(): "route": dep['route'], "departure": dep['scheduledDeparture'], "via": dep['via'], - "station": station + "station": station, + "train_number": dep['trainNumber'] } @@ -46,4 +48,25 @@ def format_via_list(via: list[str]): return "" if len(via) == 1: return via[0] - return ", ".join(via[:-1]) + " und " + via[-1] \ No newline at end of file + return ", ".join(via[:-1]) + " und " + via[-1] + +def get_train_info(station, train_ID, train_type): + url = f"https://dbf.finalrewind.org/z/{train_type}%20{train_ID}/{station}.json" + + try: + response = requests.get(url) + response.raise_for_status() + data = response.json() + except requests.RequestException: + return None + + dep = data.get("departure", []) + arrival_iso = dep["route_post_diff"][-1]["sched_arr"] + return { + "arrival": arrival_iso, + "operators": dep["operators"] + } + +def logger(msg): + current_time = datetime.now().strftime('%X') + print(f"{current_time}: {msg}") \ No newline at end of file