diff --git a/core/sig_utils.py b/core/sig_utils.py index b788bb3..151a100 100644 --- a/core/sig_utils.py +++ b/core/sig_utils.py @@ -6,7 +6,6 @@ from pyhamtools.locator import latlong_to_locator from core.cache_utils import SEMI_STATIC_URL_DATA_CACHE from core.constants import SIGS, HTTP_HEADERS from core.geo_utils import wab_wai_square_to_lat_lon -from data.sig_ref import SIGRef # Utility function to get the icon for a named SIG. If no match is found, the "circle-question" icon will be returned. @@ -25,46 +24,51 @@ def get_ref_regex_for_sig(sig): return None -# Look up details of a SIG reference (e.g. POTA park) such as name, lat/lon, and grid. +# Look up details of a SIG reference (e.g. POTA park) such as name, lat/lon, and grid. Takes in a sig_ref object which +# must at minimum have a "sig" and an "id". The rest of the object will be populated and returned. # Note there is currently no support for KRMNPA location lookup, see issue #61. -def get_sig_ref_info(sig, sig_ref_id): - sig_ref = SIGRef(id=sig_ref_id, sig=sig) +def populate_sig_ref_info(sig_ref): + if sig_ref.sig is None or sig_ref.id is None: + logging.warn("Failed to look up sig_ref info, sig or id were not set.") + + sig = sig_ref.sig + ref_id = sig_ref.id try: if sig.upper() == "POTA": - data = SEMI_STATIC_URL_DATA_CACHE.get("https://api.pota.app/park/" + sig_ref_id, headers=HTTP_HEADERS).json() + data = SEMI_STATIC_URL_DATA_CACHE.get("https://api.pota.app/park/" + ref_id, headers=HTTP_HEADERS).json() if data: fullname = data["name"] if "name" in data else None if fullname and "parktypeDesc" in data and data["parktypeDesc"] != "": fullname = fullname + " " + data["parktypeDesc"] sig_ref.name = fullname - sig_ref.url = "https://pota.app/#/park/" + sig_ref_id + sig_ref.url = "https://pota.app/#/park/" + ref_id sig_ref.grid = data["grid6"] if "grid6" in data else None sig_ref.latitude = data["latitude"] if "latitude" in data else None sig_ref.longitude = data["longitude"] if "longitude" in data else None elif sig.upper() == "SOTA": - data = SEMI_STATIC_URL_DATA_CACHE.get("https://api-db2.sota.org.uk/api/summits/" + sig_ref_id, + data = SEMI_STATIC_URL_DATA_CACHE.get("https://api-db2.sota.org.uk/api/summits/" + ref_id, headers=HTTP_HEADERS).json() if data: sig_ref.name = data["name"] if "name" in data else None - sig_ref.url = "https://www.sotadata.org.uk/en/summit/" + sig_ref_id + sig_ref.url = "https://www.sotadata.org.uk/en/summit/" + ref_id sig_ref.grid = data["locator"] if "locator" in data else None sig_ref.latitude = data["latitude"] if "latitude" in data else None sig_ref.longitude = data["longitude"] if "longitude" in data else None elif sig.upper() == "WWBOTA": - data = SEMI_STATIC_URL_DATA_CACHE.get("https://api.wwbota.org/bunkers/" + sig_ref_id, + data = SEMI_STATIC_URL_DATA_CACHE.get("https://api.wwbota.org/bunkers/" + ref_id, headers=HTTP_HEADERS).json() if data: sig_ref.name = data["name"] if "name" in data else None - sig_ref.url = "https://bunkerwiki.org/?s=" + sig_ref_id if sig_ref_id.startswith("B/G") else None + sig_ref.url = "https://bunkerwiki.org/?s=" + ref_id if ref_id.startswith("B/G") else None sig_ref.grid = data["locator"] if "locator" in data else None sig_ref.latitude = data["lat"] if "lat" in data else None sig_ref.longitude = data["long"] if "long" in data else None elif sig.upper() == "GMA" or sig.upper() == "ARLHS" or sig.upper() == "ILLW" or sig.upper() == "WCA" or sig.upper() == "MOTA" or sig.upper() == "IOTA": - data = SEMI_STATIC_URL_DATA_CACHE.get("https://www.cqgma.org/api/ref/?" + sig_ref_id, + data = SEMI_STATIC_URL_DATA_CACHE.get("https://www.cqgma.org/api/ref/?" + ref_id, headers=HTTP_HEADERS).json() if data: sig_ref.name = data["name"] if "name" in data else None - sig_ref.url = "https://www.cqgma.org/zinfo.php?ref=" + sig_ref_id + sig_ref.url = "https://www.cqgma.org/zinfo.php?ref=" + ref_id sig_ref.grid = data["locator"] if "locator" in data else None sig_ref.latitude = data["latitude"] if "latitude" in data else None sig_ref.longitude = data["longitude"] if "longitude" in data else None @@ -73,9 +77,9 @@ def get_sig_ref_info(sig, sig_ref_id): headers=HTTP_HEADERS) wwff_dr = csv.DictReader(wwff_csv_data.content.decode().splitlines()) for row in wwff_dr: - if row["reference"] == sig_ref_id: + if row["reference"] == ref_id: sig_ref.name = row["name"] if "name" in row else None - sig_ref.url = "https://wwff.co/directory/?showRef=" + sig_ref_id + sig_ref.url = "https://wwff.co/directory/?showRef=" + ref_id sig_ref.grid = row["iaruLocator"] if "iaruLocator" in row else None sig_ref.latitude = float(row["latitude"]) if "latitude" in row else None sig_ref.longitude = float(row["longitude"]) if "longitude" in row else None @@ -85,7 +89,7 @@ def get_sig_ref_info(sig, sig_ref_id): headers=HTTP_HEADERS) siota_dr = csv.DictReader(siota_csv_data.content.decode().splitlines()) for row in siota_dr: - if row["SILO_CODE"] == sig_ref_id: + if row["SILO_CODE"] == ref_id: sig_ref.name = row["NAME"] if "NAME" in row else None sig_ref.grid = row["LOCATOR"] if "LOCATOR" in row else None sig_ref.latitude = float(row["LAT"]) if "LAT" in row else None @@ -96,13 +100,13 @@ def get_sig_ref_info(sig, sig_ref_id): headers=HTTP_HEADERS).json() if data: for feature in data["features"]: - if feature["properties"]["wotaId"] == sig_ref_id: + if feature["properties"]["wotaId"] == ref_id: sig_ref.name = feature["properties"]["title"] # Fudge WOTA URLs. Outlying fell (LDO) URLs don't match their ID numbers but require 214 to be # added to them - sig_ref.url = "https://www.wota.org.uk/MM_" + sig_ref_id - if sig_ref_id.upper().startswith("LDO-"): - number = int(sig_ref_id.upper().replace("LDO-", "")) + sig_ref.url = "https://www.wota.org.uk/MM_" + ref_id + if ref_id.upper().startswith("LDO-"): + number = int(ref_id.upper().replace("LDO-", "")) sig_ref.url = "https://www.wota.org.uk/MM_LDO-" + str(number + 214) sig_ref.grid = feature["properties"]["qthLocator"] sig_ref.latitude = feature["geometry"]["coordinates"][1] @@ -112,9 +116,9 @@ def get_sig_ref_info(sig, sig_ref_id): data = SEMI_STATIC_URL_DATA_CACHE.get("https://ontheair.nz/assets/assets.json", headers=HTTP_HEADERS).json() if data: for asset in data: - if asset["code"] == sig_ref_id: + if asset["code"] == ref_id: sig_ref.name = asset["name"] - sig_ref.url = "https://ontheair.nz/assets/ZLI_OT-030" + sig_ref_id.replace("/", "_") + sig_ref.url = "https://ontheair.nz/assets/ZLI_OT-030" + ref_id.replace("/", "_") sig_ref.grid = latlong_to_locator(asset["y"], asset["x"], 6) sig_ref.latitude = asset["y"] sig_ref.longitude = asset["x"] @@ -124,14 +128,14 @@ def get_sig_ref_info(sig, sig_ref_id): sig_ref.name = sig_ref.id sig_ref.url = "https://www.beachesontheair.com/beaches/" + sig_ref.name.lower().replace(" ", "-") elif sig.upper() == "WAB" or sig.upper() == "WAI": - ll = wab_wai_square_to_lat_lon(sig_ref_id) + ll = wab_wai_square_to_lat_lon(ref_id) if ll: - sig_ref.name = sig_ref_id + sig_ref.name = ref_id sig_ref.grid = latlong_to_locator(ll[0], ll[1], 6) sig_ref.latitude = ll[0] sig_ref.longitude = ll[1] except: - logging.warn("Failed to look up sig_ref info for " + sig + " ref " + sig_ref_id + ".") + logging.warn("Failed to look up sig_ref info for " + sig + " ref " + ref_id + ".") return sig_ref diff --git a/data/alert.py b/data/alert.py index d2f9875..17b07f8 100644 --- a/data/alert.py +++ b/data/alert.py @@ -7,7 +7,7 @@ from datetime import datetime, timedelta import pytz from core.lookup_helper import lookup_helper -from core.sig_utils import get_icon_for_sig, get_sig_ref_info +from core.sig_utils import get_icon_for_sig, populate_sig_ref_info # Data class that defines an alert. @@ -102,10 +102,7 @@ class Alert: # from WAB and WAI, which count as a SIG even though there's no real lookup, just maths if self.sig_refs and len(self.sig_refs) > 0: for sig_ref in self.sig_refs: - lookup_data = get_sig_ref_info(sig_ref.sig, sig_ref.id) - if lookup_data: - # Update the sig_ref data from the lookup - sig_ref.__dict__.update(lookup_data.__dict__) + populate_sig_ref_info(sig_ref) # If the spot itself doesn't have a SIG yet, but we have at least one SIG reference, take that reference's SIG # and apply it to the whole spot. diff --git a/data/spot.py b/data/spot.py index 5a020e6..2b365db 100644 --- a/data/spot.py +++ b/data/spot.py @@ -11,7 +11,7 @@ from pyhamtools.locator import locator_to_latlong, latlong_to_locator from core.config import MAX_SPOT_AGE from core.lookup_helper import lookup_helper -from core.sig_utils import get_icon_for_sig, get_sig_ref_info, ANY_SIG_REGEX, get_ref_regex_for_sig +from core.sig_utils import get_icon_for_sig, populate_sig_ref_info, ANY_SIG_REGEX, get_ref_regex_for_sig from data.sig_ref import SIGRef @@ -279,20 +279,17 @@ class Spot: # from WAB and WAI, which count as a SIG even though there's no real lookup, just maths if self.sig_refs and len(self.sig_refs) > 0: for sig_ref in self.sig_refs: - lookup_data = get_sig_ref_info(sig_ref.sig, sig_ref.id) - if lookup_data: - # Update the sig_ref data from the lookup - sig_ref.__dict__.update(lookup_data.__dict__) - # If the spot itself doesn't have location yet, but the SIG ref does, extract it - if lookup_data.grid and not self.dx_grid: - self.dx_grid = lookup_data.grid - if lookup_data.latitude and not self.dx_latitude: - self.dx_latitude = lookup_data.latitude - self.dx_longitude = lookup_data.longitude - if self.sig == "WAB" or self.sig == "WAI": - self.dx_location_source = "WAB/WAI GRID" - else: - self.dx_location_source = "SIG REF LOOKUP" + sig_ref = populate_sig_ref_info(sig_ref) + # If the spot itself doesn't have location yet, but the SIG ref does, extract it + if sig_ref.grid and not self.dx_grid: + self.dx_grid = sig_ref.grid + if sig_ref.latitude and not self.dx_latitude: + self.dx_latitude = sig_ref.latitude + self.dx_longitude = sig_ref.longitude + if self.sig == "WAB" or self.sig == "WAI": + self.dx_location_source = "WAB/WAI GRID" + else: + self.dx_location_source = "SIG REF LOOKUP" # If the spot itself doesn't have a SIG yet, but we have at least one SIG reference, take that reference's SIG # and apply it to the whole spot. diff --git a/server/webserver.py b/server/webserver.py index b3f869b..884a289 100644 --- a/server/webserver.py +++ b/server/webserver.py @@ -12,7 +12,7 @@ from core.config import MAX_SPOT_AGE, ALLOW_SPOTTING, WEB_UI_OPTIONS from core.constants import BANDS, ALL_MODES, MODE_TYPES, SIGS, CONTINENTS, SOFTWARE_VERSION, UNKNOWN_BAND from core.lookup_helper import lookup_helper from core.prometheus_metrics_handler import page_requests_counter, get_metrics, api_requests_counter -from core.sig_utils import get_ref_regex_for_sig, get_sig_ref_info +from core.sig_utils import get_ref_regex_for_sig, populate_sig_ref_info from data.sig_ref import SIGRef from data.spot import Spot @@ -170,7 +170,7 @@ class WebServer: response.status = 422 return json.dumps("Error - '" + id + "' does not look like a valid reference ID for " + sig + ".", default=serialize_everything) - data = get_sig_ref_info(sig, id) + data = populate_sig_ref_info(SIGRef(id=id, sig=sig)) return self.serve_api(data) except Exception as e: diff --git a/webassets/apidocs/openapi.yml b/webassets/apidocs/openapi.yml index f23cf5f..ef4b8dc 100644 --- a/webassets/apidocs/openapi.yml +++ b/webassets/apidocs/openapi.yml @@ -479,7 +479,8 @@ paths: in: query description: Special Interest Group (SIG), e.g. outdoor activity programme such as POTA required: true - $ref: "#/components/schemas/SIGName" + schema: + $ref: "#/components/schemas/SIGName" - name: id in: query description: ID of a reference in that SIG