Further alert implementation #17

This commit is contained in:
Ian Renton
2025-10-06 21:06:54 +01:00
parent e0675a01f0
commit 6ee4fe288a
14 changed files with 171 additions and 67 deletions

View File

@@ -70,7 +70,8 @@ class WebServer:
if not ALLOW_SPOTTING:
response.content_type = 'application/json'
response.status = 401
return json.dumps("Error - this server does not allow new spots to be added via the API.", default=serialize_everything)
return json.dumps("Error - this server does not allow new spots to be added via the API.",
default=serialize_everything)
# Reject if no spot
if not bottle.request.query.spot:
@@ -86,7 +87,8 @@ class WebServer:
if not spot.time or not spot.dx_call:
response.content_type = 'application/json'
response.status = 422
return json.dumps("Error - 'time' and 'dx_call' must be provided as a minimum.", default=serialize_everything)
return json.dumps("Error - 'time' and 'dx_call' must be provided as a minimum.",
default=serialize_everything)
# infer missing data, and add it to our database.
spot.source = "API"
@@ -169,7 +171,6 @@ class WebServer:
spots = spots[:int(query.get("limit"))]
return spots
# Utility method to apply filters to the overall alert list and return only a subset. Enables query parameters in
# the main "alerts" GET call.
def get_alert_list_with_filters(self):
@@ -185,26 +186,26 @@ class WebServer:
alert_ids = list(self.alerts.iterkeys())
alerts = []
for k in alert_ids:
# While we persist old spots in the system for a while to produce a useful list, any alert that has already
# passed its end time can be explicitly removed from the list to return.
# TODO deal with there being no end time
if self.alerts.get(k).end_time > datetime.now(pytz.UTC).timestamp():
alerts.append(self.alerts.get(k))
alerts.append(self.alerts.get(k))
alerts = sorted(alerts, key=lambda alert: alert.start_time)
for k in query.keys():
match k:
case "received_since":
since = datetime.fromtimestamp(int(query.get(k)), pytz.UTC)
alerts = [s for s in alerts if s.received_time > since]
alerts = [a for a in alerts if a.received_time > since]
case "max_duration":
max_duration = int(query.get(k))
alerts = [a for a in alerts if (a.end_time and a.end_time - a.start_time <= max_duration) or (
not a.end_time and datetime.now(pytz.UTC).timestamp() - a.start_time <= max_duration)]
case "source":
sources = query.get(k).split(",")
alerts = [s for s in alerts if s.source in sources]
alerts = [a for a in alerts if a.source in sources]
case "sig":
sigs = query.get(k).split(",")
alerts = [s for s in alerts if s.sig in sigs]
alerts = [a for a in alerts if a.sig in sigs]
case "dx_continent":
dxconts = query.get(k).split(",")
alerts = [s for s in alerts if s.dx_continent in dxconts]
alerts = [a for a in alerts if a.dx_continent in dxconts]
# 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():
alerts = alerts[:int(query.get("limit"))]
@@ -219,7 +220,9 @@ class WebServer:
"mode_types": MODE_TYPES,
"sigs": SIGS,
# Spot/alert sources are filtered for only ones that are enabled in config, no point letting the user toggle things that aren't even available.
"spot_sources": list(map(lambda p: p["name"], filter(lambda p: p["enabled"], self.status_data["spot_providers"]))),
"alert_sources": list(map(lambda p: p["name"], filter(lambda p: p["enabled"], self.status_data["alert_providers"]))),
"spot_sources": list(
map(lambda p: p["name"], filter(lambda p: p["enabled"], self.status_data["spot_providers"]))),
"alert_sources": list(
map(lambda p: p["name"], filter(lambda p: p["enabled"], self.status_data["alert_providers"]))),
"continents": CONTINENTS,
"max_spot_age": MAX_SPOT_AGE}