From 1e704468a50c53dc98c07f3d87805b6ca16ca919 Mon Sep 17 00:00:00 2001 From: MDeLuise <66636702+MDeLuise@users.noreply.github.com> Date: Tue, 23 Jan 2024 18:12:31 +0100 Subject: [PATCH] feat: add linkace service integration --- internal/database/migrations.go | 12 +++ internal/integration/integration.go | 25 +++++ internal/integration/linkace/linkace.go | 83 +++++++++++++++++ internal/locale/translations/de_DE.json | 6 ++ internal/locale/translations/el_EL.json | 6 ++ internal/locale/translations/en_US.json | 6 ++ internal/locale/translations/es_ES.json | 6 ++ internal/locale/translations/fi_FI.json | 6 ++ internal/locale/translations/fr_FR.json | 6 ++ internal/locale/translations/hi_IN.json | 6 ++ internal/locale/translations/id_ID.json | 6 ++ internal/locale/translations/it_IT.json | 6 ++ internal/locale/translations/ja_JP.json | 6 ++ internal/locale/translations/nl_NL.json | 6 ++ internal/locale/translations/pl_PL.json | 6 ++ internal/locale/translations/pt_BR.json | 6 ++ internal/locale/translations/ru_RU.json | 6 ++ internal/locale/translations/tr_TR.json | 6 ++ internal/locale/translations/uk_UA.json | 6 ++ internal/locale/translations/zh_CN.json | 6 ++ internal/locale/translations/zh_TW.json | 6 ++ internal/model/integration.go | 6 ++ internal/storage/integration.go | 93 ++++++++++++------- .../templates/views/integrations.html | 30 ++++++ internal/ui/form/integration.go | 18 ++++ internal/ui/integration_show.go | 6 ++ 26 files changed, 347 insertions(+), 34 deletions(-) create mode 100644 internal/integration/linkace/linkace.go diff --git a/internal/database/migrations.go b/internal/database/migrations.go index be3bef84..0313e918 100644 --- a/internal/database/migrations.go +++ b/internal/database/migrations.go @@ -834,4 +834,16 @@ var migrations = []func(tx *sql.Tx) error{ _, err = tx.Exec(sql) return }, + func(tx *sql.Tx) (err error) { + sql := ` + ALTER TABLE integrations ADD COLUMN linkace_enabled bool default 'f'; + ALTER TABLE integrations ADD COLUMN linkace_url text default ''; + ALTER TABLE integrations ADD COLUMN linkace_api_key text default ''; + ALTER TABLE integrations ADD COLUMN linkace_tags text default ''; + ALTER TABLE integrations ADD COLUMN linkace_is_private bool default 't'; + ALTER TABLE integrations ADD COLUMN linkace_check_disabled bool default 't'; + ` + _, err = tx.Exec(sql) + return err + }, } diff --git a/internal/integration/integration.go b/internal/integration/integration.go index 5d0c98df..2d36b176 100644 --- a/internal/integration/integration.go +++ b/internal/integration/integration.go @@ -10,6 +10,7 @@ import ( "miniflux.app/v2/internal/integration/apprise" "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/matrixbot" "miniflux.app/v2/internal/integration/notion" @@ -180,6 +181,30 @@ func SendEntry(entry *model.Entry, userIntegrations *model.Integration) { } } + 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), diff --git a/internal/integration/linkace/linkace.go b/internal/integration/linkace/linkace.go new file mode 100644 index 00000000..75348411 --- /dev/null +++ b/internal/integration/linkace/linkace.go @@ -0,0 +1,83 @@ +package linkace + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "miniflux.app/v2/internal/urllib" + "miniflux.app/v2/internal/version" +) + +const defaultClientTimeout = 10 * time.Second + +type Client struct { + baseURL string + apiKey string + tags string + private bool + checkDisabled bool +} + +func NewClient(baseURL, apiKey, tags string, private bool, checkDisabled bool) *Client { + return &Client{baseURL: baseURL, apiKey: apiKey, tags: tags, private: private, checkDisabled: checkDisabled} +} + +func (c *Client) AddURL(entryURL, entryTitle string) error { + if c.baseURL == "" || c.apiKey == "" { + return fmt.Errorf("linkace: missing base URL or API key") + } + + tagsSplitFn := func(c rune) bool { + return c == ',' || c == ' ' + } + + apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/v1/links") + if err != nil { + return fmt.Errorf("linkace: invalid API endpoint: %v", err) + } + requestBody, err := json.Marshal(&createItemRequest{ + Url: entryURL, + Title: entryTitle, + Tags: strings.FieldsFunc(c.tags, tagsSplitFn), + Private: c.private, + CheckDisabled: c.checkDisabled, + }) + if err != nil { + return fmt.Errorf("linkace: unable to encode request body: %v", err) + } + + request, err := http.NewRequest(http.MethodPost, apiEndpoint, bytes.NewReader(requestBody)) + if err != nil { + return fmt.Errorf("linkace: unable to create request: %v", err) + } + + request.Header.Set("Content-Type", "application/json") + request.Header.Set("Accept", "application/json") + request.Header.Set("User-Agent", "Miniflux/"+version.Version) + request.Header.Set("Authorization", "Bearer "+c.apiKey) + + httpClient := &http.Client{Timeout: defaultClientTimeout} + response, err := httpClient.Do(request) + if err != nil { + return fmt.Errorf("linkace: unable to send request: %v", err) + } + defer response.Body.Close() + + if response.StatusCode >= 400 { + return fmt.Errorf("linkace: unable to create item: url=%s status=%d", apiEndpoint, response.StatusCode) + } + + return nil +} + +type createItemRequest struct { + Title string `json:"title,omitempty"` + Url string `json:"url"` + Tags []string `json:"tags,omitempty"` + Private bool `json:"is_private,omitempty"` + CheckDisabled bool `json:"check_disabled,omitempty"` +} diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json index c2b18245..f63d4e1c 100644 --- a/internal/locale/translations/de_DE.json +++ b/internal/locale/translations/de_DE.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Webseiten-Vorschau deaktivieren", "form.integration.telegram_bot_disable_notification": "Benachrichtigungen deaktivieren", "form.integration.telegram_bot_disable_buttons": "Schaltfächen deaktivieren", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Artikel in Linkding speichern", "form.integration.linkding_endpoint": "Linkding API-Endpunkt", "form.integration.linkding_api_key": "Linkding API-Schlüssel", diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json index aa338d32..631bc047 100644 --- a/internal/locale/translations/el_EL.json +++ b/internal/locale/translations/el_EL.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Αποθήκευση άρθρων στο Linkding", "form.integration.linkding_endpoint": "Τελικό σημείο Linkding API", "form.integration.linkding_api_key": "Κλειδί API Linkding", diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json index 2e7619cd..66de75cb 100644 --- a/internal/locale/translations/en_US.json +++ b/internal/locale/translations/en_US.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Save entries to Linkding", "form.integration.linkding_endpoint": "Linkding API Endpoint", "form.integration.linkding_api_key": "Linkding API key", diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json index 39f40869..0d8825ef 100644 --- a/internal/locale/translations/es_ES.json +++ b/internal/locale/translations/es_ES.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Enviar artículos a Linkding", "form.integration.linkding_endpoint": "Acceso API de Linkding", "form.integration.linkding_api_key": "Clave de API de Linkding", diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json index c05e5b40..a841342e 100644 --- a/internal/locale/translations/fi_FI.json +++ b/internal/locale/translations/fi_FI.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Tallenna artikkelit Linkkiin", "form.integration.linkding_endpoint": "Linkding API-päätepiste", "form.integration.linkding_api_key": "Linkding API-avain", diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json index 7640365d..b8569a08 100644 --- a/internal/locale/translations/fr_FR.json +++ b/internal/locale/translations/fr_FR.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Désactiver l'aperçu de la page Web", "form.integration.telegram_bot_disable_notification": "Désactiver les notifications", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Sauvegarder les articles vers Linkding", "form.integration.linkding_endpoint": "URL de l'API de Linkding", "form.integration.linkding_api_key": "Clé d'API de Linkding", diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json index 36135192..499a3e1d 100644 --- a/internal/locale/translations/hi_IN.json +++ b/internal/locale/translations/hi_IN.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "लिंक्डिन में विषयवस्तु सहेजें", "form.integration.linkding_endpoint": "लिंकिंग एपीआई समापन बिंदु", "form.integration.linkding_api_key": "लिंकिंग एपीआई कुंजी", diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json index a550e23f..5372627d 100644 --- a/internal/locale/translations/id_ID.json +++ b/internal/locale/translations/id_ID.json @@ -398,6 +398,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Simpan artikel ke Linkding", "form.integration.linkding_endpoint": "Titik URL API Linkding", "form.integration.linkding_api_key": "Kunci API Linkding", diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json index ca464cf1..fabf129f 100644 --- a/internal/locale/translations/it_IT.json +++ b/internal/locale/translations/it_IT.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Salva gli articoli su LinkAce", + "form.integration.linkace_endpoint": "Endpoint dell'API di LinkAce", + "form.integration.linkace_api_key": "API key dell'account LinkAce", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Rendi i link privati", + "form.integration.linkace_check_disabled": "Disabilita i controlli", "form.integration.linkding_activate": "Salva gli articoli su Linkding", "form.integration.linkding_endpoint": "Endpoint dell'API di Linkding", "form.integration.linkding_api_key": "API key dell'account Linkding", diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json index 5d5031bd..c0b3f20e 100644 --- a/internal/locale/translations/ja_JP.json +++ b/internal/locale/translations/ja_JP.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Linkding に記事を保存する", "form.integration.linkding_endpoint": "Linkding の API Endpoint", "form.integration.linkding_api_key": "Linkding の API key", diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json index 38d6a76c..88ae8ed9 100644 --- a/internal/locale/translations/nl_NL.json +++ b/internal/locale/translations/nl_NL.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Opslaan naar Linkding", "form.integration.linkding_endpoint": "Linkding URL", "form.integration.linkding_api_key": "Linkding API-sleutel", diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json index 7ff83d73..b77b7b67 100644 --- a/internal/locale/translations/pl_PL.json +++ b/internal/locale/translations/pl_PL.json @@ -404,6 +404,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Zapisz artykuły do Linkding", "form.integration.linkding_endpoint": "Linkding URL", "form.integration.linkding_api_key": "Linkding API key", diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json index 5fef829c..dbe02e2b 100644 --- a/internal/locale/translations/pt_BR.json +++ b/internal/locale/translations/pt_BR.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Salvar itens no Linkding", "form.integration.linkding_endpoint": "Endpoint de API do Linkding", "form.integration.linkding_api_key": "Chave de API do Linkding", diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json index e86c5bf4..3be4e412 100644 --- a/internal/locale/translations/ru_RU.json +++ b/internal/locale/translations/ru_RU.json @@ -404,6 +404,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Сохранять статьи в Linkding", "form.integration.linkding_endpoint": "Конечная точка Linkding API", "form.integration.linkding_api_key": "API-ключ Linkding", diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json index 1ac1ac31..8925ceb5 100644 --- a/internal/locale/translations/tr_TR.json +++ b/internal/locale/translations/tr_TR.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "Disable web page preview", "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Makaleleri Linkding'e kaydet", "form.integration.linkding_endpoint": "Linkding API Uç Noktası", "form.integration.linkding_api_key": "Linkding API Anahtarı", diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json index 81de6015..bbe3d071 100644 --- a/internal/locale/translations/uk_UA.json +++ b/internal/locale/translations/uk_UA.json @@ -405,6 +405,12 @@ "form.integration.telegram_bot_disable_notification": "Disable notification", "form.integration.telegram_bot_disable_buttons": "Disable buttons", "form.integration.telegram_chat_id": "ID чату", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "Зберігати статті до Linkding", "form.integration.linkding_endpoint": "Linkding API Endpoint", "form.integration.linkding_api_key": "Ключ API Linkding", diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json index d8f5cbbf..c1c70012 100644 --- a/internal/locale/translations/zh_CN.json +++ b/internal/locale/translations/zh_CN.json @@ -399,6 +399,12 @@ "form.integration.telegram_bot_disable_notification": "禁用通知", "form.integration.telegram_bot_disable_buttons": "不展示按钮", "form.integration.telegram_chat_id": "聊天ID", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "保存文章到 Linkding", "form.integration.linkding_endpoint": "Linkding API 端点", "form.integration.linkding_api_key": "Linkding API 密钥", diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json index 172e70dc..e0560d04 100644 --- a/internal/locale/translations/zh_TW.json +++ b/internal/locale/translations/zh_TW.json @@ -401,6 +401,12 @@ "form.integration.telegram_bot_disable_web_page_preview": "停用網頁預覽", "form.integration.telegram_bot_disable_notification": "停用通知", "form.integration.telegram_bot_disable_buttons": "不展示按鈕", + "form.integration.linkace_activate": "Save entries to LinkAce", + "form.integration.linkace_endpoint": "LinkAce API Endpoint", + "form.integration.linkace_api_key": "LinkAce API key", + "form.integration.linkace_tags": "LinkAce Tags", + "form.integration.linkace_is_private": "Mark link as private", + "form.integration.linkace_check_disabled": "Disable link check", "form.integration.linkding_activate": "儲存文章到 Linkding", "form.integration.linkding_endpoint": "Linkding API 端點", "form.integration.linkding_api_key": "Linkding API 金鑰", diff --git a/internal/model/integration.go b/internal/model/integration.go index 7ed3a41d..d0a6f443 100644 --- a/internal/model/integration.go +++ b/internal/model/integration.go @@ -48,6 +48,12 @@ type Integration struct { TelegramBotDisableWebPagePreview bool TelegramBotDisableNotification bool TelegramBotDisableButtons bool + LinkAceEnabled bool + LinkAceURL string + LinkAceAPIKey string + LinkAceTags string + LinkAcePrivate bool + LinkAceCheckDisabled bool LinkdingEnabled bool LinkdingURL string LinkdingAPIKey string diff --git a/internal/storage/integration.go b/internal/storage/integration.go index 4ca95d51..42d6d677 100644 --- a/internal/storage/integration.go +++ b/internal/storage/integration.go @@ -152,6 +152,12 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) { telegram_bot_disable_web_page_preview, telegram_bot_disable_notification, telegram_bot_disable_buttons, + linkace_enabled, + linkace_url, + linkace_api_key, + linkace_tags, + linkace_is_private, + linkace_check_disabled, linkding_enabled, linkding_url, linkding_api_key, @@ -230,6 +236,12 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) { &integration.TelegramBotDisableWebPagePreview, &integration.TelegramBotDisableNotification, &integration.TelegramBotDisableButtons, + &integration.LinkAceEnabled, + &integration.LinkAceURL, + &integration.LinkAceAPIKey, + &integration.LinkAceTags, + &integration.LinkAcePrivate, + &integration.LinkAceCheckDisabled, &integration.LinkdingEnabled, &integration.LinkdingURL, &integration.LinkdingAPIKey, @@ -312,41 +324,47 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error { espial_url=$35, espial_api_key=$36, espial_tags=$37, - linkding_enabled=$38, - linkding_url=$39, - linkding_api_key=$40, - linkding_tags=$41, - linkding_mark_as_unread=$42, - matrix_bot_enabled=$43, - matrix_bot_user=$44, - matrix_bot_password=$45, - matrix_bot_url=$46, - matrix_bot_chat_id=$47, - notion_enabled=$48, - notion_token=$49, - notion_page_id=$50, - readwise_enabled=$51, - readwise_api_key=$52, - apprise_enabled=$53, - apprise_url=$54, - apprise_services_url=$55, - shiori_enabled=$56, - shiori_url=$57, - shiori_username=$58, - shiori_password=$59, - shaarli_enabled=$60, - shaarli_url=$61, - shaarli_api_secret=$62, - webhook_enabled=$63, - webhook_url=$64, - webhook_secret=$65, - rssbridge_enabled=$66, - rssbridge_url=$67, - omnivore_enabled=$68, - omnivore_api_key=$69, - omnivore_url=$70 + linkace_enabled=$38, + linkace_url=$39, + linkace_api_key=$40, + linkace_tags=$41, + linkace_is_private=$42, + linkace_check_disabled=$43, + linkding_enabled=$44, + linkding_url=$45, + linkding_api_key=$46, + linkding_tags=$47, + linkding_mark_as_unread=$48, + matrix_bot_enabled=$49, + matrix_bot_user=$50, + matrix_bot_password=$51, + matrix_bot_url=$52, + matrix_bot_chat_id=$53, + notion_enabled=$54, + notion_token=$55, + notion_page_id=$56, + readwise_enabled=$57, + readwise_api_key=$58, + apprise_enabled=$59, + apprise_url=$60, + apprise_services_url=$61, + shiori_enabled=$62, + shiori_url=$63, + shiori_username=$64, + shiori_password=$65, + shaarli_enabled=$66, + shaarli_url=$67, + shaarli_api_secret=$68, + webhook_enabled=$69, + webhook_url=$70, + webhook_secret=$71, + rssbridge_enabled=$72, + rssbridge_url=$73, + omnivore_enabled=$74, + omnivore_api_key=$75, + omnivore_url=$76 WHERE - user_id=$71 + user_id=$77 ` _, err := s.db.Exec( query, @@ -387,6 +405,12 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error { integration.EspialURL, integration.EspialAPIKey, integration.EspialTags, + integration.LinkAceEnabled, + integration.LinkAceURL, + integration.LinkAceAPIKey, + integration.LinkAceTags, + integration.LinkAcePrivate, + integration.LinkAceCheckDisabled, integration.LinkdingEnabled, integration.LinkdingURL, integration.LinkdingAPIKey, @@ -449,6 +473,7 @@ func (s *Storage) HasSaveEntry(userID int64) (result bool) { espial_enabled='t' OR readwise_enabled='t' OR pocket_enabled='t' OR + linkace_enabled='t' OR linkding_enabled='t' OR apprise_enabled='t' OR shiori_enabled='t' OR diff --git a/internal/template/templates/views/integrations.html b/internal/template/templates/views/integrations.html index 9bb5b374..73a7738c 100644 --- a/internal/template/templates/views/integrations.html +++ b/internal/template/templates/views/integrations.html @@ -119,6 +119,36 @@ +
+ LinkAce +
+ + + + + + + + + + + + + + + +
+ +
+
+
+
Linkding
diff --git a/internal/ui/form/integration.go b/internal/ui/form/integration.go index c232494f..f456eb6d 100644 --- a/internal/ui/form/integration.go +++ b/internal/ui/form/integration.go @@ -54,6 +54,12 @@ type IntegrationForm struct { TelegramBotDisableWebPagePreview bool TelegramBotDisableNotification bool TelegramBotDisableButtons bool + LinkAceEnabled bool + LinkAceURL string + LinkAceAPIKey string + LinkAceTags string + LinkAcePrivate bool + LinkAceCheckDisabled bool LinkdingEnabled bool LinkdingURL string LinkdingAPIKey string @@ -126,6 +132,12 @@ func (i IntegrationForm) Merge(integration *model.Integration) { integration.TelegramBotDisableWebPagePreview = i.TelegramBotDisableWebPagePreview integration.TelegramBotDisableNotification = i.TelegramBotDisableNotification integration.TelegramBotDisableButtons = i.TelegramBotDisableButtons + integration.LinkAceEnabled = i.LinkAceEnabled + integration.LinkAceURL = i.LinkAceURL + integration.LinkAceAPIKey = i.LinkAceAPIKey + integration.LinkAceTags = i.LinkAceTags + integration.LinkAcePrivate = i.LinkAcePrivate + integration.LinkAceCheckDisabled = i.LinkAceCheckDisabled integration.LinkdingEnabled = i.LinkdingEnabled integration.LinkdingURL = i.LinkdingURL integration.LinkdingAPIKey = i.LinkdingAPIKey @@ -200,6 +212,12 @@ func NewIntegrationForm(r *http.Request) *IntegrationForm { TelegramBotDisableWebPagePreview: r.FormValue("telegram_bot_disable_web_page_preview") == "1", TelegramBotDisableNotification: r.FormValue("telegram_bot_disable_notification") == "1", TelegramBotDisableButtons: r.FormValue("telegram_bot_disable_buttons") == "1", + LinkAceEnabled: r.FormValue("linkace_enabled") == "1", + LinkAceURL: r.FormValue("linkace_url"), + LinkAceAPIKey: r.FormValue("linkace_api_key"), + LinkAceTags: r.FormValue("linkace_tags"), + LinkAcePrivate: r.FormValue("linkace_is_private") == "1", + LinkAceCheckDisabled: r.FormValue("linkace_check_disabled") == "1", LinkdingEnabled: r.FormValue("linkding_enabled") == "1", LinkdingURL: r.FormValue("linkding_url"), LinkdingAPIKey: r.FormValue("linkding_api_key"), diff --git a/internal/ui/integration_show.go b/internal/ui/integration_show.go index 813a11e1..9e6bf4d7 100644 --- a/internal/ui/integration_show.go +++ b/internal/ui/integration_show.go @@ -68,6 +68,12 @@ func (h *handler) showIntegrationPage(w http.ResponseWriter, r *http.Request) { TelegramBotDisableWebPagePreview: integration.TelegramBotDisableWebPagePreview, TelegramBotDisableNotification: integration.TelegramBotDisableNotification, TelegramBotDisableButtons: integration.TelegramBotDisableButtons, + LinkAceEnabled: integration.LinkAceEnabled, + LinkAceURL: integration.LinkAceURL, + LinkAceAPIKey: integration.LinkAceAPIKey, + LinkAceTags: integration.LinkAceTags, + LinkAcePrivate: integration.LinkAcePrivate, + LinkAceCheckDisabled: integration.LinkAceCheckDisabled, LinkdingEnabled: integration.LinkdingEnabled, LinkdingURL: integration.LinkdingURL, LinkdingAPIKey: integration.LinkdingAPIKey,