import os import logging from typing import Optional logger = logging.getLogger("api") _geoip_reader = None def _get_reader(): global _geoip_reader if _geoip_reader is not None: return _geoip_reader try: import geoip2.database db_path = os.path.join(os.path.dirname(__file__), "GeoLite2-City.mmdb") if os.path.exists(db_path): _geoip_reader = geoip2.database.Reader(db_path) logger.info("GeoIP database loaded: %s", db_path) return _geoip_reader else: logger.warning("GeoIP database not found: %s", db_path) except ImportError: logger.warning("geoip2 not installed, IP location disabled") except Exception as e: logger.warning("Failed to load GeoIP database: %s", e) return None def get_ip_location(ip: str) -> Optional[dict]: if not ip or ip in ("127.0.0.1", "localhost", "::1"): return None reader = _get_reader() if not reader: return None try: response = reader.city(ip) country = response.country.name region = response.subdivisions.most_specific.name if response.subdivisions else None city = response.city.name parts = [p for p in [country, region, city] if p] if not parts: return None return { "country": country, "region": region, "city": city, "display": " ".join(parts) } except Exception: return None def get_ip_location_text(ip: str) -> str: loc = get_ip_location(ip) return loc["display"] if loc else ""