mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-09-25 08:44:33 +00:00
Strict adherence to canonical ActivityNames, to avoid the problem where Spothole was giving out activities like ["Towers", "TOWERS"]. All uses of ActivityName should now be canonical not arbitrary strings, and attempts to convert unknown strings to activitynames will be logged for me to check out.
This commit is contained in:
@@ -3,6 +3,7 @@ from datetime import datetime
|
||||
|
||||
import pytz
|
||||
|
||||
from core.activity_utils import get_activity_by_name
|
||||
from core.enums import ActivityName
|
||||
from data.activity_ref import ActivityRef
|
||||
from data.alert import Alert
|
||||
@@ -37,7 +38,13 @@ class ParksNPeaks(HTTPAlertProvider):
|
||||
datetime.strptime(source_alert["alTime"], "%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC).timestamp()
|
||||
)
|
||||
|
||||
activity_refs = [ActivityRef(id=ref_id, activity=activity, name=ref_name)]
|
||||
# We can only add a reference if we know the activity it's for
|
||||
found_activity = get_activity_by_name(activity)
|
||||
activities = []
|
||||
activity_refs = []
|
||||
if found_activity is not None:
|
||||
activities = [found_activity.name]
|
||||
activity_refs = [ActivityRef(id=ref_id, activity=found_activity.name, name=ref_name)]
|
||||
|
||||
# Convert to our alert format
|
||||
alert = Alert(
|
||||
@@ -46,26 +53,11 @@ class ParksNPeaks(HTTPAlertProvider):
|
||||
dx_calls=[source_alert["CallSign"].upper()],
|
||||
freqs_modes=f"{source_alert['Freq']} {source_alert['MODE']}",
|
||||
comment=source_alert["Comments"],
|
||||
activities=[activity] if activity else [],
|
||||
activities=activities,
|
||||
activity_refs=activity_refs,
|
||||
start_time=start_time,
|
||||
)
|
||||
|
||||
# Log a warning for the developer if PnP gives us an unknown programme we've never seen before
|
||||
if activity and activity not in [
|
||||
ActivityName.POTA,
|
||||
ActivityName.SOTA,
|
||||
ActivityName.WWFF,
|
||||
ActivityName.HEMA,
|
||||
ActivityName.SIOTA,
|
||||
ActivityName.ZLOTA,
|
||||
ActivityName.KRMNPA,
|
||||
ActivityName.SANPCPA,
|
||||
ActivityName.LLOTA,
|
||||
ActivityName.QRP,
|
||||
]:
|
||||
logger.warning(f"PNP alert found with activity {activity}, developer needs to add support for this!")
|
||||
|
||||
# If this is POTA, SOTA or WWFF data we already have it through other means, so ignore. Otherwise, add to
|
||||
# the alert list. Note that while ZLOTA has its own spots API, it doesn't have its own alerts API. So that
|
||||
# means the PnP *spot* provider rejects ZLOTA spots here, but the PnP *alerts* provider here allows ZLOTA.
|
||||
|
||||
+28
-42
@@ -68,15 +68,6 @@ class GMA(HTTPSpotProvider):
|
||||
# Filter out some weird mode strings
|
||||
mode=Mode.from_name(source_spot["MODE"].upper()) if "<>" not in source_spot["MODE"] else None,
|
||||
comment=source_spot["TEXT"],
|
||||
activity_refs=[
|
||||
ActivityRef(
|
||||
id=source_spot["REF"],
|
||||
activity="",
|
||||
name=source_spot["NAME"],
|
||||
latitude=lat,
|
||||
longitude=lon,
|
||||
)
|
||||
],
|
||||
time=time,
|
||||
dx_latitude=lat,
|
||||
dx_longitude=lon,
|
||||
@@ -98,57 +89,52 @@ class GMA(HTTPSpotProvider):
|
||||
and ref_response.text != "\n"
|
||||
):
|
||||
ref_info = ref_response.json()
|
||||
if spot.activity_refs and ref_info and "reftype" in ref_info:
|
||||
if ref_info and "reftype" in ref_info:
|
||||
activity: ActivityName | None = None
|
||||
ref_type: ActivityRefType | None = None
|
||||
match ref_info["reftype"]:
|
||||
case "Summit":
|
||||
# Summits are a bit complicated, they can be SOTA or GMA depending on the
|
||||
# separate "sota" field:
|
||||
if "sota" in ref_info and ref_info["sota"] != "":
|
||||
spot.activity_refs[0].activity = ActivityName.SOTA
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.SUMMIT
|
||||
spot.add_activity(ActivityName.SOTA)
|
||||
activity, ref_type = ActivityName.SOTA, ActivityRefType.SUMMIT
|
||||
else:
|
||||
spot.activity_refs[0].activity = ActivityName.GMA
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.SUMMIT
|
||||
spot.add_activity(ActivityName.GMA)
|
||||
activity, ref_type = ActivityName.GMA, ActivityRefType.SUMMIT
|
||||
case "POTA":
|
||||
spot.activity_refs[0].activity = ActivityName.POTA
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.PARK
|
||||
spot.add_activity(ActivityName.POTA)
|
||||
activity, ref_type = ActivityName.POTA, ActivityRefType.PARK
|
||||
case "WWFF":
|
||||
spot.activity_refs[0].activity = ActivityName.WWFF
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.PARK
|
||||
spot.add_activity(ActivityName.WWFF)
|
||||
activity, ref_type = ActivityName.WWFF, ActivityRefType.PARK
|
||||
case "IOTA Island":
|
||||
spot.activity_refs[0].activity = ActivityName.IOTA
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.ISLAND
|
||||
spot.add_activity(ActivityName.IOTA)
|
||||
activity, ref_type = ActivityName.IOTA, ActivityRefType.ISLAND
|
||||
case "GMA Island":
|
||||
spot.activity_refs[0].activity = ActivityName.GMA_ISLANDS
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.ISLAND
|
||||
spot.add_activity(ActivityName.GMA_ISLANDS)
|
||||
activity, ref_type = ActivityName.GMA_ISLANDS, ActivityRefType.ISLAND
|
||||
case "Lighthouse (ILLW)":
|
||||
spot.activity_refs[0].activity = ActivityName.ILLW
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.LIGHTHOUSE
|
||||
spot.add_activity(ActivityName.ILLW)
|
||||
activity, ref_type = ActivityName.ILLW, ActivityRefType.LIGHTHOUSE
|
||||
case "Lighthouse (ARLHS)":
|
||||
spot.activity_refs[0].activity = ActivityName.ARLHS
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.LIGHTHOUSE
|
||||
spot.add_activity(ActivityName.ARLHS)
|
||||
activity, ref_type = ActivityName.ARLHS, ActivityRefType.LIGHTHOUSE
|
||||
case "Castle":
|
||||
spot.activity_refs[0].activity = ActivityName.WCA
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.CASTLE
|
||||
spot.add_activity(ActivityName.WCA)
|
||||
activity, ref_type = ActivityName.WCA, ActivityRefType.CASTLE
|
||||
case "Mill":
|
||||
spot.activity_refs[0].activity = ActivityName.MOTA
|
||||
spot.activity_refs[0].ref_type = ActivityRefType.MILL
|
||||
spot.add_activity(ActivityName.MOTA)
|
||||
activity, ref_type = ActivityName.MOTA, ActivityRefType.MILL
|
||||
case _:
|
||||
logger.warning(
|
||||
f"GMA spot found with ref type {ref_info['reftype']}, developer needs to add support for this!"
|
||||
)
|
||||
spot.activity_refs[0].activity = ref_info["reftype"]
|
||||
spot.add_activity(ref_info["reftype"])
|
||||
|
||||
# Now we know the activity, add the reference to the spot. If it's an activity we
|
||||
# don't know, there's no ActivityName for it, so we can't add a reference.
|
||||
if activity is not None:
|
||||
spot.activity_refs = [
|
||||
ActivityRef(
|
||||
id=source_spot["REF"],
|
||||
activity=activity,
|
||||
ref_type=ref_type,
|
||||
name=source_spot["NAME"],
|
||||
latitude=lat,
|
||||
longitude=lon,
|
||||
)
|
||||
]
|
||||
spot.add_activity(activity)
|
||||
|
||||
elif not ref_response.from_cache:
|
||||
if not ref_response.ok:
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import ClassVar
|
||||
import pytz
|
||||
import requests
|
||||
|
||||
from core.activity_utils import get_activity_by_name
|
||||
from core.constants import HTTP_HEADERS
|
||||
from core.enums import ActivityName, Mode
|
||||
from data.activity_ref import ActivityRef
|
||||
@@ -67,16 +68,19 @@ class ParksNPeaks(HTTPSpotProvider):
|
||||
|
||||
# Record activity information
|
||||
activity = source_spot["actClass"].upper()
|
||||
found_activity = get_activity_by_name(activity)
|
||||
ref_id = source_spot["actSiteID"]
|
||||
|
||||
if activity:
|
||||
spot.add_activity(activity)
|
||||
if found_activity is not None:
|
||||
spot.add_activity(found_activity.name)
|
||||
|
||||
if ref_id:
|
||||
# We can only add a reference if we know the activity it's for
|
||||
if ref_id and found_activity is not None:
|
||||
activity_refs = [
|
||||
ActivityRef(
|
||||
id=ref_id,
|
||||
activity=activity,
|
||||
activity=found_activity.name,
|
||||
# Free text location is not present in all spots, so only add it if it's set
|
||||
name=source_spot["actLocation"]
|
||||
if "actLocation" in source_spot and source_spot["actLocation"] != ""
|
||||
@@ -96,23 +100,6 @@ class ParksNPeaks(HTTPSpotProvider):
|
||||
):
|
||||
spot.comment = source_spot["actLocation"]
|
||||
|
||||
# Log a warning for the developer if PnP gives us an unknown programme we've never seen before
|
||||
if activity not in [
|
||||
ActivityName.POTA,
|
||||
ActivityName.SOTA,
|
||||
ActivityName.WWFF,
|
||||
ActivityName.HEMA,
|
||||
ActivityName.SIOTA,
|
||||
ActivityName.ZLOTA,
|
||||
ActivityName.KRMNPA,
|
||||
ActivityName.SANPCPA,
|
||||
ActivityName.LLOTA,
|
||||
ActivityName.QRP,
|
||||
]:
|
||||
logger.warning(
|
||||
f"PNP spot found with activity {activity}, developer needs to add support for this!"
|
||||
)
|
||||
|
||||
# Add new spot to the list
|
||||
new_spots.append(spot)
|
||||
return new_spots
|
||||
|
||||
+20
-11
@@ -1,13 +1,17 @@
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
import pytz
|
||||
|
||||
from core.enums import Mode
|
||||
from core.activity_utils import get_activity_by_name
|
||||
from core.enums import ActivityName, Mode
|
||||
from data.activity_ref import ActivityRef
|
||||
from data.spot import Spot
|
||||
from providers.spot.websocket_spot_provider import WebsocketSpotProvider
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class XOTA(WebsocketSpotProvider):
|
||||
"""Spot provider for servers based on the "xOTA" software at https://github.com/nischu/xOTA/
|
||||
@@ -17,12 +21,17 @@ class XOTA(WebsocketSpotProvider):
|
||||
is why we also provide an activity_ref_prefix in our config. This is applied to the reference ID, so e.g. "T-01"
|
||||
at C3 might become "C3 T-01". This allows us to provide location lookups for TOTA at several conferences."""
|
||||
|
||||
ACTIVITY = None
|
||||
ACTIVITY: ActivityName | None = None
|
||||
|
||||
def __init__(self, provider_config):
|
||||
name = provider_config.get("name", "xOTA")
|
||||
super().__init__(name, provider_config, provider_config["url"])
|
||||
self.ACTIVITY = str(provider_config["activity"]) if "activity" in provider_config else None
|
||||
found_activity = get_activity_by_name(provider_config.get("activity"))
|
||||
self.ACTIVITY = found_activity.name if found_activity else None
|
||||
if not self.ACTIVITY:
|
||||
logger.error(
|
||||
"XOTA provider has no activity reference, this is a config problem - your config needs to specify a known activity type!"
|
||||
)
|
||||
self._activity_ref_prefix = (
|
||||
str(provider_config["activity_ref_prefix"]) if "activity_ref_prefix" in provider_config else ""
|
||||
)
|
||||
@@ -31,20 +40,20 @@ class XOTA(WebsocketSpotProvider):
|
||||
string = b.decode("utf-8")
|
||||
source_spot = json.loads(string)
|
||||
ref_id = f"{self._activity_ref_prefix} {source_spot['reference']['title']}"
|
||||
activity = self.ACTIVITY
|
||||
activities = []
|
||||
activity_refs = []
|
||||
if activity is not None:
|
||||
activities = [activity]
|
||||
activity_refs = [ActivityRef(id=ref_id, activity=activity, url=source_spot["reference"]["website"])]
|
||||
spot = Spot(
|
||||
source=self.name,
|
||||
source_id=source_spot["id"],
|
||||
dx_call=source_spot["stationCallSign"].upper(),
|
||||
freq=float(source_spot["freq"]) * 1000,
|
||||
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||
activities=[self.ACTIVITY] if self.ACTIVITY else [],
|
||||
activity_refs=[
|
||||
ActivityRef(
|
||||
id=ref_id,
|
||||
activity=self.ACTIVITY or "",
|
||||
url=source_spot["reference"]["website"],
|
||||
)
|
||||
],
|
||||
activities=activities,
|
||||
activity_refs=activity_refs,
|
||||
time=datetime.now(pytz.UTC).timestamp(),
|
||||
qrt=source_spot["state"] != "active",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user