2022-09-03 19:53:08 +02:00
|
|
|
import httpx
|
|
|
|
from .objects import *
|
2022-01-03 20:56:40 +01:00
|
|
|
|
|
|
|
|
2022-09-03 19:53:08 +02:00
|
|
|
class SNCFException(Exception):
|
|
|
|
pass
|
2022-01-03 20:56:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
class SNCF:
|
|
|
|
BASE_URL = "https://api.sncf.com/v1/coverage/sncf"
|
|
|
|
|
|
|
|
def __init__(self, token: str):
|
|
|
|
self.token = token
|
|
|
|
self.source_stop_point: str = ""
|
|
|
|
self.dest_stop_point: str = ""
|
|
|
|
self.allowed_lines: list[str] = []
|
|
|
|
self.max_transfers: int = 0
|
|
|
|
self.max_duration_secs: int = 1800
|
|
|
|
self.prefered_date_format = "%H:%M"
|
2022-09-03 19:53:08 +02:00
|
|
|
self.token_validated: bool = False
|
|
|
|
self.physical_mode: Optional[PhysicalMode] = None
|
2022-01-03 20:56:40 +01:00
|
|
|
|
|
|
|
def set_source_stop_point(self, stop_point: str):
|
|
|
|
self.source_stop_point = stop_point
|
|
|
|
|
|
|
|
def set_dest_stop_point(self, stop_point: str):
|
|
|
|
self.dest_stop_point = stop_point
|
|
|
|
|
|
|
|
def set_allowed_lines(self, allowed_lines: list[str]):
|
|
|
|
self.allowed_lines = allowed_lines
|
|
|
|
|
2022-09-03 19:53:08 +02:00
|
|
|
async def get_next_journeys(self, max_count: int = 1):
|
|
|
|
if not self.physical_mode:
|
|
|
|
raise SNCFException("Use set_physical_mode before using this function")
|
|
|
|
valid_journeys: List[Journey] = []
|
|
|
|
api_response = await self.api_request(f"/journeys?from={self.source_stop_point}:{self.physical_mode}&to={self.dest_stop_point}:{self.physical_mode}&datetime={self.date_now()}&count={max_count}&disable_geojson=true")
|
2022-01-03 20:56:40 +01:00
|
|
|
journeys = api_response["journeys"]
|
|
|
|
for journey in journeys:
|
2022-09-03 19:53:08 +02:00
|
|
|
if (self.max_transfers == -1 or journey["nb_transfers"] <= self.max_transfers) and (self.max_duration_secs == -1 or journey["duration"] <= self.max_duration_secs):
|
|
|
|
valid_journeys.append(Journey(**journey))
|
2022-01-03 20:56:40 +01:00
|
|
|
return valid_journeys
|
|
|
|
|
2022-09-03 19:53:08 +02:00
|
|
|
async def api_request(self, url: str, **kwargs):
|
|
|
|
async with httpx.AsyncClient() as client:
|
|
|
|
if not kwargs.get("no_check", False) and not self.token_validated:
|
|
|
|
if not await self.test_api_key():
|
|
|
|
raise Exception("Token is invalid")
|
|
|
|
self.token_validated = True
|
|
|
|
req = await client.get(SNCF.BASE_URL + url, headers={"Authorization": self.token})
|
|
|
|
req.raise_for_status()
|
|
|
|
json = req.json()
|
|
|
|
return json
|
2022-01-03 20:56:40 +01:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def date_now() -> str:
|
|
|
|
return datetime.datetime.now().strftime("%Y%m%dT%H%M%S")
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def api_date_to_datetime(api_date: str) -> datetime:
|
|
|
|
return datetime.datetime.strptime(api_date, "%Y%m%dT%H%M%S")
|
|
|
|
|
2022-09-03 19:53:08 +02:00
|
|
|
async def test_api_key(self) -> bool:
|
2022-01-03 20:56:40 +01:00
|
|
|
try:
|
2022-09-03 19:53:08 +02:00
|
|
|
await self.api_request("", no_check=True)
|
2022-01-03 20:56:40 +01:00
|
|
|
return True
|
2022-09-03 19:53:08 +02:00
|
|
|
except httpx.RequestError:
|
2022-01-03 20:56:40 +01:00
|
|
|
return False
|
|
|
|
|
2022-09-03 19:53:08 +02:00
|
|
|
def get_cheapest_path(self) -> List[Journey]:
|
|
|
|
pass
|
2022-01-03 20:56:40 +01:00
|
|
|
|
2022-09-03 19:53:08 +02:00
|
|
|
def set_physical_mode(self, physical_mode: PhysicalModes):
|
|
|
|
self.physical_mode = physical_mode
|
|
|
|
|
|
|
|
async def get_station(self, name: str) -> List[StopArea]:
|
|
|
|
api_response = await self.api_request(f"/places?q={name}&disable_geojson=true&type=stop_area&depth=2")
|
|
|
|
places = [Place(**item) for item in api_response["places"]]
|
|
|
|
stops = []
|
|
|
|
for place in places:
|
|
|
|
if place.stop_area:
|
|
|
|
if self.physical_mode:
|
|
|
|
for physical_mode in place.stop_area.physical_modes:
|
|
|
|
if self.physical_mode == physical_mode.value:
|
|
|
|
stops.append(place.stop_area)
|
|
|
|
else:
|
|
|
|
stops.append(place.stop_area)
|
|
|
|
return stops
|