From aff41f6688bb81530b7896f3abaf39ec88fc28fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C4=93teris=20Caune?= <cuu508@gmail.com>
Date: Tue, 17 Dec 2024 08:58:31 +0200
Subject: [PATCH] Update ntfy notification template to include failure reason

cc: #1069
---
 hc/api/tests/test_notify_ntfy.py       | 22 +++++++++++++++++++---
 hc/api/transports.py                   |  1 +
 templates/integrations/ntfy_title.html |  2 +-
 3 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/hc/api/tests/test_notify_ntfy.py b/hc/api/tests/test_notify_ntfy.py
index b45ad5f5..4869e962 100644
--- a/hc/api/tests/test_notify_ntfy.py
+++ b/hc/api/tests/test_notify_ntfy.py
@@ -1,4 +1,3 @@
-
 from __future__ import annotations
 
 import json
@@ -49,6 +48,7 @@ class NotifyNtfyTestCase(BaseTestCase):
         self.flip.created = now()
         self.flip.old_status = "new"
         self.flip.new_status = "down"
+        self.flip.reason = "timeout"
 
     @patch("hc.api.transports.curl.request", autospec=True)
     def test_it_works(self, mock_post: Mock) -> None:
@@ -58,7 +58,10 @@ class NotifyNtfyTestCase(BaseTestCase):
         assert Notification.objects.count() == 1
 
         payload = mock_post.call_args.kwargs["json"]
-        self.assertEqual(payload["title"], "Foo is DOWN")
+        self.assertEqual(
+            payload["title"],
+            "Foo is DOWN (success signal did not arrive on time, grace time passed)",
+        )
         self.assertIn("Project: Alices Project", payload["message"])
         self.assertIn("Tags: foo, bar", payload["message"])
         self.assertIn("Period: 1 day", payload["message"])
@@ -68,6 +71,19 @@ class NotifyNtfyTestCase(BaseTestCase):
         self.assertEqual(payload["actions"][0]["url"], self.check.cloaked_url())
         self.assertNotIn("All the other checks are up.", payload["message"])
 
+    @patch("hc.api.transports.curl.request", autospec=True)
+    def test_it_handles_reason_fail(self, mock_post: Mock) -> None:
+        mock_post.return_value.status_code = 200
+
+        self.flip.reason = "fail"
+        self.channel.notify(self.flip)
+
+        payload = mock_post.call_args.kwargs["json"]
+        self.assertEqual(
+            payload["title"],
+            "Foo is DOWN (received a failure signal)",
+        )
+
     @patch("hc.api.transports.curl.request", autospec=True)
     def test_it_reports_last_pings_exit_code(self, mock_post: Mock) -> None:
         mock_post.return_value.status_code = 200
@@ -101,7 +117,7 @@ class NotifyNtfyTestCase(BaseTestCase):
         self.channel.notify(self.flip)
 
         payload = mock_post.call_args.kwargs["json"]
-        self.assertEqual(payload["title"], "<Name> is DOWN")
+        self.assertIn("<Name> is DOWN", payload["title"])
         self.assertIn("Project: <Alice's Project>", payload["message"])
         self.assertIn("Tags: <foo>", payload["message"])
         self.assertIn("<Foobar>", payload["message"])
diff --git a/hc/api/transports.py b/hc/api/transports.py
index fb50f04c..871ccf75 100644
--- a/hc/api/transports.py
+++ b/hc/api/transports.py
@@ -1603,6 +1603,7 @@ class Ntfy(HttpTransport):
 
     def notify(self, flip: Flip, notification: Notification) -> None:
         ctx = {
+            "flip": flip,
             "check": flip.owner,
             "status": flip.new_status,
             "ping": self.last_ping(flip),
diff --git a/templates/integrations/ntfy_title.html b/templates/integrations/ntfy_title.html
index 002e0f4b..66058573 100644
--- a/templates/integrations/ntfy_title.html
+++ b/templates/integrations/ntfy_title.html
@@ -1 +1 @@
-{{ check.name_then_code|safe }} is {{ status|upper }}
+{{ check.name_then_code|safe }} is {{ status|upper }}{% if flip.reason %} ({{ flip.reason_long }}){% endif %}