Skip to content

Commit

Permalink
Merge pull request #787 from blueberryapple/feat/adds-ntfy
Browse files Browse the repository at this point in the history
feat(notifications): Adds ntfy.sh notification option
  • Loading branch information
crazy-max authored Feb 19, 2023
2 parents 2bd5d54 + 1da9ec5 commit aaadc5d
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 0 deletions.
16 changes: 16 additions & 0 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ You can override this using the [`--config` flag or `CONFIG` env var with `serve
to:
- webmaster@example.com
- me@example.com
ntfy:
endpoint: https://ntfy.sh
topic: diun-acce65a0-b777-46f9-9a11-58c67d1579c4
priority: 3
timeout: 5s
rocketchat:
endpoint: http://rocket.foo.com:3000
channel: "#general"
Expand Down Expand Up @@ -131,6 +136,11 @@ All configuration from file can be transposed into environment variables. As an
token: Token123456
priority: 1
timeout: 10s
ntfy:
endpoint: https://ntfy.sh
topic: diun-acce65a0-b777-46f9-9a11-58c67d1579c4
priority: 3
timeout: 5s
telegram:
token: aabbccdd:11223344
chatIDs:
Expand Down Expand Up @@ -179,6 +189,11 @@ Can be transposed to:
DIUN_NOTIF_GOTIFY_PRIORITY=1
DIUN_NOTIF_GOTIFY_TIMEOUT=10s

DIUN_NOTIF_NTFY_ENDPOINT=https://ntfy.sh
DIUN_NOTIF_NTFY_TOPIC=diun-acce65a0-b777-46f9-9a11-58c67d1579c4
DIUN_NOTIF_NTFY_TAGS=whale
DIUN_NOTIF_NTFY_TIMEOUT=10s

DIUN_NOTIF_TELEGRAM_TOKEN=aabbccdd:11223344
DIUN_NOTIF_TELEGRAM_CHATIDS=123456789,987654321

Expand Down Expand Up @@ -213,6 +228,7 @@ Can be transposed to:
* [mail](../notif/mail.md)
* [matrix](../notif/matrix.md)
* [mqtt](../notif/mqtt.md)
* [ntfy](../notif/ntfy.md)
* [pushover](../notif/pushover.md)
* [rocketchat](../notif/rocketchat.md)
* [script](../notif/script.md)
Expand Down
1 change: 1 addition & 0 deletions docs/config/notif.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* [`mail`](../notif/mail.md)
* [`matrix`](../notif/matrix.md)
* [`mqtt`](../notif/mqtt.md)
* [`ntfy`](../notif/ntfy.md)
* [`pushover`](../notif/pushover.md)
* [`rocketchat`](../notif/rocketchat.md)
* [`script`](../notif/script.md)
Expand Down
53 changes: 53 additions & 0 deletions docs/notif/ntfy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Ntfy notifications

Notifications can be sent using a [ntfy](https://ntfy.sh/) instance.

## Configuration

!!! example "File"
```yaml
notif:
ntfy:
endpoint: https://ntfy.sh
topic: diun-acce65a0-b777-46f9-9a11-58c67d1579c4
priority: 3
tags:
- whale
timeout: 10s
templateTitle: "{{ .Entry.Image }} released"
templateBody: |
Docker tag {{ .Entry.Image }} which you subscribed to through {{ .Entry.Provider }} provider has been released.
```

| Name | Default | Description |
| ------------------- | ----------------------------------- | -------------------------------------------------------------------------- |
| `endpoint`[^1] | `https://ntfy.sh` | Ntfy base URL |
| `topic` | | Ntfy topic |
| `priority` | 3 | The priority of the message |
| `tags` | `["package"]` | Emoji to go in your notiication |
| `timeout` | `10s` | Timeout specifies a time limit for the request to be made |
| `templateTitle`[^1] | See [below](#default-templatetitle) | [Notification template](../faq.md#notification-template) for message title |
| `templateBody`[^1] | See [below](#default-templatebody) | [Notification template](../faq.md#notification-template) for message body |

!!! abstract "Environment variables"
* `DIUN_NOTIF_NTFY_ENDPOINT`
* `DIUN_NOTIF_NTFY_TOPIC`
* `DIUN_NOTIF_NTFY_PRIORITY`
* `DIUN_NOTIF_NTFY_TAGS`
* `DIUN_NOTIF_NTFY_TIMEOUT`
* `DIUN_NOTIF_NTFY_TEMPLATETITLE`
* `DIUN_NOTIF_NTFY_TEMPLATEBODY`

### Default `templateTitle`

```
[[ config.extra.template.notif.defaultTitle ]]
```

### Default `templateBody`

```
[[ config.extra.template.notif.defaultBody ]]
```

[^1]: Value required
9 changes: 9 additions & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ for <code>{{ .Entry.Manifest.Platform }}</code> platform.
Topic: "docker/diun",
QoS: 0,
},
Ntfy: &model.NotifNtfy{
Endpoint: "https://ntfy.sh",
Topic: "diun-acce65a0-b777-46f9-9a11-58c67d1579c4",
Priority: 3,
Tags: []string{"package"},
Timeout: utl.NewDuration(10 * time.Second),
TemplateTitle: model.NotifDefaultTemplateTitle,
TemplateBody: model.NotifDefaultTemplateBody,
},
Pushover: &model.NotifPushover{
Token: "uQiRzpo4DXghDmr9QzzfQu27cmVRsG",
Recipient: "gznej3rKEVAvPUxu9vvNnqpmZpokzF",
Expand Down
7 changes: 7 additions & 0 deletions internal/config/fixtures/config.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ notif:
client: "diun"
topic: "docker/diun"
qos: 0
ntfy:
endpoint: https://ntfy.sh
topic: diun-acce65a0-b777-46f9-9a11-58c67d1579c4
priority: 3
tags:
- package
timeout: 10s
pushover:
token: uQiRzpo4DXghDmr9QzzfQu27cmVRsG
recipient: gznej3rKEVAvPUxu9vvNnqpmZpokzF
Expand Down
7 changes: 7 additions & 0 deletions internal/config/fixtures/config.validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ notif:
client: "diun"
topic: "docker/diun"
qos: 0
ntfy:
endpoint: https://ntfy.sh
topic: diun-acce65a0-b777-46f9-9a11-58c67d1579c4
priority: 3
tags:
- package
timeout: 10s
pushover:
token: uQiRzpo4DXghDmr9QzzfQu27cmVRsG
recipient: gznej3rKEVAvPUxu9vvNnqpmZpokzF
Expand Down
1 change: 1 addition & 0 deletions internal/model/notif.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,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"`
Ntfy *NotifNtfy `yaml:"ntfy,omitempty" json:"ntfy,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"`
Expand Down
35 changes: 35 additions & 0 deletions internal/model/notif_ntfy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package model

import (
"time"

"github.com/crazy-max/diun/v4/pkg/utl"
)

// NotifNtfy holds ntfy notification configuration details
type NotifNtfy struct {
Endpoint string `yaml:"endpoint,omitempty" json:"endpoint,omitempty" validate:"required"`
Topic string `yaml:"topic,omitempty" json:"topic,omitempty" validate:"required"`
Priority int `yaml:"priority,omitempty" json:"priority,omitempty" validate:"omitempty,min=0"`
Tags []string `yaml:"tags,omitempty" json:"tags,omitempty" validate:"required"`
Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" validate:"required"`
TemplateTitle string `yaml:"templateTitle,omitempty" json:"templateTitle,omitempty" validate:"required"`
TemplateBody string `yaml:"templateBody,omitempty" json:"templateBody,omitempty" validate:"required"`
}

// GetDefaults gets the default values
func (s *NotifNtfy) GetDefaults() *NotifNtfy {
n := &NotifNtfy{}
n.SetDefaults()
return n
}

// SetDefaults sets the default values
func (s *NotifNtfy) SetDefaults() {
s.Endpoint = "https://ntfy.sh"
s.Priority = 3
s.Tags = []string{"package"}
s.Timeout = utl.NewDuration(10 * time.Second)
s.TemplateTitle = NotifDefaultTemplateTitle
s.TemplateBody = NotifDefaultTemplateBody
}
4 changes: 4 additions & 0 deletions internal/notif/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/ntfy"
"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"
Expand Down Expand Up @@ -61,6 +62,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.Ntfy != nil {
c.notifiers = append(c.notifiers, ntfy.New(config.Ntfy, meta))
}
if config.Pushover != nil {
c.notifiers = append(c.notifiers, pushover.New(config.Pushover, meta))
}
Expand Down
110 changes: 110 additions & 0 deletions internal/notif/ntfy/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package ntfy

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"

"github.com/crazy-max/diun/v4/internal/model"
"github.com/crazy-max/diun/v4/internal/msg"
"github.com/crazy-max/diun/v4/internal/notif/notifier"
)

// Client represents an active ntfy notification object
type Client struct {
*notifier.Notifier
cfg *model.NotifNtfy
meta model.Meta
}

// New creates a new ntfy notification instance
func New(config *model.NotifNtfy, 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 "ntfy"
}

// Send creates and sends a ntfy notification with an entry
func (c *Client) Send(entry model.NotifEntry) error {
hc := http.Client{
Timeout: *c.cfg.Timeout,
}

message, err := msg.New(msg.Options{
Meta: c.meta,
Entry: entry,
TemplateTitle: c.cfg.TemplateTitle,
TemplateBody: c.cfg.TemplateBody,
})
if err != nil {
return err
}

title, body, err := message.RenderMarkdown()
if err != nil {
return err
}

dataBuf := new(bytes.Buffer)
if err := json.NewEncoder(dataBuf).Encode(struct {
Topic string `json:"topic"`
Message string `json:"message"`
Title string `json:"title"`
Priority int `json:"priority"`
Tags []string `json:"tags"`
}{
Topic: c.cfg.Topic,
Message: string(body),
Title: string(title),
Priority: c.cfg.Priority,
Tags: c.cfg.Tags,
}); err != nil {
return err
}

u, err := url.Parse(c.cfg.Endpoint)
if err != nil {
return err
}

q := u.Query()
u.RawQuery = q.Encode()

req, err := http.NewRequest("POST", u.String(), dataBuf)
if err != nil {
return err
}

req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", c.meta.UserAgent)

resp, err := hc.Do(req)
if err != nil {
return err
}

if resp.StatusCode != http.StatusOK {
var errBody struct {
Error string `json:"error"`
ErrorCode int `json:"errorCode"`
ErrorDescription string `json:"errorDescription"`
}
err := json.NewDecoder(resp.Body).Decode(&errBody)
if err != nil {
return err
}
return fmt.Errorf("%d %s: %s", errBody.ErrorCode, errBody.Error, errBody.ErrorDescription)
}

return nil
}
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ nav:
- Mail: notif/mail.md
- Matrix: notif/matrix.md
- MQTT: notif/mqtt.md
- Ntfy: notif/ntfy.md
- Pushover: notif/pushover.md
- Rocket.Chat: notif/rocketchat.md
- Script: notif/script.md
Expand Down

0 comments on commit aaadc5d

Please sign in to comment.