diff --git a/README.md b/README.md index 428886a..6a1d266 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,30 @@ For every station inside of the `stations.json` you'll find an ID. You can add t 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. +##### priority +You can define priorities of transport modes while selecting a connection. Leave empty to disable + +The list should be descending, with "1" as the most important transport mode. For example, let's say, the bot should always choose Trains and other longer distance public transport modes. If it can't find any, then it should resort to Metros/Subways/Suburbans. If these are also missing at that station, then it should just use Busses/Trams: + +```json +"priority": { + "HIGHSPEED_RAIL": 1, + "LONG_DISTANCE": 1, + "NIGHT_RAIL": 1, + "REGIONAL_RAIL": 1, + "COACH": 1, + "FERRY": 1, + "METRO": 2, + "SUBURBAN": 2, + "SUBWAY": 2, + "BUS": 3, + "TRAM": 3 +} +``` +A transport mode that isn't in the priority list would immediately get assigned the value of "99", making it near impossible to get that connection. Except when there are no other connections available, of course. + +You can find the MODE names either in the console log or the stations.json from [helper tool](#stations) + ##### blacklist You can blacklist specific types of transport, the bot would then skip them while selecting a connection. You can get the type in your console (mode) ```sh diff --git a/config.json.example b/config.json.example index eed8bc9..ac23910 100644 --- a/config.json.example +++ b/config.json.example @@ -14,6 +14,8 @@ "Helsinki" ], "IDs": [], + "priority: "{ + }", "blacklist": [ "OTHER", "RIDE_SHARING" diff --git a/src/api/transitous.py b/src/api/transitous.py index 83d293b..432d40d 100644 --- a/src/api/transitous.py +++ b/src/api/transitous.py @@ -142,10 +142,12 @@ def get_random_stop_id() -> str | None: return None stop_ids_list = list(stop_ids.keys()) + chosen_stop_id = random.choice(stop_ids_list) if len(stop_ids_list) > 1: 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"Selected station: {stop_ids[chosen_stop_id]}") + return chosen_stop_id def get_random_connection(stop_id: str) -> str | None: @@ -153,60 +155,46 @@ def get_random_connection(stop_id: str) -> str | None: return None now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") - cursor = None - max_pages = 5 - min_results = 5 - trip_ids = [] - all_stop_times = [] + params = {"stopId": stop_id, "n": 50, "time": now} - for _ in range(max_pages): - params = { - "stopId": stop_id, - "n": 20, - "time": now, - } - if cursor: - params["pageCursor"] = cursor + 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: + logger(e, "Error") + return None - 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: - logger(e, "Error") - break + candidates = [] + for entry in data.get("stopTimes", []): + if entry["mode"] in blacklist: + continue + candidates.append(entry) - stop_times = data.get("stopTimes", []) - all_stop_times.extend(stop_times) + if not candidates: + logger("Couldn't find any connections", "error") + return None + + if config.connections.priority: + best_priority = None + for entry in candidates: + priority = config.connections.priority.get(entry["mode"], 99) + if best_priority is None or priority < best_priority: + best_priority = priority - for entry in stop_times: - trip_id = entry["tripId"] - if entry["mode"] in blacklist: - continue - else: - trip_ids.append(entry["tripId"]) + best_candidates = [] + for entry in candidates: + priority = config.connections.priority.get(entry["mode"], 99) + if priority == best_priority: + best_candidates.append(entry) - if len(trip_ids) >= min_results: - break - - cursor = data.get("nextPageCursor") - if not cursor: - break - - if not trip_ids: - logger("Couldn't find any connections", "error") - return None - trip_id = random.choice(trip_ids) - - from_station = None - for entry in all_stop_times: - if entry.get("tripId") == trip_id: - from_station = entry.get("place", {}).get("name") - break + chosen = random.choice(best_candidates) + else: + chosen = random.choice(candidates) return { - "trip_id": trip_id, - "from_station": from_station + "trip_id": chosen["tripId"], + "from_station": chosen.get("place", {}).get("name"), } def get_trip_details(random_connection: dict | None) -> dict | None: diff --git a/src/config.py b/src/config.py index 898b6cc..e2609ea 100644 --- a/src/config.py +++ b/src/config.py @@ -1,5 +1,5 @@ import json -from dataclasses import dataclass, field +from dataclasses import dataclass from typing import Optional @dataclass @@ -15,6 +15,7 @@ class DiscordConfig: class ConnectionsConfig: stations: list[str] IDs: list[str] + priority: dict blacklist: list[str] min_duration: int timezone: str