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