Files
URBM/internal/notify/notify.go
T
2026-06-14 23:12:39 +02:00

91 lines
2.2 KiB
Go

package notify
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"os/exec"
"strings"
"time"
"git.casaderoll.de/michael/urbm/internal/model"
)
type SecretGetter interface{ Get(string) (string, error) }
type Sender struct {
Secrets SecretGetter
Client *http.Client
NotifyPath string
RunCommand func(context.Context, string, ...string) error
}
func (s *Sender) Send(ctx context.Context, target model.NotificationTarget, title, message, severity string) error {
if !target.Enabled {
return nil
}
switch target.Type {
case "unraid":
importance := "normal"
if severity == "failed" || severity == "error" {
importance = "alert"
} else if severity == "warning" {
importance = "warning"
}
path := s.NotifyPath
if path == "" {
path = "/usr/local/emhttp/webGui/scripts/notify"
}
args := []string{"-e", "URBM", "-s", title, "-d", message, "-i", importance, "-l", "/Tools/URBM"}
if s.RunCommand != nil {
return s.RunCommand(ctx, path, args...)
}
return exec.CommandContext(ctx, path, args...).Run()
case "gotify":
token, err := s.Secrets.Get(target.TokenRef)
if err != nil {
return err
}
endpoint, err := url.Parse(strings.TrimRight(target.URL, "/") + "/message")
if err != nil {
return err
}
query := endpoint.Query()
query.Set("token", token)
endpoint.RawQuery = query.Encode()
priority := 2
if severity == "warning" {
priority = 5
} else if severity == "failed" || severity == "error" {
priority = 8
}
payload, err := json.Marshal(map[string]any{"title": title, "message": message, "priority": priority})
if err != nil {
return err
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), bytes.NewReader(payload))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
client := s.Client
if client == nil {
client = &http.Client{Timeout: 15 * time.Second}
}
response, err := client.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
if response.StatusCode < 200 || response.StatusCode >= 300 {
return fmt.Errorf("Gotify returned %s", response.Status)
}
return nil
default:
return fmt.Errorf("unsupported notification type %q", target.Type)
}
}