Browse Source

Apprise Integration

pull/272/head
Chris Caron 5 years ago
parent
commit
c2b1d00422
14 changed files with 144 additions and 1 deletions
  1. +3
    -0
      hc/api/models.py
  2. +16
    -1
      hc/api/transports.py
  3. +5
    -0
      hc/front/forms.py
  4. +21
    -0
      hc/front/tests/test_add_apprise.py
  5. +1
    -0
      hc/front/urls.py
  6. +24
    -0
      hc/front/views.py
  7. +1
    -0
      hc/settings.py
  8. +1
    -0
      requirements.txt
  9. BIN
      static/img/integrations/apprise.png
  10. +11
    -0
      templates/front/channels.html
  11. +6
    -0
      templates/front/welcome.html
  12. +49
    -0
      templates/integrations/add_apprise.html
  13. +5
    -0
      templates/integrations/apprise_description.html
  14. +1
    -0
      templates/integrations/apprise_title.html

+ 3
- 0
hc/api/models.py View File

@ -41,6 +41,7 @@ CHANNEL_KINDS = (
("trello", "Trello"), ("trello", "Trello"),
("matrix", "Matrix"), ("matrix", "Matrix"),
("whatsapp", "WhatsApp"), ("whatsapp", "WhatsApp"),
("apprise", "Apprise"),
) )
PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"} PO_PRIORITIES = {-2: "lowest", -1: "low", 0: "normal", 1: "high", 2: "emergency"}
@ -392,6 +393,8 @@ class Channel(models.Model):
return transports.Matrix(self) return transports.Matrix(self)
elif self.kind == "whatsapp": elif self.kind == "whatsapp":
return transports.WhatsApp(self) return transports.WhatsApp(self)
elif self.kind == "apprise":
return transports.Apprise(self)
else: else:
raise NotImplementedError("Unknown channel kind: %s" % self.kind) raise NotImplementedError("Unknown channel kind: %s" % self.kind)


+ 16
- 1
hc/api/transports.py View File

@ -3,6 +3,7 @@ from django.template.loader import render_to_string
from django.utils import timezone from django.utils import timezone
import json import json
import requests import requests
import apprise
from urllib.parse import quote, urlencode from urllib.parse import quote, urlencode
from hc.accounts.models import Profile from hc.accounts.models import Profile
@ -273,7 +274,7 @@ class PagerTree(HttpTransport):
class PagerTeam(HttpTransport): class PagerTeam(HttpTransport):
def notify(self, check): def notify(self, check):
url = self.channel.value url = self.channel.value
headers = {"Conent-Type": "application/json"}
headers = {"Content-Type": "application/json"}
payload = { payload = {
"incident_key": str(check.code), "incident_key": str(check.code),
"event_type": "trigger" if check.status == "down" else "resolve", "event_type": "trigger" if check.status == "down" else "resolve",
@ -461,3 +462,17 @@ class Trello(HttpTransport):
} }
return self.post(self.URL, params=params) return self.post(self.URL, params=params)
class Apprise(HttpTransport):
def notify(self, check):
a = apprise.Apprise()
title = tmpl("apprise_title.html", check=check)
body = tmpl("apprise_description.html", check=check)
a.add(self.channel.value)
notify_type = apprise.NotifyType.SUCCESS \
if check.status == "up" else apprise.NotifyType.FAILURE
return "Failed" if not \
a.notify(body=body, title=title, notify_type=notify_type) else None

+ 5
- 0
hc/front/forms.py View File

@ -159,3 +159,8 @@ class AddMatrixForm(forms.Form):
self.cleaned_data["room_id"] = doc["room_id"] self.cleaned_data["room_id"] = doc["room_id"]
return v return v
class AddAppriseForm(forms.Form):
error_css_class = "has-error"
url = forms.CharField(max_length=512)

+ 21
- 0
hc/front/tests/test_add_apprise.py View File

@ -0,0 +1,21 @@
from hc.api.models import Channel
from hc.test import BaseTestCase
class AddSlackTestCase(BaseTestCase):
def test_instructions_work(self):
self.client.login(username="[email protected]", password="password")
r = self.client.get("/integrations/add_apprise/")
self.assertContains(r, "Integration Settings", status_code=200)
def test_it_works(self):
form = {"url": "json://example.org"}
self.client.login(username="[email protected]", password="password")
r = self.client.post("/integrations/add_apprise/", form)
self.assertRedirects(r, "/integrations/")
c = Channel.objects.get()
self.assertEqual(c.kind, "apprise")
self.assertEqual(c.value, "json://example.org")
self.assertEqual(c.project, self.project)

+ 1
- 0
hc/front/urls.py View File

@ -43,6 +43,7 @@ channel_urls = [
path("add_trello/", views.add_trello, name="hc-add-trello"), path("add_trello/", views.add_trello, name="hc-add-trello"),
path("add_trello/settings/", views.trello_settings, name="hc-trello-settings"), path("add_trello/settings/", views.trello_settings, name="hc-trello-settings"),
path("add_matrix/", views.add_matrix, name="hc-add-matrix"), path("add_matrix/", views.add_matrix, name="hc-add-matrix"),
path("add_apprise/", views.add_apprise, name="hc-add-apprise"),
path("<uuid:code>/checks/", views.channel_checks, name="hc-channel-checks"), path("<uuid:code>/checks/", views.channel_checks, name="hc-channel-checks"),
path("<uuid:code>/name/", views.update_channel_name, name="hc-channel-name"), path("<uuid:code>/name/", views.update_channel_name, name="hc-channel-name"),
path("<uuid:code>/test/", views.send_test_notification, name="hc-channel-test"), path("<uuid:code>/test/", views.send_test_notification, name="hc-channel-test"),


+ 24
- 0
hc/front/views.py View File

@ -44,6 +44,7 @@ from hc.front.forms import (
ChannelNameForm, ChannelNameForm,
EmailSettingsForm, EmailSettingsForm,
AddMatrixForm, AddMatrixForm,
AddAppriseForm,
) )
from hc.front.schemas import telegram_callback from hc.front.schemas import telegram_callback
from hc.front.templatetags.hc_extras import num_down_title, down_title, sortchecks from hc.front.templatetags.hc_extras import num_down_title, down_title, sortchecks
@ -1325,6 +1326,29 @@ def add_matrix(request):
return render(request, "integrations/add_matrix.html", ctx) return render(request, "integrations/add_matrix.html", ctx)
@login_required
def add_apprise(request):
if request.method == "POST":
form = AddAppriseForm(request.POST)
if form.is_valid():
channel = Channel(project=request.project, kind="apprise")
channel.value = form.cleaned_data["url"]
channel.save()
channel.assign_all_checks()
messages.success(request, "The Apprise integration has been added!")
return redirect("hc-channels")
else:
form = AddAppriseForm()
ctx = {
"page": "channels",
"project": request.project,
"form": form,
}
return render(request, "integrations/add_apprise.html", ctx)
@login_required @login_required
@require_POST @require_POST
def trello_settings(request): def trello_settings(request):


+ 1
- 0
hc/settings.py View File

@ -204,6 +204,7 @@ MATRIX_HOMESERVER = os.getenv("MATRIX_HOMESERVER")
MATRIX_USER_ID = os.getenv("MATRIX_USER_ID") MATRIX_USER_ID = os.getenv("MATRIX_USER_ID")
MATRIX_ACCESS_TOKEN = os.getenv("MATRIX_ACCESS_TOKEN") MATRIX_ACCESS_TOKEN = os.getenv("MATRIX_ACCESS_TOKEN")
if os.path.exists(os.path.join(BASE_DIR, "hc/local_settings.py")): if os.path.exists(os.path.join(BASE_DIR, "hc/local_settings.py")):
from .local_settings import * from .local_settings import *
else: else:


+ 1
- 0
requirements.txt View File

@ -4,3 +4,4 @@ django_compressor==2.2
psycopg2==2.7.5 psycopg2==2.7.5
pytz==2019.1 pytz==2019.1
requests==2.22.0 requests==2.22.0
apprise==0.7.9

BIN
static/img/integrations/apprise.png View File

Before After
Width: 133  |  Height: 133  |  Size: 28 KiB

+ 11
- 0
templates/front/channels.html View File

@ -69,6 +69,8 @@
{% endif %} {% endif %}
{% elif ch.kind == "webhook" %} {% elif ch.kind == "webhook" %}
Webhook Webhook
{% elif ch.kind == "apprise" %}
Apprise
{% elif ch.kind == "pushbullet" %} {% elif ch.kind == "pushbullet" %}
Pushbullet Pushbullet
{% elif ch.kind == "discord" %} {% elif ch.kind == "discord" %}
@ -211,6 +213,15 @@
<a href="{% url 'hc-add-webhook' %}" class="btn btn-primary">Add Integration</a> <a href="{% url 'hc-add-webhook' %}" class="btn btn-primary">Add Integration</a>
</li> </li>
<li>
<img src="{% static 'img/integrations/apprise.png' %}"
class="icon" alt="Pushover icon" />
<h2>Apprise</h2>
<p>Receive instant push notifications using Apprise; see <a href="https://github.com/caronc/apprise#popular-notification-services" >all of the supported services here</a>.</p>
<a href="{% url 'hc-add-apprise' %}" class="btn btn-primary">Add Integration</a>
</li>
{% if enable_pushover %} {% if enable_pushover %}
<li> <li>
<img src="{% static 'img/integrations/po.png' %}" <img src="{% static 'img/integrations/po.png' %}"


+ 6
- 0
templates/front/welcome.html View File

@ -432,6 +432,12 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
<div class="col-md-2 col-sm-4 col-xs-6">
<div class="integration">
<img src="{% static 'img/integrations/apprise.png' %}" class="icon" alt="Apprise icon" />
<h3>WhatsApp<br><small>Chat</small></h3>
</div>
</div>
</div> </div>
<div class="row tour-section"> <div class="row tour-section">


+ 49
- 0
templates/integrations/add_apprise.html View File

@ -0,0 +1,49 @@
{% extends "base.html" %}
{% load humanize static hc_extras %}
{% block title %}Add Apprise - {% site_name %}{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-12">
<h1>Apprise</h1>
<p>
Identify as many Apprise URLs as you wish. You can use a comma (,) to identify
more than on URL if you wish to.
For a detailed list of all supported Apprise Notification URLs simply
<a href="https://github.com/caronc/apprise#popular-notification-services" >click here</a>.
</p>
<h2>Integration Settings</h2>
<form method="post" class="form-horizontal">
{% csrf_token %}
<div class="form-group {{ form.room_id.css_classes }}">
<label for="url" class="col-sm-2 control-label">Apprise URL</label>
<div class="col-sm-6">
<input
id="url"
type="text"
class="form-control"
name="url"
value="{{ form.url.value|default:"" }}">
{% if form.url.errors %}
<div class="help-block">
{{ form.url.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 %}

+ 5
- 0
templates/integrations/apprise_description.html View File

@ -0,0 +1,5 @@
{% load humanize %}
{{ check.name_then_code }} is {{ check.status|upper }}.
{% if check.status == "down" %}
Last ping was {{ check.last_ping|naturaltime }}.
{% endif %}

+ 1
- 0
templates/integrations/apprise_title.html View File

@ -0,0 +1 @@
{{ check.name_then_code }} is {{ check.status|upper }}

Loading…
Cancel
Save