PlanMate / planmate /flights.py
embed786's picture
Upload 9 files
6380b21 verified
from typing import List, Dict, Tuple
from .clients.amadeus_client import AmadeusClient
from .utils import format_price
def resolve_city_to_iata(city_name: str) -> Tuple[str, str]:
"""Resolve a human city name to an IATA city code using Amadeus.
Returns (iata_code, display_label). Raises RuntimeError if not found.
"""
client = AmadeusClient()
res = client.locations(city_name, subtypes="CITY")
data = res.get("data", [])
if not data:
# try airports as fallback and take the cityName + iataCode of airport
res = client.locations(city_name, subtypes="AIRPORT")
data = res.get("data", [])
if not data:
raise RuntimeError(f"Could not resolve city to IATA: {city_name}")
# Prefer exact name match then highest relevance (first)
city_lower = city_name.strip().lower()
chosen = None
for d in data:
name = (d.get("name") or "").lower()
address_city = (d.get("address", {}).get("cityName") or "").lower()
if name == city_lower or address_city == city_lower:
chosen = d
break
if not chosen:
chosen = data[0]
code = chosen.get("iataCode")
label = f"{chosen.get('name')} ({code})"
if not code:
raise RuntimeError(f"No IATA code found for: {city_name}")
return code, label
def search_airports(keyword: str) -> List[Dict]:
client = AmadeusClient()
res = client.locations(keyword)
items = []
for d in res.get("data", []):
items.append(
{
"name": d.get("name"),
"iataCode": d.get("iataCode"),
"subType": d.get("subType"),
"address": d.get("address", {}).get("cityName")
or d.get("address", {}).get("countryName"),
}
)
return items
def search_flights(
origin_code: str,
dest_code: str,
depart: str,
ret: str,
adults=1,
currency="PKR",
non_stop: bool = False,
) -> Dict:
client = AmadeusClient()
res = client.flight_offers(
origin_code, dest_code, depart, ret, adults, currency, non_stop
)
dicts = res.get("dictionaries", {})
carriers = dicts.get("carriers", {})
result = []
for offer in res.get("data", []):
price = offer.get("price", {}).get("total")
itineraries = offer.get("itineraries", [])
legs = []
for it in itineraries:
segs = []
for s in it.get("segments", []):
carrier = s.get("carrierCode")
segs.append(
{
"from": s.get("departure", {}).get("iataCode"),
"to": s.get("arrival", {}).get("iataCode"),
"dep": s.get("departure", {}).get("at"),
"arr": s.get("arrival", {}).get("at"),
"carrier": carriers.get(carrier, carrier),
"number": s.get("number"),
"duration": it.get("duration", ""),
}
)
legs.append(segs)
result.append(
{
"price": price,
"price_label": format_price(price, currency),
"legs": legs,
"oneWay": (ret is None or ret == ""),
}
)
return {"flights": result, "carriers": carriers}