Add Pushover notification (#254)

Co-authored-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax
2021-01-04 22:29:48 +01:00
committed by GitHub
parent e6ba971025
commit dc1216c221
23 changed files with 217 additions and 44 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -206,6 +206,7 @@ Can be transposed to:
* [mail](../notif/mail.md)
* [matrix](../notif/matrix.md)
* [mqtt](../notif/mqtt.md)
* [pushover](../notif/pushover.md)
* [rocketchat](../notif/rocketchat.md)
* [script](../notif/script.md)
* [slack](../notif/slack.md)

View File

@@ -6,6 +6,7 @@
* [`mail`](../notif/mail.md)
* [`matrix`](../notif/matrix.md)
* [`mqtt`](../notif/mqtt.md)
* [`pushover`](../notif/pushover.md)
* [`rocketchat`](../notif/rocketchat.md)
* [`script`](../notif/script.md)
* [`slack`](../notif/slack.md)

View File

@@ -15,16 +15,6 @@ You can send notifications to any amqp compatible server with the following sett
queue: queue
```
!!! abstract "Environment variables"
* `DIUN_NOTIF_AMQP_HOST`
* `DIUN_NOTIF_AMQP_PORT`
* `DIUN_NOTIF_AMQP_USERNAME`
* `DIUN_NOTIF_AMQP_USERNAMEFILE`
* `DIUN_NOTIF_AMQP_PASSWORD`
* `DIUN_NOTIF_AMQP_PASSWORDFILE`
* `DIUN_NOTIF_AMQP_EXCHANGE`
* `DIUN_NOTIF_AMQP_QUEUE`
| Name | Default | Description |
|--------------------|---------------|---------------|
| `host`[^1] | `localhost` | AMQP server host |
@@ -36,6 +26,16 @@ You can send notifications to any amqp compatible server with the following sett
| `exchange` | | Name of the exchange the message will be sent to |
| `queue`[^1] | | Name of the queue the message will be sent to |
!!! abstract "Environment variables"
* `DIUN_NOTIF_AMQP_HOST`
* `DIUN_NOTIF_AMQP_PORT`
* `DIUN_NOTIF_AMQP_USERNAME`
* `DIUN_NOTIF_AMQP_USERNAMEFILE`
* `DIUN_NOTIF_AMQP_PASSWORD`
* `DIUN_NOTIF_AMQP_PASSWORDFILE`
* `DIUN_NOTIF_AMQP_EXCHANGE`
* `DIUN_NOTIF_AMQP_QUEUE`
## Sample
The JSON response will look like this:

View File

@@ -18,17 +18,17 @@ Allow to send notifications to your Discord channel.
timeout: 10s
```
!!! abstract "Environment variables"
* `DIUN_NOTIF_DISCORD_WEBHOOKURL`
* `DIUN_NOTIF_DISCORD_MENTIONS`
* `DIUN_NOTIF_DISCORD_TIMEOUT`
| Name | Default | Description |
|--------------------|---------------|---------------|
| `webhookURL`[^1] | | Discord [incoming webhook URL](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) |
| `mentions` | | List of users or roles to notify |
| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
!!! abstract "Environment variables"
* `DIUN_NOTIF_DISCORD_WEBHOOKURL`
* `DIUN_NOTIF_DISCORD_MENTIONS`
* `DIUN_NOTIF_DISCORD_TIMEOUT`
## Sample
![](../assets/notif/discord-1.png)

View File

@@ -14,12 +14,6 @@ Notifications can be sent using a [Gotify](https://gotify.net/) instance.
timeout: 10s
```
!!! abstract "Environment variables"
* `DIUN_NOTIF_GOTIFY_ENDPOINT`
* `DIUN_NOTIF_GOTIFY_TOKEN`
* `DIUN_NOTIF_GOTIFY_PRIORITY`
* `DIUN_NOTIF_GOTIFY_TIMEOUT`
| Name | Default | Description |
|--------------------|---------------|---------------|
| `endpoint`[^1] | | Gotify base URL |
@@ -27,6 +21,12 @@ Notifications can be sent using a [Gotify](https://gotify.net/) instance.
| `priority` | `1` | The priority of the message |
| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
!!! abstract "Environment variables"
* `DIUN_NOTIF_GOTIFY_ENDPOINT`
* `DIUN_NOTIF_GOTIFY_TOKEN`
* `DIUN_NOTIF_GOTIFY_PRIORITY`
* `DIUN_NOTIF_GOTIFY_TIMEOUT`
## Sample
![](../assets/notif/gotify.png)

View File

@@ -29,6 +29,17 @@ You can send notifications to any MQTT compatible server with the following sett
| `topic`[^1] | | Topic the message will be sent to |
| `qos` | `0` | Ensured message delivery at specified Quality of Service (QoS) |
!!! abstract "Environment variables"
* `DIUN_NOTIF_MQTT_HOST`
* `DIUN_NOTIF_MQTT_PORT`
* `DIUN_NOTIF_MQTT_USERNAME`
* `DIUN_NOTIF_MQTT_USERNAMEFILE`
* `DIUN_NOTIF_MQTT_PASSWORD`
* `DIUN_NOTIF_MQTT_PASSWORDFILE`
* `DIUN_NOTIF_MQTT_CLIENT`
* `DIUN_NOTIF_MQTT_TOPIC`
* `DIUN_NOTIF_MQTT_QOS`
## Sample
The JSON response will look like this:

30
docs/notif/pushover.md Normal file
View File

@@ -0,0 +1,30 @@
# Pushover notifications
You can send notifications using [Pushover](https://pushover.net/).
## Configuration
!!! example "File"
```yaml
notif:
pushover:
token: uQiRzpo4DXghDmr9QzzfQu27cmVRsG
recipient: gznej3rKEVAvPUxu9vvNnqpmZpokzF
```
| Name | Default | Description |
|--------------------|---------------|---------------|
| `token` | | Pushover [application/API token](https://pushover.net/api#registration) |
| `tokenFile` | | Use content of secret file as Pushover application/API token if `token` not defined |
| `recipient` | | User key to send notification to |
| `recipientFile` | | Use content of secret file as User key if `recipient` not defined |
!!! abstract "Environment variables"
* `DIUN_NOTIF_PUSHOVER_TOKEN`
* `DIUN_NOTIF_PUSHOVER_TOKENFILE`
* `DIUN_NOTIF_PUSHOVER_RECIPIENT`
* `DIUN_NOTIF_PUSHOVER_RECIPIENTFILE`
## Sample
![](../assets/notif/pushover.png)

View File

@@ -15,13 +15,6 @@ Allow to send notifications to your Rocket.Chat channel.
timeout: 10s
```
!!! abstract "Environment variables"
* `DIUN_NOTIF_ROCKETCHAT_ENDPOINT`
* `DIUN_NOTIF_ROCKETCHAT_CHANNEL`
* `DIUN_NOTIF_ROCKETCHAT_USERID`
* `DIUN_NOTIF_ROCKETCHAT_TOKEN`
* `DIUN_NOTIF_ROCKETCHAT_TIMEOUT`
| Name | Default | Description |
|--------------------|---------------|---------------|
| `endpoint`[^1] | | Rocket.Chat base URL |
@@ -33,6 +26,13 @@ Allow to send notifications to your Rocket.Chat channel.
!!! warning
You must first create a _Personal Access Token_ through your account settings on your Rocket.Chat instance.
!!! abstract "Environment variables"
* `DIUN_NOTIF_ROCKETCHAT_ENDPOINT`
* `DIUN_NOTIF_ROCKETCHAT_CHANNEL`
* `DIUN_NOTIF_ROCKETCHAT_USERID`
* `DIUN_NOTIF_ROCKETCHAT_TOKEN`
* `DIUN_NOTIF_ROCKETCHAT_TIMEOUT`
## Sample
![](../assets/notif/rocketchat.png)

View File

@@ -14,13 +14,13 @@ You can send notifications to your Slack channel using an [incoming webhook URL]
webhookURL: https://hooks.slack.com/services/ABCD12EFG/HIJK34LMN/01234567890abcdefghij
```
!!! abstract "Environment variables"
* `DIUN_NOTIF_SLACK_WEBHOOKURL`
| Name | Default | Description |
|--------------------|---------------|---------------|
| `webhookURL`[^1] | | Slack [incoming webhook URL](https://api.slack.com/messaging/webhooks) |
!!! abstract "Environment variables"
* `DIUN_NOTIF_SLACK_WEBHOOKURL`
## Sample
![](../assets/notif/slack.png)

View File

@@ -11,13 +11,13 @@ You can send notifications to your Teams team-channel using an [incoming webhook
webhookURL: https://outlook.office.com/webhook/ABCD12EFG/HIJK34LMN/01234567890abcdefghij
```
!!! abstract "Environment variables"
* `DIUN_NOTIF_TEAMS_WEBHOOKURL`
| Name | Default | Description |
|--------------------|---------------|---------------|
| `webhookURL`[^1] | | Teams [incoming webhook URL](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/what-are-webhooks-and-connectors) |
!!! abstract "Environment variables"
* `DIUN_NOTIF_TEAMS_WEBHOOKURL`
## Sample
![](../assets/notif/teams.png)

View File

@@ -19,15 +19,15 @@ Multiple chat IDs can be provided in order to deliver notifications to multiple
- 987654321
```
!!! abstract "Environment variables"
* `DIUN_NOTIF_TELEGRAM_TOKEN`
* `DIUN_NOTIF_TELEGRAM_CHATIDS` (comma separated)
| Name | Default | Description |
|--------------------|---------------|---------------|
| `token`[^1] | | Telegram bot token |
| `chatIDs`[^1] | | List of chat IDs to send notifications to |
!!! abstract "Environment variables"
* `DIUN_NOTIF_TELEGRAM_TOKEN`
* `DIUN_NOTIF_TELEGRAM_CHATIDS` (comma separated)
## Sample
![](../assets/notif/telegram.png)

View File

@@ -16,12 +16,6 @@ You can send webhook notifications with the following settings.
timeout: 10s
```
!!! abstract "Environment variables"
* `DIUN_NOTIF_WEBHOOK_ENDPOINT`
* `DIUN_NOTIF_WEBHOOK_METHOD`
* `DIUN_NOTIF_WEBHOOK_HEADERS_<KEY>`
* `DIUN_NOTIF_WEBHOOK_TIMEOUT`
| Name | Default | Description |
|--------------------|---------------|---------------|
| `endpoint`[^1] | | URL of the HTTP request |
@@ -29,6 +23,12 @@ You can send webhook notifications with the following settings.
| `headers` | | Map of additional headers to be sent (key is case insensitive) |
| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
!!! abstract "Environment variables"
* `DIUN_NOTIF_WEBHOOK_ENDPOINT`
* `DIUN_NOTIF_WEBHOOK_METHOD`
* `DIUN_NOTIF_WEBHOOK_HEADERS_<KEY>`
* `DIUN_NOTIF_WEBHOOK_TIMEOUT`
## Sample
The JSON response will look like this:

1
go.mod
View File

@@ -13,6 +13,7 @@ require (
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df
github.com/go-playground/validator/v10 v10.4.1
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
github.com/gregdel/pushover v0.0.0-20201104094836-ddbe0c1d3a38
github.com/hako/durafmt v0.0.0-20190612201238-650ed9f29a84
github.com/imdario/mergo v0.3.11
github.com/matcornic/hermes/v2 v2.1.0

2
go.sum
View File

@@ -202,6 +202,8 @@ github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregdel/pushover v0.0.0-20201104094836-ddbe0c1d3a38 h1:jb9bDQ07E8YdegHcvFJ6r0JAQhSxT6BQjDLn/xAMu64=
github.com/gregdel/pushover v0.0.0-20201104094836-ddbe0c1d3a38/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER1PthX7to=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hako/durafmt v0.0.0-20190612201238-650ed9f29a84 h1:RvcDqcKLua4b/jtXez7ZVe9s6Iq5N6ujVevqY4FBQmM=
github.com/hako/durafmt v0.0.0-20190612201238-650ed9f29a84/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=

View File

@@ -131,6 +131,10 @@ func TestLoadFile(t *testing.T) {
Topic: "docker/diun",
QoS: 0,
},
Pushover: &model.NotifPushover{
Token: "uQiRzpo4DXghDmr9QzzfQu27cmVRsG",
Recipient: "gznej3rKEVAvPUxu9vvNnqpmZpokzF",
},
RocketChat: &model.NotifRocketChat{
Endpoint: "http://rocket.foo.com:3000",
Channel: "#general",

View File

@@ -51,6 +51,9 @@ notif:
client: "diun"
topic: "docker/diun"
qos: 0
pushover:
token: uQiRzpo4DXghDmr9QzzfQu27cmVRsG
recipient: gznej3rKEVAvPUxu9vvNnqpmZpokzF
rocketchat:
endpoint: http://rocket.foo.com:3000
channel: "#general"

View File

@@ -51,6 +51,9 @@ notif:
client: "diun"
topic: "docker/diun"
qos: 0
pushover:
token: uQiRzpo4DXghDmr9QzzfQu27cmVRsG
recipient: gznej3rKEVAvPUxu9vvNnqpmZpokzF
rocketchat:
endpoint: http://rocket.foo.com:3000
channel: "#general"

View File

@@ -31,6 +31,7 @@ type Notif struct {
Mail *NotifMail `yaml:"mail,omitempty" json:"mail,omitempty"`
Matrix *NotifMatrix `yaml:"matrix,omitempty" json:"matrix,omitempty"`
Mqtt *NotifMqtt `yaml:"mqtt,omitempty" json:"mqtt,omitempty"`
Pushover *NotifPushover `yaml:"pushover,omitempty" json:"pushover,omitempty"`
RocketChat *NotifRocketChat `yaml:"rocketchat,omitempty" json:"rocketchat,omitempty"`
Script *NotifScript `yaml:"script,omitempty" json:"script,omitempty"`
Slack *NotifSlack `yaml:"slack,omitempty" json:"slack,omitempty"`

View File

@@ -0,0 +1,20 @@
package model
// NotifPushover holds Pushover notification configuration details
type NotifPushover struct {
Token string `yaml:"token,omitempty" json:"token,omitempty" validate:"omitempty"`
TokenFile string `yaml:"tokenFile,omitempty" json:"tokenFile,omitempty" validate:"omitempty,file"`
Recipient string `yaml:"recipient,omitempty" json:"recipient,omitempty" validate:"omitempty"`
RecipientFile string `yaml:"recipientFile,omitempty" json:"recipientFile,omitempty" validate:"omitempty,file"`
Priority int `yaml:"priority,omitempty" json:"priority,omitempty" validate:"omitempty,min=-2,max=2"`
}
// GetDefaults gets the default values
func (s *NotifPushover) GetDefaults() *NotifPushover {
return nil
}
// SetDefaults sets the default values
func (s *NotifPushover) SetDefaults() {
// noop
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/crazy-max/diun/v4/internal/notif/matrix"
"github.com/crazy-max/diun/v4/internal/notif/mqtt"
"github.com/crazy-max/diun/v4/internal/notif/notifier"
"github.com/crazy-max/diun/v4/internal/notif/pushover"
"github.com/crazy-max/diun/v4/internal/notif/rocketchat"
"github.com/crazy-max/diun/v4/internal/notif/script"
"github.com/crazy-max/diun/v4/internal/notif/slack"
@@ -59,6 +60,9 @@ func New(config *model.Notif, meta model.Meta) (*Client, error) {
if config.Mqtt != nil {
c.notifiers = append(c.notifiers, mqtt.New(config.Mqtt, meta))
}
if config.Pushover != nil {
c.notifiers = append(c.notifiers, pushover.New(config.Pushover, meta))
}
if config.RocketChat != nil {
c.notifiers = append(c.notifiers, rocketchat.New(config.RocketChat, meta))
}

View File

@@ -0,0 +1,91 @@
package pushover
import (
"bytes"
"errors"
"fmt"
"text/template"
"time"
"github.com/crazy-max/diun/v4/internal/model"
"github.com/crazy-max/diun/v4/internal/notif/notifier"
"github.com/crazy-max/diun/v4/pkg/utl"
"github.com/gregdel/pushover"
)
// Client represents an active Pushover notification object
type Client struct {
*notifier.Notifier
cfg *model.NotifPushover
meta model.Meta
}
// New creates a new Pushover notification instance
func New(config *model.NotifPushover, meta model.Meta) notifier.Notifier {
return notifier.Notifier{
Handler: &Client{
cfg: config,
meta: meta,
},
}
}
// Name returns notifier's name
func (c *Client) Name() string {
return "pushover"
}
// Send creates and sends a Pushover notification with an entry
func (c *Client) Send(entry model.NotifEntry) error {
token, err := utl.GetSecret(c.cfg.Token, c.cfg.TokenFile)
if err != nil {
return errors.New("Cannot retrieve token secret for Pushover notifier")
}
recipient, err := utl.GetSecret(c.cfg.Recipient, c.cfg.RecipientFile)
if err != nil {
return errors.New("Cannot retrieve recipient secret for Pushover notifier")
}
app := pushover.New(token)
user := pushover.NewRecipient(recipient)
title := fmt.Sprintf("Image update for %s", entry.Image.String())
if entry.Status == model.ImageStatusNew {
title = fmt.Sprintf("New image %s has been added", entry.Image.String())
}
tagTpl := "{{ .Entry.Image.Domain }}/{{ .Entry.Image.Path }}:{{ .Entry.Image.Tag }}"
if len(entry.Image.HubLink) > 0 {
tagTpl = `<a href="{{ .Entry.Image.HubLink }}">{{ .Entry.Image.Domain }}/{{ .Entry.Image.Path }}:{{ .Entry.Image.Tag }}</a>`
}
var msgBuf bytes.Buffer
msgTpl := template.Must(template.New("email").Parse(fmt.Sprintf("Docker tag %s which you subscribed to through {{ .Entry.Provider }} provider has been {{ if (eq .Entry.Status \"new\") }}newly added{{ else }}updated{{ end }} on {{ .Hostname }}.", tagTpl)))
if err := msgTpl.Execute(&msgBuf, struct {
Hostname string
Entry model.NotifEntry
}{
Hostname: c.meta.Hostname,
Entry: entry,
}); err != nil {
return err
}
_, err = app.GetRecipientDetails(user)
if err != nil {
return err
}
_, err = app.SendMessage(&pushover.Message{
Message: msgBuf.String(),
Title: title,
Priority: c.cfg.Priority,
URL: c.meta.URL,
URLTitle: c.meta.Name,
Timestamp: time.Now().Unix(),
HTML: true,
}, user)
return err
}

View File

@@ -94,6 +94,7 @@ nav:
- Mail: notif/mail.md
- Matrix: notif/matrix.md
- MQTT: notif/mqtt.md
- Pushover: notif/pushover.md
- Rocket.Chat: notif/rocketchat.md
- Script: notif/script.md
- Slack: notif/slack.md