532 lines
16 KiB
Go
532 lines
16 KiB
Go
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package integration // import "miniflux.app/v2/internal/integration"
|
|
|
|
import (
|
|
"log/slog"
|
|
|
|
"miniflux.app/v2/internal/config"
|
|
"miniflux.app/v2/internal/integration/apprise"
|
|
"miniflux.app/v2/internal/integration/betula"
|
|
"miniflux.app/v2/internal/integration/espial"
|
|
"miniflux.app/v2/internal/integration/instapaper"
|
|
"miniflux.app/v2/internal/integration/linkace"
|
|
"miniflux.app/v2/internal/integration/linkding"
|
|
"miniflux.app/v2/internal/integration/linkwarden"
|
|
"miniflux.app/v2/internal/integration/matrixbot"
|
|
"miniflux.app/v2/internal/integration/notion"
|
|
"miniflux.app/v2/internal/integration/nunuxkeeper"
|
|
"miniflux.app/v2/internal/integration/omnivore"
|
|
"miniflux.app/v2/internal/integration/pinboard"
|
|
"miniflux.app/v2/internal/integration/pocket"
|
|
"miniflux.app/v2/internal/integration/raindrop"
|
|
"miniflux.app/v2/internal/integration/readeck"
|
|
"miniflux.app/v2/internal/integration/readwise"
|
|
"miniflux.app/v2/internal/integration/shaarli"
|
|
"miniflux.app/v2/internal/integration/shiori"
|
|
"miniflux.app/v2/internal/integration/telegrambot"
|
|
"miniflux.app/v2/internal/integration/wallabag"
|
|
"miniflux.app/v2/internal/integration/webhook"
|
|
"miniflux.app/v2/internal/model"
|
|
)
|
|
|
|
// SendEntry sends the entry to third-party providers when the user click on "Save".
|
|
func SendEntry(entry *model.Entry, userIntegrations *model.Integration) {
|
|
if userIntegrations.BetulaEnabled {
|
|
slog.Debug("Sending entry to Betula",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := betula.NewClient(userIntegrations.BetulaURL, userIntegrations.BetulaToken)
|
|
err := client.CreateBookmark(
|
|
entry.URL,
|
|
entry.Title,
|
|
entry.Tags,
|
|
)
|
|
|
|
if err != nil {
|
|
slog.Error("Unable to send entry to Betula",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.PinboardEnabled {
|
|
slog.Debug("Sending entry to Pinboard",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := pinboard.NewClient(userIntegrations.PinboardToken)
|
|
err := client.CreateBookmark(
|
|
entry.URL,
|
|
entry.Title,
|
|
userIntegrations.PinboardTags,
|
|
userIntegrations.PinboardMarkAsUnread,
|
|
)
|
|
|
|
if err != nil {
|
|
slog.Error("Unable to send entry to Pinboard",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.InstapaperEnabled {
|
|
slog.Debug("Sending entry to Instapaper",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := instapaper.NewClient(userIntegrations.InstapaperUsername, userIntegrations.InstapaperPassword)
|
|
if err := client.AddURL(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to Instapaper",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.WallabagEnabled {
|
|
slog.Debug("Sending entry to Wallabag",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := wallabag.NewClient(
|
|
userIntegrations.WallabagURL,
|
|
userIntegrations.WallabagClientID,
|
|
userIntegrations.WallabagClientSecret,
|
|
userIntegrations.WallabagUsername,
|
|
userIntegrations.WallabagPassword,
|
|
userIntegrations.WallabagOnlyURL,
|
|
)
|
|
|
|
if err := client.CreateEntry(entry.URL, entry.Title, entry.Content); err != nil {
|
|
slog.Error("Unable to send entry to Wallabag",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.NotionEnabled {
|
|
slog.Debug("Sending entry to Notion",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := notion.NewClient(
|
|
userIntegrations.NotionToken,
|
|
userIntegrations.NotionPageID,
|
|
)
|
|
if err := client.UpdateDocument(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to Notion",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.NunuxKeeperEnabled {
|
|
slog.Debug("Sending entry to NunuxKeeper",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := nunuxkeeper.NewClient(
|
|
userIntegrations.NunuxKeeperURL,
|
|
userIntegrations.NunuxKeeperAPIKey,
|
|
)
|
|
|
|
if err := client.AddEntry(entry.URL, entry.Title, entry.Content); err != nil {
|
|
slog.Error("Unable to send entry to NunuxKeeper",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.EspialEnabled {
|
|
slog.Debug("Sending entry to Espial",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := espial.NewClient(
|
|
userIntegrations.EspialURL,
|
|
userIntegrations.EspialAPIKey,
|
|
)
|
|
|
|
if err := client.CreateLink(entry.URL, entry.Title, userIntegrations.EspialTags); err != nil {
|
|
slog.Error("Unable to send entry to Espial",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.PocketEnabled {
|
|
slog.Debug("Sending entry to Pocket",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := pocket.NewClient(config.Opts.PocketConsumerKey(userIntegrations.PocketConsumerKey), userIntegrations.PocketAccessToken)
|
|
if err := client.AddURL(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to Pocket",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.LinkAceEnabled {
|
|
slog.Debug("Sending entry to LinkAce",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := linkace.NewClient(
|
|
userIntegrations.LinkAceURL,
|
|
userIntegrations.LinkAceAPIKey,
|
|
userIntegrations.LinkAceTags,
|
|
userIntegrations.LinkAcePrivate,
|
|
userIntegrations.LinkAceCheckDisabled,
|
|
)
|
|
if err := client.AddURL(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to LinkAce",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.LinkdingEnabled {
|
|
slog.Debug("Sending entry to Linkding",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := linkding.NewClient(
|
|
userIntegrations.LinkdingURL,
|
|
userIntegrations.LinkdingAPIKey,
|
|
userIntegrations.LinkdingTags,
|
|
userIntegrations.LinkdingMarkAsUnread,
|
|
)
|
|
if err := client.CreateBookmark(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to Linkding",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.LinkwardenEnabled {
|
|
slog.Debug("Sending entry to linkwarden",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := linkwarden.NewClient(
|
|
userIntegrations.LinkwardenURL,
|
|
userIntegrations.LinkwardenAPIKey,
|
|
)
|
|
if err := client.CreateBookmark(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to Linkwarden",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.ReadeckEnabled {
|
|
slog.Debug("Sending entry to Readeck",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := readeck.NewClient(
|
|
userIntegrations.ReadeckURL,
|
|
userIntegrations.ReadeckAPIKey,
|
|
userIntegrations.ReadeckLabels,
|
|
userIntegrations.ReadeckOnlyURL,
|
|
)
|
|
if err := client.CreateBookmark(entry.URL, entry.Title, entry.Content); err != nil {
|
|
slog.Error("Unable to send entry to Readeck",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.ReadwiseEnabled {
|
|
slog.Debug("Sending entry to Readwise",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := readwise.NewClient(
|
|
userIntegrations.ReadwiseAPIKey,
|
|
)
|
|
|
|
if err := client.CreateDocument(entry.URL); err != nil {
|
|
slog.Error("Unable to send entry to Readwise",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.ShioriEnabled {
|
|
slog.Debug("Sending entry to Shiori",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := shiori.NewClient(
|
|
userIntegrations.ShioriURL,
|
|
userIntegrations.ShioriUsername,
|
|
userIntegrations.ShioriPassword,
|
|
)
|
|
|
|
if err := client.CreateBookmark(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to Shiori",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.ShaarliEnabled {
|
|
slog.Debug("Sending entry to Shaarli",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := shaarli.NewClient(
|
|
userIntegrations.ShaarliURL,
|
|
userIntegrations.ShaarliAPISecret,
|
|
)
|
|
|
|
if err := client.CreateLink(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to Shaarli",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.WebhookEnabled {
|
|
slog.Debug("Sending entry to Webhook",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.String("webhook_url", userIntegrations.WebhookURL),
|
|
)
|
|
|
|
webhookClient := webhook.NewClient(userIntegrations.WebhookURL, userIntegrations.WebhookSecret)
|
|
if err := webhookClient.SendSaveEntryWebhookEvent(entry); err != nil {
|
|
slog.Error("Unable to send entry to Webhook",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.String("webhook_url", userIntegrations.WebhookURL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.OmnivoreEnabled {
|
|
slog.Debug("Sending entry to Omnivore",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := omnivore.NewClient(userIntegrations.OmnivoreAPIKey, userIntegrations.OmnivoreURL)
|
|
if err := client.SaveUrl(entry.URL); err != nil {
|
|
slog.Error("Unable to send entry to Omnivore",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.RaindropEnabled {
|
|
slog.Debug("Sending entry to Raindrop",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
client := raindrop.NewClient(userIntegrations.RaindropToken, userIntegrations.RaindropCollectionID, userIntegrations.RaindropTags)
|
|
if err := client.CreateRaindrop(entry.URL, entry.Title); err != nil {
|
|
slog.Error("Unable to send entry to Raindrop",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// PushEntries pushes a list of entries to activated third-party providers during feed refreshes.
|
|
func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *model.Integration) {
|
|
if userIntegrations.MatrixBotEnabled {
|
|
slog.Debug("Sending new entries to Matrix",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int("nb_entries", len(entries)),
|
|
slog.Int64("feed_id", feed.ID),
|
|
)
|
|
|
|
err := matrixbot.PushEntries(
|
|
feed,
|
|
entries,
|
|
userIntegrations.MatrixBotURL,
|
|
userIntegrations.MatrixBotUser,
|
|
userIntegrations.MatrixBotPassword,
|
|
userIntegrations.MatrixBotChatID,
|
|
)
|
|
if err != nil {
|
|
slog.Error("Unable to send new entries to Matrix",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int("nb_entries", len(entries)),
|
|
slog.Int64("feed_id", feed.ID),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
if userIntegrations.WebhookEnabled {
|
|
slog.Debug("Sending new entries to Webhook",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int("nb_entries", len(entries)),
|
|
slog.Int64("feed_id", feed.ID),
|
|
slog.String("webhook_url", userIntegrations.WebhookURL),
|
|
)
|
|
|
|
webhookClient := webhook.NewClient(userIntegrations.WebhookURL, userIntegrations.WebhookSecret)
|
|
if err := webhookClient.SendNewEntriesWebhookEvent(feed, entries); err != nil {
|
|
slog.Debug("Unable to send new entries to Webhook",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int("nb_entries", len(entries)),
|
|
slog.Int64("feed_id", feed.ID),
|
|
slog.String("webhook_url", userIntegrations.WebhookURL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
// Integrations that only support sending individual entries
|
|
if userIntegrations.TelegramBotEnabled || userIntegrations.AppriseEnabled {
|
|
for _, entry := range entries {
|
|
if userIntegrations.TelegramBotEnabled {
|
|
slog.Debug("Sending a new entry to Telegram",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
)
|
|
|
|
if err := telegrambot.PushEntry(
|
|
feed,
|
|
entry,
|
|
userIntegrations.TelegramBotToken,
|
|
userIntegrations.TelegramBotChatID,
|
|
userIntegrations.TelegramBotTopicID,
|
|
userIntegrations.TelegramBotDisableWebPagePreview,
|
|
userIntegrations.TelegramBotDisableNotification,
|
|
userIntegrations.TelegramBotDisableButtons,
|
|
); err != nil {
|
|
slog.Error("Unable to send entry to Telegram",
|
|
slog.Int64("user_id", userIntegrations.UserID),
|
|
slog.Int64("entry_id", entry.ID),
|
|
slog.String("entry_url", entry.URL),
|
|
slog.Any("error", err),
|
|
)
|
|
}
|
|
}
|
|
|
|
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),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|