From 463ec8c9884fa85c9de9b11ab945a83675b13003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Tue, 6 Oct 2020 16:43:56 +0300 Subject: [PATCH] Set the "title" and "summary" fields in MS Teams notifications Fixes: #435 --- CHANGELOG.md | 1 + hc/api/tests/test_notify.py | 13 +++++++-- hc/api/transports.py | 31 ++++++++++++++++----- templates/integrations/msteams_message.json | 3 +- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27889203..8d5c509f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. - Fix missing Resume button (#421) - When decoding inbound emails, decode encoded headers (#420) - Escape markdown in MS Teams notifications (#426) +- Set the "title" and "summary" fields in MS Teams notifications (#435) ## v1.16.0 - 2020-08-04 diff --git a/hc/api/tests/test_notify.py b/hc/api/tests/test_notify.py index fab6a569..deae430c 100644 --- a/hc/api/tests/test_notify.py +++ b/hc/api/tests/test_notify.py @@ -859,6 +859,8 @@ class NotifyTestCase(BaseTestCase): self._setup_data("msteams", "http://example.com/webhook") mock_post.return_value.status_code = 200 + self.check.name = "_underscores_ & more" + self.channel.notify(self.check) assert Notification.objects.count() == 1 @@ -866,19 +868,24 @@ class NotifyTestCase(BaseTestCase): payload = kwargs["json"] self.assertEqual(payload["@type"], "MessageCard") + # summary and title should be the same, except + # title should have any special HTML characters escaped + self.assertEqual(payload["summary"], "“_underscores_ & more” is DOWN.") + self.assertEqual(payload["title"], "“_underscores_ & more” is DOWN.") + @patch("hc.api.transports.requests.request") - def test_msteams_escapes_markdown(self, mock_post): + def test_msteams_escapes_html_and_markdown_in_desc(self, mock_post): self._setup_data("msteams", "http://example.com/webhook") mock_post.return_value.status_code = 200 - self.check.name = """ + self.check.desc = """ TEST _underscore_ `backticks` underline \\backslash\\ "quoted" """ self.channel.notify(self.check) args, kwargs = mock_post.call_args - text = kwargs["json"]["text"] + text = kwargs["json"]["sections"][0]["text"] self.assertIn(r"\_underscore\_", text) self.assertIn(r"\`backticks\`", text) diff --git a/hc/api/transports.py b/hc/api/transports.py index bbe4a3d8..ba0f1006 100644 --- a/hc/api/transports.py +++ b/hc/api/transports.py @@ -580,17 +580,34 @@ class Apprise(HttpTransport): class MsTeams(HttpTransport): + def escape_md(self, s): + # Escape special HTML characters + s = escape(s) + # Escape characters that have special meaning in Markdown + for c in r"\`*_{}[]()#+-.!|": + s = s.replace(c, "\\" + c) + return s + def notify(self, check): text = tmpl("msteams_message.json", check=check) payload = json.loads(text) - # Escape special HTML characters in check's name - safe_name = escape(check.name_then_code()) - # Escape characters that have special meaning in Markdown - for c in r"\`*_{}[]()#+-.!|": - safe_name = safe_name.replace(c, "\\" + c) - - payload["text"] = f"“{safe_name}” is {check.status.upper()}." + # MS Teams escapes HTML special characters in the summary field. + # It does not interpret summary content as Markdown. + name = check.name_then_code() + payload["summary"] = f"“{name}” is {check.status.upper()}." + + # MS teams *strips* HTML special characters from the title field. + # To avoid that, we use escape(). + # It does not interpret title as Markdown. + safe_name = escape(name) + payload["title"] = f"“{safe_name}” is {check.status.upper()}." + + # MS teams allows some HTML in the section text. + # It also interprets the section text as Markdown. + # We want to display the raw content, angle brackets and all, + # so we run escape() and then additionally escape Markdown: + payload["sections"][0]["text"] = self.escape_md(check.desc) return self.post(self.channel.value, json=payload) diff --git a/templates/integrations/msteams_message.json b/templates/integrations/msteams_message.json index c26b08d6..241aa8e5 100644 --- a/templates/integrations/msteams_message.json +++ b/templates/integrations/msteams_message.json @@ -35,8 +35,7 @@ "name": "Total Pings:", "value": "{{ check.n_pings }}" } - ], - "text": "{{ check.desc|escapejs }}" + ] } ], "potentialAction": [