Fix ipapi.is response parsing: handle flat string format
docker-build-push / build-push (push) Successful in 25s
docker-build-push / build-push (push) Successful in 25s
ipapi.is free tier returns company/asn as flat strings ("Google LLC",
"AS15169 Google LLC") not nested dicts. The old code assumed nested
objects and crashed with AttributeError when trying to call .get() on
strings. This broke IP-based signup scrutiny for every new signup.
Now handles both formats (string and dict) for backward compat. Route
field handling also simplified since free tier doesn't nest asn data.
Fixes signup accounts falling through without IP classification.
This commit is contained in:
+16
-3
@@ -937,16 +937,29 @@ def classify_signup_ip(ip: str) -> tuple[str, str, bool, str]:
|
|||||||
log.warning("ipapi.is lookup failed for ip=%s: %s", ip, exc)
|
log.warning("ipapi.is lookup failed for ip=%s: %s", ip, exc)
|
||||||
bounds = _ip_range_bounds(ip)
|
bounds = _ip_range_bounds(ip)
|
||||||
return "unknown", "", False, bounds[3] if bounds else f"{ip}/32"
|
return "unknown", "", False, bounds[3] if bounds else f"{ip}/32"
|
||||||
|
# ipapi.is returns company/asn as flat strings, not nested dicts
|
||||||
|
company = data.get("company")
|
||||||
|
org_name = company if isinstance(company, str) else (company or {}).get("name", "")
|
||||||
|
|
||||||
|
if not org_name:
|
||||||
|
asn_str = data.get("asn", "")
|
||||||
|
if isinstance(asn_str, str) and " " in asn_str:
|
||||||
|
org_name = asn_str.split(" ", 1)[1] # "AS15169 Google LLC" → "Google LLC"
|
||||||
|
|
||||||
|
asn_obj = data.get("asn")
|
||||||
|
if isinstance(asn_obj, dict):
|
||||||
|
route = asn_obj.get("route", "")
|
||||||
|
else:
|
||||||
|
route = "" # ipapi.is free tier returns asn as string, not nested object
|
||||||
|
|
||||||
intel = {
|
intel = {
|
||||||
"is_datacenter": bool(data.get("is_datacenter")),
|
"is_datacenter": bool(data.get("is_datacenter")),
|
||||||
"is_vpn": bool(data.get("is_vpn")),
|
"is_vpn": bool(data.get("is_vpn")),
|
||||||
"is_proxy": bool(data.get("is_proxy")),
|
"is_proxy": bool(data.get("is_proxy")),
|
||||||
"is_tor": bool(data.get("is_tor")),
|
"is_tor": bool(data.get("is_tor")),
|
||||||
"is_abuser": bool(data.get("is_abuser")),
|
"is_abuser": bool(data.get("is_abuser")),
|
||||||
"org": ((data.get("company") or {}).get("name")
|
"org": org_name,
|
||||||
or (data.get("asn") or {}).get("org") or ""),
|
|
||||||
}
|
}
|
||||||
route = (data.get("asn") or {}).get("route") or ""
|
|
||||||
bounds = _ip_range_bounds(ip, route)
|
bounds = _ip_range_bounds(ip, route)
|
||||||
intel["cidr"] = bounds[3] if bounds else f"{ip}/32"
|
intel["cidr"] = bounds[3] if bounds else f"{ip}/32"
|
||||||
cache_ip_intel(ip, intel, route)
|
cache_ip_intel(ip, intel, route)
|
||||||
|
|||||||
Reference in New Issue
Block a user