mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49:13 +00:00
feat(notifications): add ntfy support (#1323)
* feat(notifications): add ntfy support * fix(test): update * fix: added missing semicolon
This commit is contained in:
parent
3234f0d919
commit
3dd1629a3f
10 changed files with 197 additions and 17 deletions
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/autobrr/autobrr/internal/domain"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
|
@ -26,12 +27,11 @@ func (b *NotificationBuilderPlainText) BuildBody(payload domain.NotificationPayl
|
|||
buildPart(payload.Status != "", "\nStatus: %v", payload.Status.String())
|
||||
buildPart(payload.Indexer != "", "\nIndexer: %v", payload.Indexer)
|
||||
buildPart(payload.Filter != "", "\nFilter: %v", payload.Filter)
|
||||
buildPart(payload.Action != "", "\nAction: %v Type: %v", payload.Action, payload.ActionType)
|
||||
buildPart(len(payload.Rejections) > 0, "\nRejections: %v", strings.Join(payload.Rejections, ", "))
|
||||
|
||||
buildPart(payload.Action != "", "\nAction: %v: %v", payload.ActionType, payload.Action)
|
||||
if payload.Action != "" && payload.ActionClient != "" {
|
||||
parts = append(parts, fmt.Sprintf(" Client: %v", payload.ActionClient))
|
||||
}
|
||||
buildPart(len(payload.Rejections) > 0, "\nRejections: %v", strings.Join(payload.Rejections, ", "))
|
||||
|
||||
return strings.Join(parts, "\n")
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func (b *NotificationBuilderPlainText) BuildTitle(event domain.NotificationEvent
|
|||
domain.NotificationEventAppUpdateAvailable: "Autobrr update available",
|
||||
domain.NotificationEventPushApproved: "Push Approved",
|
||||
domain.NotificationEventPushRejected: "Push Rejected",
|
||||
domain.NotificationEventPushError: "Error",
|
||||
domain.NotificationEventPushError: "Push Error",
|
||||
domain.NotificationEventIRCDisconnected: "IRC Disconnected",
|
||||
domain.NotificationEventIRCReconnected: "IRC Reconnected",
|
||||
domain.NotificationEventTest: "Test",
|
||||
|
|
131
internal/notification/ntfy.go
Normal file
131
internal/notification/ntfy.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
// Copyright (c) 2021 - 2023, Ludvig Lundgren and the autobrr contributors.
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/autobrr/autobrr/internal/domain"
|
||||
"github.com/autobrr/autobrr/pkg/errors"
|
||||
"github.com/autobrr/autobrr/pkg/sharedhttp"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type ntfyMessage struct {
|
||||
Message string `json:"message"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
type ntfySender struct {
|
||||
log zerolog.Logger
|
||||
Settings domain.Notification
|
||||
builder NotificationBuilderPlainText
|
||||
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func NewNtfySender(log zerolog.Logger, settings domain.Notification) domain.NotificationSender {
|
||||
return &ntfySender{
|
||||
log: log.With().Str("sender", "ntfy").Logger(),
|
||||
Settings: settings,
|
||||
builder: NotificationBuilderPlainText{},
|
||||
httpClient: &http.Client{
|
||||
Timeout: time.Second * 30,
|
||||
Transport: sharedhttp.Transport,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ntfySender) Send(event domain.NotificationEvent, payload domain.NotificationPayload) error {
|
||||
m := ntfyMessage{
|
||||
Message: s.builder.BuildBody(payload),
|
||||
Title: s.builder.BuildTitle(event),
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, s.Settings.Host, strings.NewReader(m.Message))
|
||||
if err != nil {
|
||||
s.log.Error().Err(err).Msgf("ntfy client request error: %v", event)
|
||||
return errors.Wrap(err, "could not create request")
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "text/pain")
|
||||
req.Header.Set("User-Agent", "autobrr")
|
||||
|
||||
req.Header.Set("Title", m.Title)
|
||||
if s.Settings.Priority > 0 {
|
||||
req.Header.Set("Priority", strconv.Itoa(int(s.Settings.Priority)))
|
||||
}
|
||||
|
||||
// set basic auth or access token
|
||||
if s.Settings.Username != "" && s.Settings.Password != "" {
|
||||
req.SetBasicAuth(s.Settings.Username, s.Settings.Password)
|
||||
} else if s.Settings.Token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+s.Settings.Token)
|
||||
}
|
||||
|
||||
res, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
s.log.Error().Err(err).Msgf("ntfy client request error: %v", event)
|
||||
return errors.Wrap(err, "could not make request: %+v", req)
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
s.log.Error().Err(err).Msgf("ntfy client request error: %v", event)
|
||||
return errors.Wrap(err, "could not read data")
|
||||
}
|
||||
|
||||
s.log.Trace().Msgf("ntfy status: %v response: %v", res.StatusCode, string(body))
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
s.log.Error().Err(err).Msgf("ntfy client request error: %v", string(body))
|
||||
return errors.New("bad status: %v body: %v", res.StatusCode, string(body))
|
||||
}
|
||||
|
||||
s.log.Debug().Msg("notification successfully sent to ntfy")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ntfySender) CanSend(event domain.NotificationEvent) bool {
|
||||
if s.isEnabled() && s.isEnabledEvent(event) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *ntfySender) isEnabled() bool {
|
||||
if s.Settings.Enabled {
|
||||
if s.Settings.Host == "" {
|
||||
s.log.Warn().Msg("ntfy missing host")
|
||||
return false
|
||||
}
|
||||
|
||||
if s.Settings.Token == "" {
|
||||
s.log.Warn().Msg("ntfy missing application token")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *ntfySender) isEnabledEvent(event domain.NotificationEvent) bool {
|
||||
for _, e := range s.Settings.Events {
|
||||
if e == string(event) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
|
@ -249,6 +249,8 @@ func (s *service) Test(ctx context.Context, notification domain.Notification) er
|
|||
agent = NewPushoverSender(s.log, notification)
|
||||
case domain.NotificationTypeGotify:
|
||||
agent = NewGotifySender(s.log, notification)
|
||||
case domain.NotificationTypeNtfy:
|
||||
agent = NewNtfySender(s.log, notification)
|
||||
case domain.NotificationTypeLunaSea:
|
||||
agent = NewLunaSeaSender(s.log, notification)
|
||||
default:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue