Use whoami for location lookup (#50934)

This commit is contained in:
Joakim Sørensen
2021-05-23 05:34:48 +02:00
committed by GitHub
parent 0cbcb9e0d6
commit 7ff14b47a8
11 changed files with 121 additions and 152 deletions

View File

@@ -12,9 +12,7 @@ from typing import Any
import aiohttp
ELEVATION_URL = "https://api.open-elevation.com/api/v1/lookup"
IP_API = "http://ip-api.com/json"
IPAPI = "https://ipapi.co/json/"
WHOAMI_URL = "https://whoami.home-assistant.io/v1"
# Constants from https://github.com/maurycyp/vincenty
# Earth ellipsoid according to WGS 84
@@ -34,7 +32,6 @@ LocationInfo = collections.namedtuple(
[
"ip",
"country_code",
"country_name",
"region_code",
"region_name",
"city",
@@ -51,10 +48,7 @@ async def async_detect_location_info(
session: aiohttp.ClientSession,
) -> LocationInfo | None:
"""Detect location information."""
data = await _get_ipapi(session)
if data is None:
data = await _get_ip_api(session)
data = await _get_whoami(session)
if data is None:
return None
@@ -164,10 +158,10 @@ def vincenty(
return round(s, 6)
async def _get_ipapi(session: aiohttp.ClientSession) -> dict[str, Any] | None:
"""Query ipapi.co for location data."""
async def _get_whoami(session: aiohttp.ClientSession) -> dict[str, Any] | None:
"""Query whoami.home-assistant.io for location data."""
try:
resp = await session.get(IPAPI, timeout=5)
resp = await session.get(WHOAMI_URL, timeout=30)
except (aiohttp.ClientError, asyncio.TimeoutError):
return None
@@ -176,44 +170,14 @@ async def _get_ipapi(session: aiohttp.ClientSession) -> dict[str, Any] | None:
except (aiohttp.ClientError, ValueError):
return None
# ipapi allows 30k free requests/month. Some users exhaust those.
if raw_info.get("latitude") == "Sign up to access":
return None
return {
"ip": raw_info.get("ip"),
"country_code": raw_info.get("country"),
"country_name": raw_info.get("country_name"),
"region_code": raw_info.get("region_code"),
"region_name": raw_info.get("region"),
"city": raw_info.get("city"),
"zip_code": raw_info.get("postal"),
"zip_code": raw_info.get("postal_code"),
"time_zone": raw_info.get("timezone"),
"latitude": raw_info.get("latitude"),
"longitude": raw_info.get("longitude"),
}
async def _get_ip_api(session: aiohttp.ClientSession) -> dict[str, Any] | None:
"""Query ip-api.com for location data."""
try:
resp = await session.get(IP_API, timeout=5)
except (aiohttp.ClientError, asyncio.TimeoutError):
return None
try:
raw_info = await resp.json()
except (aiohttp.ClientError, ValueError):
return None
return {
"ip": raw_info.get("query"),
"country_code": raw_info.get("countryCode"),
"country_name": raw_info.get("country"),
"region_code": raw_info.get("region"),
"region_name": raw_info.get("regionName"),
"city": raw_info.get("city"),
"zip_code": raw_info.get("zip"),
"time_zone": raw_info.get("timezone"),
"latitude": raw_info.get("lat"),
"longitude": raw_info.get("lon"),
"latitude": float(raw_info.get("latitude")),
"longitude": float(raw_info.get("longitude")),
}