""" Free geolocation module using OpenStreetMap Nominatim API. Converts place names to coordinates. No API key required. Works offline with a fallback dictionary of Indian cities. """ import requests import json import os # Offline fallback: major Indian cities + water bodies OFFLINE_LOCATIONS = { 'silchar': (24.81, 92.80), 'guwahati': (26.14, 91.74), 'delhi': (28.61, 77.23), 'mumbai': (19.08, 72.88), 'chennai': (13.08, 80.27), 'kolkata': (22.57, 88.36), 'bengaluru': (12.97, 77.59), 'varanasi': (25.32, 83.01), 'haridwar': (29.95, 78.16), 'rishikesh': (30.09, 78.27), 'srinagar': (34.08, 74.80), 'dal lake': (34.11, 74.86), 'barak river': (24.80, 92.82), 'ganga river varanasi': (25.30, 83.01), 'yamuna river delhi': (28.66, 77.23), 'brahmaputra guwahati': (26.18, 91.75), 'chilika lake': (19.72, 85.31), 'loktak lake': (24.55, 93.83), 'vembanad lake': (9.58, 76.42), } def search_location(query: str) -> dict: """ Search for a location by name. Returns {'name': str, 'lat': float, 'lon': float, 'source': str} or {'error': str} """ query = query.strip().lower() # Check offline cache first if query in OFFLINE_LOCATIONS: lat, lon = OFFLINE_LOCATIONS[query] return {'name': query.title(), 'lat': lat, 'lon': lon, 'source': 'offline_cache'} # Partial match in offline cache for key, (lat, lon) in OFFLINE_LOCATIONS.items(): if query in key or key in query: return {'name': key.title(), 'lat': lat, 'lon': lon, 'source': 'offline_partial_match'} # Try OpenStreetMap Nominatim (free, no key needed) try: url = 'https://nominatim.openstreetmap.org/search' params = { 'q': query, 'format': 'json', 'limit': 3, 'countrycodes': 'in' # Bias toward India } headers = {'User-Agent': 'Divine-Earthly-Water-Guardian/1.0'} resp = requests.get(url, params=params, headers=headers, timeout=10) if resp.status_code == 200 and resp.json(): results = resp.json() best = results[0] return { 'name': best.get('display_name', query), 'lat': float(best['lat']), 'lon': float(best['lon']), 'source': 'openstreetmap', 'all_results': [ {'name': r['display_name'], 'lat': float(r['lat']), 'lon': float(r['lon'])} for r in results[:3] ] } except Exception as e: pass return {'error': f'Location "{query}" not found. Try a nearby city or lat/lon manually.'} if __name__ == '__main__': # Test for q in ['Silchar', 'Dal Lake', 'Varanasi Ganga', 'NonexistentPlace']: print(f'{q}:', search_location(q))