diff --git a/static/images/integrations/bot_avatars/freshping.png b/static/images/integrations/bot_avatars/freshping.png new file mode 100644 index 0000000000..c7d9779e53 Binary files /dev/null and b/static/images/integrations/bot_avatars/freshping.png differ diff --git a/static/images/integrations/freshping/001.png b/static/images/integrations/freshping/001.png new file mode 100644 index 0000000000..e0a02491a8 Binary files /dev/null and b/static/images/integrations/freshping/001.png differ diff --git a/static/images/integrations/logos/freshping.svg b/static/images/integrations/logos/freshping.svg new file mode 100644 index 0000000000..d375538db4 --- /dev/null +++ b/static/images/integrations/logos/freshping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/zerver/lib/integrations.py b/zerver/lib/integrations.py index 1188649d02..451fff0554 100644 --- a/zerver/lib/integrations.py +++ b/zerver/lib/integrations.py @@ -373,6 +373,7 @@ WEBHOOK_INTEGRATIONS: List[WebhookIntegration] = [ WebhookIntegration("errbit", ["monitoring"], display_name="Errbit"), WebhookIntegration("flock", ["customer-support"], display_name="Flock"), WebhookIntegration("freshdesk", ["customer-support"]), + WebhookIntegration("freshping", ["monitoring"], display_name="Freshping"), WebhookIntegration("front", ["customer-support"], display_name="Front"), WebhookIntegration("gitea", ["version-control"], stream_name="commits"), WebhookIntegration( @@ -712,6 +713,7 @@ DOC_SCREENSHOT_CONFIG: Dict[str, List[BaseScreenshotConfig]] = { "freshdesk": [ ScreenshotConfig("ticket_created.json", image_name="004.png", use_basic_auth=True) ], + "freshping": [ScreenshotConfig("freshping_check_unreachable.json")], "front": [ScreenshotConfig("inbound_message.json")], "gci": [ScreenshotConfig("task_abandoned_by_student.json")], "gitea": [ScreenshotConfig("pull_request__merged.json")], diff --git a/zerver/webhooks/freshping/__init__.py b/zerver/webhooks/freshping/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/zerver/webhooks/freshping/doc.md b/zerver/webhooks/freshping/doc.md new file mode 100644 index 0000000000..57f0305c8e --- /dev/null +++ b/zerver/webhooks/freshping/doc.md @@ -0,0 +1,18 @@ +Receive Freshping notifications in Zulip! + +1. {!create-stream.md!} + +1. {!create-bot-construct-url-indented.md!} + +1. Go to your **Freshping** dashboard and click **Settings**. + Click **Integrations** and then click **Create Integration** + under **Webhooks**. + +1. Set **Domain URL** to the URL create above. Click **Create**. + +1. You can test the webhook by clicking **Test** to ensure it is + configured correctly. + +{!congrats.md!} + +![](/static/images/integrations/freshping/001.png) diff --git a/zerver/webhooks/freshping/fixtures/freshping_check_reachable.json b/zerver/webhooks/freshping/fixtures/freshping_check_reachable.json new file mode 100644 index 0000000000..cf01fda6ce --- /dev/null +++ b/zerver/webhooks/freshping/fixtures/freshping_check_reachable.json @@ -0,0 +1,26 @@ +{ + "organization_name": "Example Org", + "webhook_event_id": 5301955, + "organization_id": 156000, + "webhook_type": "AL", + "webhook_event_data": { + "check_state_name": "Available", + "check_computed_target_response_time": 1000, + "application_id": 155565, + "recently_started_check_state_name": null, + "check_id": 585767, + "recently_started_check_start_time": null, + "http_status_code": 200, + "request_start_time": "2021-04-15T19:57:32.607484+00:00", + "check_name": "Test Check", + "recently_started_check_http_status_code": null, + "application_name": " 's Application", + "recently_started_check_response_time": null, + "request_url": "https://example.com", + "check_target_response_time": 1000, + "@type": "MessageCard", + "response_time": 140 + }, + "webhook_id": 24172, + "webhook_event_created_on": "2021-04-15T19:57:33.035824+00:00" +} diff --git a/zerver/webhooks/freshping/fixtures/freshping_check_test.json b/zerver/webhooks/freshping/fixtures/freshping_check_test.json new file mode 100644 index 0000000000..2294db608d --- /dev/null +++ b/zerver/webhooks/freshping/fixtures/freshping_check_test.json @@ -0,0 +1,24 @@ +{ + "organization_name": "Example Org", + "webhook_event_id": 5301811, + "organization_id": 156000, + "webhook_type": "AL", + "webhook_event_data": { + "check_state_name": "Available", + "check_target_response_time": 100, + "recently_started_check_state_name": null, + "check_id": 1, + "recently_started_check_start_time": null, + "http_status_code": 200, + "request_start_time": "2021-04-15T19:36:31.812658+00:00", + "check_name": "Example check", + "recently_started_check_http_status_code": null, + "application_name": "Webhook test", + "recently_started_check_response_time": null, + "request_url": "https://www.example.com/", + "check_computed_target_response_time": 200, + "response_time": 50 + }, + "webhook_id": 24172, + "webhook_event_created_on": "2021-04-15T19:36:31.812999+00:00" +} diff --git a/zerver/webhooks/freshping/fixtures/freshping_check_unreachable.json b/zerver/webhooks/freshping/fixtures/freshping_check_unreachable.json new file mode 100644 index 0000000000..8cda6c9067 --- /dev/null +++ b/zerver/webhooks/freshping/fixtures/freshping_check_unreachable.json @@ -0,0 +1,26 @@ +{ + "organization_name": "Example Org", + "webhook_event_id": 5301855, + "organization_id": 156000, + "webhook_type": "AL", + "webhook_event_data": { + "check_state_name": "Reporting Error", + "check_computed_target_response_time": 1000, + "application_id": 155565, + "recently_started_check_state_name": null, + "check_id": 585767, + "recently_started_check_start_time": null, + "http_status_code": 521, + "request_start_time": "2021-04-15T19:46:47.644166+00:00", + "check_name": "Test Check", + "recently_started_check_http_status_code": null, + "application_name": " 's Application", + "recently_started_check_response_time": null, + "request_url": "https://example.com", + "check_target_response_time": 1000, + "@type": "MessageCard", + "response_time": 635 + }, + "webhook_id": 24172, + "webhook_event_created_on": "2021-04-15T19:46:49.077370+00:00" +} diff --git a/zerver/webhooks/freshping/tests.py b/zerver/webhooks/freshping/tests.py new file mode 100644 index 0000000000..e8e92847a4 --- /dev/null +++ b/zerver/webhooks/freshping/tests.py @@ -0,0 +1,34 @@ +from zerver.lib.test_classes import WebhookTestCase + + +class FreshpingHookTests(WebhookTestCase): + STREAM_NAME = "freshping" + URL_TEMPLATE = "/api/v1/external/freshping?api_key={api_key}&stream={stream}" + FIXTURE_DIR_NAME = "freshping" + + def test_freshping_check_test(self) -> None: + """ + Tests if freshping check test is handled correctly + """ + expected_topic = "Freshping" + expected_message = "Freshping webhook has been successfully configured." + self.check_webhook("freshping_check_test", expected_topic, expected_message) + + def test_freshping_check_unreachable(self) -> None: + """ + Tests if freshping check unreachable is handled correctly + """ + expected_topic = "Test Check" + expected_message = """ +https://example.com has just become unreachable. +Error Code: 521. +""".strip() + self.check_webhook("freshping_check_unreachable", expected_topic, expected_message) + + def test_freshping_check_reachable(self) -> None: + """ + Tests if freshping check reachable is handled correctly + """ + expected_topic = "Test Check" + expected_message = "https://example.com is back up and no longer unreachable." + self.check_webhook("freshping_check_reachable", expected_topic, expected_message) diff --git a/zerver/webhooks/freshping/view.py b/zerver/webhooks/freshping/view.py new file mode 100644 index 0000000000..c5a59ecf73 --- /dev/null +++ b/zerver/webhooks/freshping/view.py @@ -0,0 +1,55 @@ +from typing import Any, Dict + +from django.http import HttpRequest, HttpResponse + +from zerver.decorator import REQ, has_request_variables, webhook_view +from zerver.lib.response import json_success +from zerver.lib.webhooks.common import check_send_webhook_message, get_setup_webhook_message +from zerver.models import UserProfile + +FRESHPING_TOPIC_TEMPLATE_TEST = "Freshping" +FRESHPING_TOPIC_TEMPLATE = "{check_name}" + +FRESHPING_MESSAGE_TEMPLATE_UNREACHABLE = """ +{request_url} has just become unreachable. +Error Code: {http_status_code}. +""".strip() +FRESHPING_MESSAGE_TEMPLATE_UP = "{request_url} is back up and no longer unreachable." + + +@webhook_view("Freshping") +@has_request_variables +def api_freshping_webhook( + request: HttpRequest, + user_profile: UserProfile, + payload: Dict[str, Any] = REQ(argument_type="body"), +) -> HttpResponse: + + body = get_body_for_http_request(payload) + subject = get_subject_for_http_request(payload) + + check_send_webhook_message(request, user_profile, subject, body) + return json_success() + + +def get_subject_for_http_request(payload: Dict[str, Any]) -> str: + webhook_event_data = payload["webhook_event_data"] + if webhook_event_data["application_name"] == "Webhook test": + subject = FRESHPING_TOPIC_TEMPLATE_TEST + else: + subject = FRESHPING_TOPIC_TEMPLATE.format(check_name=webhook_event_data["check_name"]) + + return subject + + +def get_body_for_http_request(payload: Dict[str, Any]) -> str: + webhook_event_data = payload["webhook_event_data"] + if webhook_event_data["check_state_name"] == "Reporting Error": + body = FRESHPING_MESSAGE_TEMPLATE_UNREACHABLE.format(**webhook_event_data) + elif webhook_event_data["check_state_name"] == "Available": + if webhook_event_data["application_name"] == "Webhook test": + body = get_setup_webhook_message("Freshping") + else: + body = FRESHPING_MESSAGE_TEMPLATE_UP.format(**webhook_event_data) + + return body