From b2d5265f7e81835dca206158038f5078ec830ad0 Mon Sep 17 00:00:00 2001 From: moanos Date: Tue, 7 Jan 2025 12:48:01 +0100 Subject: [PATCH] feat: Use photon for querying --- notfellchen.cfg | 3 ++ src/fellchensammlung/tools/geo.py | 71 ++++++++++++++++++++++++------- src/notfellchen/settings.py | 3 ++ 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/notfellchen.cfg b/notfellchen.cfg index 1cb847e..525c935 100644 --- a/notfellchen.cfg +++ b/notfellchen.cfg @@ -24,4 +24,7 @@ console-only=true app_log_level=INFO django_log_level=INFO +[geocoding] +api_url=https://photon.hyteck.de/api +api_format=photon diff --git a/src/fellchensammlung/tools/geo.py b/src/fellchensammlung/tools/geo.py index 87e1b97..760998f 100644 --- a/src/fellchensammlung/tools/geo.py +++ b/src/fellchensammlung/tools/geo.py @@ -25,6 +25,7 @@ def zoom_level_for_radius(radius) -> int: else: return 4 + def calculate_distance_between_coordinates(position1, position2): """ Calculate the distance between two points identified by coordinates @@ -66,8 +67,41 @@ class RequestMock: return ResponseMock() +class GeoFeature: + + @staticmethod + def geofeatures_from_photon_result(result): + geofeatures = [] + for feature in result["features"]: + geojson = {} + geojson['name'] = feature["properties"]["name"] + geojson['place_id'] = feature["properties"]["osm_id"] + geojson['lat'] = feature["geometry"]["coordinates"][1] + geojson['lon'] = feature["geometry"]["coordinates"][0] + geofeatures.append(geojson) + return geofeatures + + @staticmethod + def geofeatures_from_nominatim_result(result): + geofeatures = [] + for feature in result: + geojson = {} + if "name" in feature: + geojson['name'] = feature["name"] + else: + geojson['name'] = feature["display_name"] + geojson['place_id'] = feature["place_id"] + geojson['lat'] = feature["lat"] + geojson['lon'] = feature["lon"] + geofeatures.append(geojson) + return geofeatures + + class GeoAPI: api_url = settings.GEOCODING_API_URL + api_format = settings.GEOCODING_API_FORMAT + assert api_format in ['nominatim', 'photon'] + # Set User-Agent headers as required by most usage policies (and it's the nice thing to do) headers = { 'User-Agent': f"Notfellchen {nf_version}", @@ -88,17 +122,27 @@ class GeoAPI: def get_geojson_for_query(self, location_string): try: - result = self.requests.get(self.api_url, - {"q": location_string, - "format": "jsonv2"}, - headers=self.headers).json() + if self.api_format == 'nominatim': + result = self.requests.get(self.api_url, + {"q": location_string, + "format": "jsonv2"}, + headers=self.headers).json() + geofeatures = GeoFeature.geofeatures_from_nominatim_result(result) + elif self.api_format == 'photon': + result = self.requests.get(self.api_url, + {"q": location_string}, + headers=self.headers).json() + geofeatures = GeoFeature.geofeatures_from_photon_result(result) + else: + raise NotImplementedError + except Exception as e: - logging.warning(f"Exception {e} when querying Nominatim") + logging.warning(f"Exception {e} when querying geocoding server") return None - if len(result) == 0: - logging.warning(f"Couldn't find a result for {location_string} when querying Nominatim") + if len(geofeatures) == 0: + logging.warning(f"Couldn't find a result for {location_string} when querying geocoding server") return None - return result + return geofeatures class LocationProxy: @@ -111,14 +155,11 @@ class LocationProxy: Creates the location proxy from the location string """ self.geo_api = GeoAPI() - geojson = self.geo_api.get_geojson_for_query(location_string) - if geojson is None: + geofeatures = self.geo_api.get_geojson_for_query(location_string) + if geofeatures is None: raise ValueError - result = geojson[0] - if "name" in result: - self.name = result["name"] - else: - self.name = result["display_name"] + result = geofeatures[0] + self.name = result["name"] self.place_id = result["place_id"] self.latitude = result["lat"] self.longitude = result["lon"] diff --git a/src/notfellchen/settings.py b/src/notfellchen/settings.py index 5551c96..cd63595 100644 --- a/src/notfellchen/settings.py +++ b/src/notfellchen/settings.py @@ -90,6 +90,9 @@ HEALTHCHECKS_URL = config.get("monitoring", "healthchecks_url", fallback=None) """ GEOCODING """ GEOCODING_API_URL = config.get("geocoding", "api_url", fallback="https://nominatim.hyteck.de/search") +# GEOCODING_API_FORMAT is allowed to be one of ['nominatim', 'photon'] +GEOCODING_API_FORMAT = config.get("geocoding", "api_format", fallback="nominatim") + """ Tile Server """ MAP_TILE_SERVER = config.get("map", "tile_server", fallback="https://tiles.hyteck.de")