mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-09-20 22:37:44 +00:00
Refactor activity names to use an enum instead of a string to avoid typos #147
This commit is contained in:
@@ -3,9 +3,9 @@ import re
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator, locator_to_latlong
|
from pyhamtools.locator import latlong_to_locator, locator_to_latlong
|
||||||
|
|
||||||
from core.constants import ACTIVITIES
|
from core.activity_utils import get_activity_by_name
|
||||||
from core.data_store import DATA_STORE
|
from core.data_store import DATA_STORE
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from core.geo_utils import wab_wai_square_to_lat_lon
|
from core.geo_utils import wab_wai_square_to_lat_lon
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
|
|
||||||
@@ -30,10 +30,10 @@ def get_activity_ref_info(activity_name, ref_id):
|
|||||||
activity_ref = ActivityRef(sig=activity_name, id=ref_id)
|
activity_ref = ActivityRef(sig=activity_name, id=ref_id)
|
||||||
|
|
||||||
# We can always get the reference type and the icon from the activity itself
|
# We can always get the reference type and the icon from the activity itself
|
||||||
for activity in ACTIVITIES:
|
activity = get_activity_by_name(activity_name)
|
||||||
if activity.name.upper() == activity_name.upper():
|
if activity:
|
||||||
activity_ref.ref_type = activity.ref_type
|
activity_ref.ref_type = activity.ref_type
|
||||||
activity_ref.icon = activity.icon
|
activity_ref.icon = activity.icon
|
||||||
|
|
||||||
try:
|
try:
|
||||||
### FUDGES ###
|
### FUDGES ###
|
||||||
@@ -41,7 +41,7 @@ def get_activity_ref_info(activity_name, ref_id):
|
|||||||
# DME fudge. Our database has leading zeros padding to 5 digits which is the expected format, but not all
|
# DME fudge. Our database has leading zeros padding to 5 digits which is the expected format, but not all
|
||||||
# activators add leading zeros. We also need to normalise "DME 01234" to "DME-01234" to match what's in our
|
# activators add leading zeros. We also need to normalise "DME 01234" to "DME-01234" to match what's in our
|
||||||
# database.
|
# database.
|
||||||
if activity_name.upper() == "DME":
|
if activity_name.upper() == ActivityName.DME:
|
||||||
match = re.match(r"DME[\- ](\d{3,5})", ref_id, re.IGNORECASE)
|
match = re.match(r"DME[\- ](\d{3,5})", ref_id, re.IGNORECASE)
|
||||||
if match:
|
if match:
|
||||||
number = match.group(1)
|
number = match.group(1)
|
||||||
@@ -49,21 +49,21 @@ def get_activity_ref_info(activity_name, ref_id):
|
|||||||
|
|
||||||
# DTMBA spotters sometimes include spaces and dashes, our regex allows them but they must be removed here so we
|
# DTMBA spotters sometimes include spaces and dashes, our regex allows them but they must be removed here so we
|
||||||
# can look up against the official list which doesn't have them
|
# can look up against the official list which doesn't have them
|
||||||
if activity_name.upper() == "DTMBA":
|
if activity_name.upper() == ActivityName.DTMBA:
|
||||||
ref_id = ref_id.replace("-", "").replace(" ", "")
|
ref_id = ref_id.replace("-", "").replace(" ", "")
|
||||||
|
|
||||||
### NO DATA ACTIVITIES ###
|
### NO DATA ACTIVITIES ###
|
||||||
#
|
#
|
||||||
# If the activity is HEMA or BIWOTA, we have no way to either generate useful data or look it up on a
|
# If the activity is HEMA or BIWOTA, we have no way to either generate useful data or look it up on a
|
||||||
# reference list, so just skip the lookup here.
|
# reference list, so just skip the lookup here.
|
||||||
if activity_name.upper() == "HEMA" or activity_name.upper() == "BIWOTA":
|
if activity_name.upper() == ActivityName.HEMA or activity_name.upper() == ActivityName.BIWOTA:
|
||||||
return activity_ref
|
return activity_ref
|
||||||
|
|
||||||
### PROGRAMMATIC DATA GENERATION INSTEAD OF LOOKUPS ###
|
### PROGRAMMATIC DATA GENERATION INSTEAD OF LOOKUPS ###
|
||||||
#
|
#
|
||||||
# If the activity is Tiles, WAB, WAI or BOTA (Beaches), we don't have anything to look up from the data
|
# If the activity is Tiles, WAB, WAI or BOTA (Beaches), we don't have anything to look up from the data
|
||||||
# store, we can calculate all the information we are going to get directly.
|
# store, we can calculate all the information we are going to get directly.
|
||||||
if activity_name.upper() == "TILES":
|
if activity_name.upper() == ActivityName.TILES.upper():
|
||||||
# Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same
|
# Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same
|
||||||
if not activity_ref.name:
|
if not activity_ref.name:
|
||||||
activity_ref.name = activity_ref.id
|
activity_ref.name = activity_ref.id
|
||||||
@@ -75,7 +75,7 @@ def get_activity_ref_info(activity_name, ref_id):
|
|||||||
activity_ref.longitude = ll[1]
|
activity_ref.longitude = ll[1]
|
||||||
return activity_ref
|
return activity_ref
|
||||||
|
|
||||||
elif activity_name.upper() == "WAB" or activity_name.upper() == "WAI":
|
elif activity_name.upper() == ActivityName.WAB or activity_name.upper() == ActivityName.WAI:
|
||||||
ll = wab_wai_square_to_lat_lon(ref_id)
|
ll = wab_wai_square_to_lat_lon(ref_id)
|
||||||
if ll:
|
if ll:
|
||||||
activity_ref.name = ref_id
|
activity_ref.name = ref_id
|
||||||
@@ -87,7 +87,7 @@ def get_activity_ref_info(activity_name, ref_id):
|
|||||||
logger.warning("Invalid lat/lon received for WAB/WAI reference")
|
logger.warning("Invalid lat/lon received for WAB/WAI reference")
|
||||||
return activity_ref
|
return activity_ref
|
||||||
|
|
||||||
elif activity_name.upper() == "BOTA":
|
elif activity_name.upper() == ActivityName.BOTA:
|
||||||
# For BOTA all we can ever generate is the URL, there is no data file or lookup for lat/longs
|
# For BOTA all we can ever generate is the URL, there is no data file or lookup for lat/longs
|
||||||
if not activity_ref.name:
|
if not activity_ref.name:
|
||||||
activity_ref.name = activity_ref.id
|
activity_ref.name = activity_ref.id
|
||||||
@@ -97,11 +97,11 @@ def get_activity_ref_info(activity_name, ref_id):
|
|||||||
)
|
)
|
||||||
return activity_ref
|
return activity_ref
|
||||||
|
|
||||||
elif activity_name.upper() == "GMA Islands":
|
elif activity_name.upper() == ActivityName.GMA_ISLANDS.upper():
|
||||||
# GMA Islands is a bit of a mess of GMA and IOTA references. Try looking them both up and see what returns
|
# GMA Islands is a bit of a mess of GMA and IOTA references. Try looking them both up and see what returns
|
||||||
# the best result.
|
# the best result.
|
||||||
iota_lookup = get_activity_ref_info("IOTA", ref_id)
|
iota_lookup = get_activity_ref_info(ActivityName.IOTA, ref_id)
|
||||||
gma_lookup = get_activity_ref_info("GMA", ref_id)
|
gma_lookup = get_activity_ref_info(ActivityName.GMA, ref_id)
|
||||||
for key, value in iota_lookup.__dict__.items():
|
for key, value in iota_lookup.__dict__.items():
|
||||||
if value is not None and activity_ref.__dict__.get(key) is None:
|
if value is not None and activity_ref.__dict__.get(key) is None:
|
||||||
activity_ref.__dict__[key] = value
|
activity_ref.__dict__[key] = value
|
||||||
|
|||||||
+20
-12
@@ -1,23 +1,31 @@
|
|||||||
from core.constants import ACTIVITIES
|
from data.activities import ACTIVITIES
|
||||||
|
|
||||||
|
|
||||||
|
def get_activity_by_name(name):
|
||||||
|
"""Utility function to resolve an arbitrary, case-insensitive activity name string (e.g. from a spot comment, a
|
||||||
|
provider, or an API request) to the matching known Activity. Returns None if no match is found."""
|
||||||
|
|
||||||
|
if not name:
|
||||||
|
return None
|
||||||
|
for activity_name, activity in ACTIVITIES.items():
|
||||||
|
if activity_name.upper() == name.upper():
|
||||||
|
return activity
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_ref_regex_for_activity(activity):
|
def get_ref_regex_for_activity(activity):
|
||||||
"""Utility function to get the regex string for an activity reference for a named activity. If no match is
|
"""Utility function to get the regex string for an activity reference for a named activity. If no match is
|
||||||
found, None will be returned."""
|
found, None will be returned."""
|
||||||
|
|
||||||
for a in ACTIVITIES:
|
found = get_activity_by_name(activity)
|
||||||
if a.name.upper() == activity.upper():
|
return found.ref_regex if found else None
|
||||||
return a.ref_regex
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_icon_for_activity(activity):
|
def get_icon_for_activity(activity):
|
||||||
"""Utility function to get the icon for a named activity. If no match is found, None will be returned."""
|
"""Utility function to get the icon for a named activity. If no match is found, None will be returned."""
|
||||||
|
|
||||||
for a in ACTIVITIES:
|
found = get_activity_by_name(activity)
|
||||||
if a.name.upper() == activity.upper():
|
return found.icon if found else None
|
||||||
return a.icon
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_activity_name_from_comment_name(activity):
|
def get_activity_name_from_comment_name(activity):
|
||||||
@@ -25,11 +33,11 @@ def get_activity_name_from_comment_name(activity):
|
|||||||
but there are some cases (e.g. is "TOTA" Towers, Tiles or Toilets?) where we need to transform one to the
|
but there are some cases (e.g. is "TOTA" Towers, Tiles or Toilets?) where we need to transform one to the
|
||||||
other."""
|
other."""
|
||||||
|
|
||||||
for a in ACTIVITIES:
|
for activity_name, a in ACTIVITIES.items():
|
||||||
if any(n.upper() == activity.upper() for n in a.comment_names):
|
if any(n.upper() == activity.upper() for n in a.comment_names):
|
||||||
return a.name
|
return activity_name
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
# Regex matching any activity's "comment name", i.e. how it may be referred to in spot comments
|
# Regex matching any activity's "comment name", i.e. how it may be referred to in spot comments
|
||||||
ANY_ACTIVITY_REGEX = rf"({'|'.join(n for a in ACTIVITIES for n in a.comment_names)})"
|
ANY_ACTIVITY_REGEX = rf"({'|'.join(n for a in ACTIVITIES.values() for n in a.comment_names)})"
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
from core.config import SERVER_OWNER_CALLSIGN
|
from core.config import SERVER_OWNER_CALLSIGN
|
||||||
from core.enums import ActivityRefType, ActivityType
|
|
||||||
from data.activity import Activity
|
|
||||||
from data.band import Band
|
from data.band import Band
|
||||||
|
|
||||||
# General software
|
# General software
|
||||||
@@ -10,442 +8,6 @@ SOFTWARE_VERSION = "2.2-pre"
|
|||||||
HTTP_HEADERS = {"User-Agent": f"Spothole v{SOFTWARE_VERSION} (operated by {SERVER_OWNER_CALLSIGN})"}
|
HTTP_HEADERS = {"User-Agent": f"Spothole v{SOFTWARE_VERSION} (operated by {SERVER_OWNER_CALLSIGN})"}
|
||||||
HAMQTH_PRG = f"Spothole v{SOFTWARE_VERSION} operated by {SERVER_OWNER_CALLSIGN}".replace(" ", "_")
|
HAMQTH_PRG = f"Spothole v{SOFTWARE_VERSION} operated by {SERVER_OWNER_CALLSIGN}".replace(" ", "_")
|
||||||
|
|
||||||
# Activities
|
|
||||||
ACTIVITIES = [
|
|
||||||
Activity(
|
|
||||||
name="Contest",
|
|
||||||
comment_names=["CONTEST"],
|
|
||||||
description="Contest",
|
|
||||||
sig_type=ActivityType.TRADITIONAL,
|
|
||||||
icon="fa-trophy",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="DXpedition",
|
|
||||||
comment_names=[],
|
|
||||||
description="Radio expedition to a remote location",
|
|
||||||
sig_type=ActivityType.TRADITIONAL,
|
|
||||||
icon="fa-book-atlas",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="Satellite",
|
|
||||||
comment_names=[],
|
|
||||||
description="Amateur Radio Satellite",
|
|
||||||
sig_type=ActivityType.TRADITIONAL,
|
|
||||||
icon="fa-satellite",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="EME",
|
|
||||||
comment_names=[],
|
|
||||||
description="Earth-Moon-Earth (Moonbounce)",
|
|
||||||
sig_type=ActivityType.TRADITIONAL,
|
|
||||||
icon="fa-moon",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="/AM",
|
|
||||||
comment_names=[],
|
|
||||||
description="Aeronautical Mobile",
|
|
||||||
sig_type=ActivityType.TRADITIONAL,
|
|
||||||
icon="fa-plane",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="/MM",
|
|
||||||
comment_names=[],
|
|
||||||
description="Maritime Mobile",
|
|
||||||
sig_type=ActivityType.TRADITIONAL,
|
|
||||||
icon="fa-sailboat",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="QRP",
|
|
||||||
comment_names=["QRP"],
|
|
||||||
description="Low power",
|
|
||||||
sig_type=ActivityType.TRADITIONAL,
|
|
||||||
icon="fa-volume-low",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="POTA",
|
|
||||||
comment_names=["POTA"],
|
|
||||||
description="Parks on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.PARK,
|
|
||||||
ref_regex=r"[A-Z]{2}\-\d{4,5}|K\-TEST",
|
|
||||||
icon="fa-tree",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="SOTA",
|
|
||||||
comment_names=["SOTA"],
|
|
||||||
description="Summits on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.SUMMIT,
|
|
||||||
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
|
|
||||||
icon="fa-mountain-sun",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="WWFF",
|
|
||||||
comment_names=["WWFF"],
|
|
||||||
description="World Wide Flora & Fauna",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.PARK,
|
|
||||||
ref_regex=r"[A-Z0-9]{1,3}FF\-\d{4}",
|
|
||||||
icon="fa-seedling",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="GMA",
|
|
||||||
comment_names=["GMA"],
|
|
||||||
description="Global Mountain Activity",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.SUMMIT,
|
|
||||||
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
|
|
||||||
icon="fa-person-hiking",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="WWBOTA",
|
|
||||||
comment_names=["WWBOTA", "BOTA"],
|
|
||||||
description="Worldwide Bunkers on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.BUNKER,
|
|
||||||
ref_regex=r"B\/[A-Z0-9]{1,3}\-\d{3,4}",
|
|
||||||
icon="fa-radiation",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="HEMA",
|
|
||||||
comment_names=["HEMA"],
|
|
||||||
description="HuMPs Excluding Marilyns Award",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.SUMMIT,
|
|
||||||
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{3}\-\d{3}",
|
|
||||||
icon="fa-mound",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="IOTA",
|
|
||||||
comment_names=["IOTA"],
|
|
||||||
description="Islands on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.ISLAND,
|
|
||||||
ref_regex=r"[A-Z]{2}\-\d{3}",
|
|
||||||
icon="fa-book-atlas",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="GMA Islands",
|
|
||||||
comment_names=[],
|
|
||||||
description="Global Mountain Activity - Islands",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.ISLAND,
|
|
||||||
ref_regex=r"(([A-Z]{2}\-\d{3})|([A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}))",
|
|
||||||
icon="fa-person-hiking",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="ARLHS",
|
|
||||||
comment_names=["ARLHS"],
|
|
||||||
description="Amateur Radio Lighthouse Society",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.LIGHTHOUSE,
|
|
||||||
ref_regex=r"[A-Z]{3}[\- ]\d{3,4}",
|
|
||||||
icon="fa-house-flood-water",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="ILLW",
|
|
||||||
comment_names=["ILLW"],
|
|
||||||
description="International Lighthouse & Lightship Weekend",
|
|
||||||
sig_type=ActivityType.EVENT,
|
|
||||||
ref_type=ActivityRefType.LIGHTHOUSE,
|
|
||||||
ref_regex=r"[A-Z]{2}\d{4}",
|
|
||||||
icon="fa-house-flood-water",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="MOTA",
|
|
||||||
comment_names=["MOTA"],
|
|
||||||
description="Mills on the Air",
|
|
||||||
sig_type=ActivityType.EVENT,
|
|
||||||
ref_type=ActivityRefType.MILL,
|
|
||||||
ref_regex=r"X\d{4,6}",
|
|
||||||
icon="fa-fan",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="SIOTA",
|
|
||||||
comment_names=["SIOTA"],
|
|
||||||
description="Silos on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.SILO,
|
|
||||||
ref_regex=r"[A-Z]{2}\-[A-Z]{3}\d",
|
|
||||||
icon="fa-wheat-awn",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="WCA",
|
|
||||||
comment_names=["WCA"],
|
|
||||||
description="World Castles Award",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.CASTLE,
|
|
||||||
ref_regex=r"[A-Z0-9]{1,3}\-\d{5}",
|
|
||||||
icon="fa-chess-rook",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="ZLOTA",
|
|
||||||
comment_names=["ZLOTA"],
|
|
||||||
description="New Zealand on the Air",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=None,
|
|
||||||
ref_regex=r"ZL[A-Z]/[A-Z]{2}\-\d{3,4}",
|
|
||||||
icon="fa-kiwi-bird",
|
|
||||||
region_flag="🇳🇿",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="WOTA",
|
|
||||||
comment_names=["WOTA"],
|
|
||||||
description="Wainwrights on the Air",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.SUMMIT,
|
|
||||||
ref_regex=r"[A-Z]{3}-[0-9]{2}",
|
|
||||||
icon="fa-w",
|
|
||||||
region_flag="🇬🇧",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="BOTA",
|
|
||||||
comment_names=[],
|
|
||||||
description="Beaches on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.BEACH,
|
|
||||||
icon="fa-umbrella-beach",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="KRMNPA",
|
|
||||||
comment_names=["KRMNPA"],
|
|
||||||
description="Keith Roget Memorial National Parks Award",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.PARK,
|
|
||||||
ref_regex=r"VKFF\-\d{4}",
|
|
||||||
icon="fa-earth-oceania",
|
|
||||||
region_flag="🇦🇺",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="SANPCPA",
|
|
||||||
comment_names=["SANPCPA"],
|
|
||||||
description="South Australian National Parks and Conservation Parks Award",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.PARK,
|
|
||||||
ref_regex=r"VKFF\-\d{4}",
|
|
||||||
icon="fa-earth-oceania",
|
|
||||||
region_flag="🇦🇺",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="LLOTA",
|
|
||||||
comment_names=["LLOTA"],
|
|
||||||
description="Lagos y Lagunas on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.LAKE,
|
|
||||||
ref_regex=r"LL[A-Z]{2}\-\d{4}",
|
|
||||||
icon="fa-water",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="Towers",
|
|
||||||
comment_names=["TOTA"],
|
|
||||||
description="Towers on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.TOWER,
|
|
||||||
ref_regex=r"[A-Z]{2,3}R\-\d{4}",
|
|
||||||
icon="fa-tower-observation",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="Tiles",
|
|
||||||
comment_names=[],
|
|
||||||
description="Tiles on the Air",
|
|
||||||
sig_type=ActivityType.ADVENTURE,
|
|
||||||
ref_type=ActivityRefType.GRID,
|
|
||||||
ref_regex=r"[A-Za-z]{2}[0-9]{2}[A-Za-z]{2}",
|
|
||||||
icon="fa-square",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="RaDAR Rally",
|
|
||||||
comment_names=["RaDAR"],
|
|
||||||
description="RaDAR Rally",
|
|
||||||
sig_type=ActivityType.EVENT,
|
|
||||||
icon="fa-headset",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="WAB",
|
|
||||||
comment_names=["WAB"],
|
|
||||||
description="Worked All Britain",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.GRID,
|
|
||||||
ref_regex=r"[A-Z]{1,2}[0-9]{2}",
|
|
||||||
icon="fa-table-cells-large",
|
|
||||||
region_flag="🇬🇧",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="WAI",
|
|
||||||
comment_names=["WAI"],
|
|
||||||
description="Worked All Ireland",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.GRID,
|
|
||||||
ref_regex=r"[A-Z][0-9]{2}",
|
|
||||||
icon="fa-table-cells-large",
|
|
||||||
region_flag="🇮🇪",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="DMF",
|
|
||||||
comment_names=["DMF"],
|
|
||||||
description="Diplôme des Moulins de France",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.MILL,
|
|
||||||
icon="fa-fan",
|
|
||||||
region_flag="🇫🇷",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="DME",
|
|
||||||
comment_names=["DME"],
|
|
||||||
description="Diploma Municipios de España",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.TOWN,
|
|
||||||
ref_regex=r"DME[\- ]\d{3,5}",
|
|
||||||
icon="fa-building",
|
|
||||||
region_flag="🇪🇸",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="FEA",
|
|
||||||
comment_names=["FEA"],
|
|
||||||
description="Diploma Faros de España",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.LIGHTHOUSE,
|
|
||||||
# FEA references are technically [DE]\-\d{4}(\.\d)? but spotters always seem to miss out the D- or E-
|
|
||||||
# prefix and just use FEA-1234 or FEA 1234, so allow for that. The FEA activity ref data provider adds both
|
|
||||||
# forms to the database.
|
|
||||||
ref_regex=r"([DE]|FEA)[\- ]\d{4}(\.\d)?",
|
|
||||||
icon="fa-house-flood-water",
|
|
||||||
region_flag="🇪🇸",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="DMUE",
|
|
||||||
comment_names=["DMUE"],
|
|
||||||
description="Diploma Museos de España",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.BUILDING,
|
|
||||||
ref_regex=r"MUE[A-Z]{2}-\d{3}",
|
|
||||||
icon="fa-landmark",
|
|
||||||
region_flag="🇪🇸",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="DMVE",
|
|
||||||
comment_names=["DMVE"],
|
|
||||||
description="Diploma Monumentos y Vestigios de España",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.BUILDING,
|
|
||||||
ref_regex=r"MV[A-Z]{1,2}-\d{4}",
|
|
||||||
icon="fa-monument",
|
|
||||||
region_flag="🇪🇸",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="DCE",
|
|
||||||
comment_names=["DCE"],
|
|
||||||
description="Diploma Castillos de España",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.CASTLE,
|
|
||||||
ref_regex=r"C[A-Z]{1,2}-\d{3}",
|
|
||||||
icon="fa-chess-rook",
|
|
||||||
region_flag="🇪🇸",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="DEFE",
|
|
||||||
comment_names=["DEFE"],
|
|
||||||
description="Diploma Estaciones de Ferrocarril de España",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.BUILDING,
|
|
||||||
ref_regex=r"EF[A-Z]{1,2}-\d{3}",
|
|
||||||
icon="fa-train",
|
|
||||||
region_flag="🇪🇸",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="DTMBA",
|
|
||||||
comment_names=["DTMBA"],
|
|
||||||
description="Diploma Teatri Musei e Belle Arti",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.BUILDING,
|
|
||||||
ref_regex=r"I-?[0-9]{3,4}\s?[A-Z]{2}",
|
|
||||||
icon="fa-landmark",
|
|
||||||
region_flag="🇮🇹",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="BIWOTA",
|
|
||||||
comment_names=["BIWOTA"],
|
|
||||||
description="British Inland Waterways on the Air",
|
|
||||||
sig_type=ActivityType.EVENT,
|
|
||||||
ref_type=ActivityRefType.WATERWAY,
|
|
||||||
icon="fa-ship",
|
|
||||||
region_flag="🇬🇧",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="COTA",
|
|
||||||
comment_names=["COTA"],
|
|
||||||
description="Castles on the Air",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.CASTLE,
|
|
||||||
ref_regex=r"[A-Z]{3}\-[0-9]{3,5}",
|
|
||||||
icon="fa-chess-rook",
|
|
||||||
region_flag="🇩🇪",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="PGA",
|
|
||||||
comment_names=["PGA"],
|
|
||||||
description="Polish Gmina Award",
|
|
||||||
sig_type=ActivityType.REGIONAL,
|
|
||||||
ref_type=ActivityRefType.REGION,
|
|
||||||
ref_regex=r"[A-Z]{2}[0-9]{2}",
|
|
||||||
icon="fa-g",
|
|
||||||
region_flag="🇵🇱",
|
|
||||||
refs_globally_unique=False,
|
|
||||||
),
|
|
||||||
Activity(
|
|
||||||
name="Toilets",
|
|
||||||
comment_names=[],
|
|
||||||
description="Toilets on the Air",
|
|
||||||
sig_type=ActivityType.EVENT,
|
|
||||||
ref_type=ActivityRefType.TOILET,
|
|
||||||
ref_regex=r"T\-[0-9]{2}",
|
|
||||||
icon="fa-toilet",
|
|
||||||
region_flag="🏴☠️",
|
|
||||||
refs_globally_unique=True,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Band definitions
|
# Band definitions
|
||||||
BANDS = [
|
BANDS = [
|
||||||
Band(name="2200m", start_freq=135700, end_freq=137800),
|
Band(name="2200m", start_freq=135700, end_freq=137800),
|
||||||
|
|||||||
@@ -90,6 +90,60 @@ class LocationSourceForCallsign(str, Enum):
|
|||||||
DXCC = "DXCC"
|
DXCC = "DXCC"
|
||||||
|
|
||||||
|
|
||||||
|
# Definitions of every activity Spothole knows about, keyed by the ActivityName enum. An enum is used for the
|
||||||
|
# names to avoid typos when using literal strings like "POTA" all over the place.
|
||||||
|
class ActivityName(str, Enum):
|
||||||
|
"""Canonical name of every activity. Spothole uses these rather than literals like "POTA" around the code
|
||||||
|
to ensure I don't accidentally introduce typos."""
|
||||||
|
|
||||||
|
CONTEST = "Contest"
|
||||||
|
DXPEDITION = "DXpedition"
|
||||||
|
SATELLITE = "Satellite"
|
||||||
|
EME = "EME"
|
||||||
|
AERONAUTICAL_MOBILE = "/AM"
|
||||||
|
MARITIME_MOBILE = "/MM"
|
||||||
|
QRP = "QRP"
|
||||||
|
POTA = "POTA"
|
||||||
|
SOTA = "SOTA"
|
||||||
|
WWFF = "WWFF"
|
||||||
|
GMA = "GMA"
|
||||||
|
WWBOTA = "WWBOTA"
|
||||||
|
HEMA = "HEMA"
|
||||||
|
IOTA = "IOTA"
|
||||||
|
GMA_ISLANDS = "GMA Islands"
|
||||||
|
ARLHS = "ARLHS"
|
||||||
|
ILLW = "ILLW"
|
||||||
|
MOTA = "MOTA"
|
||||||
|
SIOTA = "SIOTA"
|
||||||
|
WCA = "WCA"
|
||||||
|
ZLOTA = "ZLOTA"
|
||||||
|
WOTA = "WOTA"
|
||||||
|
BOTA = "BOTA"
|
||||||
|
KRMNPA = "KRMNPA"
|
||||||
|
SANPCPA = "SANPCPA"
|
||||||
|
LLOTA = "LLOTA"
|
||||||
|
TOWERS = "Towers"
|
||||||
|
TILES = "Tiles"
|
||||||
|
RADAR_RALLY = "RaDAR Rally"
|
||||||
|
WAB = "WAB"
|
||||||
|
WAI = "WAI"
|
||||||
|
DMF = "DMF"
|
||||||
|
DME = "DME"
|
||||||
|
FEA = "FEA"
|
||||||
|
DMUE = "DMUE"
|
||||||
|
DMVE = "DMVE"
|
||||||
|
DCE = "DCE"
|
||||||
|
DEFE = "DEFE"
|
||||||
|
DTMBA = "DTMBA"
|
||||||
|
BIWOTA = "BIWOTA"
|
||||||
|
COTA = "COTA"
|
||||||
|
PGA = "PGA"
|
||||||
|
TOILETS = "Toilets"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.value)
|
||||||
|
|
||||||
|
|
||||||
class ActivityRefType(str, Enum):
|
class ActivityRefType(str, Enum):
|
||||||
"""Type of an activity reference."""
|
"""Type of an activity reference."""
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,444 @@
|
|||||||
|
from core.enums import ActivityName, ActivityType, ActivityRefType
|
||||||
|
from data.activity import Activity
|
||||||
|
|
||||||
|
|
||||||
|
ACTIVITIES: dict[ActivityName, Activity] = {
|
||||||
|
ActivityName.CONTEST: Activity(
|
||||||
|
name=ActivityName.CONTEST,
|
||||||
|
# No sensible way to determine *which* contest, but if we set comment_names=["CONTEST"] then at least
|
||||||
|
# any spots with "contest" in the comment will get allocated to this activity.
|
||||||
|
comment_names=["CONTEST"],
|
||||||
|
description="Contest",
|
||||||
|
sig_type=ActivityType.TRADITIONAL,
|
||||||
|
icon="fa-trophy",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.DXPEDITION: Activity(
|
||||||
|
name=ActivityName.DXPEDITION,
|
||||||
|
# DXpedition stations are never really spotted with "DXpedition" in the comments, but we can assign
|
||||||
|
# this activity to a spot other ways.
|
||||||
|
comment_names=[],
|
||||||
|
description="Radio expedition to a remote location",
|
||||||
|
sig_type=ActivityType.TRADITIONAL,
|
||||||
|
icon="fa-book-atlas",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.SATELLITE: Activity(
|
||||||
|
name=ActivityName.SATELLITE,
|
||||||
|
comment_names=[],
|
||||||
|
description="Amateur Radio Satellite",
|
||||||
|
sig_type=ActivityType.TRADITIONAL,
|
||||||
|
icon="fa-satellite",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.EME: Activity(
|
||||||
|
name=ActivityName.EME,
|
||||||
|
comment_names=[],
|
||||||
|
description="Earth-Moon-Earth (Moonbounce)",
|
||||||
|
sig_type=ActivityType.TRADITIONAL,
|
||||||
|
icon="fa-moon",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.AERONAUTICAL_MOBILE: Activity(
|
||||||
|
name=ActivityName.AERONAUTICAL_MOBILE,
|
||||||
|
# Don't pick /AM out of comments, spot.py will handle picking it out of the callsign
|
||||||
|
comment_names=[],
|
||||||
|
description="Aeronautical Mobile",
|
||||||
|
sig_type=ActivityType.TRADITIONAL,
|
||||||
|
icon="fa-plane",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.MARITIME_MOBILE: Activity(
|
||||||
|
name=ActivityName.MARITIME_MOBILE,
|
||||||
|
# Don't pick /MM out of comments, spot.py will handle picking it out of the callsign
|
||||||
|
comment_names=[],
|
||||||
|
description="Maritime Mobile",
|
||||||
|
sig_type=ActivityType.TRADITIONAL,
|
||||||
|
icon="fa-sailboat",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.QRP: Activity(
|
||||||
|
name=ActivityName.QRP,
|
||||||
|
comment_names=["QRP"],
|
||||||
|
description="Low power",
|
||||||
|
sig_type=ActivityType.TRADITIONAL,
|
||||||
|
icon="fa-volume-low",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.POTA: Activity(
|
||||||
|
name=ActivityName.POTA,
|
||||||
|
comment_names=["POTA"],
|
||||||
|
description="Parks on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.PARK,
|
||||||
|
ref_regex=r"[A-Z]{2}\-\d{4,5}|K\-TEST",
|
||||||
|
icon="fa-tree",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.SOTA: Activity(
|
||||||
|
name=ActivityName.SOTA,
|
||||||
|
comment_names=["SOTA"],
|
||||||
|
description="Summits on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.SUMMIT,
|
||||||
|
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
|
||||||
|
icon="fa-mountain-sun",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.WWFF: Activity(
|
||||||
|
name=ActivityName.WWFF,
|
||||||
|
comment_names=["WWFF"],
|
||||||
|
description="World Wide Flora & Fauna",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.PARK,
|
||||||
|
ref_regex=r"[A-Z0-9]{1,3}FF\-\d{4}",
|
||||||
|
icon="fa-seedling",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.GMA: Activity(
|
||||||
|
name=ActivityName.GMA,
|
||||||
|
comment_names=["GMA"],
|
||||||
|
description="Global Mountain Activity",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.SUMMIT,
|
||||||
|
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}",
|
||||||
|
icon="fa-person-hiking",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.WWBOTA: Activity(
|
||||||
|
name=ActivityName.WWBOTA,
|
||||||
|
comment_names=["WWBOTA", "BOTA"],
|
||||||
|
description="Worldwide Bunkers on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.BUNKER,
|
||||||
|
ref_regex=r"B\/[A-Z0-9]{1,3}\-\d{3,4}",
|
||||||
|
icon="fa-radiation",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.HEMA: Activity(
|
||||||
|
name=ActivityName.HEMA,
|
||||||
|
comment_names=["HEMA"],
|
||||||
|
description="HuMPs Excluding Marilyns Award",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.SUMMIT,
|
||||||
|
ref_regex=r"[A-Z0-9]{1,3}\/[A-Z]{3}\-\d{3}",
|
||||||
|
icon="fa-mound",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.IOTA: Activity(
|
||||||
|
name=ActivityName.IOTA,
|
||||||
|
comment_names=["IOTA"],
|
||||||
|
description="Islands on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.ISLAND,
|
||||||
|
ref_regex=r"[A-Z]{2}\-\d{3}",
|
||||||
|
icon="fa-book-atlas",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.GMA_ISLANDS: Activity(
|
||||||
|
name=ActivityName.GMA_ISLANDS,
|
||||||
|
comment_names=[],
|
||||||
|
description="Global Mountain Activity - Islands",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.ISLAND,
|
||||||
|
ref_regex=r"(([A-Z]{2}\-\d{3})|([A-Z0-9]{1,3}\/[A-Z]{2}\-\d{3}))",
|
||||||
|
icon="fa-person-hiking",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.ARLHS: Activity(
|
||||||
|
name=ActivityName.ARLHS,
|
||||||
|
comment_names=["ARLHS"],
|
||||||
|
description="Amateur Radio Lighthouse Society",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.LIGHTHOUSE,
|
||||||
|
ref_regex=r"[A-Z]{3}[\- ]\d{3,4}",
|
||||||
|
icon="fa-house-flood-water",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.ILLW: Activity(
|
||||||
|
name=ActivityName.ILLW,
|
||||||
|
comment_names=["ILLW"],
|
||||||
|
description="International Lighthouse & Lightship Weekend",
|
||||||
|
sig_type=ActivityType.EVENT,
|
||||||
|
ref_type=ActivityRefType.LIGHTHOUSE,
|
||||||
|
ref_regex=r"[A-Z]{2}\d{4}",
|
||||||
|
icon="fa-house-flood-water",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.MOTA: Activity(
|
||||||
|
name=ActivityName.MOTA,
|
||||||
|
comment_names=["MOTA"],
|
||||||
|
description="Mills on the Air",
|
||||||
|
sig_type=ActivityType.EVENT,
|
||||||
|
ref_type=ActivityRefType.MILL,
|
||||||
|
ref_regex=r"X\d{4,6}",
|
||||||
|
icon="fa-fan",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.SIOTA: Activity(
|
||||||
|
name=ActivityName.SIOTA,
|
||||||
|
comment_names=["SIOTA"],
|
||||||
|
description="Silos on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.SILO,
|
||||||
|
ref_regex=r"[A-Z]{2}\-[A-Z]{3}\d",
|
||||||
|
icon="fa-wheat-awn",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.WCA: Activity(
|
||||||
|
name=ActivityName.WCA,
|
||||||
|
comment_names=["WCA"],
|
||||||
|
description="World Castles Award",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.CASTLE,
|
||||||
|
ref_regex=r"[A-Z0-9]{1,3}\-\d{5}",
|
||||||
|
icon="fa-chess-rook",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.ZLOTA: Activity(
|
||||||
|
name=ActivityName.ZLOTA,
|
||||||
|
comment_names=["ZLOTA"],
|
||||||
|
description="New Zealand on the Air",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=None,
|
||||||
|
ref_regex=r"ZL[A-Z]/[A-Z]{2}\-\d{3,4}",
|
||||||
|
icon="fa-kiwi-bird",
|
||||||
|
region_flag="🇳🇿",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.WOTA: Activity(
|
||||||
|
name=ActivityName.WOTA,
|
||||||
|
comment_names=["WOTA"],
|
||||||
|
description="Wainwrights on the Air",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.SUMMIT,
|
||||||
|
ref_regex=r"[A-Z]{3}-[0-9]{2}",
|
||||||
|
icon="fa-w",
|
||||||
|
region_flag="🇬🇧",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.BOTA: Activity(
|
||||||
|
name=ActivityName.BOTA,
|
||||||
|
comment_names=[],
|
||||||
|
description="Beaches on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.BEACH,
|
||||||
|
icon="fa-umbrella-beach",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.KRMNPA: Activity(
|
||||||
|
name=ActivityName.KRMNPA,
|
||||||
|
comment_names=["KRMNPA"],
|
||||||
|
description="Keith Roget Memorial National Parks Award",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.PARK,
|
||||||
|
ref_regex=r"VKFF\-\d{4}",
|
||||||
|
icon="fa-earth-oceania",
|
||||||
|
region_flag="🇦🇺",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.SANPCPA: Activity(
|
||||||
|
name=ActivityName.SANPCPA,
|
||||||
|
comment_names=["SANPCPA"],
|
||||||
|
description="South Australian National Parks and Conservation Parks Award",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.PARK,
|
||||||
|
ref_regex=r"VKFF\-\d{4}",
|
||||||
|
icon="fa-earth-oceania",
|
||||||
|
region_flag="🇦🇺",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.LLOTA: Activity(
|
||||||
|
name=ActivityName.LLOTA,
|
||||||
|
comment_names=["LLOTA"],
|
||||||
|
description="Lagos y Lagunas on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.LAKE,
|
||||||
|
ref_regex=r"LL[A-Z]{2}\-\d{4}",
|
||||||
|
icon="fa-water",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.TOWERS: Activity(
|
||||||
|
name=ActivityName.TOWERS,
|
||||||
|
comment_names=["TOTA"],
|
||||||
|
description="Towers on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.TOWER,
|
||||||
|
ref_regex=r"[A-Z]{2,3}R\-\d{4}",
|
||||||
|
icon="fa-tower-observation",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.TILES: Activity(
|
||||||
|
name=ActivityName.TILES,
|
||||||
|
comment_names=[],
|
||||||
|
description="Tiles on the Air",
|
||||||
|
sig_type=ActivityType.ADVENTURE,
|
||||||
|
ref_type=ActivityRefType.GRID,
|
||||||
|
ref_regex=r"[A-Za-z]{2}[0-9]{2}[A-Za-z]{2}",
|
||||||
|
icon="fa-square",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.RADAR_RALLY: Activity(
|
||||||
|
name=ActivityName.RADAR_RALLY,
|
||||||
|
comment_names=["RaDAR"],
|
||||||
|
description="RaDAR Rally",
|
||||||
|
sig_type=ActivityType.EVENT,
|
||||||
|
icon="fa-headset",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.WAB: Activity(
|
||||||
|
name=ActivityName.WAB,
|
||||||
|
comment_names=["WAB"],
|
||||||
|
description="Worked All Britain",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.GRID,
|
||||||
|
ref_regex=r"[A-Z]{1,2}[0-9]{2}",
|
||||||
|
icon="fa-table-cells-large",
|
||||||
|
region_flag="🇬🇧",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.WAI: Activity(
|
||||||
|
name=ActivityName.WAI,
|
||||||
|
comment_names=["WAI"],
|
||||||
|
description="Worked All Ireland",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.GRID,
|
||||||
|
ref_regex=r"[A-Z][0-9]{2}",
|
||||||
|
icon="fa-table-cells-large",
|
||||||
|
region_flag="🇮🇪",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.DMF: Activity(
|
||||||
|
name=ActivityName.DMF,
|
||||||
|
comment_names=["DMF"],
|
||||||
|
description="Diplôme des Moulins de France",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.MILL,
|
||||||
|
icon="fa-fan",
|
||||||
|
region_flag="🇫🇷",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.DME: Activity(
|
||||||
|
name=ActivityName.DME,
|
||||||
|
comment_names=["DME"],
|
||||||
|
description="Diploma Municipios de España",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.TOWN,
|
||||||
|
ref_regex=r"DME[\- ]\d{3,5}",
|
||||||
|
icon="fa-building",
|
||||||
|
region_flag="🇪🇸",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.FEA: Activity(
|
||||||
|
name=ActivityName.FEA,
|
||||||
|
comment_names=["FEA"],
|
||||||
|
description="Diploma Faros de España",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.LIGHTHOUSE,
|
||||||
|
# FEA references are technically [DE]\-\d{4}(\.\d)? but spotters always seem to miss out the D- or E-
|
||||||
|
# prefix and just use FEA-1234 or FEA 1234, so allow for that. The FEA activity ref data provider adds both
|
||||||
|
# forms to the database.
|
||||||
|
ref_regex=r"([DE]|FEA)[\- ]\d{4}(\.\d)?",
|
||||||
|
icon="fa-house-flood-water",
|
||||||
|
region_flag="🇪🇸",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.DMUE: Activity(
|
||||||
|
name=ActivityName.DMUE,
|
||||||
|
comment_names=["DMUE"],
|
||||||
|
description="Diploma Museos de España",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.BUILDING,
|
||||||
|
ref_regex=r"MUE[A-Z]{2}-\d{3}",
|
||||||
|
icon="fa-landmark",
|
||||||
|
region_flag="🇪🇸",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.DMVE: Activity(
|
||||||
|
name=ActivityName.DMVE,
|
||||||
|
comment_names=["DMVE"],
|
||||||
|
description="Diploma Monumentos y Vestigios de España",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.BUILDING,
|
||||||
|
ref_regex=r"MV[A-Z]{1,2}-\d{4}",
|
||||||
|
icon="fa-monument",
|
||||||
|
region_flag="🇪🇸",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.DCE: Activity(
|
||||||
|
name=ActivityName.DCE,
|
||||||
|
comment_names=["DCE"],
|
||||||
|
description="Diploma Castillos de España",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.CASTLE,
|
||||||
|
ref_regex=r"C[A-Z]{1,2}-\d{3}",
|
||||||
|
icon="fa-chess-rook",
|
||||||
|
region_flag="🇪🇸",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.DEFE: Activity(
|
||||||
|
name=ActivityName.DEFE,
|
||||||
|
comment_names=["DEFE"],
|
||||||
|
description="Diploma Estaciones de Ferrocarril de España",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.BUILDING,
|
||||||
|
ref_regex=r"EF[A-Z]{1,2}-\d{3}",
|
||||||
|
icon="fa-train",
|
||||||
|
region_flag="🇪🇸",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.DTMBA: Activity(
|
||||||
|
name=ActivityName.DTMBA,
|
||||||
|
comment_names=["DTMBA"],
|
||||||
|
description="Diploma Teatri Musei e Belle Arti",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.BUILDING,
|
||||||
|
ref_regex=r"I-?[0-9]{3,4}\s?[A-Z]{2}",
|
||||||
|
icon="fa-landmark",
|
||||||
|
region_flag="🇮🇹",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
ActivityName.BIWOTA: Activity(
|
||||||
|
name=ActivityName.BIWOTA,
|
||||||
|
comment_names=["BIWOTA"],
|
||||||
|
description="British Inland Waterways on the Air",
|
||||||
|
sig_type=ActivityType.EVENT,
|
||||||
|
ref_type=ActivityRefType.WATERWAY,
|
||||||
|
icon="fa-ship",
|
||||||
|
region_flag="🇬🇧",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.COTA: Activity(
|
||||||
|
name=ActivityName.COTA,
|
||||||
|
comment_names=["COTA"],
|
||||||
|
description="Castles on the Air",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.CASTLE,
|
||||||
|
ref_regex=r"[A-Z]{3}\-[0-9]{3,5}",
|
||||||
|
icon="fa-chess-rook",
|
||||||
|
region_flag="🇩🇪",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.PGA: Activity(
|
||||||
|
name=ActivityName.PGA,
|
||||||
|
comment_names=["PGA"],
|
||||||
|
description="Polish Gmina Award",
|
||||||
|
sig_type=ActivityType.REGIONAL,
|
||||||
|
ref_type=ActivityRefType.REGION,
|
||||||
|
ref_regex=r"[A-Z]{2}[0-9]{2}",
|
||||||
|
icon="fa-g",
|
||||||
|
region_flag="🇵🇱",
|
||||||
|
refs_globally_unique=False,
|
||||||
|
),
|
||||||
|
ActivityName.TOILETS: Activity(
|
||||||
|
name=ActivityName.TOILETS,
|
||||||
|
comment_names=[],
|
||||||
|
description="Toilets on the Air",
|
||||||
|
sig_type=ActivityType.EVENT,
|
||||||
|
ref_type=ActivityRefType.TOILET,
|
||||||
|
ref_regex=r"T\-[0-9]{2}",
|
||||||
|
icon="fa-toilet",
|
||||||
|
region_flag="🏴☠️",
|
||||||
|
refs_globally_unique=True,
|
||||||
|
),
|
||||||
|
}
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
from core.enums import ActivityRefType, ActivityType
|
from core.enums import ActivityName, ActivityRefType, ActivityType
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -15,7 +15,7 @@ class Activity:
|
|||||||
match what references (such as parks and summits) look like for that programme."""
|
match what references (such as parks and summits) look like for that programme."""
|
||||||
|
|
||||||
# Activity name as used in the UI and API, e.g. "Towers"
|
# Activity name as used in the UI and API, e.g. "Towers"
|
||||||
name: str
|
name: ActivityName
|
||||||
# Description, e.g. "Towers on the Air"
|
# Description, e.g. "Towers on the Air"
|
||||||
description: str
|
description: str
|
||||||
# Type, either Worldwide, Regional or Event. Used for sorting in the web UI.
|
# Type, either Worldwide, Regional or Event. Used for sorting in the web UI.
|
||||||
|
|||||||
+11
-10
@@ -18,9 +18,9 @@ from core.activity_utils import (
|
|||||||
)
|
)
|
||||||
from core.call_lookup_helper import get_call_info
|
from core.call_lookup_helper import get_call_info
|
||||||
from core.config import MAX_SPOT_AGE
|
from core.config import MAX_SPOT_AGE
|
||||||
from core.constants import ACTIVITIES, PROPAGATION_MODES
|
from core.constants import PROPAGATION_MODES
|
||||||
from core.data_store import DATA_STORE
|
from core.data_store import DATA_STORE
|
||||||
from core.enums import Continent, LocationSourceForSpot, Mode, ModeSource, ModeType
|
from core.enums import ActivityName, Continent, LocationSourceForSpot, Mode, ModeSource, ModeType
|
||||||
from core.geo_utils import lat_lon_to_cq_zone, lat_lon_to_itu_zone
|
from core.geo_utils import lat_lon_to_cq_zone, lat_lon_to_itu_zone
|
||||||
from core.utils import (
|
from core.utils import (
|
||||||
get_flag_for_dxcc,
|
get_flag_for_dxcc,
|
||||||
@@ -29,6 +29,7 @@ from core.utils import (
|
|||||||
infer_mode_from_frequency,
|
infer_mode_from_frequency,
|
||||||
infer_mode_type_from_mode,
|
infer_mode_type_from_mode,
|
||||||
)
|
)
|
||||||
|
from data.activities import ACTIVITIES
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -311,7 +312,7 @@ class Spot:
|
|||||||
# name, but where the activity reference is unique-looking enough that we can't confuse it with any other
|
# name, but where the activity reference is unique-looking enough that we can't confuse it with any other
|
||||||
# activity.
|
# activity.
|
||||||
if self.comment:
|
if self.comment:
|
||||||
for activity in ACTIVITIES:
|
for activity in ACTIVITIES.values():
|
||||||
if activity.refs_globally_unique and activity.ref_regex:
|
if activity.refs_globally_unique and activity.ref_regex:
|
||||||
ref_matches = re.finditer(
|
ref_matches = re.finditer(
|
||||||
r"(^|\W)(" + activity.ref_regex + r")($|\W)", self.comment, re.IGNORECASE
|
r"(^|\W)(" + activity.ref_regex + r")($|\W)", self.comment, re.IGNORECASE
|
||||||
@@ -343,7 +344,7 @@ class Spot:
|
|||||||
):
|
):
|
||||||
self.dx_latitude = activity_ref.latitude
|
self.dx_latitude = activity_ref.latitude
|
||||||
self.dx_longitude = activity_ref.longitude
|
self.dx_longitude = activity_ref.longitude
|
||||||
if self.sig == "WAB" or self.sig == "WAI" or self.sig == "Tiles":
|
if self.sig in (ActivityName.WAB, ActivityName.WAI, ActivityName.TILES):
|
||||||
self.dx_location_source = LocationSourceForSpot.GRID
|
self.dx_location_source = LocationSourceForSpot.GRID
|
||||||
else:
|
else:
|
||||||
self.dx_location_source = LocationSourceForSpot.SIG_REF_LOOKUP
|
self.dx_location_source = LocationSourceForSpot.SIG_REF_LOOKUP
|
||||||
@@ -380,16 +381,16 @@ class Spot:
|
|||||||
|
|
||||||
# Set activities based on propagation mode
|
# Set activities based on propagation mode
|
||||||
if self.propagation_mode == "Satellite" and not self.sig:
|
if self.propagation_mode == "Satellite" and not self.sig:
|
||||||
self.sig = "Satellite"
|
self.sig = ActivityName.SATELLITE
|
||||||
if self.propagation_mode == "Earth-Moon-Earth" and not self.sig:
|
if self.propagation_mode == "Earth-Moon-Earth" and not self.sig:
|
||||||
self.sig = "EME"
|
self.sig = ActivityName.EME
|
||||||
|
|
||||||
# Set activities based on the DX callsign suffix
|
# Set activities based on the DX callsign suffix
|
||||||
if self.dx_call and not self.sig:
|
if self.dx_call and not self.sig:
|
||||||
if self.dx_call.upper().endswith("/AM"):
|
if self.dx_call.upper().endswith(ActivityName.AERONAUTICAL_MOBILE):
|
||||||
self.sig = "/AM"
|
self.sig = ActivityName.AERONAUTICAL_MOBILE
|
||||||
elif self.dx_call.upper().endswith("/MM"):
|
elif self.dx_call.upper().endswith(ActivityName.MARITIME_MOBILE):
|
||||||
self.sig = "/MM"
|
self.sig = ActivityName.MARITIME_MOBILE
|
||||||
|
|
||||||
# Parse "de_grid -> dx_grid" structures from the comment
|
# Parse "de_grid -> dx_grid" structures from the comment
|
||||||
if self.comment:
|
if self.comment:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class ARLHS(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Amateur Radio Light House Society"""
|
"""Activity ref data provider for Amateur Radio Light House Society"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "ARLHS"
|
ACTIVITY = ActivityName.ARLHS
|
||||||
DATA_URL = "https://www.gma.rocks/download/lighthouse.csv"
|
DATA_URL = "https://www.gma.rocks/download/lighthouse.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ class COTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Castles on the Air"""
|
"""Activity ref data provider for Castles on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "COTA"
|
ACTIVITY = ActivityName.COTA
|
||||||
DATA_URL = "https://www.cotagroup.org/cotagroup/map/data/castles-all-7d90ee2a5e1175e5dece1bbf9dc87504.json"
|
DATA_URL = "https://www.cotagroup.org/cotagroup/map/data/castles-all-7d90ee2a5e1175e5dece1bbf9dc87504.json"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ class DCE(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Diploma Castillos de España"""
|
"""Activity ref data provider for Diploma Castillos de España"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 365
|
POLL_INTERVAL_DAYS = 365
|
||||||
ACTIVITY = "DCE"
|
ACTIVITY = ActivityName.DCE
|
||||||
DATA_URL = "https://www.acracb.org/dce/descargas/General/directorio_referencias_dce.xls"
|
DATA_URL = "https://www.acracb.org/dce/descargas/General/directorio_referencias_dce.xls"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ class DEFE(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Diploma Estationes de Ferrocarril de España"""
|
"""Activity ref data provider for Diploma Estationes de Ferrocarril de España"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 365
|
POLL_INTERVAL_DAYS = 365
|
||||||
ACTIVITY = "DEFE"
|
ACTIVITY = ActivityName.DEFE
|
||||||
DATA_URL = "https://www.acracb.org/defe/descargas/General/directorio_referencias_defe.xls"
|
DATA_URL = "https://www.acracb.org/defe/descargas/General/directorio_referencias_defe.xls"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.local_file_activity_ref_data_provider import (
|
from providers.activityrefdata.local_file_activity_ref_data_provider import (
|
||||||
LocalFileActivityRefDataProvider,
|
LocalFileActivityRefDataProvider,
|
||||||
@@ -13,7 +13,7 @@ from providers.activityrefdata.local_file_activity_ref_data_provider import (
|
|||||||
class DME(LocalFileActivityRefDataProvider):
|
class DME(LocalFileActivityRefDataProvider):
|
||||||
"""Activity ref data provider for Diploma Municipios de Espana"""
|
"""Activity ref data provider for Diploma Municipios de Espana"""
|
||||||
|
|
||||||
ACTIVITY = "DME"
|
ACTIVITY = ActivityName.DME
|
||||||
PATH = "datafiles/MUNICIPIOS.csv"
|
PATH = "datafiles/MUNICIPIOS.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ class DMUE(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Diploma Museos de España"""
|
"""Activity ref data provider for Diploma Museos de España"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 365
|
POLL_INTERVAL_DAYS = 365
|
||||||
ACTIVITY = "DMUE"
|
ACTIVITY = ActivityName.DMUE
|
||||||
DATA_URL = "https://dmue.radiogalena.es/nom_dmue.csv"
|
DATA_URL = "https://dmue.radiogalena.es/nom_dmue.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ class DMVE(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Diploma Monumentos y Vestigios de España"""
|
"""Activity ref data provider for Diploma Monumentos y Vestigios de España"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 365
|
POLL_INTERVAL_DAYS = 365
|
||||||
ACTIVITY = "DMVE"
|
ACTIVITY = ActivityName.DMVE
|
||||||
DATA_URL = "https://www.acracb.org/dmve/descargas/General/directorio_referencias_dmve.xls"
|
DATA_URL = "https://www.acracb.org/dmve/descargas/General/directorio_referencias_dmve.xls"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ class DTMBA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Diploma Teatri Musei Belle Arti"""
|
"""Activity ref data provider for Diploma Teatri Musei Belle Arti"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "DTMBA"
|
ACTIVITY = ActivityName.DTMBA
|
||||||
DATA_URL = "https://www.iu1fig.com/share/iz0eik/dtmba/export.php"
|
DATA_URL = "https://www.iu1fig.com/share/iz0eik/dtmba/export.php"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
import pdfplumber
|
import pdfplumber
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ class FEA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Diploma Faros de España"""
|
"""Activity ref data provider for Diploma Faros de España"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "FEA"
|
ACTIVITY = ActivityName.FEA
|
||||||
DATA_URL = "http://ea5ol.net/Lista%20Faros.pdf"
|
DATA_URL = "http://ea5ol.net/Lista%20Faros.pdf"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class FileDownloadActivityRefDataProvider(ActivityRefDataProvider):
|
|||||||
self._url = url
|
self._url = url
|
||||||
self._poll_interval = poll_interval
|
self._poll_interval = poll_interval
|
||||||
self._thread = None
|
self._thread = None
|
||||||
self._url_data_cache = URLDataCache(f"sigrefdata_{sig_name}") # cache dir name kept for continuity
|
self._url_data_cache = URLDataCache(f"activity_ref_data_{sig_name}")
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
# Fire off the polling thread. It will poll immediately on startup, then sleep for poll_interval between
|
# Fire off the polling thread. It will poll immediately on startup, then sleep for poll_interval between
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class GMA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Global Mountain Activity"""
|
"""Activity ref data provider for Global Mountain Activity"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "GMA"
|
ACTIVITY = ActivityName.GMA
|
||||||
DATA_URL = "https://www.gma.rocks/download/summits.csv"
|
DATA_URL = "https://www.gma.rocks/download/summits.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class ILLW(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for International Lighthouse & Lightship Weekend"""
|
"""Activity ref data provider for International Lighthouse & Lightship Weekend"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "ILLW"
|
ACTIVITY = ActivityName.ILLW
|
||||||
DATA_URL = "https://www.gma.rocks/download/lighthouse.csv"
|
DATA_URL = "https://www.gma.rocks/download/lighthouse.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -16,7 +16,7 @@ class IOTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Islands on the Air"""
|
"""Activity ref data provider for Islands on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 365
|
POLL_INTERVAL_DAYS = 365
|
||||||
ACTIVITY = "IOTA"
|
ACTIVITY = ActivityName.IOTA
|
||||||
DATA_URL = "https://www.iota-world.org/islands-on-the-air/downloads/download-file.html?path=groups.json"
|
DATA_URL = "https://www.iota-world.org/islands-on-the-air/downloads/download-file.html?path=groups.json"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from core.enums import ActivityName
|
||||||
from providers.activityrefdata.pnp_kml_activity_ref_data_provider import (
|
from providers.activityrefdata.pnp_kml_activity_ref_data_provider import (
|
||||||
ParksNPeaksKMLActivityRefDataProvider,
|
ParksNPeaksKMLActivityRefDataProvider,
|
||||||
)
|
)
|
||||||
@@ -7,7 +8,7 @@ class KRMNPA(ParksNPeaksKMLActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for the Keith Roget Memorrial National Parks Award (KRMNPA)."""
|
"""Activity ref data provider for the Keith Roget Memorrial National Parks Award (KRMNPA)."""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 365
|
POLL_INTERVAL_DAYS = 365
|
||||||
ACTIVITY = "KRMNPA"
|
ACTIVITY = ActivityName.KRMNPA
|
||||||
DATA_URL = "https://parksnpeaks.org/getPOI.php?poiClass=KRMNPA&poiFormat=4"
|
DATA_URL = "https://parksnpeaks.org/getPOI.php?poiClass=KRMNPA&poiFormat=4"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import locator_to_latlong
|
from pyhamtools.locator import locator_to_latlong
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -13,7 +13,7 @@ class LLOTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Lagos y Lagunas on the Air"""
|
"""Activity ref data provider for Lagos y Lagunas on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 7
|
POLL_INTERVAL_DAYS = 7
|
||||||
ACTIVITY = "LLOTA"
|
ACTIVITY = ActivityName.LLOTA
|
||||||
DATA_URL = "https://llota.app/api/public/references"
|
DATA_URL = "https://llota.app/api/public/references"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class MOTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Mills on the Air"""
|
"""Activity ref data provider for Mills on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "MOTA"
|
ACTIVITY = ActivityName.MOTA
|
||||||
DATA_URL = "https://www.gma.rocks/download/mills.csv"
|
DATA_URL = "https://www.gma.rocks/download/mills.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from time import sleep
|
|||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
from providers.activityrefdata.file_download_activity_ref_data_provider import FileDownloadActivityRefDataProvider
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ class PGA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Polish Gmina Award"""
|
"""Activity ref data provider for Polish Gmina Award"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "PGA"
|
ACTIVITY = ActivityName.PGA
|
||||||
DATA_URL = "http://www.spga.pl/lista_pga2.php"
|
DATA_URL = "http://www.spga.pl/lista_pga2.php"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class POTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Parks on the Air"""
|
"""Activity ref data provider for Parks on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 7
|
POLL_INTERVAL_DAYS = 7
|
||||||
ACTIVITY = "POTA"
|
ACTIVITY = ActivityName.POTA
|
||||||
DATA_URL = "https://pota.app/all_parks_ext.csv"
|
DATA_URL = "https://pota.app/all_parks_ext.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from core.enums import ActivityName
|
||||||
from providers.activityrefdata.pnp_kml_activity_ref_data_provider import (
|
from providers.activityrefdata.pnp_kml_activity_ref_data_provider import (
|
||||||
ParksNPeaksKMLActivityRefDataProvider,
|
ParksNPeaksKMLActivityRefDataProvider,
|
||||||
)
|
)
|
||||||
@@ -7,7 +8,7 @@ class SANPCPA(ParksNPeaksKMLActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for the South Australia National Parks and Conservation Parks Award (SANPCPA)."""
|
"""Activity ref data provider for the South Australia National Parks and Conservation Parks Award (SANPCPA)."""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 365
|
POLL_INTERVAL_DAYS = 365
|
||||||
ACTIVITY = "SANPCPA"
|
ACTIVITY = ActivityName.SANPCPA
|
||||||
DATA_URL = "https://parksnpeaks.org/getPOI.php?poiClass=SANPCPA&poiFormat=4"
|
DATA_URL = "https://parksnpeaks.org/getPOI.php?poiClass=SANPCPA&poiFormat=4"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class SIOTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Silos on the Air"""
|
"""Activity ref data provider for Silos on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "SIOTA"
|
ACTIVITY = ActivityName.SIOTA
|
||||||
DATA_URL = "https://www.silosontheair.com/data/silos.csv"
|
DATA_URL = "https://www.silosontheair.com/data/silos.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -14,7 +14,7 @@ class SOTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Summits on the Air"""
|
"""Activity ref data provider for Summits on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "SOTA"
|
ACTIVITY = ActivityName.SOTA
|
||||||
DATA_URL = "https://storage.sota.org.uk/summitslist.csv"
|
DATA_URL = "https://storage.sota.org.uk/summitslist.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import csv
|
import csv
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.local_file_activity_ref_data_provider import (
|
from providers.activityrefdata.local_file_activity_ref_data_provider import (
|
||||||
LocalFileActivityRefDataProvider,
|
LocalFileActivityRefDataProvider,
|
||||||
@@ -10,7 +10,7 @@ from providers.activityrefdata.local_file_activity_ref_data_provider import (
|
|||||||
class Toilets(LocalFileActivityRefDataProvider):
|
class Toilets(LocalFileActivityRefDataProvider):
|
||||||
"""Activity ref data provider for Toilets on the Air"""
|
"""Activity ref data provider for Toilets on the Air"""
|
||||||
|
|
||||||
ACTIVITY = "Toilets"
|
ACTIVITY = ActivityName.TOILETS
|
||||||
PATH = "datafiles/toilets.csv"
|
PATH = "datafiles/toilets.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class Towers(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Towers on the Air"""
|
"""Activity ref data provider for Towers on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "Towers"
|
ACTIVITY = ActivityName.TOWERS
|
||||||
DATA_URL = "https://wwtota.com/servis/generate_csv.php?ref=&filter=all"
|
DATA_URL = "https://wwtota.com/servis/generate_csv.php?ref=&filter=all"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -17,7 +17,7 @@ class WCA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for World Castles Award"""
|
"""Activity ref data provider for World Castles Award"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "WCA"
|
ACTIVITY = ActivityName.WCA
|
||||||
DATA_URL = "https://polo.ham2k.com/data/activities/wca/all-castles.csv"
|
DATA_URL = "https://polo.ham2k.com/data/activities/wca/all-castles.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -11,7 +11,7 @@ class WOTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Wainwrights on the Air"""
|
"""Activity ref data provider for Wainwrights on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 365
|
POLL_INTERVAL_DAYS = 365
|
||||||
ACTIVITY = "WOTA"
|
ACTIVITY = ActivityName.WOTA
|
||||||
DATA_URL = "https://www.wota.org.uk/mapping/data/summits.json"
|
DATA_URL = "https://www.wota.org.uk/mapping/data/summits.json"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class WWBOTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Worldwide Bunkers on the Air"""
|
"""Activity ref data provider for Worldwide Bunkers on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "WWBOTA"
|
ACTIVITY = ActivityName.WWBOTA
|
||||||
DATA_URL = "https://api.wwbota.org/bunkers/?format=CSV"
|
DATA_URL = "https://api.wwbota.org/bunkers/?format=CSV"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import csv
|
import csv
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -12,7 +12,7 @@ class WWFF(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for Worldwide Flora & Fauna"""
|
"""Activity ref data provider for Worldwide Flora & Fauna"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "WWFF"
|
ACTIVITY = ActivityName.WWFF
|
||||||
DATA_URL = "https://wwff.co/wwff-data/wwff_directory.csv"
|
DATA_URL = "https://wwff.co/wwff-data/wwff_directory.csv"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from time import sleep
|
|||||||
|
|
||||||
from pyhamtools.locator import latlong_to_locator
|
from pyhamtools.locator import latlong_to_locator
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
from providers.activityrefdata.file_download_activity_ref_data_provider import (
|
||||||
FileDownloadActivityRefDataProvider,
|
FileDownloadActivityRefDataProvider,
|
||||||
@@ -13,7 +13,7 @@ class ZLOTA(FileDownloadActivityRefDataProvider):
|
|||||||
"""Activity ref data provider for New Zealand on the Air"""
|
"""Activity ref data provider for New Zealand on the Air"""
|
||||||
|
|
||||||
POLL_INTERVAL_DAYS = 30
|
POLL_INTERVAL_DAYS = 30
|
||||||
ACTIVITY = "ZLOTA"
|
ACTIVITY = ActivityName.ZLOTA
|
||||||
DATA_URL = "https://ontheair.nz/assets/assets.json"
|
DATA_URL = "https://ontheair.nz/assets/assets.json"
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from datetime import datetime, timedelta
|
|||||||
import pytz
|
import pytz
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.http_alert_provider import HTTPAlertProvider
|
from providers.alert.http_alert_provider import HTTPAlertProvider
|
||||||
@@ -55,8 +56,8 @@ class BOTA(HTTPAlertProvider):
|
|||||||
alert = Alert(
|
alert = Alert(
|
||||||
source=self.name,
|
source=self.name,
|
||||||
dx_calls=[dx_call],
|
dx_calls=[dx_call],
|
||||||
sig="BOTA",
|
sig=ActivityName.BOTA,
|
||||||
sig_refs=[ActivityRef(id=ref_name, sig="BOTA")],
|
sig_refs=[ActivityRef(id=ref_name, sig=ActivityName.BOTA)],
|
||||||
start_time=date_time.timestamp(),
|
start_time=date_time.timestamp(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.http_alert_provider import HTTPAlertProvider
|
from providers.alert.http_alert_provider import HTTPAlertProvider
|
||||||
@@ -34,11 +35,11 @@ class Hamsat(HTTPAlertProvider):
|
|||||||
dx_calls=[source_alert["callsign"].upper()],
|
dx_calls=[source_alert["callsign"].upper()],
|
||||||
freqs_modes=freqs_modes,
|
freqs_modes=freqs_modes,
|
||||||
comment=source_alert["comment"],
|
comment=source_alert["comment"],
|
||||||
sig="Satellite",
|
sig=ActivityName.SATELLITE,
|
||||||
# Fudge an activity ref to provide the remaining bits of data we need: the satellite and the operator's grid
|
# Fudge an activity ref to provide the remaining bits of data we need: the satellite and the operator's grid
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
sig="Satellite",
|
sig=ActivityName.SATELLITE,
|
||||||
id=f"{source_alert['satellite']['name']} from {source_alert['grids'][0]}",
|
id=f"{source_alert['satellite']['name']} from {source_alert['grids'][0]}",
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import pytz
|
|||||||
from rss_parser import Parser
|
from rss_parser import Parser
|
||||||
from rss_parser.models.rss import RSS
|
from rss_parser.models.rss import RSS
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.http_alert_provider import HTTPAlertProvider
|
from providers.alert.http_alert_provider import HTTPAlertProvider
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@ class NG3K(HTTPAlertProvider):
|
|||||||
comment=f"{by}; {comment}; {qsl_info}",
|
comment=f"{by}; {comment}; {qsl_info}",
|
||||||
start_time=start_timestamp,
|
start_time=start_timestamp,
|
||||||
end_time=end_timestamp,
|
end_time=end_timestamp,
|
||||||
sig="DXpedition",
|
sig=ActivityName.DXPEDITION,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add to our list.
|
# Add to our list.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.http_alert_provider import HTTPAlertProvider
|
from providers.alert.http_alert_provider import HTTPAlertProvider
|
||||||
@@ -39,7 +40,7 @@ class ParksNPeaks(HTTPAlertProvider):
|
|||||||
activity_refs = []
|
activity_refs = []
|
||||||
# PnP can give us an alert of class "QRP" which is the only one that's not a real activity in Spothole's
|
# PnP can give us an alert of class "QRP" which is the only one that's not a real activity in Spothole's
|
||||||
# list, so mask this out if we got it.
|
# list, so mask this out if we got it.
|
||||||
if activity != "QRP":
|
if activity != ActivityName.QRP:
|
||||||
activity_refs = [ActivityRef(id=ref_id, sig=activity, name=ref_name)]
|
activity_refs = [ActivityRef(id=ref_id, sig=activity, name=ref_name)]
|
||||||
|
|
||||||
# Convert to our alert format
|
# Convert to our alert format
|
||||||
@@ -56,22 +57,22 @@ class ParksNPeaks(HTTPAlertProvider):
|
|||||||
|
|
||||||
# Log a warning for the developer if PnP gives us an unknown programme we've never seen before
|
# Log a warning for the developer if PnP gives us an unknown programme we've never seen before
|
||||||
if activity and activity not in [
|
if activity and activity not in [
|
||||||
"POTA",
|
ActivityName.POTA,
|
||||||
"SOTA",
|
ActivityName.SOTA,
|
||||||
"WWFF",
|
ActivityName.WWFF,
|
||||||
"HEMA",
|
ActivityName.HEMA,
|
||||||
"SIOTA",
|
ActivityName.SIOTA,
|
||||||
"ZLOTA",
|
ActivityName.ZLOTA,
|
||||||
"KRMNPA",
|
ActivityName.KRMNPA,
|
||||||
"SANPCPA",
|
ActivityName.SANPCPA,
|
||||||
"LLOTA",
|
ActivityName.LLOTA,
|
||||||
"QRP",
|
ActivityName.QRP,
|
||||||
]:
|
]:
|
||||||
logger.warning(f"PNP alert found with activity {activity}, developer needs to add support for this!")
|
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
|
# 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
|
# 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.
|
# means the PnP *spot* provider rejects ZLOTA spots here, but the PnP *alerts* provider here allows ZLOTA.
|
||||||
if activity not in ["POTA", "SOTA", "WWFF"]:
|
if activity not in [ActivityName.POTA, ActivityName.SOTA, ActivityName.WWFF]:
|
||||||
new_alerts.append(alert)
|
new_alerts.append(alert)
|
||||||
return new_alerts
|
return new_alerts
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.http_alert_provider import HTTPAlertProvider
|
from providers.alert.http_alert_provider import HTTPAlertProvider
|
||||||
@@ -27,11 +28,11 @@ class POTA(HTTPAlertProvider):
|
|||||||
dx_calls=[source_alert["activator"].upper()],
|
dx_calls=[source_alert["activator"].upper()],
|
||||||
freqs_modes=source_alert["frequencies"],
|
freqs_modes=source_alert["frequencies"],
|
||||||
comment=source_alert["comments"],
|
comment=source_alert["comments"],
|
||||||
sig="POTA",
|
sig=ActivityName.POTA,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=source_alert["reference"],
|
id=source_alert["reference"],
|
||||||
sig="POTA",
|
sig=ActivityName.POTA,
|
||||||
name=source_alert["name"],
|
name=source_alert["name"],
|
||||||
url=f"https://pota.app/#/park/{source_alert['reference']}",
|
url=f"https://pota.app/#/park/{source_alert['reference']}",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import re
|
|||||||
from icalendar import Event
|
from icalendar import Event
|
||||||
|
|
||||||
from core.enums import Continent
|
from core.enums import Continent
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.ical_alert_provider import ICALAlertProvider
|
from providers.alert.ical_alert_provider import ICALAlertProvider
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ class RSGBICALAlertProvider(ICALAlertProvider):
|
|||||||
comment=summary,
|
comment=summary,
|
||||||
start_time=start_timestamp,
|
start_time=start_timestamp,
|
||||||
end_time=end_timestamp,
|
end_time=end_timestamp,
|
||||||
sig="Contest",
|
sig=ActivityName.CONTEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
return alert
|
return alert
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.http_alert_provider import HTTPAlertProvider
|
from providers.alert.http_alert_provider import HTTPAlertProvider
|
||||||
@@ -33,11 +34,11 @@ class SOTA(HTTPAlertProvider):
|
|||||||
dx_names=[source_alert["activatorName"].upper()],
|
dx_names=[source_alert["activatorName"].upper()],
|
||||||
freqs_modes=source_alert["frequency"],
|
freqs_modes=source_alert["frequency"],
|
||||||
comment=source_alert["comments"],
|
comment=source_alert["comments"],
|
||||||
sig="SOTA",
|
sig=ActivityName.SOTA,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=f"{source_alert['associationCode']}/{source_alert['summitCode']}",
|
id=f"{source_alert['associationCode']}/{source_alert['summitCode']}",
|
||||||
sig="SOTA",
|
sig=ActivityName.SOTA,
|
||||||
name=summit_name,
|
name=summit_name,
|
||||||
activation_score=summit_points,
|
activation_score=summit_points,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from icalendar import Event
|
from icalendar import Event
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.ical_alert_provider import ICALAlertProvider
|
from providers.alert.ical_alert_provider import ICALAlertProvider
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ class WA7BNM(ICALAlertProvider):
|
|||||||
url=url,
|
url=url,
|
||||||
start_time=start_timestamp,
|
start_time=start_timestamp,
|
||||||
end_time=end_timestamp,
|
end_time=end_timestamp,
|
||||||
sig="Contest",
|
sig=ActivityName.CONTEST,
|
||||||
)
|
)
|
||||||
|
|
||||||
return alert
|
return alert
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import pytz
|
|||||||
from rss_parser import Parser as RSSParser
|
from rss_parser import Parser as RSSParser
|
||||||
from rss_parser.models.rss import RSS
|
from rss_parser.models.rss import RSS
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.http_alert_provider import HTTPAlertProvider
|
from providers.alert.http_alert_provider import HTTPAlertProvider
|
||||||
@@ -74,7 +75,7 @@ class WOTA(HTTPAlertProvider):
|
|||||||
dx_calls=[dx_call],
|
dx_calls=[dx_call],
|
||||||
freqs_modes=freqs_modes,
|
freqs_modes=freqs_modes,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
sig_refs=[ActivityRef(id=ref, sig="WOTA", name=ref_name)] if ref else [],
|
sig_refs=[ActivityRef(id=ref, sig=ActivityName.WOTA, name=ref_name)] if ref else [],
|
||||||
start_time=time.timestamp(),
|
start_time=time.timestamp(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.alert import Alert
|
from data.alert import Alert
|
||||||
from providers.alert.http_alert_provider import HTTPAlertProvider
|
from providers.alert.http_alert_provider import HTTPAlertProvider
|
||||||
@@ -27,8 +28,8 @@ class WWFF(HTTPAlertProvider):
|
|||||||
dx_calls=[source_alert["activator_call"].upper()],
|
dx_calls=[source_alert["activator_call"].upper()],
|
||||||
freqs_modes=f"{source_alert['band']} {source_alert['mode']}",
|
freqs_modes=f"{source_alert['band']} {source_alert['mode']}",
|
||||||
comment=source_alert["remarks"],
|
comment=source_alert["remarks"],
|
||||||
sig="WWFF",
|
sig=ActivityName.WWFF,
|
||||||
sig_refs=[ActivityRef(id=source_alert["reference"], sig="WWFF")],
|
sig_refs=[ActivityRef(id=source_alert["reference"], sig=ActivityName.WWFF)],
|
||||||
start_time=datetime.strptime(source_alert["utc_start"], "%Y-%m-%d %H:%M:%S")
|
start_time=datetime.strptime(source_alert["utc_start"], "%Y-%m-%d %H:%M:%S")
|
||||||
.replace(tzinfo=pytz.UTC)
|
.replace(tzinfo=pytz.UTC)
|
||||||
.timestamp(),
|
.timestamp(),
|
||||||
|
|||||||
+18
-17
@@ -4,7 +4,8 @@ from datetime import datetime
|
|||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
from core.enums import ActivityRefType, Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from core.url_data_cache import URLDataCache
|
from core.url_data_cache import URLDataCache
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
@@ -106,40 +107,40 @@ class GMA(HTTPSpotProvider):
|
|||||||
spot.sig_refs
|
spot.sig_refs
|
||||||
and ref_info
|
and ref_info
|
||||||
and "reftype" in ref_info
|
and "reftype" in ref_info
|
||||||
and ref_info["reftype"] not in ["POTA", "WWFF"]
|
and ref_info["reftype"] not in [ActivityName.POTA, ActivityName.WWFF]
|
||||||
and (
|
and (
|
||||||
ref_info["reftype"] != "Summit" or "sota" not in ref_info or ref_info["sota"] == ""
|
ref_info["reftype"] != "Summit" or "sota" not in ref_info or ref_info["sota"] == ""
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
match ref_info["reftype"]:
|
match ref_info["reftype"]:
|
||||||
case "Summit":
|
case "Summit":
|
||||||
spot.sig_refs[0].sig = "GMA"
|
spot.sig_refs[0].sig = ActivityName.GMA
|
||||||
spot.sig_refs[0].ref_type = ActivityRefType.SUMMIT
|
spot.sig_refs[0].ref_type = ActivityRefType.SUMMIT
|
||||||
spot.sig = "GMA"
|
spot.sig = ActivityName.GMA
|
||||||
case "IOTA Island":
|
case "IOTA Island":
|
||||||
spot.sig_refs[0].sig = "IOTA"
|
spot.sig_refs[0].sig = ActivityName.IOTA
|
||||||
spot.sig_refs[0].ref_type = ActivityRefType.ISLAND
|
spot.sig_refs[0].ref_type = ActivityRefType.ISLAND
|
||||||
spot.sig = "IOTA"
|
spot.sig = ActivityName.IOTA
|
||||||
case "GMA Island":
|
case "GMA Island":
|
||||||
spot.sig_refs[0].sig = "GMA Islands"
|
spot.sig_refs[0].sig = ActivityName.GMA_ISLANDS
|
||||||
spot.sig_refs[0].ref_type = ActivityRefType.ISLAND
|
spot.sig_refs[0].ref_type = ActivityRefType.ISLAND
|
||||||
spot.sig = "GMA Islands"
|
spot.sig = ActivityName.GMA_ISLANDS
|
||||||
case "Lighthouse (ILLW)":
|
case "Lighthouse (ILLW)":
|
||||||
spot.sig_refs[0].sig = "ILLW"
|
spot.sig_refs[0].sig = ActivityName.ILLW
|
||||||
spot.sig_refs[0].ref_type = ActivityRefType.LIGHTHOUSE
|
spot.sig_refs[0].ref_type = ActivityRefType.LIGHTHOUSE
|
||||||
spot.sig = "ILLW"
|
spot.sig = ActivityName.ILLW
|
||||||
case "Lighthouse (ARLHS)":
|
case "Lighthouse (ARLHS)":
|
||||||
spot.sig_refs[0].sig = "ARLHS"
|
spot.sig_refs[0].sig = ActivityName.ARLHS
|
||||||
spot.sig_refs[0].ref_type = ActivityRefType.LIGHTHOUSE
|
spot.sig_refs[0].ref_type = ActivityRefType.LIGHTHOUSE
|
||||||
spot.sig = "ARLHS"
|
spot.sig = ActivityName.ARLHS
|
||||||
case "Castle":
|
case "Castle":
|
||||||
spot.sig_refs[0].sig = "WCA"
|
spot.sig_refs[0].sig = ActivityName.WCA
|
||||||
spot.sig_refs[0].ref_type = ActivityRefType.CASTLE
|
spot.sig_refs[0].ref_type = ActivityRefType.CASTLE
|
||||||
spot.sig = "WCA"
|
spot.sig = ActivityName.WCA
|
||||||
case "Mill":
|
case "Mill":
|
||||||
spot.sig_refs[0].sig = "MOTA"
|
spot.sig_refs[0].sig = ActivityName.MOTA
|
||||||
spot.sig_refs[0].ref_type = ActivityRefType.MILL
|
spot.sig_refs[0].ref_type = ActivityRefType.MILL
|
||||||
spot.sig = "MOTA"
|
spot.sig = ActivityName.MOTA
|
||||||
case _:
|
case _:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"GMA spot found with ref type {ref_info['reftype']}, developer needs to add support for this!"
|
f"GMA spot found with ref type {ref_info['reftype']}, developer needs to add support for this!"
|
||||||
@@ -170,7 +171,7 @@ class GMA(HTTPSpotProvider):
|
|||||||
return new_spots
|
return new_spots
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "GMA"
|
return activity == ActivityName.GMA
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
# TODO: Implement.
|
# TODO: Implement.
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import requests
|
|||||||
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
|
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
from core.enums import ActivityRefType, Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -62,11 +63,11 @@ class HEMA(HTTPSpotProvider):
|
|||||||
freq=float(freq_mode_match.group(1)) * 1000000,
|
freq=float(freq_mode_match.group(1)) * 1000000,
|
||||||
mode=Mode.from_name(freq_mode_match.group(2).upper()),
|
mode=Mode.from_name(freq_mode_match.group(2).upper()),
|
||||||
comment=spotter_comment_match.group(2),
|
comment=spotter_comment_match.group(2),
|
||||||
sig="HEMA",
|
sig=ActivityName.HEMA,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=spot_items[3].upper(),
|
id=spot_items[3].upper(),
|
||||||
sig="HEMA",
|
sig=ActivityName.HEMA,
|
||||||
name=spot_items[4],
|
name=spot_items[4],
|
||||||
latitude=float(spot_items[7]),
|
latitude=float(spot_items[7]),
|
||||||
longitude=float(spot_items[8]),
|
longitude=float(spot_items[8]),
|
||||||
@@ -90,7 +91,7 @@ class HEMA(HTTPSpotProvider):
|
|||||||
return new_spots
|
return new_spots
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "HEMA"
|
return activity == ActivityName.HEMA
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
# TODO: Implement. Currently blocked awaiting their API team to make a change to allow us to spot with a
|
# TODO: Implement. Currently blocked awaiting their API team to make a change to allow us to spot with a
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from core.enums import ActivityRefType, Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -34,11 +35,11 @@ class LLOTA(HTTPSpotProvider):
|
|||||||
freq=float(source_spot["frequency"]) * 1000000,
|
freq=float(source_spot["frequency"]) * 1000000,
|
||||||
mode=Mode.from_name(source_spot["mode"].upper()),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=comment,
|
comment=comment,
|
||||||
sig="LLOTA",
|
sig=ActivityName.LLOTA,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=source_spot["reference"],
|
id=source_spot["reference"],
|
||||||
sig="LLOTA",
|
sig=ActivityName.LLOTA,
|
||||||
name=source_spot["reference_name"],
|
name=source_spot["reference_name"],
|
||||||
ref_type=ActivityRefType.LAKE,
|
ref_type=ActivityRefType.LAKE,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import requests
|
|||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
from core.enums import Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -21,15 +22,15 @@ class ParksNPeaks(HTTPSpotProvider):
|
|||||||
SPOTS_URL = "https://www.parksnpeaks.org/api/ALL"
|
SPOTS_URL = "https://www.parksnpeaks.org/api/ALL"
|
||||||
SUBMIT_URL = "https://www.parksnpeaks.org/api/SPOT/"
|
SUBMIT_URL = "https://www.parksnpeaks.org/api/SPOT/"
|
||||||
SUBMITTABLE_ACTIVITIES = [
|
SUBMITTABLE_ACTIVITIES = [
|
||||||
"POTA",
|
ActivityName.POTA,
|
||||||
"SOTA",
|
ActivityName.SOTA,
|
||||||
"WWFF",
|
ActivityName.WWFF,
|
||||||
"HEMA",
|
ActivityName.HEMA,
|
||||||
"WOTA",
|
ActivityName.WOTA,
|
||||||
"ZLOTA",
|
ActivityName.ZLOTA,
|
||||||
"SIOTA",
|
ActivityName.SIOTA,
|
||||||
"KRMNPA",
|
ActivityName.KRMNPA,
|
||||||
"SANPCPA",
|
ActivityName.SANPCPA,
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, provider_config):
|
def __init__(self, provider_config):
|
||||||
@@ -68,7 +69,7 @@ class ParksNPeaks(HTTPSpotProvider):
|
|||||||
# programme with a defined set of references
|
# programme with a defined set of references
|
||||||
activity = source_spot["actClass"].upper()
|
activity = source_spot["actClass"].upper()
|
||||||
ref_id = source_spot["actSiteID"]
|
ref_id = source_spot["actSiteID"]
|
||||||
if activity and activity != "" and activity != "QRP" and ref_id and ref_id != "":
|
if activity and activity != "" and activity != ActivityName.QRP and ref_id and ref_id != "":
|
||||||
spot.sig = activity
|
spot.sig = activity
|
||||||
activity_refs = [
|
activity_refs = [
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
@@ -84,15 +85,15 @@ class ParksNPeaks(HTTPSpotProvider):
|
|||||||
|
|
||||||
# Log a warning for the developer if PnP gives us an unknown programme we've never seen before
|
# Log a warning for the developer if PnP gives us an unknown programme we've never seen before
|
||||||
if activity not in [
|
if activity not in [
|
||||||
"POTA",
|
ActivityName.POTA,
|
||||||
"SOTA",
|
ActivityName.SOTA,
|
||||||
"WWFF",
|
ActivityName.WWFF,
|
||||||
"HEMA",
|
ActivityName.HEMA,
|
||||||
"SIOTA",
|
ActivityName.SIOTA,
|
||||||
"ZLOTA",
|
ActivityName.ZLOTA,
|
||||||
"KRMNPA",
|
ActivityName.KRMNPA,
|
||||||
"SANPCPA",
|
ActivityName.SANPCPA,
|
||||||
"LLOTA",
|
ActivityName.LLOTA,
|
||||||
]:
|
]:
|
||||||
logger.warning(f"PNP spot found with activity {activity}, developer needs to add support for this!")
|
logger.warning(f"PNP spot found with activity {activity}, developer needs to add support for this!")
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import pytz
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
from core.enums import ActivityRefType, Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -33,11 +34,11 @@ class POTA(HTTPSpotProvider):
|
|||||||
freq=float(source_spot["frequency"]) * 1000 if source_spot["frequency"] != "INVALID" else None,
|
freq=float(source_spot["frequency"]) * 1000 if source_spot["frequency"] != "INVALID" else None,
|
||||||
mode=Mode.from_name(source_spot["mode"].upper()),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=source_spot["comments"],
|
comment=source_spot["comments"],
|
||||||
sig="POTA",
|
sig=ActivityName.POTA,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=source_spot["reference"],
|
id=source_spot["reference"],
|
||||||
sig="POTA",
|
sig=ActivityName.POTA,
|
||||||
name=source_spot["name"],
|
name=source_spot["name"],
|
||||||
latitude=source_spot["latitude"],
|
latitude=source_spot["latitude"],
|
||||||
longitude=source_spot["longitude"],
|
longitude=source_spot["longitude"],
|
||||||
@@ -58,7 +59,7 @@ class POTA(HTTPSpotProvider):
|
|||||||
return new_spots
|
return new_spots
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "POTA"
|
return activity == ActivityName.POTA
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
sig_ref = spot.sig_refs[0].id if spot.sig_refs else None
|
sig_ref = spot.sig_refs[0].id if spot.sig_refs else None
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import requests
|
|||||||
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
|
from requests.exceptions import ConnectionError, ConnectTimeout, ReadTimeout
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
from core.enums import ActivityRefType, Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -56,11 +57,11 @@ class SOTA(HTTPSpotProvider):
|
|||||||
# Seen SOTA spots with no frequency!
|
# Seen SOTA spots with no frequency!
|
||||||
mode=Mode.from_name(source_spot["mode"].upper()),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=source_spot["comments"],
|
comment=source_spot["comments"],
|
||||||
sig="SOTA",
|
sig=ActivityName.SOTA,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=source_spot["summitCode"],
|
id=source_spot["summitCode"],
|
||||||
sig="SOTA",
|
sig=ActivityName.SOTA,
|
||||||
name=source_spot["summitName"],
|
name=source_spot["summitName"],
|
||||||
latitude=source_spot["latitude"],
|
latitude=source_spot["latitude"],
|
||||||
longitude=source_spot["longitude"],
|
longitude=source_spot["longitude"],
|
||||||
@@ -83,7 +84,7 @@ class SOTA(HTTPSpotProvider):
|
|||||||
return new_spots
|
return new_spots
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "SOTA"
|
return activity == ActivityName.SOTA
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
# TODO test this method works
|
# TODO test this method works
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ from datetime import datetime
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from core.constants import HTTP_HEADERS
|
from core.constants import HTTP_HEADERS
|
||||||
from core.enums import ActivityRefType, LocationSourceForSpot, Mode
|
from core.enums import LocationSourceForSpot, Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -58,13 +59,13 @@ class Tiles(HTTPSpotProvider):
|
|||||||
freq=freq,
|
freq=freq,
|
||||||
mode=Mode.from_name(source_spot["mode"].upper()),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=source_spot["notes"],
|
comment=source_spot["notes"],
|
||||||
sig="Tiles",
|
sig=ActivityName.TILES,
|
||||||
# Tiles spots can include POTA & SOTA references, but ignore those on the basis that we will get them separately from the POTA/SOTA providers anyway.
|
# Tiles spots can include POTA & SOTA references, but ignore those on the basis that we will get them separately from the POTA/SOTA providers anyway.
|
||||||
# Just take the grid reference itself as the single Tiles activity reference.
|
# Just take the grid reference itself as the single Tiles activity reference.
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=source_spot["maidenhead_grid"],
|
id=source_spot["maidenhead_grid"],
|
||||||
sig="Tiles",
|
sig=ActivityName.TILES,
|
||||||
name=source_spot["maidenhead_grid"],
|
name=source_spot["maidenhead_grid"],
|
||||||
latitude=source_spot["latitude"],
|
latitude=source_spot["latitude"],
|
||||||
longitude=source_spot["longitude"],
|
longitude=source_spot["longitude"],
|
||||||
@@ -84,7 +85,7 @@ class Tiles(HTTPSpotProvider):
|
|||||||
return new_spots
|
return new_spots
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "Tiles"
|
return activity == ActivityName.TILES
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
# Tiles on the air currently only supports *self* spots
|
# Tiles on the air currently only supports *self* spots
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from core.enums import ActivityRefType
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -34,8 +34,8 @@ class Towers(HTTPSpotProvider):
|
|||||||
dx_call=source_spot["call"].upper(),
|
dx_call=source_spot["call"].upper(),
|
||||||
freq=likely_freq,
|
freq=likely_freq,
|
||||||
comment=source_spot["comment"],
|
comment=source_spot["comment"],
|
||||||
sig="Towers",
|
sig=ActivityName.TOWERS,
|
||||||
sig_refs=[ActivityRef(id=source_spot["ref"], sig="Towers", ref_type=ActivityRefType.TOWER)],
|
sig_refs=[ActivityRef(id=source_spot["ref"], sig=ActivityName.TOWERS, ref_type=ActivityRefType.TOWER)],
|
||||||
time=datetime.strptime(response_json["updated"][:10] + source_spot["time"], "%Y-%m-%d%H:%M")
|
time=datetime.strptime(response_json["updated"][:10] + source_spot["time"], "%Y-%m-%d%H:%M")
|
||||||
.replace(tzinfo=pytz.utc)
|
.replace(tzinfo=pytz.utc)
|
||||||
.timestamp(),
|
.timestamp(),
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import pytz
|
|||||||
from rss_parser import Parser
|
from rss_parser import Parser
|
||||||
from rss_parser.models.rss import RSS
|
from rss_parser.models.rss import RSS
|
||||||
|
|
||||||
from core.enums import ActivityRefType, Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -90,8 +91,12 @@ class WOTA(HTTPSpotProvider):
|
|||||||
freq=freq_hz,
|
freq=freq_hz,
|
||||||
mode=Mode.from_name(mode),
|
mode=Mode.from_name(mode),
|
||||||
comment=comment,
|
comment=comment,
|
||||||
sig="WOTA",
|
sig=ActivityName.WOTA,
|
||||||
sig_refs=[ActivityRef(id=ref, sig="WOTA", name=ref_name, ref_type=ActivityRefType.SUMMIT)] if ref else [],
|
sig_refs=(
|
||||||
|
[ActivityRef(id=ref, sig=ActivityName.WOTA, name=ref_name, ref_type=ActivityRefType.SUMMIT)]
|
||||||
|
if ref
|
||||||
|
else []
|
||||||
|
),
|
||||||
time=time.timestamp(),
|
time=time.timestamp(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -105,7 +110,7 @@ class WOTA(HTTPSpotProvider):
|
|||||||
return new_spots
|
return new_spots
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "WOTA"
|
return activity == ActivityName.WOTA
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
# TODO Ask M5TEA if he's happy to share how this is done from his app
|
# TODO Ask M5TEA if he's happy to share how this is done from his app
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from core.enums import ActivityRefType, Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.sse_spot_provider import SSESpotProvider
|
from providers.spot.sse_spot_provider import SSESpotProvider
|
||||||
@@ -23,7 +24,7 @@ class WWBOTA(SSESpotProvider):
|
|||||||
for ref in source_spot["references"]:
|
for ref in source_spot["references"]:
|
||||||
activity_ref = ActivityRef(
|
activity_ref = ActivityRef(
|
||||||
id=ref["reference"],
|
id=ref["reference"],
|
||||||
sig="WWBOTA",
|
sig=ActivityName.WWBOTA,
|
||||||
name=ref["name"],
|
name=ref["name"],
|
||||||
latitude=ref["lat"],
|
latitude=ref["lat"],
|
||||||
longitude=ref["long"],
|
longitude=ref["long"],
|
||||||
@@ -38,7 +39,7 @@ class WWBOTA(SSESpotProvider):
|
|||||||
freq=float(source_spot["freq"]) * 1000000,
|
freq=float(source_spot["freq"]) * 1000000,
|
||||||
mode=Mode.from_name(source_spot["mode"].upper()) if "mode" in source_spot else None,
|
mode=Mode.from_name(source_spot["mode"].upper()) if "mode" in source_spot else None,
|
||||||
comment=source_spot["comment"],
|
comment=source_spot["comment"],
|
||||||
sig="WWBOTA",
|
sig=ActivityName.WWBOTA,
|
||||||
sig_refs=refs,
|
sig_refs=refs,
|
||||||
time=datetime.fromisoformat(source_spot["time"].replace("Z", "+00:00")).timestamp(),
|
time=datetime.fromisoformat(source_spot["time"].replace("Z", "+00:00")).timestamp(),
|
||||||
# WWBOTA spots can contain multiple references for bunkers being activated simultaneously. For
|
# WWBOTA spots can contain multiple references for bunkers being activated simultaneously. For
|
||||||
@@ -53,7 +54,7 @@ class WWBOTA(SSESpotProvider):
|
|||||||
return spot if source_spot["type"] != "Test" else None
|
return spot if source_spot["type"] != "Test" else None
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "WWBOTA"
|
return activity == ActivityName.WWBOTA
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
# TODO: Implement. WWBOTA API docs cover this: https://api.wwbota.org/#tag/Spots/operation/create_spot_spots__post
|
# TODO: Implement. WWBOTA API docs cover this: https://api.wwbota.org/#tag/Spots/operation/create_spot_spots__post
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ from datetime import datetime
|
|||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from core.enums import ActivityRefType, Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName, ActivityRefType
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -30,11 +31,11 @@ class WWFF(HTTPSpotProvider):
|
|||||||
freq=float(source_spot["frequency_khz"]) * 1000,
|
freq=float(source_spot["frequency_khz"]) * 1000,
|
||||||
mode=Mode.from_name(source_spot["mode"].upper()),
|
mode=Mode.from_name(source_spot["mode"].upper()),
|
||||||
comment=source_spot["remarks"],
|
comment=source_spot["remarks"],
|
||||||
sig="WWFF",
|
sig=ActivityName.WWFF,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=source_spot["reference"],
|
id=source_spot["reference"],
|
||||||
sig="WWFF",
|
sig=ActivityName.WWFF,
|
||||||
name=source_spot["reference_name"],
|
name=source_spot["reference_name"],
|
||||||
latitude=source_spot["latitude"],
|
latitude=source_spot["latitude"],
|
||||||
longitude=source_spot["longitude"],
|
longitude=source_spot["longitude"],
|
||||||
@@ -52,7 +53,7 @@ class WWFF(HTTPSpotProvider):
|
|||||||
return new_spots
|
return new_spots
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "WWFF"
|
return activity == ActivityName.WWFF
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
# TODO: Implement. Spotting to WWFF should be possible, need to look up the Spotline docs or copy approach from
|
# TODO: Implement. Spotting to WWFF should be possible, need to look up the Spotline docs or copy approach from
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from datetime import datetime
|
|||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
from core.enums import Mode
|
from core.enums import Mode
|
||||||
|
from core.enums import ActivityName
|
||||||
from data.activity_ref import ActivityRef
|
from data.activity_ref import ActivityRef
|
||||||
from data.spot import Spot
|
from data.spot import Spot
|
||||||
from providers.spot.http_spot_provider import HTTPSpotProvider
|
from providers.spot.http_spot_provider import HTTPSpotProvider
|
||||||
@@ -35,11 +36,11 @@ class ZLOTA(HTTPSpotProvider):
|
|||||||
freq=freq_hz,
|
freq=freq_hz,
|
||||||
mode=Mode.from_name(source_spot["mode"].upper().strip()),
|
mode=Mode.from_name(source_spot["mode"].upper().strip()),
|
||||||
comment=source_spot["comments"],
|
comment=source_spot["comments"],
|
||||||
sig="ZLOTA",
|
sig=ActivityName.ZLOTA,
|
||||||
sig_refs=[
|
sig_refs=[
|
||||||
ActivityRef(
|
ActivityRef(
|
||||||
id=source_spot["reference"],
|
id=source_spot["reference"],
|
||||||
sig="ZLOTA",
|
sig=ActivityName.ZLOTA,
|
||||||
name=source_spot["name"],
|
name=source_spot["name"],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -52,7 +53,7 @@ class ZLOTA(HTTPSpotProvider):
|
|||||||
return new_spots
|
return new_spots
|
||||||
|
|
||||||
def can_submit_spot(self, activity):
|
def can_submit_spot(self, activity):
|
||||||
return activity == "ZLOTA"
|
return activity == ActivityName.ZLOTA
|
||||||
|
|
||||||
def submit_spot(self, spot, credentials):
|
def submit_spot(self, spot, credentials):
|
||||||
# TODO: Implement. Spotting to ZLOTA is supported via POST, see https://ontheair.nz/api
|
# TODO: Implement. Spotting to ZLOTA is supported via POST, see https://ontheair.nz/api
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
Vestigios de España (DMVE), Diploma Estaciones de Ferrocarril de España (DEFE), Diploma Teatri Musei e Belle
|
Vestigios de España (DMVE), Diploma Estaciones de Ferrocarril de España (DEFE), Diploma Teatri Musei e Belle
|
||||||
Arti (DTMBA), British Inland Waterways on the Air (BIWOTA), Castles on the Air (COTA), Polish Gmina Award (PGA),
|
Arti (DTMBA), British Inland Waterways on the Air (BIWOTA), Castles on the Air (COTA), Polish Gmina Award (PGA),
|
||||||
Diplôme des Moulins de France (DMF), RaDAR Rally, and Toilets on the Air.</p>
|
Diplôme des Moulins de France (DMF), RaDAR Rally, and Toilets on the Air.</p>
|
||||||
<p>As of the time of writing in August 2026, I think Spothole captures most outdoor radio programmes that have a
|
<p>As of the time of writing in August 2026, I think Spothole captures most radio programmes that have a
|
||||||
defined, downloadable reference list, and almost certainly those that have a spotting/alerting API. If you know
|
defined, downloadable reference list, and almost certainly those that have a spotting/alerting API. If you know
|
||||||
of one I've missed, please let me know!</p>
|
of one I've missed, please let me know!</p>
|
||||||
<h4 class="mt-4">Why can I filter spots by both Activity and Source? Isn't that basically the same thing?</h4>
|
<h4 class="mt-4">Why can I filter spots by both Activity and Source? Isn't that basically the same thing?</h4>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import tornado_eventsource.handler
|
|||||||
from tornado import httputil
|
from tornado import httputil
|
||||||
from tornado.web import Application
|
from tornado.web import Application
|
||||||
|
|
||||||
|
from core.enums import ActivityName
|
||||||
from core.utils import safe_json_dumps
|
from core.utils import safe_json_dumps
|
||||||
from data.lookup_credentials import extract_credentials
|
from data.lookup_credentials import extract_credentials
|
||||||
|
|
||||||
@@ -168,13 +169,13 @@ def alert_allowed_by_query(alert, query):
|
|||||||
# the alert is a dxpedition, or contests_skip_max_duration_check and the alert is a contest, it also
|
# the alert is a dxpedition, or contests_skip_max_duration_check and the alert is a contest, it also
|
||||||
# always passes the check.
|
# always passes the check.
|
||||||
if (
|
if (
|
||||||
alert.sig == "DXpedition"
|
alert.sig == ActivityName.DXPEDITION
|
||||||
and "dxpeditions_skip_max_duration_check" in query
|
and "dxpeditions_skip_max_duration_check" in query
|
||||||
and query.get("dxpeditions_skip_max_duration_check").upper() == "TRUE"
|
and query.get("dxpeditions_skip_max_duration_check").upper() == "TRUE"
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
if (
|
if (
|
||||||
alert.sig == "Contest"
|
alert.sig == ActivityName.CONTEST
|
||||||
and "contests_skip_max_duration_check" in query
|
and "contests_skip_max_duration_check" in query
|
||||||
and query.get("contests_skip_max_duration_check").upper() == "TRUE"
|
and query.get("contests_skip_max_duration_check").upper() == "TRUE"
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ from tornado import httputil
|
|||||||
from tornado.web import Application
|
from tornado.web import Application
|
||||||
|
|
||||||
from core.activity_lookup_helper import populate_missing_activity_ref_info
|
from core.activity_lookup_helper import populate_missing_activity_ref_info
|
||||||
from core.activity_utils import get_ref_regex_for_activity
|
from core.activity_utils import get_activity_by_name, get_ref_regex_for_activity
|
||||||
from core.call_lookup_helper import get_call_info
|
from core.call_lookup_helper import get_call_info
|
||||||
from core.constants import ACTIVITIES
|
|
||||||
from core.geo_utils import (
|
from core.geo_utils import (
|
||||||
lat_lon_for_grid_sw_corner_plus_size,
|
lat_lon_for_grid_sw_corner_plus_size,
|
||||||
lat_lon_to_cq_zone,
|
lat_lon_to_cq_zone,
|
||||||
@@ -85,7 +84,7 @@ class APILookupActivityRefHandler(tornado.web.RequestHandler):
|
|||||||
if "sig" in query_params and "id" in query_params:
|
if "sig" in query_params and "id" in query_params:
|
||||||
activity = str(query_params.get("sig")).upper()
|
activity = str(query_params.get("sig")).upper()
|
||||||
ref_id = str(query_params.get("id")).upper()
|
ref_id = str(query_params.get("id")).upper()
|
||||||
if activity in [a.name.upper() for a in ACTIVITIES]:
|
if get_activity_by_name(activity):
|
||||||
if not get_ref_regex_for_activity(activity) or re.match(
|
if not get_ref_regex_for_activity(activity) or re.match(
|
||||||
get_ref_regex_for_activity(activity), ref_id
|
get_ref_regex_for_activity(activity), ref_id
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ from tornado import httputil
|
|||||||
from tornado.web import Application
|
from tornado.web import Application
|
||||||
|
|
||||||
from core.config import ALLOW_SPOTTING, MAX_SPOT_AGE
|
from core.config import ALLOW_SPOTTING, MAX_SPOT_AGE
|
||||||
from core.constants import ACTIVITIES, BANDS, PROPAGATION_MODES
|
from core.constants import BANDS, PROPAGATION_MODES
|
||||||
from core.enums import Continent, Mode, ModeType
|
from core.enums import Continent, Mode, ModeType
|
||||||
from core.utils import safe_json_dumps
|
from core.utils import safe_json_dumps
|
||||||
|
from data.activities import ACTIVITIES
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ class APIOptionsHandler(tornado.web.RequestHandler):
|
|||||||
# for provider in self._spot_providers:
|
# for provider in self._spot_providers:
|
||||||
# if not provider.enabled:
|
# if not provider.enabled:
|
||||||
# continue
|
# continue
|
||||||
# for activity in ACTIVITIES:
|
# for activity in ACTIVITIES.values():
|
||||||
# if provider.can_submit_spot(activity.name):
|
# if provider.can_submit_spot(activity.name):
|
||||||
# spot_submit_providers.setdefault(activity.name, []).append(provider.name)
|
# spot_submit_providers.setdefault(activity.name, []).append(provider.name)
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ class APIOptionsHandler(tornado.web.RequestHandler):
|
|||||||
"bands": BANDS,
|
"bands": BANDS,
|
||||||
"modes": [m.value for m in Mode],
|
"modes": [m.value for m in Mode],
|
||||||
"mode_types": [t.value for t in ModeType],
|
"mode_types": [t.value for t in ModeType],
|
||||||
"sigs": ACTIVITIES,
|
"sigs": list(ACTIVITIES.values()),
|
||||||
"spot_providers": spot_providers,
|
"spot_providers": spot_providers,
|
||||||
"spot_providers_enabled_by_default": spot_providers_enabled_by_default,
|
"spot_providers_enabled_by_default": spot_providers_enabled_by_default,
|
||||||
"alert_providers": alert_providers,
|
"alert_providers": alert_providers,
|
||||||
|
|||||||
Reference in New Issue
Block a user