mirror of
https://github.com/kaaninchen/Gleiswechsel.git
synced 2026-09-17 16:52:47 +00:00
transitous rewrite: some minor info embed improvements
This commit is contained in:
@@ -2,8 +2,10 @@ import discord
|
|||||||
from src.utils import config, logger
|
from src.utils import config, logger
|
||||||
from src.dc.handlers import rename_vc
|
from src.dc.handlers import rename_vc
|
||||||
from src.dc.helpers import validate_channel
|
from src.dc.helpers import validate_channel
|
||||||
|
from src.dc.commands import setup_commands
|
||||||
|
|
||||||
bot = discord.Bot(intents=discord.Intents.all())
|
bot = discord.Bot(intents=discord.Intents.all())
|
||||||
|
setup_commands(bot=bot)
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
@@ -18,3 +20,15 @@ try:
|
|||||||
bot.run(config["token"])
|
bot.run(config["token"])
|
||||||
except:
|
except:
|
||||||
logger("Feher peim parsen des tokens", "fatal")
|
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
|
||||||
|
'''
|
||||||
+30
-17
@@ -1,7 +1,8 @@
|
|||||||
import requests
|
import requests
|
||||||
import random
|
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"]
|
stations = config["stations"]
|
||||||
blacklist = config["blacklist"]
|
blacklist = config["blacklist"]
|
||||||
@@ -14,8 +15,8 @@ headers = {
|
|||||||
endpoint = "https://api.transitous.org"
|
endpoint = "https://api.transitous.org"
|
||||||
|
|
||||||
def get_random_stop_id() -> str:
|
def get_random_stop_id() -> str:
|
||||||
stop = random.choice(stations)
|
assigned_station = random.choice(stations)
|
||||||
req = f"{endpoint}/api/v1/geocode?text={stop}"
|
req = f"{endpoint}/api/v1/geocode?text={assigned_station}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.get(req, headers=headers)
|
response = requests.get(req, headers=headers)
|
||||||
@@ -26,7 +27,7 @@ def get_random_stop_id() -> str:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
if response.status_code == 404:
|
if response.status_code == 404:
|
||||||
logger(f"Error finding station '{stop}'")
|
logger(f"Error finding station '{assigned_station}'")
|
||||||
|
|
||||||
for entry in data:
|
for entry in data:
|
||||||
if entry.get("type") != "STOP":
|
if entry.get("type") != "STOP":
|
||||||
@@ -54,7 +55,8 @@ def get_random_connection(stop_id: str) -> str:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
trip_ids = []
|
trip_ids = []
|
||||||
for entry in data.get("stopTimes", []):
|
stop_times = data.get("stopTimes", [])
|
||||||
|
for entry in stop_times:
|
||||||
trip_id = entry["tripId"]
|
trip_id = entry["tripId"]
|
||||||
if entry["mode"] in blacklist:
|
if entry["mode"] in blacklist:
|
||||||
continue
|
continue
|
||||||
@@ -71,9 +73,14 @@ def get_random_connection(stop_id: str) -> str:
|
|||||||
logger("Couldn't find any connection", "fatal")
|
logger("Couldn't find any connection", "fatal")
|
||||||
return None
|
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}"
|
req = f"{endpoint}/api/v2/trip?tripId={trip_id}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -88,31 +95,37 @@ def get_trip_details(trip_id: str) -> dict:
|
|||||||
|
|
||||||
display_name = legs["displayName"]
|
display_name = legs["displayName"]
|
||||||
trip_from = legs["tripFrom"]["name"]
|
trip_from = legs["tripFrom"]["name"]
|
||||||
trip_to = legs["tripTo"]["name"]
|
goes_to = legs["tripTo"]["name"]
|
||||||
start_time = legs["startTime"]
|
start_time = legs["startTime"]
|
||||||
end_time = legs["endTime"]
|
end_time = legs["endTime"]
|
||||||
mode = legs["mode"]
|
mode = legs["mode"]
|
||||||
|
|
||||||
|
departure = convert_iso_string(start_time)
|
||||||
|
arrival = convert_iso_string(end_time)
|
||||||
train_name = get_train_name(display_name, mode)
|
train_name = get_train_name(display_name, mode)
|
||||||
|
|
||||||
|
|
||||||
trip_details = {
|
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,
|
"short_name": display_name,
|
||||||
"from": trip_from,
|
"from": from_station,
|
||||||
"to": trip_to,
|
"to": goes_to,
|
||||||
"agency": legs["agencyName"],
|
"agency": legs["agencyName"],
|
||||||
"route_color": legs.get("routeColor"),
|
"route_color": legs.get("routeColor"),
|
||||||
"duration": legs["duration"],
|
"duration": legs["duration"],
|
||||||
"start_time": start_time,
|
"departure": departure,
|
||||||
"end_time": end_time,
|
"arrival": arrival,
|
||||||
"mode": mode,
|
"mode": mode,
|
||||||
"stops": {}
|
"stops": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
trip_details["stops"][trip_from] = start_time
|
trip_details["stops"][trip_from] = departure
|
||||||
for stop in legs["intermediateStops"]:
|
for stop in legs["intermediateStops"]:
|
||||||
trip_details["stops"][stop["name"]] = stop["arrival"]
|
arrival = convert_iso_string(stop["arrival"])
|
||||||
trip_details["stops"][trip_to] = end_time
|
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
|
return trip_details
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
||||||
@@ -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
|
||||||
+5
-4
@@ -8,14 +8,15 @@ from src.utils import logger, channel_formatting
|
|||||||
_scheduled_task: asyncio.Task | None = None
|
_scheduled_task: asyncio.Task | None = None
|
||||||
|
|
||||||
async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = False):
|
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():
|
if not from_scheduler and _scheduled_task and not _scheduled_task.done():
|
||||||
_scheduled_task.cancel()
|
_scheduled_task.cancel()
|
||||||
|
|
||||||
station_id = transitous.get_random_stop_id()
|
station_id = transitous.get_random_stop_id()
|
||||||
trip_id = transitous.get_random_connection(station_id)
|
connection = transitous.get_random_connection(station_id)
|
||||||
trip = transitous.get_trip_details(trip_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"]
|
long_name = trip["long_name"]
|
||||||
|
|
||||||
print("-----------------")
|
print("-----------------")
|
||||||
@@ -25,7 +26,7 @@ async def rename_vc(bot: discord.Bot, voice_channel, from_scheduler: bool = Fals
|
|||||||
|
|
||||||
formatting = channel_formatting(trip["mode"])
|
formatting = channel_formatting(trip["mode"])
|
||||||
await voice_channel.edit(name=f"{formatting}{long_name}")
|
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!")
|
logger(f"Name geändert!")
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -1,5 +1,6 @@
|
|||||||
import discord
|
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):
|
def validate_channel(bot: discord.bot, server_id: int, channel_id: int):
|
||||||
guild = bot.get_guild(server_id)
|
guild = bot.get_guild(server_id)
|
||||||
@@ -13,3 +14,18 @@ def validate_channel(bot: discord.bot, server_id: int, channel_id: int):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
return channel
|
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")
|
||||||
@@ -2,8 +2,10 @@ import json
|
|||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import src.data.operators as operators
|
||||||
from src.data.emojis import emoji_list
|
from src.data.emojis import emoji_list
|
||||||
|
|
||||||
|
|
||||||
with open("config.json", "r") as file:
|
with open("config.json", "r") as file:
|
||||||
config = json.load(file)
|
config = json.load(file)
|
||||||
|
|
||||||
@@ -14,6 +16,10 @@ def logger(msg, log_type="info") -> str:
|
|||||||
if status == "FATAL":
|
if status == "FATAL":
|
||||||
os._exit(1)
|
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:
|
def channel_formatting(mode: str) -> str:
|
||||||
formatting = config.get("formatting", "")
|
formatting = config.get("formatting", "")
|
||||||
|
|
||||||
@@ -33,3 +39,25 @@ def get_train_name(train_name: str, mode: str) -> str:
|
|||||||
train = train_name
|
train = train_name
|
||||||
|
|
||||||
return train
|
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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user