From 92af0761aa4a43bee52c024856ec3b9855b93e1c Mon Sep 17 00:00:00 2001 From: Ian Renton Date: Sun, 2 Nov 2025 16:18:33 +0000 Subject: [PATCH] Move checks for multiple references in comments out of POTA and DX Cluster classes into the main infer_missing() function for spots. #54 --- core/sig_utils.py | 2 +- data/spot.py | 43 +++++++++++++++++++++++++++++++++++--- spotproviders/dxcluster.py | 16 -------------- spotproviders/pota.py | 6 ------ 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/core/sig_utils.py b/core/sig_utils.py index 4fe2e13..83d2344 100644 --- a/core/sig_utils.py +++ b/core/sig_utils.py @@ -19,7 +19,7 @@ def get_icon_for_sig(sig): # Utility function to get the regex string for a SIG reference for a named SIG. If no match is found, None will be returned. def get_ref_regex_for_sig(sig): for s in SIGS: - if s.name == sig: + if s.name.upper() == sig.upper(): return s.ref_regex return None diff --git a/data/spot.py b/data/spot.py index 54b0d9a..7679053 100644 --- a/data/spot.py +++ b/data/spot.py @@ -11,7 +11,8 @@ from pyhamtools.locator import locator_to_latlong, latlong_to_locator from core.constants import DXCC_FLAGS 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, get_sig_ref_info, ANY_SIG_REGEX, get_ref_regex_for_sig +from data.sig_ref import SIGRef # Data class that defines a spot. @@ -235,6 +236,33 @@ class Spot: if self.dx_latitude: self.dx_location_source = "SPOT" + # See if we already have a SIG reference, but the comment looks like it contains more for the same SIG. This + # should catch e.g. POTA comments like "2-fer: GB-0001 GB-0002". + if self.sig_refs and len(self.sig_refs) > 0: + sig = self.sig_refs[0].sig.upper() + all_comment_refs = re.findall(get_ref_regex_for_sig(sig), self.comment) + for ref in all_comment_refs: + self.append_sig_ref_if_missing(SIGRef(id=ref.upper(), sig=sig)) + + # See if the comment looks like it contains any SIGs (and optionally SIG references) that we can + # add to the spot. This should catch cluster spot comments like "POTA GB-0001 WWFF GFF-0001" and e.g. POTA + # comments like "also WWFF GFF-0001". + sig_matches = re.finditer(r"(^|\W)" + ANY_SIG_REGEX + r"($|\W)", self.comment, re.IGNORECASE) + for sig_match in sig_matches: + # First of all, if we haven't got a SIG for this spot set yet, now we have. This covers things like cluster + # spots where the comment is just "POTA". + found_sig = sig_match.group(2).upper() + if not self.sig: + self.sig = found_sig + + # Now look to see if that SIG name was followed by something that looks like a reference ID for that SIG. + # If so, add that to the sig_refs list for this spot. + ref_regex = get_ref_regex_for_sig(found_sig) + if ref_regex: + ref_matches = re.finditer(r"(^|\W)" + found_sig + r"($|\W)(" + ref_regex + r")($|\W)", self.comment, re.IGNORECASE) + for ref_match in ref_matches: + self.append_sig_ref_if_missing(SIGRef(id=ref_match.group(3).upper(), sig=found_sig)) + # Fetch SIG data. In case a particular API doesn't provide a full set of name, lat, lon & grid for a reference # in its initial call, we use this code to populate the rest of the data. This includes working out grid refs # from WAB and WAI, which count as a SIG even though there's no real lookup, just maths @@ -260,8 +288,8 @@ class Spot: if self.sig_refs and len(self.sig_refs) > 0 and not self.sig: self.sig = self.sig_refs[0].sig - # Icon from SIG - if self.sig and not self.icon: + # Icon from SIG if we have one + if self.sig: self.icon = get_icon_for_sig(self.sig) # DX Grid to lat/lon and vice versa in case one is missing @@ -338,3 +366,12 @@ class Spot: # JSON serialise def to_json(self): return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True) + + # Append a sig_ref to the list, so long as it's not already there. + def append_sig_ref_if_missing(self, new_sig_ref): + if not self.sig_refs: + self.sig_refs = [] + for sig_ref in self.sig_refs: + if sig_ref.id.upper() == new_sig_ref.id.upper() and sig_ref.sig.upper() == new_sig_ref.sig.upper(): + return + self.sig_refs.append(new_sig_ref) diff --git a/spotproviders/dxcluster.py b/spotproviders/dxcluster.py index d37770c..56304d5 100644 --- a/spotproviders/dxcluster.py +++ b/spotproviders/dxcluster.py @@ -8,8 +8,6 @@ import pytz import telnetlib3 from core.config import SERVER_OWNER_CALLSIGN -from core.sig_utils import ANY_SIG_REGEX, get_ref_regex_for_sig -from data.sig_ref import SIGRef from data.spot import Spot from spotproviders.spot_provider import SpotProvider @@ -77,20 +75,6 @@ class DXCluster(SpotProvider): icon="desktop", time=spot_datetime.timestamp()) - # See if the comment looks like it contains a SIG (and optionally SIG reference). Currently, - # only one sig ref is supported. Note that this code is specifically in the DX Cluster class and - # not in the general "spot" infer_missing() method. Because we only support one SIG per spot - # at the moment (see issue #54), we don't want to risk e.g. a POTA spot with comment "WWFF GFF-0001" - # being converted into a WWFF spot. - sig_match = re.search(r"(^|\W)" + ANY_SIG_REGEX + r"($|\W)", spot.comment, re.IGNORECASE) - if sig_match: - spot.sig = sig_match.group(2).upper() - ref_regex = get_ref_regex_for_sig(spot.sig) - if ref_regex: - sig_ref_match = re.search(r"(^|\W)" + spot.sig + r"($|\W)(" + ref_regex + r")($|\W)", spot.comment, re.IGNORECASE) - if sig_ref_match: - spot.sig_refs = [SIGRef(id=sig_ref_match.group(3).upper(), sig=spot.sig)] - # Add to our list self.submit(spot) diff --git a/spotproviders/pota.py b/spotproviders/pota.py index 623c341..03eb47d 100644 --- a/spotproviders/pota.py +++ b/spotproviders/pota.py @@ -38,12 +38,6 @@ class POTA(HTTPSpotProvider): dx_latitude=source_spot["latitude"], dx_longitude=source_spot["longitude"]) - # Sometimes we can get other refs in the comments for n-fer activations, extract them - all_comment_refs = re.findall(get_ref_regex_for_sig("POTA"), spot.comment) - for r in all_comment_refs: - if r not in list(map(lambda ref: ref.id, spot.sig_refs)): - spot.sig_refs.append(SIGRef(id=r.upper(), sig="POTA")) - # Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do # that for us. new_spots.append(spot)