This commit is contained in:
Josh Hawkins 2024-12-15 12:24:03 -06:00
parent 17f8939f97
commit 17ee5c2ab8
3 changed files with 74 additions and 43 deletions

View File

@ -13,6 +13,7 @@ from frigate.const import (
CLEAR_ONGOING_REVIEW_SEGMENTS, CLEAR_ONGOING_REVIEW_SEGMENTS,
INSERT_MANY_RECORDINGS, INSERT_MANY_RECORDINGS,
INSERT_PREVIEW, INSERT_PREVIEW,
NOTIFICATION_TEST,
REQUEST_REGION_GRID, REQUEST_REGION_GRID,
UPDATE_CAMERA_ACTIVITY, UPDATE_CAMERA_ACTIVITY,
UPDATE_EMBEDDINGS_REINDEX_PROGRESS, UPDATE_EMBEDDINGS_REINDEX_PROGRESS,
@ -191,6 +192,9 @@ class Dispatcher:
json.dumps(self.embeddings_reindex.copy()), json.dumps(self.embeddings_reindex.copy()),
) )
def handle_notification_test():
self.publish("notification_test", "Test notification")
# Dictionary mapping topic to handlers # Dictionary mapping topic to handlers
topic_handlers = { topic_handlers = {
INSERT_MANY_RECORDINGS: handle_insert_many_recordings, INSERT_MANY_RECORDINGS: handle_insert_many_recordings,
@ -202,6 +206,7 @@ class Dispatcher:
UPDATE_EVENT_DESCRIPTION: handle_update_event_description, UPDATE_EVENT_DESCRIPTION: handle_update_event_description,
UPDATE_MODEL_STATE: handle_update_model_state, UPDATE_MODEL_STATE: handle_update_model_state,
UPDATE_EMBEDDINGS_REINDEX_PROGRESS: handle_update_embeddings_reindex_progress, UPDATE_EMBEDDINGS_REINDEX_PROGRESS: handle_update_embeddings_reindex_progress,
NOTIFICATION_TEST: handle_notification_test,
"restart": handle_restart, "restart": handle_restart,
"embeddingsReindexProgress": handle_embeddings_reindex_progress, "embeddingsReindexProgress": handle_embeddings_reindex_progress,
"modelState": handle_model_state, "modelState": handle_model_state,

View File

@ -116,17 +116,71 @@ class WebPushClient(Communicator): # type: ignore[misc]
if topic == "reviews": if topic == "reviews":
self.send_alert(json.loads(payload)) self.send_alert(json.loads(payload))
elif topic == "notification_test":
self.send_notification_test()
def send_alert(self, payload: dict[str, any]) -> None: def send_push_notification(
self,
user: str,
payload: dict[str, Any],
title: str,
message: str,
direct_url: str = "",
image: str = "",
notification_type: str = "alert",
ttl: int = 0,
) -> None:
for pusher in self.web_pushers[user]:
endpoint = pusher.subscription_info["endpoint"]
headers = self.claim_headers[endpoint[: endpoint.index("/", 10)]].copy()
headers["urgency"] = "high"
resp = pusher.send(
headers=headers,
ttl=ttl,
data=json.dumps(
{
"title": title,
"message": message,
"direct_url": direct_url,
"image": image,
"id": payload.get("after", {}).get("id", ""),
"type": notification_type,
}
),
)
if resp.status_code in (404, 410):
self.expired_subs.setdefault(user, []).append(endpoint)
elif resp.status_code != 201:
logger.warning(
f"Failed to send notification to {user} :: {resp.headers}"
)
def send_notification_test(self) -> None:
if not self.config.notifications.email: if not self.config.notifications.email:
return return
self.check_registrations() self.check_registrations()
# Only notify for alerts for user in self.web_pushers:
if payload["after"]["severity"] != "alert": self.send_push_notification(
user=user,
payload={},
title="Test Notification",
message="This is a test notification from Frigate.",
notification_type="test",
)
def send_alert(self, payload: dict[str, Any]) -> None:
if (
not self.config.notifications.email
or payload["after"]["severity"] != "alert"
):
return return
self.check_registrations()
state = payload["type"] state = payload["type"]
# Don't notify if message is an update and important fields don't have an update # Don't notify if message is an update and important fields don't have an update
@ -155,47 +209,18 @@ class WebPushClient(Communicator): # type: ignore[misc]
# if event is ongoing open to live view otherwise open to recordings view # if event is ongoing open to live view otherwise open to recordings view
direct_url = f"/review?id={reviewId}" if state == "end" else f"/#{camera}" direct_url = f"/review?id={reviewId}" if state == "end" else f"/#{camera}"
ttl = 3600 if state == "end" else 0
for user, pushers in self.web_pushers.items(): for user in self.web_pushers:
for pusher in pushers: self.send_push_notification(
endpoint = pusher.subscription_info["endpoint"] user=user,
payload=payload,
# set headers for notification behavior title=title,
headers = self.claim_headers[ message=message,
endpoint[0 : endpoint.index("/", 10)] direct_url=direct_url,
].copy() image=image,
headers["urgency"] = "high" ttl=ttl,
ttl = 3600 if state == "end" else 0 )
# send message
resp = pusher.send(
headers=headers,
ttl=ttl,
data=json.dumps(
{
"title": title,
"message": message,
"direct_url": direct_url,
"image": image,
"id": reviewId,
"type": "alert",
}
),
)
if resp.status_code == 201:
pass
elif resp.status_code == 404 or resp.status_code == 410:
# subscription is not found or has been unsubscribed
if not self.expired_subs.get(user):
self.expired_subs[user] = []
self.expired_subs[user].append(pusher.subscription_info["endpoint"])
# the subscription no longer exists and should be removed
else:
logger.warning(
f"Failed to send notification to {user} :: {resp.headers}"
)
self.cleanup_registrations() self.cleanup_registrations()

View File

@ -102,6 +102,7 @@ UPDATE_CAMERA_ACTIVITY = "update_camera_activity"
UPDATE_EVENT_DESCRIPTION = "update_event_description" UPDATE_EVENT_DESCRIPTION = "update_event_description"
UPDATE_MODEL_STATE = "update_model_state" UPDATE_MODEL_STATE = "update_model_state"
UPDATE_EMBEDDINGS_REINDEX_PROGRESS = "handle_embeddings_reindex_progress" UPDATE_EMBEDDINGS_REINDEX_PROGRESS = "handle_embeddings_reindex_progress"
NOTIFICATION_TEST = "notification_test"
# Stats Values # Stats Values