diff --git a/hc/api/models.py b/hc/api/models.py index 11bafe69..7b781936 100644 --- a/hc/api/models.py +++ b/hc/api/models.py @@ -51,6 +51,7 @@ CHANNEL_KINDS = ( ("zulip", "Zulip"), ("spike", "Spike"), ("call", "Phone Call"), + ("linenotify", "LineNotify"), ) PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"} @@ -463,6 +464,8 @@ class Channel(models.Model): return transports.Spike(self) elif self.kind == "call": return transports.Call(self) + elif self.kind == "linenotify": + return transports.LineNotify(self) else: raise NotImplementedError("Unknown channel kind: %s" % self.kind) @@ -747,6 +750,14 @@ class Channel(models.Model): doc = json.loads(self.value) return doc["to"] + @property + def linenotify_token(self): + assert self.kind == "linenotify" + if not self.value.startswith("{"): + return self.value + + doc = json.loads(self.value) + return doc["token"] class Notification(models.Model): class Meta: diff --git a/hc/api/transports.py b/hc/api/transports.py index 5a9ce6c4..3aa36e8d 100644 --- a/hc/api/transports.py +++ b/hc/api/transports.py @@ -619,3 +619,17 @@ class Spike(HttpTransport): } return self.post(url, json=payload, headers=headers) + + +class LineNotify(HttpTransport): + URL = "https://notify-api.line.me/api/notify" + + def notify(self, check): + headers = { + "Content-Type": "multipart/form-data", + "Authorization": "Bearer %s" % settings.LINE_NOTIFY_ACCESS_TOKEN, + } + payload = { + "message": tmpl("linenotify_message.html", check=check) + } + return self.post(URL, headers=headers, params=payload) diff --git a/hc/front/forms.py b/hc/front/forms.py index fd9f0a32..8aac9966 100644 --- a/hc/front/forms.py +++ b/hc/front/forms.py @@ -104,6 +104,8 @@ class AddOpsGenieForm(forms.Form): region = forms.ChoiceField(initial="us", choices=(("us", "US"), ("eu", "EU"))) key = forms.CharField(max_length=40) +class AddLineNotifyForm(forms.Form): + token = forms.CharField(max_length=40) PRIO_CHOICES = [ ("-2", "Lowest Priority"), diff --git a/hc/front/tests/test_add_linenotify.py b/hc/front/tests/test_add_linenotify.py new file mode 100644 index 00000000..f8777bb2 --- /dev/null +++ b/hc/front/tests/test_add_linenotify.py @@ -0,0 +1,16 @@ +from django.test.utils import override_settings +from hc.api.models import Channel +from hc.test import BaseTestCase + +@override_settings(LINE_NOTIFY_ACCESS_TOKEN="foo") +class AddLineNotifyTestCase(BaseTestCase): + url = "/integrations/add_linenotify/" + + def setUp(self): + super(AddLineNotifyTestCase, self).setUp() + self.url = "/projects/%s/add_linenotify/" % self.project.code + + def test_instructions_work(self): + self.client.login(username="alice@example.org", password="password") + r = self.client.get(self.url) + self.assertContains(r, "LineNotify") diff --git a/hc/front/urls.py b/hc/front/urls.py index b99292b2..eee31f7a 100644 --- a/hc/front/urls.py +++ b/hc/front/urls.py @@ -79,6 +79,7 @@ project_urls = [ path("add_whatsapp/", views.add_whatsapp, name="hc-add-whatsapp"), path("add_zulip/", views.add_zulip, name="hc-add-zulip"), path("add_spike/", views.add_spike, name="hc-add-spike"), + path("add_linenotify/", views.add_linenotify, name="hc-add-linenotify"), path("badges/", views.badges, name="hc-badges"), path("checks/", views.my_checks, name="hc-checks"), path("checks/add/", views.add_check, name="hc-add-check"), diff --git a/hc/front/views.py b/hc/front/views.py index 74850e9a..6e1e855d 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -273,6 +273,7 @@ def index(request): "enable_telegram": settings.TELEGRAM_TOKEN is not None, "enable_trello": settings.TRELLO_APP_KEY is not None, "enable_whatsapp": settings.TWILIO_USE_WHATSAPP, + "enable_linenotify": settings.LINE_NOTIFY_ACCESS_TOKEN is not None, "registration_open": settings.REGISTRATION_OPEN, } @@ -711,6 +712,7 @@ def channels(request, code): "enable_telegram": settings.TELEGRAM_TOKEN is not None, "enable_trello": settings.TRELLO_APP_KEY is not None, "enable_whatsapp": settings.TWILIO_USE_WHATSAPP, + "enable_linenotify": settings.LINE_NOTIFY_ACCESS_TOKEN is not None, "use_payments": settings.USE_PAYMENTS, } @@ -1381,6 +1383,26 @@ def add_opsgenie(request, code): ctx = {"page": "channels", "project": project, "form": form} return render(request, "integrations/add_opsgenie.html", ctx) +# @require_setting("LINE_NOTIFY_ACCESS_TOKEN") +@login_required +def add_linenotify(request, code): + project = _get_project_for_user(request, code) + + if request.method == "POST": + form = forms.AddLineNotifyForm(request.POST) + if form.is_valid(): + channel = Channel(project=project, kind="linenotify") + channel.value = form.cleaned_data["value"] + channel.save() + + channel.assign_all_checks() + return redirect("hc-p-channels", project.code) + else: + form = forms.AddLineNotifyForm() + + ctx = {"page": "channels", "project": project, "form": form} + return render(request, "integrations/add_linenotify.html", ctx) + @login_required def add_victorops(request, code): diff --git a/hc/settings.py b/hc/settings.py index 9dd4c992..ea078a03 100644 --- a/hc/settings.py +++ b/hc/settings.py @@ -208,6 +208,9 @@ PD_VENDOR_KEY = os.getenv("PD_VENDOR_KEY") # Trello TRELLO_APP_KEY = os.getenv("TRELLO_APP_KEY") +# Line notify integration +LINE_NOTIFY_ACCESS_TOKEN = os.getenv("LINE_NOTIFY_ACCESS_TOKEN") + # Matrix MATRIX_HOMESERVER = os.getenv("MATRIX_HOMESERVER") MATRIX_USER_ID = os.getenv("MATRIX_USER_ID") diff --git a/static/img/integrations/linenotify.png b/static/img/integrations/linenotify.png new file mode 100644 index 00000000..9f0aa226 Binary files /dev/null and b/static/img/integrations/linenotify.png differ diff --git a/static/img/integrations/setup_linenotify_1.png b/static/img/integrations/setup_linenotify_1.png new file mode 100644 index 00000000..c004ee1f Binary files /dev/null and b/static/img/integrations/setup_linenotify_1.png differ diff --git a/static/img/integrations/setup_linenotify_2.png b/static/img/integrations/setup_linenotify_2.png new file mode 100644 index 00000000..f735cb44 Binary files /dev/null and b/static/img/integrations/setup_linenotify_2.png differ diff --git a/static/img/integrations/setup_linenotify_3.png b/static/img/integrations/setup_linenotify_3.png new file mode 100644 index 00000000..1286d895 Binary files /dev/null and b/static/img/integrations/setup_linenotify_3.png differ diff --git a/templates/front/channels.html b/templates/front/channels.html index 6a972be5..8e1a5f12 100644 --- a/templates/front/channels.html +++ b/templates/front/channels.html @@ -412,6 +412,17 @@ Add Integration + {% comment %} {% if enable_linenotify %} {% endcomment %} +
  • + LineNotify icon + +

    LineNotify

    +

    Get a LineNotify message when a check goes up or down.

    + Add Integration +
  • + {% comment %} {% endif %} {% endcomment %} +