diff --git a/alertproviders/sota.py b/alertproviders/sota.py new file mode 100644 index 0000000..ced3579 --- /dev/null +++ b/alertproviders/sota.py @@ -0,0 +1,37 @@ +from datetime import datetime + +import pytz + +from alertproviders.http_alert_provider import HTTPAlertProvider +from data.alert import Alert + + +# Alert provider for Summits on the Air +class SOTA(HTTPAlertProvider): + POLL_INTERVAL_SEC = 3600 + 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) + + def http_response_to_alerts(self, http_response): + new_alerts = [] + # Iterate through source data + for source_alert in http_response.json(): + # Convert to our alert format + alert = Alert(source=self.name, + source_id=source_alert["id"], + dx_call=source_alert["activatingCallsign"].upper(), + dx_name=source_alert["activatorName"].upper(), + freqs_modes=source_alert["frequency"], + comment=source_alert["comments"], + sig="SOTA", + sig_refs=[source_alert["associationCode"] + "/" + source_alert["summitCode"]], + sig_refs_names=[source_alert["summitDetails"]], + icon="mountain-sun", + start_time=datetime.strptime(source_alert["dateActivated"], + "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=pytz.UTC).timestamp()) + + # Add to our list + new_alerts.append(alert) + return new_alerts diff --git a/alertproviders/wwff.py b/alertproviders/wwff.py new file mode 100644 index 0000000..98cc34c --- /dev/null +++ b/alertproviders/wwff.py @@ -0,0 +1,37 @@ +from datetime import datetime + +import pytz + +from alertproviders.http_alert_provider import HTTPAlertProvider +from data.alert import Alert + + +# Alert provider for Worldwide Flora and Fauna +class WWFF(HTTPAlertProvider): + POLL_INTERVAL_SEC = 3600 + 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) + + def http_response_to_alerts(self, http_response): + new_alerts = [] + # Iterate through source data + for source_alert in http_response.json(): + # Convert to our alert format + alert = Alert(source=self.name, + source_id=source_alert["id"], + dx_call=source_alert["activator_call"].upper(), + freqs_modes=source_alert["band"] + " " + source_alert["mode"], + comment=source_alert["remarks"], + sig="WWFF", + sig_refs=[source_alert["reference"]], + icon="seedling", + start_time=datetime.strptime(source_alert["utc_start"], + "%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC).timestamp(), + end_time=datetime.strptime(source_alert["utc_end"], + "%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC).timestamp()) + + # Add to our list + new_alerts.append(alert) + return new_alerts diff --git a/config-example.yml b/config-example.yml index 180d3d2..448394e 100644 --- a/config-example.yml +++ b/config-example.yml @@ -68,6 +68,14 @@ alert-providers: class: "POTA" name: "POTA" enabled: true + - + class: "SOTA" + name: "SOTA" + enabled: true + - + class: "WWFF" + name: "WWFF" + enabled: true # Port to open the local web server on web-server-port: 8080 diff --git a/webassets/css/style.css b/webassets/css/style.css index 7060cd1..26504d7 100644 --- a/webassets/css/style.css +++ b/webassets/css/style.css @@ -63,7 +63,7 @@ appears on mobile */ --bs-table-bg-type: var(--bs-table-striped-bg); } -td.nowrap { +td.nowrap, span.nowrap { text-wrap: nowrap; } diff --git a/webassets/js/alerts.js b/webassets/js/alerts.js index e09fb7a..1d8b13e 100644 --- a/webassets/js/alerts.js +++ b/webassets/js/alerts.js @@ -85,8 +85,15 @@ function addAlertRowsToTable(tbody, alerts) { // Format UTC times for display var start_time = moment.unix(a["start_time"]).utc(); var start_time_formatted = start_time.format("YYYY-MM-DD HH:mm"); - var end_time = moment.unix(a["end_time"]).utc(); - var end_time_formatted = (end_time != null) ? end_time.format("YYYY-MM-DD HH:mm") : "Not specified"; + var end_time_unix = moment.unix(a["end_time"]); + var end_time = end_time_unix.utc(); + var end_time_formatted = (end_time_unix != null && end_time_unix > 0 && end_time != null) ? end_time.format("YYYY-MM-DD HH:mm") : "---"; + + // Format DX flag + var dx_flag = ""; + if (a["dx_flag"] && a["dx_flag"] != null && a["dx_flag"] != "") { + dx_flag = a["dx_flag"]; + } // Format dx country var dx_country = a["dx_country"] @@ -115,13 +122,13 @@ function addAlertRowsToTable(tbody, alerts) { // Format sig_refs var sig_refs = "" if (a["sig_refs"]) { - sig_refs = a["sig_refs"].join(", ") + sig_refs = a["sig_refs"].map(a => `${a}`).join(", "); } // Populate the row $tr.append(`