diff --git a/internal/integration/apprise/apprise.go b/internal/integration/apprise/apprise.go index 7d48b9eb..25ef5369 100644 --- a/internal/integration/apprise/apprise.go +++ b/internal/integration/apprise/apprise.go @@ -7,6 +7,7 @@ import ( "bytes" "encoding/json" "fmt" + "log/slog" "net/http" "time" @@ -26,43 +27,53 @@ func NewClient(serviceURL, baseURL string) *Client { return &Client{serviceURL, baseURL} } -func (c *Client) SendNotification(entry *model.Entry) error { +func (c *Client) SendNotification(feed *model.Feed, entries model.Entries) error { if c.baseURL == "" || c.servicesURL == "" { return fmt.Errorf("apprise: missing base URL or services URL") } - message := "[" + entry.Title + "]" + "(" + entry.URL + ")" + "\n\n" - apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/notify") - if err != nil { - return fmt.Errorf(`apprise: invalid API endpoint: %v`, err) - } + for _, entry := range entries { + message := "[" + entry.Title + "]" + "(" + entry.URL + ")" + "\n\n" + apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/notify") + if err != nil { + return fmt.Errorf(`apprise: invalid API endpoint: %v`, err) + } - requestBody, err := json.Marshal(map[string]any{ - "urls": c.servicesURL, - "body": message, - "title": entry.Feed.Title, - }) - if err != nil { - return fmt.Errorf("apprise: unable to encode request body: %v", err) - } + requestBody, err := json.Marshal(map[string]any{ + "urls": c.servicesURL, + "body": message, + "title": feed.Title, + }) + if err != nil { + return fmt.Errorf("apprise: unable to encode request body: %v", err) + } - request, err := http.NewRequest(http.MethodPost, apiEndpoint, bytes.NewReader(requestBody)) - if err != nil { - return fmt.Errorf("apprise: unable to create request: %v", err) - } + request, err := http.NewRequest(http.MethodPost, apiEndpoint, bytes.NewReader(requestBody)) + if err != nil { + return fmt.Errorf("apprise: unable to create request: %v", err) + } - request.Header.Set("Content-Type", "application/json") - request.Header.Set("User-Agent", "Miniflux/"+version.Version) + request.Header.Set("Content-Type", "application/json") + request.Header.Set("User-Agent", "Miniflux/"+version.Version) - httpClient := &http.Client{Timeout: defaultClientTimeout} - response, err := httpClient.Do(request) - if err != nil { - return fmt.Errorf("apprise: unable to send request: %v", err) - } - defer response.Body.Close() + slog.Debug("Sending Apprise notification", + slog.String("apprise_url", c.baseURL), + slog.String("services_url", c.servicesURL), + slog.String("title", feed.Title), + slog.String("body", message), + slog.String("entry_url", entry.URL), + ) - if response.StatusCode >= 400 { - return fmt.Errorf("apprise: unable to send a notification: url=%s status=%d", apiEndpoint, response.StatusCode) + httpClient := &http.Client{Timeout: defaultClientTimeout} + response, err := httpClient.Do(request) + if err != nil { + return fmt.Errorf("apprise: unable to send request: %v", err) + } + defer response.Body.Close() + + if response.StatusCode >= 400 { + return fmt.Errorf("apprise: unable to send a notification: url=%s status=%d", apiEndpoint, response.StatusCode) + } } return nil diff --git a/internal/integration/integration.go b/internal/integration/integration.go index 850811c9..ff84a699 100644 --- a/internal/integration/integration.go +++ b/internal/integration/integration.go @@ -513,8 +513,30 @@ func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *mode } } + if userIntegrations.AppriseEnabled { + slog.Debug("Sending new entries to Apprise", + slog.Int64("user_id", userIntegrations.UserID), + slog.Int("nb_entries", len(entries)), + slog.Int64("feed_id", feed.ID), + ) + + appriseServiceURLs := userIntegrations.AppriseServicesURL + if feed.AppriseServiceURLs != "" { + appriseServiceURLs = feed.AppriseServiceURLs + } + + client := apprise.NewClient( + appriseServiceURLs, + userIntegrations.AppriseURL, + ) + + if err := client.SendNotification(feed, entries); err != nil { + slog.Warn("Unable to send new entries to Apprise", slog.Any("error", err)) + } + } + // Integrations that only support sending individual entries - if userIntegrations.TelegramBotEnabled || userIntegrations.AppriseEnabled { + if userIntegrations.TelegramBotEnabled { for _, entry := range entries { if userIntegrations.TelegramBotEnabled { slog.Debug("Sending a new entry to Telegram", @@ -541,35 +563,7 @@ func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *mode ) } } - - if userIntegrations.AppriseEnabled { - slog.Debug("Sending a new entry to Apprise", - slog.Int64("user_id", userIntegrations.UserID), - slog.Int64("entry_id", entry.ID), - slog.String("entry_url", entry.URL), - slog.String("apprise_url", userIntegrations.AppriseURL), - ) - - appriseServiceURLs := userIntegrations.AppriseServicesURL - if feed.AppriseServiceURLs != "" { - appriseServiceURLs = feed.AppriseServiceURLs - } - - client := apprise.NewClient( - appriseServiceURLs, - userIntegrations.AppriseURL, - ) - - if err := client.SendNotification(entry); err != nil { - slog.Error("Unable to send entry to Apprise", - slog.Int64("user_id", userIntegrations.UserID), - slog.Int64("entry_id", entry.ID), - slog.String("entry_url", entry.URL), - slog.String("apprise_url", userIntegrations.AppriseURL), - slog.Any("error", err), - ) - } - } } } + }