diff --git a/core/enums.py b/core/enums.py index 7b23f57..107c236 100644 --- a/core/enums.py +++ b/core/enums.py @@ -138,6 +138,7 @@ class ActivityName(str, Enum): BIWOTA = "BIWOTA" COTA = "COTA" PGA = "PGA" + JOTA = "JOTA" TOILETS = "Toilets" def __str__(self): diff --git a/core/status_reporter.py b/core/status_reporter.py index 41f9612..6261e49 100644 --- a/core/status_reporter.py +++ b/core/status_reporter.py @@ -52,7 +52,10 @@ class StatusReporter: """Thread entry point: report immediately on startup, then on each interval until stopped""" while True: - self._report() + try: + self._report() + except Exception: + logger.exception("Exception in Status Reporter thread") if self._stop_event.wait(timeout=self._run_interval): break diff --git a/data/activities.py b/data/activities.py index c1b68c6..2bf3056 100644 --- a/data/activities.py +++ b/data/activities.py @@ -180,28 +180,6 @@ ACTIVITIES: dict[ActivityName, Activity] = { comment_names=["ARLHS"], icon="fa-house-flood-water", ), - ActivityName.ILLW: Activity( - name=ActivityName.ILLW, - description="International Lighthouse & Lightship Weekend", - activity_type=ActivityType.EVENT, - has_refs=True, - refs_globally_unique=False, - ref_type=ActivityRefType.LIGHTHOUSE, - ref_regex=r"[A-Z]{2}\d{4}", - comment_names=["ILLW"], - icon="fa-house-flood-water", - ), - ActivityName.MOTA: Activity( - name=ActivityName.MOTA, - description="Mills on the Air", - activity_type=ActivityType.EVENT, - has_refs=True, - refs_globally_unique=True, - ref_type=ActivityRefType.MILL, - ref_regex=r"X\d{4,6}", - comment_names=["MOTA"], - icon="fa-fan", - ), ActivityName.SIOTA: Activity( name=ActivityName.SIOTA, description="Silos on the Air", @@ -225,32 +203,6 @@ ACTIVITIES: dict[ActivityName, Activity] = { comment_names=["WCA"], icon="fa-chess-rook", ), - ActivityName.ZLOTA: Activity( - name=ActivityName.ZLOTA, - description="New Zealand on the Air", - activity_type=ActivityType.REGIONAL, - has_refs=True, - refs_globally_unique=True, - ref_type=None, - ref_regex=r"ZL[A-Z]/[A-Z]{2}\-\d{3,4}", - comment_names=["ZLOTA"], - icon="fa-kiwi-bird", - region_flag="🇳🇿", - alerts_possible=True, - ), - ActivityName.WOTA: Activity( - name=ActivityName.WOTA, - description="Wainwrights on the Air", - activity_type=ActivityType.REGIONAL, - has_refs=True, - refs_globally_unique=False, - ref_type=ActivityRefType.SUMMIT, - ref_regex=r"[A-Z]{3}-[0-9]{2}", - comment_names=["WOTA"], - icon="fa-w", - region_flag="🇬🇧", - alerts_possible=True, - ), ActivityName.BOTA: Activity( name=ActivityName.BOTA, description="Beaches on the Air", @@ -262,32 +214,6 @@ ACTIVITIES: dict[ActivityName, Activity] = { icon="fa-umbrella-beach", alerts_possible=True, ), - ActivityName.KRMNPA: Activity( - name=ActivityName.KRMNPA, - description="Keith Roget Memorial National Parks Award", - activity_type=ActivityType.REGIONAL, - has_refs=True, - refs_globally_unique=False, - ref_type=ActivityRefType.PARK, - ref_regex=r"VKFF\-\d{4}", - comment_names=["KRMNPA"], - icon="fa-earth-oceania", - region_flag="🇦🇺", - alerts_possible=True, - ), - ActivityName.SANPCPA: Activity( - name=ActivityName.SANPCPA, - description="South Australian National Parks and Conservation Parks Award", - activity_type=ActivityType.REGIONAL, - has_refs=True, - refs_globally_unique=False, - ref_type=ActivityRefType.PARK, - ref_regex=r"VKFF\-\d{4}", - comment_names=["SANPCPA"], - icon="fa-earth-oceania", - region_flag="🇦🇺", - alerts_possible=True, - ), ActivityName.LLOTA: Activity( name=ActivityName.LLOTA, description="Lagos y Lagunas on the Air", @@ -322,14 +248,57 @@ ACTIVITIES: dict[ActivityName, Activity] = { comment_names=[], icon="fa-square", ), - ActivityName.RADAR_RALLY: Activity( - name=ActivityName.RADAR_RALLY, - description="RaDAR Rally", - activity_type=ActivityType.EVENT, - has_refs=False, + ActivityName.ZLOTA: Activity( + name=ActivityName.ZLOTA, + description="New Zealand on the Air", + activity_type=ActivityType.REGIONAL, + has_refs=True, + refs_globally_unique=True, + ref_type=None, + ref_regex=r"ZL[A-Z]/[A-Z]{2}\-\d{3,4}", + comment_names=["ZLOTA"], + icon="fa-kiwi-bird", + region_flag="🇳🇿", + alerts_possible=True, + ), + ActivityName.WOTA: Activity( + name=ActivityName.WOTA, + description="Wainwrights on the Air", + activity_type=ActivityType.REGIONAL, + has_refs=True, refs_globally_unique=False, - comment_names=["RaDAR"], - icon="fa-headset", + ref_type=ActivityRefType.SUMMIT, + ref_regex=r"[A-Z]{3}-[0-9]{2}", + comment_names=["WOTA"], + icon="fa-w", + region_flag="🇬🇧", + alerts_possible=True, + ), + ActivityName.KRMNPA: Activity( + name=ActivityName.KRMNPA, + description="Keith Roget Memorial National Parks Award", + activity_type=ActivityType.REGIONAL, + has_refs=True, + refs_globally_unique=False, + ref_type=ActivityRefType.PARK, + ref_regex=r"VKFF\-\d{4}", + comment_names=["KRMNPA"], + icon="fa-earth-oceania", + region_flag="🇦🇺", + alerts_possible=True, + ), + ActivityName.SANPCPA: Activity( + name=ActivityName.SANPCPA, + description="South Australian National Parks and Conservation Parks Award", + activity_type=ActivityType.REGIONAL, + has_refs=True, + refs_globally_unique=False, + ref_type=ActivityRefType.PARK, + ref_regex=r"VKFF\-\d{4}", + comment_names=["SANPCPA"], + icon="fa-earth-oceania", + region_flag="🇦🇺", + alerts_possible=True, ), ActivityName.WAB: Activity( name=ActivityName.WAB, @@ -453,17 +422,6 @@ ACTIVITIES: dict[ActivityName, Activity] = { icon="fa-landmark", region_flag="🇮🇹", ), - ActivityName.BIWOTA: Activity( - name=ActivityName.BIWOTA, - description="British Inland Waterways on the Air", - activity_type=ActivityType.EVENT, - has_refs=False, - refs_globally_unique=False, - ref_type=ActivityRefType.WATERWAY, - comment_names=["BIWOTA"], - icon="fa-ship", - region_flag="🇬🇧", - ), ActivityName.COTA: Activity( name=ActivityName.COTA, description="Castles on the Air", @@ -488,6 +446,57 @@ ACTIVITIES: dict[ActivityName, Activity] = { icon="fa-g", region_flag="🇵🇱", ), + ActivityName.JOTA: Activity( + name=ActivityName.JOTA, + description="Jamboree on the Air", + activity_type=ActivityType.EVENT, + has_refs=False, + refs_globally_unique=False, + comment_names=["JOTA"], + icon="fa-campground", + ), + ActivityName.ILLW: Activity( + name=ActivityName.ILLW, + description="International Lighthouse & Lightship Weekend", + activity_type=ActivityType.EVENT, + has_refs=True, + refs_globally_unique=False, + ref_type=ActivityRefType.LIGHTHOUSE, + ref_regex=r"[A-Z]{2}\d{4}", + comment_names=["ILLW"], + icon="fa-house-flood-water", + ), + ActivityName.MOTA: Activity( + name=ActivityName.MOTA, + description="Mills on the Air", + activity_type=ActivityType.EVENT, + has_refs=True, + refs_globally_unique=True, + ref_type=ActivityRefType.MILL, + ref_regex=r"X\d{4,6}", + comment_names=["MOTA"], + icon="fa-fan", + ), + ActivityName.RADAR_RALLY: Activity( + name=ActivityName.RADAR_RALLY, + description="RaDAR Rally", + activity_type=ActivityType.EVENT, + has_refs=False, + refs_globally_unique=False, + comment_names=["RaDAR"], + icon="fa-headset", + ), + ActivityName.BIWOTA: Activity( + name=ActivityName.BIWOTA, + description="British Inland Waterways on the Air", + activity_type=ActivityType.EVENT, + has_refs=False, + refs_globally_unique=False, + ref_type=ActivityRefType.WATERWAY, + comment_names=["BIWOTA"], + icon="fa-ship", + region_flag="🇬🇧", + ), ActivityName.TOILETS: Activity( name=ActivityName.TOILETS, description="Toilets on the Air", diff --git a/static/apidocs/openapi.yml b/static/apidocs/openapi.yml index 1e6df06..2b0226f 100644 --- a/static/apidocs/openapi.yml +++ b/static/apidocs/openapi.yml @@ -7,11 +7,7 @@ info: You can find out more information about Spothole at https://spothole.app/help, and specifically about creating a client to this API at https://spothole.app/help/usage/clients. - The API provided by https://spothole.app is provided free of charge, and no authentication is required. By using it, you accept the following: - * You wrote the client code yourself, OR, if you got an AI to write it for you, you promise to read and understand what it wrote before contacting me about any problems. - * You set a sensible refresh rate and will not try to take down the server by bombarding it with tons of requests. - * There is no uptime guarantee. This is a hobby project and sometimes I will accidentally break stuff. - * Trans rights are human rights. + While I provide this API for free, there are some conditions of use that you must adhere to. These are not onerous, but ensure the API can remain available to everyone. These apply even if you are getting an AI to write your client software for you. See https://spothole.app/help/usage/clients#terms for details. ## Changelog diff --git a/templates/add-spot.html b/templates/add-spot.html index 7d8534f..82001fd 100644 --- a/templates/add-spot.html +++ b/templates/add-spot.html @@ -77,7 +77,7 @@ - + diff --git a/templates/alerts.html b/templates/alerts.html index 2a1d88e..1c6f802 100644 --- a/templates/alerts.html +++ b/templates/alerts.html @@ -85,7 +85,7 @@ - + diff --git a/templates/bands.html b/templates/bands.html index 1d106fa..bd4bf1c 100644 --- a/templates/bands.html +++ b/templates/bands.html @@ -76,8 +76,8 @@ - - + + diff --git a/templates/base.html b/templates/base.html index 318967f..b334f70 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,6 +1,6 @@ {% extends "skeleton.html" %} {% block head_extra %} - + @@ -16,10 +16,10 @@ window.fetchEventSource = fetchEventSource; - - - - + + + + {% end %} {% block body %}
Spothole collects no data about you on a permanent basis. All spots and alerts are "timed out" and deleted from - the system after a set interval, which by default is one hour for spots and one week for alerts.
-Settings you select from Spothole's menus are sent to the server, in order to provide the data with the requested - filters. They are also stored in your browser's local storage, so that your preferences are remembered between - sessions.
-The data you provide can optionally include your login credentials for QRZ.com and HamQTH. You can provide these - in the "Your Data" menu of most pages. If you do, Spothole will augment the data it produces with lookups from - these - services, which can for example provide more accurate markers on the map tab, and operator names when you mouse - over a DX callsign. Spothole will still work fine if you don't provide these. The values you enter are sent to - Spothole via HTTPS so are protected in transit, though of course you do have to trust Spothole with this - sensitive data in order to use this feature.
-Any data you send as part of a query, such as your QRZ or HamQTH credentials, is used only for the lifetime of - that - query and is not saved anywhere apart from your own device.
-Spothole uses no trackers, no ads, and no cookies.
- {% if len(web_ui_options["support_button_html"]) > 0 %} -Caveat: The owner of this server has chosen to inject their own content into the "spots" page. - This is designed for a "donate" or "support this server" button. The functionality of this injected content is - the responsibility of the server owner, rather than the Spothole software.
- {% end %} -Spothole is open source, so you can audit the code if you - like.
+Spothole collects no data about you on a permanent basis. All spots and alerts are "timed out" and deleted from + the system after a set interval, which by default is one hour for spots and one week for alerts.
+Settings you select from Spothole's menus are sent to the server, in order to provide the data with the requested + filters. They are also stored in your browser's local storage, so that your preferences are remembered between + sessions.
+The data you provide can optionally include your login credentials for QRZ.com and HamQTH. You can provide these + in the "Your Data" menu of most pages. If you do, Spothole will augment the data it produces with lookups from + these + services, which can for example provide more accurate markers on the map tab, and operator names when you mouse + over a DX callsign. Spothole will still work fine if you don't provide these. The values you enter are sent to + Spothole via HTTPS so are protected in transit, though of course you do have to trust Spothole with this + sensitive data in order to use this feature.
+Any data you send as part of a query, such as your QRZ or HamQTH credentials, is used only for the lifetime of + that + query and is not saved anywhere apart from your own device.
+Spothole uses no trackers, no ads, and no cookies.
+{% if len(web_ui_options["support_button_html"]) > 0 %} +Caveat: The owner of this server has chosen to inject their own content into the "spots" page. + This is designed for a "donate" or "support this server" button. The functionality of this injected content is + the responsibility of the server owner, rather than the Spothole software.
+{% end %} +Spothole is open source, so you can audit the code if you + like.
+ +This server is run by an amateur radio operator with callsign {{ server_owner_callsign }}. You should contact them if + you have any issues with the website.
+Spothole exists as an aggregator of data from many other sources. To the best of my knowledge, all these sources + either:
+If you represent one of these data sources and would like it removed from Spothole, please let me know.
+Spothole does not produce any real data of its own. Information such as spots and alerts that Spothole displays are + entered by users, often of other websites. The data may be the property of the user or the other website, depending + on their terms and conditions.
{% end %} diff --git a/templates/help/usage.html b/templates/help/usage.html index 49b89c3..a146bf4 100644 --- a/templates/help/usage.html +++ b/templates/help/usage.html @@ -6,7 +6,8 @@ technical skill:One of the key strengths of Spothole is that the API is well-defined and open to anyone to use. This means you can @@ -34,11 +32,10 @@
Please don't hammer the API with an unnecessarily high request rate. For example, Spothole only queries the POTA API - once every two minutes, so if your client is interested in POTA data there's no need to poll Spothole any more often - than that.
-If you absolutely must be informed within seconds of a spot arriving in Spothole, please use the SSE endpoints
- instead, e.g. https://spothole.app/api/v3/spots/stream.
If you're fetching spot data, you're unlikely to need a sub-minute refresh time. For example, Spothole only queries
+ the POTA API once every two minutes, so if your client is interested in POTA data there's no need to poll Spothole
+ any more often than that. If you absolutely must be informed within seconds of a spot arriving in Spothole, please
+ use the SSE endpoints instead, e.g. https://spothole.app/api/v3/spots/stream, or the Telnet server.
If you want to handle different types of spot or alert differently within your client, please consider making a
single request to the Spothole API to retrieve all the data, then filtering on your side. For example, call
https://spothole.app/api/v3/spots?activity=POTA,SOTA rather than making two separate calls to
@@ -50,4 +47,33 @@
all means base your own project on data from the main server if you like, but if you want any control over
reliability and downtime, please run your own copy instead.)
There are some simple, hopefully not onerous terms and conditions that you should agree to before writing a client + for the Spothole API. These probably aren't legally binding, and I'm just a random guy on the internet, I'm not + going to sue you for breaching them. But having these conditions in place ensures Spothole can continue to operate + without me burning out and with no payment required. In the collaborative and respectful tradition of amateur radio, + please read and understand them.
+When creating a Spothole client, you agree that:
+Although Spothole is designed "API first" and designed so that more technical users to write their own clients, the + majority of Spothole users use it via its web interface. This page describes that interface and how to use it.
+Across the top of the page, or hidden behind the hamburger menu + button on + mobile, is the main menu which + provides access to all of Spothole's features. These are:
+Conditions, Status, + Help and + API are stanalone pages, while the others have many more options as discussed below.
+ +The spots page displays the traditional web-based "DX cluster" view, with a table of spots. The latest will appear at + the top of the table, and old ones will fall off the bottom. The list keeps itself up to date automatically, but if + you need to temporarily pause it, you can use the Run and + Stop buttons.
+On small screens such as mobile phones, the table will reflow into multiple lines per spot, keeping the alternating + background shading so you can tell spots apart.
+A Search box is provided; this filters the spots so that only DX callsigns or comments that match your entry will be + shown. You can use this to look for specific callsign prefixes, or activities that aren't covered in the main + filters.
+Three buttons at the top of the table provide the means for you to customise what you see and what data is used. + They are common to all the spot/alert pages, and are labelled + Filters, Display and Your data. Clicking each one will expand a menu of further + options.
+ +The Filters panel allows to to adjust what spots and alerts you will see. You can filter by band, mode, DX continent, + DE (spotter) continent, activity, and/or data source.
+Activities include traditional amateur radio activities like DXpeditions and Contests, "adventure" activities like + POTA and SOTA, regional activities specific to a certain country, and event-based activities that only happen at + certain times of year.
+Any of these filter options can be turned on and off as you like.
+ +The Display panel allows to to adjust other aspects of the spots you see. You can configure how many spots you get + on the page, whether UTC or local time is used, what colour scheme is used for pages and frequency bands, which + columns are shown in the table, and whether an audio sound effect is played when new spots pop up.
+In the list of columns, three are disabled by default: Distance, Bearing, and "Worked?". Distance and bearing can + be enabled if you enter your grid locator under Your data. + "Worked?" adds a checkbox next to each row so you can tick off stations you've worked. There's currently no logger + integration; this is just for a quick check when you're using Spothole standalone.
+ +The Your Data panel allows you to enter information specific to you. You can enter your QRZ.com and/or HamQTH + credentials, which will allow Spothole to fetch better data for the spots. You can set your grid locator, and clear + the list of calls you've worked, supporting the features discussed under "Display". You can also enter a list of + "Wanted Calls" (including partial calls), which will cause matching spots to have a gold highlight to catch your + eye.
+ +The map display shows spots visually on a map of the world. The location chosen can be based on various sources, + such as POTA park locations, QRZ.com lookup of an operator's home location, grids in the spot comments, and so on. + They are not guaranteed to be accurate, but should give a rough guide to where in the world each operator is. + You can click on the markers for more information about each spot.
+The Display menu on the + Map page has a few differences to the one on the + Spots page:
+The bands display shows each amateur radio band that has active spots as a column, from lowest frequency at the top + to highest frequency at the bottom. Within it, markers indcate the callsign of the operator spotted on that + frequency. +
+By hovering your mouse over the callsign, you can see the mode and the exact frequency.
+ +The upcoming page shows future park and summit activations, satellite operations, DXpeditions and contests from + various sources, in a table.
+The table differs slightly from the table on the Spots page. + Here, the entries are in the opposite order, with "now" at the top, going further into the future as you scroll + down. The table is also split into three sections: "On Now", "Starting in the next 24 hours", and "Starting later". + Because upcoming alerts don't pop up as often as spots, there is no automatic refresh on this page.
+This page has a unique card in the Filters settings, "Duration + Limit". This allows you to hide long-running activations that hang around in the list for a long time, allowing you + to see the more time-limited ones. Because this is usually only a problem with POTA (where some people add an alert + several weeks long to say they'll be activating at some point during their holiday), you can choose to exclude + DXpeditions and Contests from this filter, because there will almost always be someone on the air during the whole + time the event is live.
+Some upcoming alerts, such as DXpeditions and Contests, have links where you can learn more about them.
+ +The Add Spot page allows you to add a new spot into the Spothole system directly. Currently, this stays within + Spothole and is not sent "upstream" to DX clusters, POTA, SOTA etc. regardless of any activity you select.
+ +{% end %} diff --git a/templates/map.html b/templates/map.html index 76a3a30..416290b 100644 --- a/templates/map.html +++ b/templates/map.html @@ -113,8 +113,8 @@ const CARTODB_API_KEY = "{{ web_ui_options.get('cartodb_api_key', '') }}"; - - + + diff --git a/templates/spots.html b/templates/spots.html index 04c6f90..efc7a3f 100644 --- a/templates/spots.html +++ b/templates/spots.html @@ -125,8 +125,8 @@ - - + + diff --git a/templates/status.html b/templates/status.html index 02e0cfb..2fcc89c 100644 --- a/templates/status.html +++ b/templates/status.html @@ -96,7 +96,7 @@ - +