import csv import importlib.resources import logging import requests log = logging.getLogger(__name__) NOMINATIM_URL = "https://nominatim.openstreetmap.org/search" _USER_AGENT = "planemapper/0.1 (https://github.com/football2801/planeMapper)" def _lookup_icao(code: str) -> tuple[float, float, str] | None: traversable = importlib.resources.files("planemapper.data").joinpath("airports.csv") with traversable.open("r", encoding="utf-8") as fh: reader = csv.DictReader(fh) for row in reader: if row["ident"] == code: return float(row["latitude_deg"]), float(row["longitude_deg"]), row["name"] return None def _geocode(query: str) -> tuple[float, float, str] | None: resp = requests.get( NOMINATIM_URL, params={"q": query, "format": "json", "limit": 1}, headers={"User-Agent": _USER_AGENT}, timeout=10, ) resp.raise_for_status() results = resp.json() if not results: return None r = results[0] return float(r["lat"]), float(r["lon"]), r["display_name"] def resolve(query: str) -> tuple[float, float, str]: query = query.strip().upper() if len(query) == 4 and query.isalpha(): result = _lookup_icao(query) if result is None: raise ValueError("ICAO code not found — try an address instead") log.info("ICAO %s resolved to %s", query, result[2]) return result result = _geocode(query) if result is None: raise ValueError("Location not found — try a different search term") log.info("Address '%s' resolved to %s", query, result[2]) return result