Implement spot API filtering

This commit is contained in:
Ian Renton
2025-09-28 18:20:27 +01:00
parent 69e0ba0a8d
commit 5a9da59e25
2 changed files with 39 additions and 9 deletions

View File

@@ -69,13 +69,45 @@ class WebServer:
# Utility method to apply filters to the overall spot list and return only a subset. Enables query parameters in
# the main "spots" GET call. The "query" parameter should be the result of bottle's request.query, and is a MultiDict
def get_spot_list_with_filters(self, query):
spot_subset = self.spot_list[:]
# Create a shallow copy of the spot list, ordered by spot time. We'll then filter it accordingly.
# We can filter by spot time and received time with "since" and "received_since", which take a UNIX timestamp
# in seconds UTC.
# We can also filter by source, sig, band, mode, dx_continent and de_continent. Each of these accepts a single
# value or a comma-separated list.
# We can provide a "limit" number as well. Spots are always returned newest-first; "limit" limits to only the
# most recent X spots.
spots = sorted(self.spot_list, key=lambda spot: spot.time, reverse=True)
for k in query.keys():
print(k + ": " + query.get(k))
return spot_subset
match k:
case "since":
since = datetime.fromtimestamp(int(query.get(k)), pytz.UTC)
spots = [s for s in spots if s.time > since]
case "received_since":
since = datetime.fromtimestamp(int(query.get(k)), pytz.UTC)
spots = [s for s in spots if s.received_time > since]
case "source":
sources = query.get(k).split(",")
spots = [s for s in spots if s.source in sources]
case "sig":
sigs = query.get(k).split(",")
spots = [s for s in spots if s.sig in sigs]
case "band":
bands = query.get(k).split(",")
spots = [s for s in spots if s.band in bands]
case "mode":
modes = query.get(k).split(",")
spots = [s for s in spots if s.mode in modes]
case "dx_continent":
dxconts = query.get(k).split(",")
spots = [s for s in spots if s.dx_continent in dxconts]
case "de_continent":
deconts = query.get(k).split(",")
spots = [s for s in spots if s.de_continent in deconts]
# If we have a "limit" parameter, we apply that last, regardless of where it appeared in the list of keys.
if "limit" in query.keys():
spots = spots[:int(query.get("limit"))]
return spots
# Todo serve Server-Sent Events to frontend - see https://medium.com/@tdenton8772/streaming-api-design-using-python-and-javascript-1b0ce8adb703
# Todo serve Server-Sent Events to frontend? - see https://medium.com/@tdenton8772/streaming-api-design-using-python-and-javascript-1b0ce8adb703
# Todo serve apidocs