- Add GeoLite2-City.mmdb database for IP lookup - Create geoip.py module for IP location services - Extract client IP from requests and log location info - Pass location context to LLM prompts for enhanced responses
57 lines
1.6 KiB
Python
57 lines
1.6 KiB
Python
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 ""
|