from __future__ import annotations from typing import Optional, Dict import os import requests from functools import lru_cache # Nominatimの利用規約に従ってUAと連絡先を付与 def _ua() -> Dict[str, str]: email = os.getenv("GEOCODING_EMAIL") or os.getenv("CONTACT_EMAIL") or "example@example.com" return {"User-Agent": f"HF-Space-Trip-Planner/1.0 (contact: {email})"} @lru_cache(maxsize=512) def geocode_city(city: str) -> Optional[Dict[str, object]]: """ 文字列の都市名から緯度経度を取得(Nominatim / OpenStreetMap)。 成功時: {"lat": float, "lon": float, "display_name": str} 失敗時: None """ if not city or not str(city).strip(): return None q = str(city).strip() url = "https://nominatim.openstreetmap.org/search" params = { "q": q, "format": "jsonv2", "addressdetails": 1, "limit": 1, } try: r = requests.get(url, params=params, headers=_ua(), timeout=20) r.raise_for_status() items = r.json() if not items: return None j = items[0] lat = float(j["lat"]) lon = float(j["lon"]) name = j.get("display_name") or q return {"lat": lat, "lon": lon, "display_name": name} except Exception: return None