2023-01-08 12:22:36 +00:00
|
|
|
"""Interface with the Brittany Ferries API."""
|
|
|
|
|
|
|
|
from typing import Any, TypedDict
|
|
|
|
|
|
|
|
import requests
|
2023-09-11 07:00:20 +01:00
|
|
|
import json
|
2023-01-08 12:22:36 +00:00
|
|
|
|
|
|
|
from . import Vehicle
|
|
|
|
|
|
|
|
api_root_url = "https://www.brittany-ferries.co.uk/api/ferry/v1/"
|
2023-04-16 19:56:26 +01:00
|
|
|
ua = "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0"
|
|
|
|
|
|
|
|
headers = {"User-Agent": ua}
|
2023-01-08 12:22:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
class VehicleDict(TypedDict):
|
|
|
|
"""Description of vechicle in the format expected by the API."""
|
|
|
|
|
|
|
|
type: str
|
|
|
|
registrations: list[str]
|
|
|
|
height: int
|
|
|
|
length: int
|
2023-09-11 07:00:20 +01:00
|
|
|
extras: dict[str, None | bool]
|
2023-01-08 12:22:36 +00:00
|
|
|
|
|
|
|
|
2023-09-11 07:00:20 +01:00
|
|
|
def vehicle_dict(v: Vehicle, rear_mounted_bike_carrier: bool = False) -> VehicleDict:
|
2023-01-08 12:22:36 +00:00
|
|
|
"""Return vehicle detail in the format for the Brittany Ferries API."""
|
2023-09-11 07:00:20 +01:00
|
|
|
rmbc = True if rear_mounted_bike_carrier else None
|
2023-01-08 12:22:36 +00:00
|
|
|
return {
|
|
|
|
"type": v.type,
|
|
|
|
"registrations": [v.registration],
|
|
|
|
"height": v.height,
|
|
|
|
"length": v.length,
|
2023-09-11 07:00:20 +01:00
|
|
|
"extras": {"rearMountedBikeCarrier": rmbc},
|
2023-01-08 12:22:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def get_prices(
|
|
|
|
departure_port: str,
|
|
|
|
arrival_port: str,
|
|
|
|
from_date: str,
|
|
|
|
to_date: str,
|
|
|
|
vehicle: Vehicle,
|
2023-04-16 19:56:26 +01:00
|
|
|
adults: int = 2,
|
|
|
|
small_dogs: int = 1,
|
2023-09-11 07:00:20 +01:00
|
|
|
rear_mounted_bike_carrier: bool = False,
|
2023-01-08 12:22:36 +00:00
|
|
|
) -> dict[str, Any]:
|
|
|
|
"""Call Brittany Ferries API to get details of crossings."""
|
|
|
|
url = api_root_url + "crossing/prices"
|
|
|
|
|
|
|
|
post_data = {
|
|
|
|
"bookingReference": None,
|
2023-04-16 19:56:26 +01:00
|
|
|
"pets": {"smallDogs": small_dogs, "largeDogs": 0, "cats": 0},
|
|
|
|
"passengers": {"adults": adults, "children": 0, "infants": 0},
|
2023-09-11 07:00:20 +01:00
|
|
|
"vehicle": vehicle_dict(vehicle, rear_mounted_bike_carrier),
|
2023-01-08 12:22:36 +00:00
|
|
|
"departurePort": departure_port,
|
|
|
|
"arrivalPort": arrival_port,
|
|
|
|
"disability": None,
|
|
|
|
"sponsor": None,
|
|
|
|
"fromDate": f"{from_date}T00:00:00",
|
|
|
|
"toDate": f"{to_date}T23:59:59",
|
|
|
|
}
|
|
|
|
|
2023-04-16 19:56:26 +01:00
|
|
|
r = requests.post(url, json=post_data, headers=headers)
|
2023-01-08 12:22:36 +00:00
|
|
|
data: dict[str, Any] = r.json()
|
2023-09-11 07:00:20 +01:00
|
|
|
if "crossings" not in data:
|
|
|
|
print(json.dumps(data, indent=2))
|
2023-01-08 12:22:36 +00:00
|
|
|
return data
|
|
|
|
|
|
|
|
|
|
|
|
def get_accommodations(
|
|
|
|
departure_port: str,
|
|
|
|
arrival_port: str,
|
|
|
|
departure_date: str,
|
|
|
|
ticket_tier: str,
|
|
|
|
vehicle: Vehicle,
|
2023-08-10 14:05:07 +01:00
|
|
|
adults: int,
|
|
|
|
small_dogs: int,
|
2023-09-11 07:00:20 +01:00
|
|
|
rear_mounted_bike_carrier: bool = False,
|
2023-01-08 12:22:36 +00:00
|
|
|
) -> dict[str, Any]:
|
|
|
|
"""Grab cabin details."""
|
|
|
|
url = api_root_url + "crossing/accommodations"
|
|
|
|
post_data = {
|
|
|
|
"bookingReference": None,
|
|
|
|
"departurePort": departure_port,
|
|
|
|
"arrivalPort": arrival_port,
|
|
|
|
"departureDate": departure_date,
|
2023-08-10 14:05:07 +01:00
|
|
|
"passengers": {"adults": adults, "children": 0, "infants": 0},
|
2023-01-08 12:22:36 +00:00
|
|
|
"disability": None,
|
2023-09-11 07:00:20 +01:00
|
|
|
"vehicle": vehicle_dict(vehicle, rear_mounted_bike_carrier),
|
2023-01-08 12:22:36 +00:00
|
|
|
"petCabinsNeeded": True,
|
|
|
|
"ticketTier": ticket_tier,
|
2023-08-10 14:05:07 +01:00
|
|
|
"pets": {"smallDogs": small_dogs, "largeDogs": 0, "cats": 0},
|
2023-01-08 12:22:36 +00:00
|
|
|
"sponsor": None,
|
|
|
|
"offerType": "NONE",
|
|
|
|
}
|
|
|
|
|
2023-04-16 19:56:26 +01:00
|
|
|
json_data: dict[str, Any] = requests.post(
|
|
|
|
url, json=post_data, headers=headers
|
|
|
|
).json()
|
2023-09-11 07:00:20 +01:00
|
|
|
if "crossings" not in json_data:
|
|
|
|
print()
|
|
|
|
print(json.dumps(post_data, indent=2))
|
|
|
|
print()
|
|
|
|
print(json.dumps(json_data, indent=2))
|
2023-01-08 12:22:36 +00:00
|
|
|
return json_data
|