prism/service/integration/webpush/sender.go

73 lines
1.8 KiB
Go

package webpush
import (
"bytes"
"encoding/json"
"fmt"
"log/slog"
"net/http"
"prism/service/notification"
webpush "github.com/SherClockHolmes/webpush-go"
)
type Sender struct {
logger *slog.Logger
}
func NewSender(logger *slog.Logger) *Sender {
return &Sender{
logger: logger,
}
}
func (s *Sender) Send(mapping *notification.Mapping, notif notification.Notification) error {
if mapping.WebPush == nil {
return fmt.Errorf("no push endpoint configured for %s", mapping.AppName)
}
payload, err := json.Marshal(notif)
if err != nil {
return fmt.Errorf("failed to marshal notification: %w", err)
}
if mapping.WebPush.HasEncryption() {
subscription := &webpush.Subscription{
Endpoint: mapping.WebPush.Endpoint,
Keys: webpush.Keys{
P256dh: mapping.WebPush.P256dh,
Auth: mapping.WebPush.Auth,
},
}
resp, err := webpush.SendNotification(payload, subscription, &webpush.Options{
VAPIDPrivateKey: mapping.WebPush.VapidPrivateKey,
TTL: 86400,
})
if err != nil {
return fmt.Errorf("failed to send webpush: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("webpush returned status %d", resp.StatusCode)
}
s.logger.Debug("Sent encrypted webpush notification", "app", mapping.AppName, "url", mapping.WebPush.Endpoint)
} else {
resp, err := http.Post(mapping.WebPush.Endpoint, "application/json", bytes.NewBuffer(payload))
if err != nil {
return fmt.Errorf("failed to send webhook: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("webhook returned status %d", resp.StatusCode)
}
s.logger.Debug("Sent plain webhook notification", "app", mapping.AppName, "url", mapping.WebPush.Endpoint)
}
return nil
}