From 266468f938ac15eb7586b282bd09e4eadb4e68ae Mon Sep 17 00:00:00 2001 From: Ian Renton Date: Thu, 30 Jul 2026 18:56:53 +0100 Subject: [PATCH] Most providers don't need the ability to override names --- alertproviders/alert_provider.py | 4 +- alertproviders/bota.py | 2 +- alertproviders/http_alert_provider.py | 4 +- alertproviders/ng3k.py | 2 +- alertproviders/parksnpeaks.py | 2 +- alertproviders/pota.py | 2 +- alertproviders/sota.py | 2 +- alertproviders/wota.py | 2 +- alertproviders/wwff.py | 2 +- config-example.yml | 39 +++---------------- solarconditionsproviders/giroionosonde.py | 2 +- solarconditionsproviders/hamqsl.py | 2 +- .../http_solar_conditions_provider.py | 4 +- solarconditionsproviders/kc2gprop.py | 2 +- solarconditionsproviders/noaa3dayforecast.py | 2 +- .../solar_conditions_provider.py | 4 +- spotproviders/aprsis.py | 2 +- spotproviders/dxcluster.py | 7 +++- spotproviders/gma.py | 2 +- spotproviders/hema.py | 2 +- spotproviders/http_spot_provider.py | 4 +- spotproviders/llota.py | 2 +- spotproviders/parksnpeaks.py | 2 +- spotproviders/pota.py | 2 +- spotproviders/rbn.py | 3 +- spotproviders/sota.py | 2 +- spotproviders/spot_provider.py | 4 +- spotproviders/sse_spot_provider.py | 4 +- spotproviders/tiles.py | 2 +- spotproviders/towers.py | 2 +- spotproviders/ukpacketnet.py | 2 +- spotproviders/websocket_spot_provider.py | 4 +- spotproviders/wota.py | 2 +- spotproviders/wwbota.py | 2 +- spotproviders/wwff.py | 2 +- spotproviders/xota.py | 3 +- spotproviders/zlota.py | 2 +- templates/about.html | 1 - templates/add_spot.html | 2 +- templates/alerts.html | 2 +- templates/bands.html | 4 +- templates/base.html | 10 ++--- templates/conditions.html | 2 +- templates/map.html | 4 +- templates/spots.html | 4 +- templates/status.html | 2 +- 46 files changed, 72 insertions(+), 93 deletions(-) diff --git a/alertproviders/alert_provider.py b/alertproviders/alert_provider.py index c8b3dce..9645e97 100644 --- a/alertproviders/alert_provider.py +++ b/alertproviders/alert_provider.py @@ -8,10 +8,10 @@ from core.config import MAX_ALERT_AGE class AlertProvider: """Generic alert provider class. Subclasses of this query the individual APIs for alerts.""" - def __init__(self, provider_config): + def __init__(self, name, provider_config): """Constructor""" - self.name = provider_config["name"] + self.name = name self.enabled = provider_config["enabled"] self.last_update_time = datetime.min.replace(tzinfo=pytz.UTC) self.status = "Not Started" if self.enabled else "Disabled" diff --git a/alertproviders/bota.py b/alertproviders/bota.py index 75ce33f..003a405 100644 --- a/alertproviders/bota.py +++ b/alertproviders/bota.py @@ -15,7 +15,7 @@ class BOTA(HTTPAlertProvider): ALERTS_URL = "https://www.beachesontheair.com/" def __init__(self, provider_config): - super().__init__(provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("BOTA", provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_alerts(self, http_response): new_alerts = [] diff --git a/alertproviders/http_alert_provider.py b/alertproviders/http_alert_provider.py index 9bef504..2522b1b 100644 --- a/alertproviders/http_alert_provider.py +++ b/alertproviders/http_alert_provider.py @@ -14,8 +14,8 @@ class HTTPAlertProvider(AlertProvider): """Generic alert provider class for providers that request data via HTTP(S). Just for convenience to avoid code duplication. Subclasses of this query the individual APIs for data.""" - def __init__(self, provider_config, url, poll_interval): - super().__init__(provider_config) + def __init__(self, name, provider_config, url, poll_interval): + super().__init__(name, provider_config) self._url = url self._poll_interval = poll_interval self._thread = None diff --git a/alertproviders/ng3k.py b/alertproviders/ng3k.py index ac54b0e..8b69d46 100644 --- a/alertproviders/ng3k.py +++ b/alertproviders/ng3k.py @@ -18,7 +18,7 @@ class NG3K(HTTPAlertProvider): AS_CALL_PATTERN = re.compile("as ([a-z0-9/]+)", re.IGNORECASE) def __init__(self, provider_config): - super().__init__(provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("NG3K", provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_alerts(self, http_response): new_alerts = [] diff --git a/alertproviders/parksnpeaks.py b/alertproviders/parksnpeaks.py index 010d99c..7dfb61b 100644 --- a/alertproviders/parksnpeaks.py +++ b/alertproviders/parksnpeaks.py @@ -15,7 +15,7 @@ class ParksNPeaks(HTTPAlertProvider): ALERTS_URL = "https://parksnpeaks.org/api/ALERTS/" def __init__(self, provider_config): - super().__init__(provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("ParksNPeaks", provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_alerts(self, http_response): new_alerts = [] diff --git a/alertproviders/pota.py b/alertproviders/pota.py index 2bff164..1285f02 100644 --- a/alertproviders/pota.py +++ b/alertproviders/pota.py @@ -14,7 +14,7 @@ class POTA(HTTPAlertProvider): ALERTS_URL = "https://api.pota.app/activation" def __init__(self, provider_config): - super().__init__(provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("POTA", provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_alerts(self, http_response): new_alerts = [] diff --git a/alertproviders/sota.py b/alertproviders/sota.py index 6d44153..f1621d7 100644 --- a/alertproviders/sota.py +++ b/alertproviders/sota.py @@ -14,7 +14,7 @@ class SOTA(HTTPAlertProvider): ALERTS_URL = "https://api-db2.sota.org.uk/api/alerts/365/all/all" def __init__(self, provider_config): - super().__init__(provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("SOTA", provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_alerts(self, http_response): new_alerts = [] diff --git a/alertproviders/wota.py b/alertproviders/wota.py index f91e525..7712eca 100644 --- a/alertproviders/wota.py +++ b/alertproviders/wota.py @@ -18,7 +18,7 @@ class WOTA(HTTPAlertProvider): RSS_DATE_TIME_FORMAT = "%a, %d %b %Y %H:%M:%S %z" def __init__(self, provider_config): - super().__init__(provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("WOTA", provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_alerts(self, http_response): new_alerts = [] diff --git a/alertproviders/wwff.py b/alertproviders/wwff.py index a49d543..8a424c2 100644 --- a/alertproviders/wwff.py +++ b/alertproviders/wwff.py @@ -14,7 +14,7 @@ class WWFF(HTTPAlertProvider): ALERTS_URL = "https://spots.wwff.co/static/agendas.json" def __init__(self, provider_config): - super().__init__(provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("WWFF", provider_config, self.ALERTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_alerts(self, http_response): new_alerts = [] diff --git a/config-example.yml b/config-example.yml index 2b545dc..3a63665 100644 --- a/config-example.yml +++ b/config-example.yml @@ -19,66 +19,55 @@ base-url: "http://localhost:8080" # Spot providers to use. This is an example set, tailor it to your liking by commenting and uncommenting. # RBN and APRS-IS are supported but have such a high data rate, you probably don't want them enabled. -# Each provider needs a class, a name, and an enabled/disabled state. Some require more config such as hostnames/IP +# Each provider needs a class and an enabled/disabled state. Some require more config such as hostnames/IP # addresses and ports. You can duplicate them if you like, e.g. to support several DX clusters. RBN uses two ports, 7000 # for CW/RTTY and 7001 for FT8, so if you want both, you need two entries, as shown below. # Feel free to write your own provider classes! There are details in the README. spot-providers: - class: "POTA" - name: "POTA" enabled: true - class: "SOTA" - name: "SOTA" enabled: true - class: "WWFF" - name: "WWFF" enabled: true - class: "WWBOTA" - name: "WWBOTA" enabled: true - class: "GMA" - name: "GMA" enabled: true # GMA requires an API key to fetch spots. After creating an account on cqgma.org, email support and request one. api-key: "" - class: "HEMA" - name: "HEMA" enabled: true - class: "ParksNPeaks" - name: "ParksNPeaks" enabled: true - class: "ZLOTA" - name: "ZLOTA" enabled: true - class: "WOTA" - name: "WOTA" enabled: true - class: "LLOTA" - name: "LLOTA" enabled: true - class: "Towers" - name: "Towers" enabled: true - class: "Tiles" - name: "Tiles" enabled: true - class: "APRSIS" - name: "APRS-IS" enabled: false - class: "DXCluster" + # Clusters have a "name" property in case you want to say which cluster node the data is from, or connect to + # several clusters and name them separately. name: "HRD Cluster" enabled: true host: "hrd.wa9pie.net" @@ -99,18 +88,12 @@ spot-providers: enabled: false host: "w3lpl.net" port: 7373 - # Prompt the cluster node gives when asking for a callsign to log in. Varies between cluster node software. login_prompt: "Please enter your call:" - # Callsign Spothole will use to log into this cluster. Ensure the SSID (e.g. -99) is different to any personal - # connection you might make to this cluster node. login_callsign: "N0CALL-99" - # Whether to allow RBN spots that come via this cluster. If you don't want RBN spots or you are making a separate - # connection to RBN directly, leave this as False. If you want RBN spots from this cluster, set this to True. (Make - # sure you aren't also separately connecting to RBN directly, otherwise you may get duplicate spots.) Note that not - # all clusters sent RBN spots anyway. allow_rbn_spots: false - class: "RBN" + - # RBN sources have a "name" property in case you want to differentiate between the CW/RTTY and FT8 sources. name: "RBN CW/RTTY" enabled: false port: 7000 @@ -127,11 +110,12 @@ spot-providers: enabled-by-default-in-web-ui: false - class: "UKPacketNet" - name: "UK Packet Radio Net" enabled: false enabled-by-default-in-web-ui: false - class: "XOTA" + # xOTA sources have a "name" property so you can define what programme it is for, since xOTA is generic software + # for running "something-on-the-air" programmes. name: "39C3 TOTA" enabled: false url: "wss://39c3.totawatch.de/api/spot/live" @@ -152,31 +136,24 @@ spot-providers: # Alert providers to use. Same setup as the spot providers list above. alert-providers: - class: "POTA" - name: "POTA" enabled: true - class: "SOTA" - name: "SOTA" enabled: true - class: "WWFF" - name: "WWFF" enabled: true - class: "ParksNPeaks" - name: "ParksNPeaks" enabled: true - class: "WOTA" - name: "WOTA" enabled: true - class: "BOTA" - name: "BOTA" enabled: true - class: "NG3K" - name: "NG3K" enabled: true @@ -184,19 +161,15 @@ alert-providers: # conditions, etc.) and make it available via the /api/v1/solar endpoint. solar-condition-providers: - class: "HamQSL" - name: "HamQSL" enabled: true - class: "NOAA3dayForecast" - name: "NOAA 3-day Forecast" enabled: true - class: "GIROIonosonde" - name: "GIRO Ionosonde Data" enabled: true - class: "KC2GProp" - name: "KC2G Propagation Data" enabled: true # Maximum time to keep spots and alerts in the system before deleting them. By default, one hour for spots and one week diff --git a/solarconditionsproviders/giroionosonde.py b/solarconditionsproviders/giroionosonde.py index 1c5795f..a0c94a8 100644 --- a/solarconditionsproviders/giroionosonde.py +++ b/solarconditionsproviders/giroionosonde.py @@ -30,7 +30,7 @@ class GIROIonosonde(SolarConditionsProvider): data, but is less reliable and often offline.""" def __init__(self, provider_config): - super().__init__(provider_config) + super().__init__("GIRO Ionosonde Data", provider_config) self._stations = self._load_stations() self._thread = None self._stop_event = Event() diff --git a/solarconditionsproviders/hamqsl.py b/solarconditionsproviders/hamqsl.py index 92c5306..2d35606 100644 --- a/solarconditionsproviders/hamqsl.py +++ b/solarconditionsproviders/hamqsl.py @@ -15,7 +15,7 @@ class HamQSL(HTTPSolarConditionsProvider): Provides solar flux index, geomagnetic indices, and HF/VHF propagation condition summaries.""" def __init__(self, provider_config): - super().__init__(provider_config, URL, POLL_INTERVAL) + super().__init__("HamQSL", provider_config, URL, POLL_INTERVAL) def _http_response_to_solar_conditions(self, http_response): root = ElementTree.fromstring(http_response.text) diff --git a/solarconditionsproviders/http_solar_conditions_provider.py b/solarconditionsproviders/http_solar_conditions_provider.py index 0f7903e..b5d20be 100644 --- a/solarconditionsproviders/http_solar_conditions_provider.py +++ b/solarconditionsproviders/http_solar_conditions_provider.py @@ -14,8 +14,8 @@ class HTTPSolarConditionsProvider(SolarConditionsProvider): """Generic solar conditions provider for providers that request data via HTTP(S). Subclasses implement _http_response_to_solar_conditions() to parse the specific API response format.""" - def __init__(self, provider_config, url, poll_interval): - super().__init__(provider_config) + def __init__(self, name, provider_config, url, poll_interval): + super().__init__(name, provider_config) self._url = url self._poll_interval = poll_interval self._thread = None diff --git a/solarconditionsproviders/kc2gprop.py b/solarconditionsproviders/kc2gprop.py index 16af204..1229206 100644 --- a/solarconditionsproviders/kc2gprop.py +++ b/solarconditionsproviders/kc2gprop.py @@ -24,7 +24,7 @@ class KC2GProp(SolarConditionsProvider): online, but has fewer stations and does not provide LUF data.""" def __init__(self, provider_config): - super().__init__(provider_config) + super().__init__("KC2G Propagation Data", provider_config) self._thread = None self._stop_event = Event() diff --git a/solarconditionsproviders/noaa3dayforecast.py b/solarconditionsproviders/noaa3dayforecast.py index de5bf1a..52a7750 100644 --- a/solarconditionsproviders/noaa3dayforecast.py +++ b/solarconditionsproviders/noaa3dayforecast.py @@ -13,7 +13,7 @@ class NOAA3dayForecast(HTTPSolarConditionsProvider): corresponding fields in the solar conditions object..""" def __init__(self, provider_config): - super().__init__(provider_config, URL, POLL_INTERVAL) + super().__init__("NOAA 3-day Forecast", provider_config, URL, POLL_INTERVAL) @staticmethod def _parse_percentage_table(lines, section_header, year): diff --git a/solarconditionsproviders/solar_conditions_provider.py b/solarconditionsproviders/solar_conditions_provider.py index 6967166..bc939f7 100644 --- a/solarconditionsproviders/solar_conditions_provider.py +++ b/solarconditionsproviders/solar_conditions_provider.py @@ -7,11 +7,11 @@ class SolarConditionsProvider: """Generic solar conditions provider class. Subclasses of this query individual APIs for space weather and propagation data.""" - def __init__(self, provider_config): + def __init__(self, name, provider_config): """Constructor""" self._solar_conditions_cache = None - self.name = provider_config["name"] + self.name = name self.enabled = provider_config["enabled"] self.last_update_time = datetime.min.replace(tzinfo=pytz.UTC) self.status = "Not Started" if self.enabled else "Disabled" diff --git a/spotproviders/aprsis.py b/spotproviders/aprsis.py index 9178949..4aaac7c 100644 --- a/spotproviders/aprsis.py +++ b/spotproviders/aprsis.py @@ -14,7 +14,7 @@ class APRSIS(SpotProvider): """Spot provider for the APRS-IS.""" def __init__(self, provider_config): - super().__init__(provider_config) + super().__init__("APRS-IS", provider_config) self._thread = Thread(target=self._connect) self._thread.daemon = True self._aprsis = None diff --git a/spotproviders/dxcluster.py b/spotproviders/dxcluster.py index 3cb4c37..db00fc6 100644 --- a/spotproviders/dxcluster.py +++ b/spotproviders/dxcluster.py @@ -26,7 +26,8 @@ class DXCluster(SpotProvider): def __init__(self, provider_config): """Constructor requires hostname and port""" - super().__init__(provider_config) + name = provider_config["name"] if "name" in provider_config else "Cluster" + super().__init__(name, provider_config) self._hostname = provider_config["host"] self._port = provider_config["port"] self._login_prompt = provider_config["login_prompt"] if "login_prompt" in provider_config else "login:" @@ -59,6 +60,10 @@ class DXCluster(SpotProvider): self._telnet.write((self._login_callsign + "\n").encode("latin-1")) connected = True logging.info("DX Cluster " + self._hostname + " connected.") + except ConnectionRefusedError: + self.status = "Error" + logging.warning("Connection refused to DX cluster " + self._hostname) + sleep(300) except Exception: self.status = "Error" logging.exception("Exception while connecting to DX Cluster Provider (" + self._hostname + ").") diff --git a/spotproviders/gma.py b/spotproviders/gma.py index 3942238..8a7d2f0 100644 --- a/spotproviders/gma.py +++ b/spotproviders/gma.py @@ -26,7 +26,7 @@ class GMA(HTTPSpotProvider): provider_config["enabled"] = False logging.warning("GMA spot provider configured but no api key was provided, this API will not be queried.") - super().__init__(provider_config, self.SPOTS_URL + "?key=" + self.api_key, self.POLL_INTERVAL_SEC) + super().__init__("GMA", provider_config, self.SPOTS_URL + "?key=" + self.api_key, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/hema.py b/spotproviders/hema.py index b5d2d13..05dc4e7 100644 --- a/spotproviders/hema.py +++ b/spotproviders/hema.py @@ -25,7 +25,7 @@ class HEMA(HTTPSpotProvider): SPOTTER_COMMENT_PATTERN = re.compile("^\\((.*)\\) (.*)$") def __init__(self, provider_config): - super().__init__(provider_config, self.SPOT_SEED_URL, self.POLL_INTERVAL_SEC) + super().__init__("HEMA", provider_config, self.SPOT_SEED_URL, self.POLL_INTERVAL_SEC) self._spot_seed = "" def _http_response_to_spots(self, http_response): diff --git a/spotproviders/http_spot_provider.py b/spotproviders/http_spot_provider.py index bf083a5..08eaa4f 100644 --- a/spotproviders/http_spot_provider.py +++ b/spotproviders/http_spot_provider.py @@ -15,8 +15,8 @@ class HTTPSpotProvider(SpotProvider): """Generic spot provider class for providers that request data via HTTP(S). Just for convenience to avoid code duplication. Subclasses of this query the individual APIs for data.""" - def __init__(self, provider_config, url, poll_interval): - super().__init__(provider_config) + def __init__(self, name, provider_config, url, poll_interval): + super().__init__(name, provider_config) self._url = url self._poll_interval = poll_interval self._thread = None diff --git a/spotproviders/llota.py b/spotproviders/llota.py index 609c158..7ec8ea4 100644 --- a/spotproviders/llota.py +++ b/spotproviders/llota.py @@ -12,7 +12,7 @@ class LLOTA(HTTPSpotProvider): SPOTS_URL = "https://llota.app/api/public/spots" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("LLOTA", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/parksnpeaks.py b/spotproviders/parksnpeaks.py index 0a7ea7a..808857e 100644 --- a/spotproviders/parksnpeaks.py +++ b/spotproviders/parksnpeaks.py @@ -17,7 +17,7 @@ class ParksNPeaks(HTTPSpotProvider): SIOTA_LIST_URL = "https://www.silosontheair.com/data/silos.csv" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("ParksNPeaks", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/pota.py b/spotproviders/pota.py index e3eafbf..0d29440 100644 --- a/spotproviders/pota.py +++ b/spotproviders/pota.py @@ -14,7 +14,7 @@ class POTA(HTTPSpotProvider): SPOTS_URL = "https://api.pota.app/spot/activator" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("POTA", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/rbn.py b/spotproviders/rbn.py index 038a8be..4fbf8c6 100644 --- a/spotproviders/rbn.py +++ b/spotproviders/rbn.py @@ -23,7 +23,8 @@ class RBN(SpotProvider): def __init__(self, provider_config): """Constructor requires port number.""" - super().__init__(provider_config) + name = provider_config["name"] if "name" in provider_config else "RBN" + super().__init__(name, provider_config) self._port = provider_config["port"] self._telnet = None self._thread = Thread(target=self._handle) diff --git a/spotproviders/sota.py b/spotproviders/sota.py index eef05b4..ca7079d 100644 --- a/spotproviders/sota.py +++ b/spotproviders/sota.py @@ -23,7 +23,7 @@ class SOTA(HTTPSpotProvider): SUMMIT_URL_ROOT = "https://api-db2.sota.org.uk/api/summits/" def __init__(self, provider_config): - super().__init__(provider_config, self.EPOCH_URL, self.POLL_INTERVAL_SEC) + super().__init__("SOTA", provider_config, self.EPOCH_URL, self.POLL_INTERVAL_SEC) self._api_epoch = "" def _http_response_to_spots(self, http_response): diff --git a/spotproviders/spot_provider.py b/spotproviders/spot_provider.py index 7647d6f..6b19a2c 100644 --- a/spotproviders/spot_provider.py +++ b/spotproviders/spot_provider.py @@ -8,10 +8,10 @@ from core.config import MAX_SPOT_AGE class SpotProvider: """Generic spot provider class. Subclasses of this query the individual APIs for data.""" - def __init__(self, provider_config): + def __init__(self, name, provider_config): """Constructor""" - self.name = provider_config["name"] + self.name = name self.enabled = provider_config["enabled"] self.last_update_time = datetime.min.replace(tzinfo=pytz.UTC) self.last_spot_time = datetime.min.replace(tzinfo=pytz.UTC) diff --git a/spotproviders/sse_spot_provider.py b/spotproviders/sse_spot_provider.py index 6fa25d2..312e854 100644 --- a/spotproviders/sse_spot_provider.py +++ b/spotproviders/sse_spot_provider.py @@ -13,8 +13,8 @@ from spotproviders.spot_provider import SpotProvider class SSESpotProvider(SpotProvider): """Spot provider using Server-Sent Events.""" - def __init__(self, provider_config, url): - super().__init__(provider_config) + def __init__(self, name, provider_config, url): + super().__init__(name, provider_config) self._url = url self._event_source = None self._thread = None diff --git a/spotproviders/tiles.py b/spotproviders/tiles.py index ae56faa..b22eddd 100644 --- a/spotproviders/tiles.py +++ b/spotproviders/tiles.py @@ -12,7 +12,7 @@ class Tiles(HTTPSpotProvider): SPOTS_URL = "https://icneuzxitdqtofutxbla.supabase.co/functions/v1/spots?active_hours=24" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("Tiles", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/towers.py b/spotproviders/towers.py index 4f337ed..6d09022 100644 --- a/spotproviders/towers.py +++ b/spotproviders/towers.py @@ -13,7 +13,7 @@ class Towers(HTTPSpotProvider): SPOTS_URL = "https://wwtota.com/api/cluster_live.php" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("Towers", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/ukpacketnet.py b/spotproviders/ukpacketnet.py index 7d4758a..dc309d3 100644 --- a/spotproviders/ukpacketnet.py +++ b/spotproviders/ukpacketnet.py @@ -14,7 +14,7 @@ class UKPacketNet(HTTPSpotProvider): SPOTS_URL = "https://nodes.ukpacketradio.network/api/nodedata" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("UK Packet Net", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/websocket_spot_provider.py b/spotproviders/websocket_spot_provider.py index 0c6c8d5..25c9161 100644 --- a/spotproviders/websocket_spot_provider.py +++ b/spotproviders/websocket_spot_provider.py @@ -13,8 +13,8 @@ from spotproviders.spot_provider import SpotProvider class WebsocketSpotProvider(SpotProvider): """Spot provider using websockets.""" - def __init__(self, provider_config, url): - super().__init__(provider_config) + def __init__(self, name, provider_config, url): + super().__init__(name, provider_config) self._url = url self._ws = None self._thread = None diff --git a/spotproviders/wota.py b/spotproviders/wota.py index bd903b0..079968f 100644 --- a/spotproviders/wota.py +++ b/spotproviders/wota.py @@ -21,7 +21,7 @@ class WOTA(HTTPSpotProvider): RSS_DATE_TIME_FORMAT = "%a, %d %b %Y %H:%M:%S %z" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("WOTA", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/wwbota.py b/spotproviders/wwbota.py index c2358c7..53204b3 100644 --- a/spotproviders/wwbota.py +++ b/spotproviders/wwbota.py @@ -12,7 +12,7 @@ class WWBOTA(SSESpotProvider): SPOTS_URL = "https://api.wwbota.net/spots/" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL) + super().__init__("WWBOTA", provider_config, self.SPOTS_URL) def _sse_message_to_spot(self, message): source_spot = json.loads(message) diff --git a/spotproviders/wwff.py b/spotproviders/wwff.py index 38bd042..8e3642e 100644 --- a/spotproviders/wwff.py +++ b/spotproviders/wwff.py @@ -14,7 +14,7 @@ class WWFF(HTTPSpotProvider): SPOTS_URL = "https://spots.wwff.co/static/spots.json" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("WWFF", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/spotproviders/xota.py b/spotproviders/xota.py index bd55eae..8513650 100644 --- a/spotproviders/xota.py +++ b/spotproviders/xota.py @@ -21,7 +21,8 @@ class XOTA(WebsocketSpotProvider): SIG = None def __init__(self, provider_config): - super().__init__(provider_config, provider_config["url"]) + name = provider_config["name"] if "name" in provider_config else "xOTA" + super().__init__(name, provider_config, provider_config["url"]) locations_csv = str(provider_config["locations-csv"]) if "locations-csv" in provider_config else None self.SIG = str(provider_config["sig"]) if "sig" in provider_config else None diff --git a/spotproviders/zlota.py b/spotproviders/zlota.py index cb65c32..1480620 100644 --- a/spotproviders/zlota.py +++ b/spotproviders/zlota.py @@ -15,7 +15,7 @@ class ZLOTA(HTTPSpotProvider): LIST_URL = "https://ontheair.nz/assets/assets.json" def __init__(self, provider_config): - super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) + super().__init__("ZLOTA", provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC) def _http_response_to_spots(self, http_response): new_spots = [] diff --git a/templates/about.html b/templates/about.html index bbeda55..e958702 100644 --- a/templates/about.html +++ b/templates/about.html @@ -117,7 +117,6 @@
  • Some SIGs, such as Worked all Britain (WAB), don't have their own spotting site and can only be identified through comments on spots retrieved from other sources.
  • -
  • SIGs have well-defined names, whereas the server owner may name the sources as they see fit.
  • Spothole's web interface exists not just for the end user, but also as a reference implementation for the API, so I have chosen to demonstrate both methods of filtering.

    diff --git a/templates/add_spot.html b/templates/add_spot.html index 23a9cc8..540222d 100644 --- a/templates/add_spot.html +++ b/templates/add_spot.html @@ -76,7 +76,7 @@ - + diff --git a/templates/alerts.html b/templates/alerts.html index 75f3540..453ffd0 100644 --- a/templates/alerts.html +++ b/templates/alerts.html @@ -75,7 +75,7 @@ - + diff --git a/templates/bands.html b/templates/bands.html index 5c181bd..5d839d4 100644 --- a/templates/bands.html +++ b/templates/bands.html @@ -75,8 +75,8 @@ - - + + diff --git a/templates/base.html b/templates/base.html index 9dd03cb..288c228 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,6 +1,6 @@ {% extends "skeleton.html" %} {% block head_extra %} - + @@ -10,10 +10,10 @@ - - - - + + + + {% end %} {% block body %}
    diff --git a/templates/conditions.html b/templates/conditions.html index 9eea747..4211675 100644 --- a/templates/conditions.html +++ b/templates/conditions.html @@ -284,7 +284,7 @@
    - + diff --git a/templates/map.html b/templates/map.html index ad5e684..0b94bfd 100644 --- a/templates/map.html +++ b/templates/map.html @@ -108,8 +108,8 @@ - - + + diff --git a/templates/spots.html b/templates/spots.html index b659a50..e33c181 100644 --- a/templates/spots.html +++ b/templates/spots.html @@ -116,8 +116,8 @@ - - + + diff --git a/templates/status.html b/templates/status.html index 8b0a5ea..f7223ec 100644 --- a/templates/status.html +++ b/templates/status.html @@ -59,7 +59,7 @@ - +