diff --git a/homeassistant/util/location.py b/homeassistant/util/location.py index 16aec2ec617..f77d1752d6a 100644 --- a/homeassistant/util/location.py +++ b/homeassistant/util/location.py @@ -10,8 +10,8 @@ from typing import Any, Optional, Tuple, Dict import requests ELEVATION_URL = 'http://maps.googleapis.com/maps/api/elevation/json' -FREEGEO_API = 'https://freegeoip.net/json/' IP_API = 'http://ip-api.com/json' +IPAPI = 'https://ipapi.co/json/' # Constants from https://github.com/maurycyp/vincenty # Earth ellipsoid according to WGS 84 @@ -35,7 +35,7 @@ LocationInfo = collections.namedtuple( def detect_location_info() -> Optional[LocationInfo]: """Detect location information.""" - data = _get_freegeoip() + data = _get_ipapi() if data is None: data = _get_ip_api() @@ -159,22 +159,22 @@ def vincenty(point1: Tuple[float, float], point2: Tuple[float, float], return round(s, 6) -def _get_freegeoip() -> Optional[Dict[str, Any]]: - """Query freegeoip.io for location data.""" +def _get_ipapi() -> Optional[Dict[str, Any]]: + """Query ipapi.co for location data.""" try: - raw_info = requests.get(FREEGEO_API, timeout=5).json() + raw_info = requests.get(IPAPI, timeout=5).json() except (requests.RequestException, ValueError): return None return { 'ip': raw_info.get('ip'), - 'country_code': raw_info.get('country_code'), + '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_name'), + 'region_name': raw_info.get('region'), 'city': raw_info.get('city'), - 'zip_code': raw_info.get('zip_code'), - 'time_zone': raw_info.get('time_zone'), + 'zip_code': raw_info.get('postal'), + 'time_zone': raw_info.get('timezone'), 'latitude': raw_info.get('latitude'), 'longitude': raw_info.get('longitude'), } diff --git a/tests/fixtures/freegeoip.io.json b/tests/fixtures/freegeoip.io.json deleted file mode 100644 index 8afdaba070e..00000000000 --- a/tests/fixtures/freegeoip.io.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "ip": "1.2.3.4", - "country_code": "US", - "country_name": "United States", - "region_code": "CA", - "region_name": "California", - "city": "San Diego", - "zip_code": "92122", - "time_zone": "America\/Los_Angeles", - "latitude": 32.8594, - "longitude": -117.2073, - "metro_code": 825 -} diff --git a/tests/fixtures/ipapi.co.json b/tests/fixtures/ipapi.co.json new file mode 100644 index 00000000000..f1dc58a756b --- /dev/null +++ b/tests/fixtures/ipapi.co.json @@ -0,0 +1,20 @@ +{ + "ip": "1.2.3.4", + "city": "Bern", + "region": "Bern", + "region_code": "BE", + "country": "CH", + "country_name": "Switzerland", + "continent_code": "EU", + "in_eu": false, + "postal": "3000", + "latitude": 46.9480278, + "longitude": 7.4490812, + "timezone": "Europe/Zurich", + "utc_offset": "+0100", + "country_calling_code": "+41", + "currency": "CHF", + "languages": "de-CH,fr-CH,it-CH,rm", + "asn": "AS6830", + "org": "Liberty Global B.V." +} \ No newline at end of file diff --git a/tests/util/test_location.py b/tests/util/test_location.py index d83979affd0..7d0df7edb18 100644 --- a/tests/util/test_location.py +++ b/tests/util/test_location.py @@ -30,62 +30,59 @@ class TestLocationUtil(TestCase): def test_get_distance_to_same_place(self): """Test getting the distance.""" - meters = location_util.distance(COORDINATES_PARIS[0], - COORDINATES_PARIS[1], - COORDINATES_PARIS[0], - COORDINATES_PARIS[1]) + meters = location_util.distance( + COORDINATES_PARIS[0], COORDINATES_PARIS[1], + COORDINATES_PARIS[0], COORDINATES_PARIS[1]) assert meters == 0 def test_get_distance(self): """Test getting the distance.""" - meters = location_util.distance(COORDINATES_PARIS[0], - COORDINATES_PARIS[1], - COORDINATES_NEW_YORK[0], - COORDINATES_NEW_YORK[1]) + meters = location_util.distance( + COORDINATES_PARIS[0], COORDINATES_PARIS[1], + COORDINATES_NEW_YORK[0], COORDINATES_NEW_YORK[1]) assert meters/1000 - DISTANCE_KM < 0.01 def test_get_kilometers(self): """Test getting the distance between given coordinates in km.""" - kilometers = location_util.vincenty(COORDINATES_PARIS, - COORDINATES_NEW_YORK) + kilometers = location_util.vincenty( + COORDINATES_PARIS, COORDINATES_NEW_YORK) assert round(kilometers, 2) == DISTANCE_KM def test_get_miles(self): """Test getting the distance between given coordinates in miles.""" - miles = location_util.vincenty(COORDINATES_PARIS, - COORDINATES_NEW_YORK, - miles=True) + miles = location_util.vincenty( + COORDINATES_PARIS, COORDINATES_NEW_YORK, miles=True) assert round(miles, 2) == DISTANCE_MILES @requests_mock.Mocker() - def test_detect_location_info_freegeoip(self, m): - """Test detect location info using freegeoip.""" - m.get(location_util.FREEGEO_API, - text=load_fixture('freegeoip.io.json')) + def test_detect_location_info_ipapi(self, m): + """Test detect location info using ipapi.co.""" + m.get( + location_util.IPAPI, text=load_fixture('ipapi.co.json')) info = location_util.detect_location_info(_test_real=True) assert info is not None assert info.ip == '1.2.3.4' - assert info.country_code == 'US' - assert info.country_name == 'United States' - assert info.region_code == 'CA' - assert info.region_name == 'California' - assert info.city == 'San Diego' - assert info.zip_code == '92122' - assert info.time_zone == 'America/Los_Angeles' - assert info.latitude == 32.8594 - assert info.longitude == -117.2073 - assert not info.use_metric + assert info.country_code == 'CH' + assert info.country_name == 'Switzerland' + assert info.region_code == 'BE' + assert info.region_name == 'Bern' + assert info.city == 'Bern' + assert info.zip_code == '3000' + assert info.time_zone == 'Europe/Zurich' + assert info.latitude == 46.9480278 + assert info.longitude == 7.4490812 + assert info.use_metric @requests_mock.Mocker() - @patch('homeassistant.util.location._get_freegeoip', return_value=None) - def test_detect_location_info_ipapi(self, mock_req, mock_freegeoip): - """Test detect location info using freegeoip.""" - mock_req.get(location_util.IP_API, - text=load_fixture('ip-api.com.json')) + @patch('homeassistant.util.location._get_ipapi', return_value=None) + def test_detect_location_info_ip_api(self, mock_req, mock_ipapi): + """Test detect location info using ip-api.com.""" + mock_req.get( + location_util.IP_API, text=load_fixture('ip-api.com.json')) info = location_util.detect_location_info(_test_real=True) @@ -103,11 +100,10 @@ class TestLocationUtil(TestCase): assert not info.use_metric @patch('homeassistant.util.location.elevation', return_value=0) - @patch('homeassistant.util.location._get_freegeoip', return_value=None) + @patch('homeassistant.util.location._get_ipapi', return_value=None) @patch('homeassistant.util.location._get_ip_api', return_value=None) - def test_detect_location_info_both_queries_fail(self, mock_ipapi, - mock_freegeoip, - mock_elevation): + def test_detect_location_info_both_queries_fail( + self, mock_ipapi, mock_ip_api, mock_elevation): """Ensure we return None if both queries fail.""" info = location_util.detect_location_info(_test_real=True) assert info is None @@ -115,8 +111,8 @@ class TestLocationUtil(TestCase): @patch('homeassistant.util.location.requests.get', side_effect=requests.RequestException) def test_freegeoip_query_raises(self, mock_get): - """Test freegeoip query when the request to API fails.""" - info = location_util._get_freegeoip() + """Test ipapi.co query when the request to API fails.""" + info = location_util._get_ipapi() assert info is None @patch('homeassistant.util.location.requests.get',