1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-06-27 16:36:00 +00:00
miniflux-v2/internal/integration/pushover/pushover.go
2025-02-13 20:50:37 -08:00

138 lines
3 KiB
Go

// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package pushover // import "miniflux.app/v2/internal/integration/pushover"
import (
"bytes"
"encoding/json"
"fmt"
"log/slog"
"net/http"
"strings"
"time"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/version"
)
const (
defaultClientTimeout = 10 * time.Second
defaultPushoverURL = "https://api.pushover.net"
)
type Client struct {
prefix string
token string
user string
device string
priority int
}
type Message struct {
Token string `json:"token"`
User string `json:"user"`
Title string `json:"title"`
Message string `json:"message"`
Priority int `json:"priority"`
URL string `json:"url"`
URLTitle string `json:"url_title"`
Device string `json:"device,omitempty"`
}
type ErrorResponse struct {
User string `json:"user"`
Errors []string `json:"errors"`
Status int `json:"status"`
Request string `json:"request"`
}
func New(user, token string, priority int, device, urlPrefix string) *Client {
if urlPrefix == "" {
urlPrefix = defaultPushoverURL
}
if priority < -2 {
priority = -2
}
if priority > 2 {
priority = 2
}
return &Client{
user: user,
token: token,
device: device,
prefix: urlPrefix,
priority: priority,
}
}
func (c *Client) SendMessages(feed *model.Feed, entries model.Entries) error {
if c.token == "" || c.user == "" {
return fmt.Errorf("pushover token and user are required")
}
for _, entry := range entries {
msg := &Message{
User: c.user,
Token: c.token,
Device: c.device,
Message: entry.Title,
Title: feed.Title,
Priority: c.priority,
URL: entry.URL,
}
slog.Debug("Sending Pushover message",
slog.Int("priority", msg.Priority),
slog.String("message", msg.Message),
slog.String("entry_url", msg.URL),
)
if err := c.makeRequest(msg); err != nil {
return fmt.Errorf("c.makeRequest: %w", err)
}
}
return nil
}
func (c *Client) makeRequest(payload *Message) error {
jsonData, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("json.Marshal: %w", err)
}
url := c.prefix + "/1/messages.json"
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(jsonData))
if err != nil {
return fmt.Errorf("http.NewRequest: %w", err)
}
req.Header.Add("Content-Type", "application/json")
req.Header.Set("User-Agent", "Miniflux/"+version.Version)
httpClient := &http.Client{Timeout: defaultClientTimeout}
resp, err := httpClient.Do(req)
if err != nil {
return fmt.Errorf("httpClient.Do: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusBadRequest {
errorMessage := resp.Status
var errResp ErrorResponse
if err := json.NewDecoder(resp.Body).Decode(&errResp); err != nil {
if len(errResp.Errors) > 0 {
errorMessage = strings.Join(errResp.Errors, ",")
}
}
return fmt.Errorf("pushover API error (%d): %s", resp.StatusCode, errorMessage)
}
return nil
}