From ca62b0b36b5f5ecaf13e54f9b4c13c1f745cbfbb Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Sat, 27 Apr 2024 20:35:56 -0700 Subject: [PATCH] integration/raindrop: initial draft implementation --- internal/database/migrations.go | 10 +++ internal/integration/integration.go | 20 +++++ internal/integration/raindrop/raindrop.go | 78 +++++++++++++++++++ internal/locale/translations/de_DE.json | 4 + internal/locale/translations/el_EL.json | 4 + internal/locale/translations/en_US.json | 4 + internal/locale/translations/es_ES.json | 4 + internal/locale/translations/fi_FI.json | 4 + internal/locale/translations/fr_FR.json | 4 + internal/locale/translations/hi_IN.json | 4 + internal/locale/translations/id_ID.json | 4 + internal/locale/translations/it_IT.json | 4 + internal/locale/translations/ja_JP.json | 4 + internal/locale/translations/nl_NL.json | 4 + internal/locale/translations/pl_PL.json | 4 + internal/locale/translations/pt_BR.json | 4 + internal/locale/translations/ru_RU.json | 4 + internal/locale/translations/tr_TR.json | 4 + internal/locale/translations/uk_UA.json | 4 + internal/locale/translations/zh_CN.json | 4 + internal/locale/translations/zh_TW.json | 4 + internal/model/integration.go | 4 + internal/storage/integration.go | 25 +++++- .../templates/views/integrations.html | 22 ++++++ internal/ui/form/integration.go | 12 +++ internal/ui/integration_show.go | 4 + 26 files changed, 243 insertions(+), 4 deletions(-) create mode 100644 internal/integration/raindrop/raindrop.go diff --git a/internal/database/migrations.go b/internal/database/migrations.go index fa3c3972..df2a5dc7 100644 --- a/internal/database/migrations.go +++ b/internal/database/migrations.go @@ -888,4 +888,14 @@ var migrations = []func(tx *sql.Tx) error{ _, err = tx.Exec(`DROP INDEX entries_feed_url_idx`) return err }, + func(tx *sql.Tx) (err error) { + sql := ` + ALTER TABLE integrations ADD COLUMN raindrop_enabled bool default 'f'; + ALTER TABLE integrations ADD COLUMN raindrop_token text default ''; + ALTER TABLE integrations ADD COLUMN raindrop_collection_id text default ''; + ALTER TABLE integrations ADD COLUMN raindrop_tags text default ''; + ` + _, err = tx.Exec(sql) + return err + }, } diff --git a/internal/integration/integration.go b/internal/integration/integration.go index 710679ff..64447bc9 100644 --- a/internal/integration/integration.go +++ b/internal/integration/integration.go @@ -19,6 +19,7 @@ import ( "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" @@ -359,6 +360,7 @@ func SendEntry(entry *model.Entry, userIntegrations *model.Integration) { ) } } + if userIntegrations.OmnivoreEnabled { slog.Debug("Sending entry to Omnivore", slog.Int64("user_id", userIntegrations.UserID), @@ -376,6 +378,24 @@ func SendEntry(entry *model.Entry, userIntegrations *model.Integration) { ) } } + + 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. diff --git a/internal/integration/raindrop/raindrop.go b/internal/integration/raindrop/raindrop.go new file mode 100644 index 00000000..52506db1 --- /dev/null +++ b/internal/integration/raindrop/raindrop.go @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package raindrop // import "miniflux.app/v2/internal/integration/raindrop" + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "miniflux.app/v2/internal/version" +) + +const defaultClientTimeout = 10 * time.Second + +type Client struct { + token string + collectionID string + tags []string +} + +func NewClient(token, collectionID, tags string) *Client { + return &Client{token: token, collectionID: collectionID, tags: strings.Split(tags, ",")} +} + +// https://developer.raindrop.io/v1/raindrops/single#create-raindrop +func (c *Client) CreateRaindrop(entryURL, entryTitle string) error { + if c.token == "" { + return fmt.Errorf("raindrop: missing token") + } + + var request *http.Request + requestBodyJson, err := json.Marshal(&raindrop{ + Link: entryURL, + Title: entryTitle, + Collection: collection{Id: c.collectionID}, + Tags: c.tags, + }) + if err != nil { + return fmt.Errorf("raindrop: unable to encode request body: %v", err) + } + + request, err = http.NewRequest(http.MethodPost, "https://api.raindrop.io/rest/v1/raindrop", bytes.NewReader(requestBodyJson)) + if err != nil { + return fmt.Errorf("raindrop: unable to create request: %v", err) + } + request.Header.Set("Content-Type", "application/json") + + request.Header.Set("User-Agent", "Miniflux/"+version.Version) + request.Header.Set("Authorization", "Bearer "+c.token) + + httpClient := &http.Client{Timeout: defaultClientTimeout} + response, err := httpClient.Do(request) + if err != nil { + return fmt.Errorf("raindrop: unable to send request: %v", err) + } + defer response.Body.Close() + + if response.StatusCode >= 400 { + return fmt.Errorf("raindrop: unable to create bookmark: status=%d", response.StatusCode) + } + + return nil +} + +type raindrop struct { + Link string `json:"link"` + Title string `json:"title"` + Collection collection `json:"collection,omitempty"` + Tags []string `json:"tags"` +} + +type collection struct { + Id string `json:"$id"` +} diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json index b8cceb46..0f43cfb3 100644 --- a/internal/locale/translations/de_DE.json +++ b/internal/locale/translations/de_DE.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Passwort für Matrix-Benutzer", "form.integration.matrix_bot_url": "URL des Matrix-Servers", "form.integration.matrix_bot_chat_id": "ID des Matrix-Raums", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Artikel in Readeck speichern", "form.integration.readeck_endpoint": "Readeck API-Endpunkt", "form.integration.readeck_api_key": "Readeck API-Schlüssel", diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json index 42758fb7..34e80d0b 100644 --- a/internal/locale/translations/el_EL.json +++ b/internal/locale/translations/el_EL.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Κωδικός πρόσβασης για τον χρήστη Matrix", "form.integration.matrix_bot_url": "URL διακομιστή Matrix", "form.integration.matrix_bot_chat_id": "Αναγνωριστικό της αίθουσας Matrix", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Αποθήκευση άρθρων στο Readeck", "form.integration.readeck_endpoint": "Τελικό σημείο Readeck API", "form.integration.readeck_api_key": "Κλειδί API Readeck", diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json index 61e14f8e..ab47eb75 100644 --- a/internal/locale/translations/en_US.json +++ b/internal/locale/translations/en_US.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Password for Matrix user", "form.integration.matrix_bot_url": "Matrix server URL", "form.integration.matrix_bot_chat_id": "ID of Matrix Room", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Save entries to readeck", "form.integration.readeck_endpoint": "Readeck API Endpoint", "form.integration.readeck_api_key": "Readeck API key", diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json index cdb4b9df..499e3eb3 100644 --- a/internal/locale/translations/es_ES.json +++ b/internal/locale/translations/es_ES.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Contraseña para el usuario de Matrix", "form.integration.matrix_bot_url": "URL del servidor de Matrix", "form.integration.matrix_bot_chat_id": "ID de la sala de Matrix", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Enviar artículos a Readeck", "form.integration.readeck_endpoint": "Acceso API de Readeck", "form.integration.readeck_api_key": "Clave de API de Readeck", diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json index 922b6356..7028ad1c 100644 --- a/internal/locale/translations/fi_FI.json +++ b/internal/locale/translations/fi_FI.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Matrix-käyttäjän salasana", "form.integration.matrix_bot_url": "Matrix-palvelimen URL-osoite", "form.integration.matrix_bot_chat_id": "Matrix-huoneen tunnus", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Tallenna artikkelit Readeckiin", "form.integration.readeck_endpoint": "Readeck API-päätepiste", "form.integration.readeck_api_key": "Readeck API-avain", diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json index c533a15c..b73a8d95 100644 --- a/internal/locale/translations/fr_FR.json +++ b/internal/locale/translations/fr_FR.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Mot de passe de l'utilisateur Matrix", "form.integration.matrix_bot_url": "URL du serveur Matrix", "form.integration.matrix_bot_chat_id": "Identifiant de la salle Matrix", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Sauvegarder les articles vers Readeck", "form.integration.readeck_endpoint": "URL de l'API de Readeck", "form.integration.readeck_api_key": "Clé d'API de Readeck", diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json index b857b1c9..92922079 100644 --- a/internal/locale/translations/hi_IN.json +++ b/internal/locale/translations/hi_IN.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "मैट्रिक्स उपयोगकर्ता के लिए पासवर्ड", "form.integration.matrix_bot_url": "मैट्रिक्स सर्वर URL", "form.integration.matrix_bot_chat_id": "मैट्रिक्स रूम की आईडी", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Readeck में विषयवस्तु सहेजें", "form.integration.readeck_endpoint": "Readeck·एपीआई·समापन·बिंदु", "form.integration.readeck_api_key": "Readeck एपीआई कुंजी", diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json index a0ac7880..16e66ff1 100644 --- a/internal/locale/translations/id_ID.json +++ b/internal/locale/translations/id_ID.json @@ -442,6 +442,10 @@ "form.integration.matrix_bot_password": "Kata Sandi Matrix", "form.integration.matrix_bot_url": "URL Peladen Matrix", "form.integration.matrix_bot_chat_id": "ID Ruang Matrix", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Simpan artikel ke Readeck", "form.integration.readeck_endpoint": "Titik URL API Readeck", "form.integration.readeck_api_key": "Kunci API Readeck", diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json index e3b12225..c9edd6f2 100644 --- a/internal/locale/translations/it_IT.json +++ b/internal/locale/translations/it_IT.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Password per l'utente Matrix", "form.integration.matrix_bot_url": "URL del server Matrix", "form.integration.matrix_bot_chat_id": "ID della stanza Matrix", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Salva gli articoli su Readeck", "form.integration.readeck_endpoint": "Endpoint dell'API di Readeck", "form.integration.readeck_api_key": "API key dell'account Readeck", diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json index 55f6de83..0beb0759 100644 --- a/internal/locale/translations/ja_JP.json +++ b/internal/locale/translations/ja_JP.json @@ -442,6 +442,10 @@ "form.integration.matrix_bot_password": "Matrixユーザ用パスワード", "form.integration.matrix_bot_url": "MatrixサーバーのURL", "form.integration.matrix_bot_chat_id": "MatrixルームのID", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Readeck に記事を保存する", "form.integration.readeck_endpoint": "Readeck の API Endpoint", "form.integration.readeck_api_key": "Readeck の API key", diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json index c9b235e2..3f17f631 100644 --- a/internal/locale/translations/nl_NL.json +++ b/internal/locale/translations/nl_NL.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Wachtwoord voor Matrix-gebruiker", "form.integration.matrix_bot_url": "URL van de Matrix-server", "form.integration.matrix_bot_chat_id": "ID van Matrix-kamer", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Opslaan naar Readeck", "form.integration.readeck_endpoint": "Readeck URL", "form.integration.readeck_api_key": "Readeck API-sleutel", diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json index 78c49876..ddaf0d8b 100644 --- a/internal/locale/translations/pl_PL.json +++ b/internal/locale/translations/pl_PL.json @@ -462,6 +462,10 @@ "form.integration.matrix_bot_password": "Hasło dla użytkownika Matrix", "form.integration.matrix_bot_url": "URL serwera Matrix", "form.integration.matrix_bot_chat_id": "Identyfikator pokoju Matrix", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Zapisz artykuły do Readeck", "form.integration.readeck_endpoint": "Readeck URL", "form.integration.readeck_api_key": "Readeck API key", diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json index dd9dca9c..8502b778 100644 --- a/internal/locale/translations/pt_BR.json +++ b/internal/locale/translations/pt_BR.json @@ -452,6 +452,10 @@ "form.integration.matrix_bot_password": "Palavra-passe para utilizador da Matrix", "form.integration.matrix_bot_url": "URL do servidor Matrix", "form.integration.matrix_bot_chat_id": "Identificação da sala Matrix", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Salvar itens no Readeck", "form.integration.readeck_endpoint": "Endpoint de API do Readeck", "form.integration.readeck_api_key": "Chave de API do Readeck", diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json index 636ef54e..2d17fae9 100644 --- a/internal/locale/translations/ru_RU.json +++ b/internal/locale/translations/ru_RU.json @@ -462,6 +462,10 @@ "form.integration.matrix_bot_password": "Пароль пользователя Matrix", "form.integration.matrix_bot_url": "Ссылка на сервер Matrix", "form.integration.matrix_bot_chat_id": "ID комнаты Matrix", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Сохранять статьи в Readeck", "form.integration.readeck_endpoint": "Конечная точка Readeck API", "form.integration.readeck_api_key": "API-ключ Readeck", diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json index 87a67025..3edd074b 100644 --- a/internal/locale/translations/tr_TR.json +++ b/internal/locale/translations/tr_TR.json @@ -222,6 +222,10 @@ "form.integration.pocket_activate": "Makaleleri Pocket'a kaydet", "form.integration.pocket_connect_link": "Pocket hesabını bağla", "form.integration.pocket_consumer_key": "Pocket Consumer Anahtarı", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Makaleleri Readeck'e kaydet", "form.integration.readeck_api_key": "Readeck API Anahtarı", "form.integration.readeck_endpoint": "Readeck API Uç Noktası", diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json index 221a4ca9..a7563fe6 100644 --- a/internal/locale/translations/uk_UA.json +++ b/internal/locale/translations/uk_UA.json @@ -462,6 +462,10 @@ "form.integration.matrix_bot_password": "Пароль для користувача Matrix", "form.integration.matrix_bot_url": "URL-адреса сервера Матриці", "form.integration.matrix_bot_chat_id": "Ідентифікатор кімнати Матриці", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "Зберігати статті до Readeck", "form.integration.readeck_endpoint": "Readeck API Endpoint", "form.integration.readeck_api_key": "Ключ API Readeck", diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json index d1797c24..ba0d1f57 100644 --- a/internal/locale/translations/zh_CN.json +++ b/internal/locale/translations/zh_CN.json @@ -442,6 +442,10 @@ "form.integration.matrix_bot_password": "Matrix Bot 密码", "form.integration.matrix_bot_url": "Matrix 服务器 URL", "form.integration.matrix_bot_chat_id": "Matrix 聊天 ID", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "保存文章到 Readeck", "form.integration.readeck_endpoint": "Readeck API 端点", "form.integration.readeck_api_key": "Readeck API 密钥", diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json index 35be9e2b..57f50b08 100644 --- a/internal/locale/translations/zh_TW.json +++ b/internal/locale/translations/zh_TW.json @@ -442,6 +442,10 @@ "form.integration.matrix_bot_password": "Matrix 的密碼", "form.integration.matrix_bot_url": "Matrix 伺服器的 URL", "form.integration.matrix_bot_chat_id": "Matrix 房間 ID", + "form.integration.raindrop_activate": "Save entries to Raindrop", + "form.integration.raindrop_token": "(Test) Token", + "form.integration.raindrop_collection_id": "Collection ID", + "form.integration.raindrop_tags": "Tags (comma-separated)", "form.integration.readeck_activate": "儲存文章到 Readeck", "form.integration.readeck_endpoint": "Readeck API 端點", "form.integration.readeck_api_key": "Readeck API 金鑰", diff --git a/internal/model/integration.go b/internal/model/integration.go index 4ab70c18..05e4cec7 100644 --- a/internal/model/integration.go +++ b/internal/model/integration.go @@ -90,4 +90,8 @@ type Integration struct { OmnivoreEnabled bool OmnivoreAPIKey string OmnivoreURL string + RaindropEnabled bool + RaindropToken string + RaindropCollectionID string + RaindropTags string } diff --git a/internal/storage/integration.go b/internal/storage/integration.go index d3f3d0eb..2b848ac3 100644 --- a/internal/storage/integration.go +++ b/internal/storage/integration.go @@ -193,7 +193,11 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) { rssbridge_url, omnivore_enabled, omnivore_api_key, - omnivore_url + omnivore_url, + raindrop_enabled, + raindrop_token, + raindrop_collection_id, + raindrop_tags FROM integrations WHERE @@ -286,6 +290,10 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) { &integration.OmnivoreEnabled, &integration.OmnivoreAPIKey, &integration.OmnivoreURL, + &integration.RaindropEnabled, + &integration.RaindropToken, + &integration.RaindropCollectionID, + &integration.RaindropTags, ) switch { case err == sql.ErrNoRows: @@ -386,9 +394,13 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error { omnivore_url=$81, linkwarden_enabled=$82, linkwarden_url=$83, - linkwarden_api_key=$84 + linkwarden_api_key=$84, + raindrop_enabled=$85, + raindrop_token=$86, + raindrop_collection_id=$87, + raindrop_tags=$88 WHERE - user_id=$85 + user_id=$89 ` _, err := s.db.Exec( query, @@ -476,6 +488,10 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error { integration.LinkwardenEnabled, integration.LinkwardenURL, integration.LinkwardenAPIKey, + integration.RaindropEnabled, + integration.RaindropToken, + integration.RaindropCollectionID, + integration.RaindropTags, integration.UserID, ) @@ -513,7 +529,8 @@ func (s *Storage) HasSaveEntry(userID int64) (result bool) { readeck_enabled='t' OR shaarli_enabled='t' OR webhook_enabled='t' OR - omnivore_enabled='t' + omnivore_enabled='t' OR + raindrop_enabled='t' ) ` if err := s.db.QueryRow(query, userID).Scan(&result); err != nil { diff --git a/internal/template/templates/views/integrations.html b/internal/template/templates/views/integrations.html index 41504147..66d03154 100644 --- a/internal/template/templates/views/integrations.html +++ b/internal/template/templates/views/integrations.html @@ -326,6 +326,28 @@ +
+ Raindrop +
+ + + + + + + + + + + +
+ +
+
+
+
Readeck
diff --git a/internal/ui/form/integration.go b/internal/ui/form/integration.go index 7bc5cf91..7809a3ff 100644 --- a/internal/ui/form/integration.go +++ b/internal/ui/form/integration.go @@ -96,6 +96,10 @@ type IntegrationForm struct { OmnivoreEnabled bool OmnivoreAPIKey string OmnivoreURL string + RaindropEnabled bool + RaindropToken string + RaindropCollectionID string + RaindropTags string } // Merge copy form values to the model. @@ -181,6 +185,10 @@ func (i IntegrationForm) Merge(integration *model.Integration) { integration.OmnivoreEnabled = i.OmnivoreEnabled integration.OmnivoreAPIKey = i.OmnivoreAPIKey integration.OmnivoreURL = i.OmnivoreURL + integration.RaindropEnabled = i.RaindropEnabled + integration.RaindropToken = i.RaindropToken + integration.RaindropCollectionID = i.RaindropCollectionID + integration.RaindropTags = i.RaindropTags } // NewIntegrationForm returns a new IntegrationForm. @@ -269,6 +277,10 @@ func NewIntegrationForm(r *http.Request) *IntegrationForm { OmnivoreEnabled: r.FormValue("omnivore_enabled") == "1", OmnivoreAPIKey: r.FormValue("omnivore_api_key"), OmnivoreURL: r.FormValue("omnivore_url"), + RaindropEnabled: r.FormValue("raindrop_enabled") == "1", + RaindropToken: r.FormValue("raindrop_token"), + RaindropCollectionID: r.FormValue("raindrop_collection_id"), + RaindropTags: r.FormValue("raindrop_tags"), } } diff --git a/internal/ui/integration_show.go b/internal/ui/integration_show.go index 03bc73b6..8b3299a4 100644 --- a/internal/ui/integration_show.go +++ b/internal/ui/integration_show.go @@ -110,6 +110,10 @@ func (h *handler) showIntegrationPage(w http.ResponseWriter, r *http.Request) { OmnivoreEnabled: integration.OmnivoreEnabled, OmnivoreAPIKey: integration.OmnivoreAPIKey, OmnivoreURL: integration.OmnivoreURL, + RaindropEnabled: integration.RaindropEnabled, + RaindropToken: integration.RaindropToken, + RaindropCollectionID: integration.RaindropCollectionID, + RaindropTags: integration.RaindropTags, } sess := session.New(h.store, request.SessionID(r))