forked from GithubBackups/healthchecks
Test LineNotify integration with healthcheck
This commit is contained in:
parent
2346ac3e80
commit
65b65188d1
@ -51,6 +51,7 @@ CHANNEL_KINDS = (
|
|||||||
("zulip", "Zulip"),
|
("zulip", "Zulip"),
|
||||||
("spike", "Spike"),
|
("spike", "Spike"),
|
||||||
("call", "Phone Call"),
|
("call", "Phone Call"),
|
||||||
|
("linenotify", "LineNotify"),
|
||||||
)
|
)
|
||||||
|
|
||||||
PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"}
|
PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"}
|
||||||
@ -463,6 +464,8 @@ class Channel(models.Model):
|
|||||||
return transports.Spike(self)
|
return transports.Spike(self)
|
||||||
elif self.kind == "call":
|
elif self.kind == "call":
|
||||||
return transports.Call(self)
|
return transports.Call(self)
|
||||||
|
elif self.kind == "linenotify":
|
||||||
|
return transports.LineNotify(self)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("Unknown channel kind: %s" % self.kind)
|
raise NotImplementedError("Unknown channel kind: %s" % self.kind)
|
||||||
|
|
||||||
@ -747,6 +750,14 @@ class Channel(models.Model):
|
|||||||
doc = json.loads(self.value)
|
doc = json.loads(self.value)
|
||||||
return doc["to"]
|
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 Notification(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -619,3 +619,17 @@ class Spike(HttpTransport):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return self.post(url, json=payload, headers=headers)
|
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)
|
||||||
|
@ -104,6 +104,8 @@ class AddOpsGenieForm(forms.Form):
|
|||||||
region = forms.ChoiceField(initial="us", choices=(("us", "US"), ("eu", "EU")))
|
region = forms.ChoiceField(initial="us", choices=(("us", "US"), ("eu", "EU")))
|
||||||
key = forms.CharField(max_length=40)
|
key = forms.CharField(max_length=40)
|
||||||
|
|
||||||
|
class AddLineNotifyForm(forms.Form):
|
||||||
|
token = forms.CharField(max_length=40)
|
||||||
|
|
||||||
PRIO_CHOICES = [
|
PRIO_CHOICES = [
|
||||||
("-2", "Lowest Priority"),
|
("-2", "Lowest Priority"),
|
||||||
|
16
hc/front/tests/test_add_linenotify.py
Normal file
16
hc/front/tests/test_add_linenotify.py
Normal file
@ -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")
|
@ -79,6 +79,7 @@ project_urls = [
|
|||||||
path("add_whatsapp/", views.add_whatsapp, name="hc-add-whatsapp"),
|
path("add_whatsapp/", views.add_whatsapp, name="hc-add-whatsapp"),
|
||||||
path("add_zulip/", views.add_zulip, name="hc-add-zulip"),
|
path("add_zulip/", views.add_zulip, name="hc-add-zulip"),
|
||||||
path("add_spike/", views.add_spike, name="hc-add-spike"),
|
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("badges/", views.badges, name="hc-badges"),
|
||||||
path("checks/", views.my_checks, name="hc-checks"),
|
path("checks/", views.my_checks, name="hc-checks"),
|
||||||
path("checks/add/", views.add_check, name="hc-add-check"),
|
path("checks/add/", views.add_check, name="hc-add-check"),
|
||||||
|
@ -273,6 +273,7 @@ def index(request):
|
|||||||
"enable_telegram": settings.TELEGRAM_TOKEN is not None,
|
"enable_telegram": settings.TELEGRAM_TOKEN is not None,
|
||||||
"enable_trello": settings.TRELLO_APP_KEY is not None,
|
"enable_trello": settings.TRELLO_APP_KEY is not None,
|
||||||
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
|
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
|
||||||
|
"enable_linenotify": settings.LINE_NOTIFY_ACCESS_TOKEN is not None,
|
||||||
"registration_open": settings.REGISTRATION_OPEN,
|
"registration_open": settings.REGISTRATION_OPEN,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -711,6 +712,7 @@ def channels(request, code):
|
|||||||
"enable_telegram": settings.TELEGRAM_TOKEN is not None,
|
"enable_telegram": settings.TELEGRAM_TOKEN is not None,
|
||||||
"enable_trello": settings.TRELLO_APP_KEY is not None,
|
"enable_trello": settings.TRELLO_APP_KEY is not None,
|
||||||
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
|
"enable_whatsapp": settings.TWILIO_USE_WHATSAPP,
|
||||||
|
"enable_linenotify": settings.LINE_NOTIFY_ACCESS_TOKEN is not None,
|
||||||
"use_payments": settings.USE_PAYMENTS,
|
"use_payments": settings.USE_PAYMENTS,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1381,6 +1383,26 @@ def add_opsgenie(request, code):
|
|||||||
ctx = {"page": "channels", "project": project, "form": form}
|
ctx = {"page": "channels", "project": project, "form": form}
|
||||||
return render(request, "integrations/add_opsgenie.html", ctx)
|
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
|
@login_required
|
||||||
def add_victorops(request, code):
|
def add_victorops(request, code):
|
||||||
|
@ -208,6 +208,9 @@ PD_VENDOR_KEY = os.getenv("PD_VENDOR_KEY")
|
|||||||
# Trello
|
# Trello
|
||||||
TRELLO_APP_KEY = os.getenv("TRELLO_APP_KEY")
|
TRELLO_APP_KEY = os.getenv("TRELLO_APP_KEY")
|
||||||
|
|
||||||
|
# Line notify integration
|
||||||
|
LINE_NOTIFY_ACCESS_TOKEN = os.getenv("LINE_NOTIFY_ACCESS_TOKEN")
|
||||||
|
|
||||||
# Matrix
|
# Matrix
|
||||||
MATRIX_HOMESERVER = os.getenv("MATRIX_HOMESERVER")
|
MATRIX_HOMESERVER = os.getenv("MATRIX_HOMESERVER")
|
||||||
MATRIX_USER_ID = os.getenv("MATRIX_USER_ID")
|
MATRIX_USER_ID = os.getenv("MATRIX_USER_ID")
|
||||||
|
BIN
static/img/integrations/linenotify.png
Normal file
BIN
static/img/integrations/linenotify.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
static/img/integrations/setup_linenotify_1.png
Normal file
BIN
static/img/integrations/setup_linenotify_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 253 KiB |
BIN
static/img/integrations/setup_linenotify_2.png
Normal file
BIN
static/img/integrations/setup_linenotify_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 121 KiB |
BIN
static/img/integrations/setup_linenotify_3.png
Normal file
BIN
static/img/integrations/setup_linenotify_3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 79 KiB |
@ -412,6 +412,17 @@
|
|||||||
<a href="{% url 'hc-add-zulip' project.code %}" class="btn btn-primary">Add Integration</a>
|
<a href="{% url 'hc-add-zulip' project.code %}" class="btn btn-primary">Add Integration</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
{% comment %} {% if enable_linenotify %} {% endcomment %}
|
||||||
|
<li>
|
||||||
|
<img src="{% static 'img/integrations/linenotify.png' %}"
|
||||||
|
class="icon" alt="LineNotify icon" />
|
||||||
|
|
||||||
|
<h2>LineNotify</h2>
|
||||||
|
<p>Get a LineNotify message when a check goes up or down.</p>
|
||||||
|
<a href="{% url 'hc-add-linenotify' project.code %}" class="btn btn-primary">Add Integration</a>
|
||||||
|
</li>
|
||||||
|
{% comment %} {% endif %} {% endcomment %}
|
||||||
|
|
||||||
<li class="link-to-github">
|
<li class="link-to-github">
|
||||||
<img src="{% static 'img/integrations/missing.png' %}"
|
<img src="{% static 'img/integrations/missing.png' %}"
|
||||||
class="icon" alt="Suggest New Integration" />
|
class="icon" alt="Suggest New Integration" />
|
||||||
|
@ -642,6 +642,15 @@
|
|||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% comment %} {% if enable_linenotify %} {% endcomment %}
|
||||||
|
<div class="col-lg-2 col-md-3 col-sm-4 col-xs-6">
|
||||||
|
<div class="integration">
|
||||||
|
<img src="{% static 'img/integrations/linenotify.png' %}" class="icon" alt="" />
|
||||||
|
<h3>LineNotify<br><small>Chat</small></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% comment %} {% endif %} {% endcomment %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row tour-section">
|
<div class="row tour-section">
|
||||||
|
105
templates/integrations/add_linenotify.html
Normal file
105
templates/integrations/add_linenotify.html
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load humanize static hc_extras %}
|
||||||
|
|
||||||
|
{% block title %}LineNotify Integration for {% site_name %}{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h1>LineNotify</h1>
|
||||||
|
|
||||||
|
<p><a href="https://notify-bot.line.me/en/">LineNotify</a>
|
||||||
|
allows you to send web notifications directly to your LINE chats.
|
||||||
|
If you use or plan on using LineNotify,
|
||||||
|
you can set up {% site_name %} to post status updates directly to an appropriate LineNotify channel.
|
||||||
|
Here are a few steps that can integrate it with your {% site_name %} account.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Setup Guide</h2>
|
||||||
|
|
||||||
|
<div class="row ai-step">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<span class="step-no"></span>
|
||||||
|
<p>
|
||||||
|
Log into your Line account,
|
||||||
|
go to <strong>My Pages</strong> in the upper right corner.
|
||||||
|
In the <strong>My Pages</strong>, scroll to the bottom of the page,
|
||||||
|
and click on <strong>Generate token</strong> button.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="marker-wrap">
|
||||||
|
<span style="left: 77%; top: 14%;" class="marker"></span>
|
||||||
|
<img
|
||||||
|
class="ai-guide-screenshot"
|
||||||
|
alt="Screenshot"
|
||||||
|
src="{% static 'img/integrations/setup_linenotify_1.png' %}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row ai-step">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<span class="step-no"></span>
|
||||||
|
<p>
|
||||||
|
It will pop up the <strong>Generate token</strong> Form.
|
||||||
|
Fill out the details, and click the button.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<img
|
||||||
|
class="ai-guide-screenshot"
|
||||||
|
alt="Screenshot"
|
||||||
|
src="{% static 'img/integrations/setup_linenotify_2.png' %}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row ai-step">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<span class="step-no"></span>
|
||||||
|
<p>
|
||||||
|
Copy the displayed <strong>Token</strong> and paste it
|
||||||
|
in the form below.
|
||||||
|
Save the integration, and it's done!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<img
|
||||||
|
class="ai-guide-screenshot"
|
||||||
|
alt="Screenshot"
|
||||||
|
src="{% static 'img/integrations/setup_linenotify_3.png' %}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Integration Settings</h2>
|
||||||
|
|
||||||
|
<form method="post" class="form-horizontal">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="form-group {{ form.value.css_classes }}">
|
||||||
|
<label for="api-token" class="col-sm-2 control-label">API Token</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input
|
||||||
|
id="api-token"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
name="token"
|
||||||
|
placeholder=""
|
||||||
|
value="{{ form.token.value|default:"" }}">
|
||||||
|
|
||||||
|
{% if form.token.errors %}
|
||||||
|
<div class="help-block">
|
||||||
|
{{ form.token.errors|join:"" }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button type="submit" class="btn btn-primary">Save Integration</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
6
templates/integrations/linenotify_message.html
Normal file
6
templates/integrations/linenotify_message.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{% load humanize %}
|
||||||
|
{% if check.status == "down" %}
|
||||||
|
The check "{{ check.name_then_code }}" is <b>DOWN</b>. Last ping was {{ check.last_ping|naturaltime }}.
|
||||||
|
{% else %}
|
||||||
|
The check "{{ check.name_then_code }}" is now <b>UP</b>.
|
||||||
|
{% endif %}
|
Loading…
x
Reference in New Issue
Block a user