diff --git a/internal/database/migrations.go b/internal/database/migrations.go
index 10975de0..59d08012 100644
--- a/internal/database/migrations.go
+++ b/internal/database/migrations.go
@@ -709,26 +709,36 @@ var migrations = []func(tx *sql.Tx) error{
},
func(tx *sql.Tx) (err error) {
sql := `
- ALTER TABLE integrations ADD COLUMN notion_enabled bool default 'f';
- ALTER TABLE integrations ADD COLUMN notion_token text default '';
- ALTER TABLE integrations ADD COLUMN notion_page_id text default '';
+ ALTER TABLE integrations ADD COLUMN notion_enabled bool default 'f';
+ ALTER TABLE integrations ADD COLUMN notion_token text default '';
+ ALTER TABLE integrations ADD COLUMN notion_page_id text default '';
`
_, err = tx.Exec(sql)
return err
},
func(tx *sql.Tx) (err error) {
sql := `
- ALTER TABLE integrations ADD COLUMN readwise_enabled bool default 'f';
- ALTER TABLE integrations ADD COLUMN readwise_api_key text default '';
+ ALTER TABLE integrations ADD COLUMN readwise_enabled bool default 'f';
+ ALTER TABLE integrations ADD COLUMN readwise_api_key text default '';
`
_, err = tx.Exec(sql)
return err
},
func(tx *sql.Tx) (err error) {
sql := `
- ALTER TABLE integrations ADD COLUMN apprise_enabled bool default 'f';
- ALTER TABLE integrations ADD COLUMN apprise_url text default '';
- ALTER TABLE integrations ADD COLUMN apprise_services_url text default '';
+ ALTER TABLE integrations ADD COLUMN apprise_enabled bool default 'f';
+ ALTER TABLE integrations ADD COLUMN apprise_url text default '';
+ ALTER TABLE integrations ADD COLUMN apprise_services_url text default '';
+ `
+ _, err = tx.Exec(sql)
+ return err
+ },
+ func(tx *sql.Tx) (err error) {
+ sql := `
+ ALTER TABLE integrations ADD COLUMN shiori_enabled bool default 'f';
+ ALTER TABLE integrations ADD COLUMN shiori_url text default '';
+ ALTER TABLE integrations ADD COLUMN shiori_username text default '';
+ ALTER TABLE integrations ADD COLUMN shiori_password text default '';
`
_, err = tx.Exec(sql)
return err
diff --git a/internal/integration/integration.go b/internal/integration/integration.go
index faa263d2..1b47638e 100644
--- a/internal/integration/integration.go
+++ b/internal/integration/integration.go
@@ -15,6 +15,7 @@ import (
"miniflux.app/v2/internal/integration/pinboard"
"miniflux.app/v2/internal/integration/pocket"
"miniflux.app/v2/internal/integration/readwise"
+ "miniflux.app/v2/internal/integration/shiori"
"miniflux.app/v2/internal/integration/telegrambot"
"miniflux.app/v2/internal/integration/wallabag"
"miniflux.app/v2/internal/logger"
@@ -137,6 +138,20 @@ func SendEntry(entry *model.Entry, integration *model.Integration) {
logger.Error("[Integration] UserID #%d: %v", integration.UserID, err)
}
}
+
+ if integration.ShioriEnabled {
+ logger.Debug("[Integration] Sending Entry #%d %q for User #%d to Shiori", entry.ID, entry.URL, integration.UserID)
+
+ client := shiori.NewClient(
+ integration.ShioriURL,
+ integration.ShioriUsername,
+ integration.ShioriPassword,
+ )
+
+ if err := client.AddBookmark(entry.URL, entry.Title); err != nil {
+ logger.Error("[Integration] Unable to send entry #%d to Shiori for user #%d: %v", entry.ID, integration.UserID, err)
+ }
+ }
}
// PushEntries pushes an entry array to third-party providers during feed refreshes.
diff --git a/internal/integration/shiori/shiori.go b/internal/integration/shiori/shiori.go
new file mode 100644
index 00000000..c55a530d
--- /dev/null
+++ b/internal/integration/shiori/shiori.go
@@ -0,0 +1,132 @@
+// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+package shiori // import "miniflux.app/v2/internal/integration/shiori"
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "time"
+
+ "miniflux.app/v2/internal/url"
+ "miniflux.app/v2/internal/version"
+)
+
+const defaultClientTimeout = 10 * time.Second
+
+type Client struct {
+ baseURL string
+ username string
+ password string
+}
+
+func NewClient(baseURL, username, password string) *Client {
+ return &Client{baseURL: baseURL, username: username, password: password}
+}
+
+func (c *Client) AddBookmark(entryURL, entryTitle string) error {
+ if c.baseURL == "" || c.username == "" || c.password == "" {
+ return fmt.Errorf("shiori: missing base URL, username or password")
+ }
+
+ sessionID, err := c.authenticate()
+ if err != nil {
+ return fmt.Errorf("shiori: unable to authenticate: %v", err)
+ }
+
+ apiEndpoint, err := url.JoinBaseURLAndPath(c.baseURL, "/api/bookmarks")
+ if err != nil {
+ return fmt.Errorf("shiori: invalid API endpoint: %v", err)
+ }
+
+ requestBody, err := json.Marshal(&addBookmarkRequest{
+ URL: entryURL,
+ Title: entryTitle,
+ CreateArchive: true,
+ })
+
+ if err != nil {
+ return fmt.Errorf("shiori: unable to encode request body: %v", err)
+ }
+
+ request, err := http.NewRequest("POST", apiEndpoint, bytes.NewReader(requestBody))
+ if err != nil {
+ return fmt.Errorf("shiori: 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("X-Session-Id", sessionID)
+
+ httpClient := &http.Client{Timeout: defaultClientTimeout}
+
+ response, err := httpClient.Do(request)
+ if err != nil {
+ return fmt.Errorf("shiori: unable to send request: %v", err)
+ }
+ defer response.Body.Close()
+
+ if response.StatusCode != http.StatusOK {
+ return fmt.Errorf("shiori: unable to create bookmark: url=%s status=%d", apiEndpoint, response.StatusCode)
+ }
+
+ return nil
+}
+
+func (c *Client) authenticate() (sessionID string, err error) {
+ apiEndpoint, err := url.JoinBaseURLAndPath(c.baseURL, "/api/login")
+ if err != nil {
+ return "", fmt.Errorf("shiori: invalid API endpoint: %v", err)
+ }
+
+ requestBody, err := json.Marshal(&authRequest{Username: c.username, Password: c.password})
+ if err != nil {
+ return "", fmt.Errorf("shiori: unable to encode request body: %v", err)
+ }
+
+ request, err := http.NewRequest("POST", apiEndpoint, bytes.NewReader(requestBody))
+ if err != nil {
+ return "", fmt.Errorf("shiori: 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)
+
+ httpClient := &http.Client{Timeout: defaultClientTimeout}
+
+ response, err := httpClient.Do(request)
+ if err != nil {
+ return "", fmt.Errorf("shiori: unable to send request: %v", err)
+ }
+ defer response.Body.Close()
+
+ if response.StatusCode != http.StatusOK {
+ return "", fmt.Errorf("shiori: unable to authenticate: url=%s status=%d", apiEndpoint, response.StatusCode)
+ }
+
+ var authResponse authResponse
+ if err := json.NewDecoder(response.Body).Decode(&authResponse); err != nil {
+ return "", fmt.Errorf("shiori: unable to decode response: %v", err)
+ }
+
+ return authResponse.SessionID, nil
+}
+
+type authRequest struct {
+ Username string `json:"username"`
+ Password string `json:"password"`
+}
+
+type authResponse struct {
+ SessionID string `json:"session"`
+}
+
+type addBookmarkRequest struct {
+ URL string `json:"url"`
+ Title string `json:"title"`
+ CreateArchive bool `json:"createArchive"`
+}
diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json
index d06830b8..4455d53e 100644
--- a/internal/locale/translations/de_DE.json
+++ b/internal/locale/translations/de_DE.json
@@ -381,6 +381,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.shiori_activate": "Artikel in Shiori",
+ "form.integration.shiori_endpoint": "Shiori API-Endpunkt",
+ "form.integration.shiori_username": "Shiori Benutzername",
+ "form.integration.shiori_password": "Shiori Passwort",
"form.api_key.label.description": "API-Schlüsselbezeichnung",
"form.submit.loading": "Lade...",
"form.submit.saving": "Speichern...",
diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json
index e7774136..e3928be5 100644
--- a/internal/locale/translations/el_EL.json
+++ b/internal/locale/translations/el_EL.json
@@ -381,6 +381,10 @@
"form.integration.matrix_bot_password": "Κωδικός πρόσβασης για τον χρήστη Matrix",
"form.integration.matrix_bot_url": "URL διακομιστή Matrix",
"form.integration.matrix_bot_chat_id": "Αναγνωριστικό της αίθουσας Matrix",
+ "form.integration.shiori_activate": "Αποθήκευση άρθρων στο Shiori",
+ "form.integration.shiori_endpoint": "Τελικό σημείο Shiori",
+ "form.integration.shiori_username": "Όνομα Χρήστη Shiori",
+ "form.integration.shiori_password": "Κωδικός Πρόσβασης Shiori",
"form.api_key.label.description": "Ετικέτα κλειδιού API",
"form.submit.loading": "Φόρτωση...",
"form.submit.saving": "Αποθήκευση...",
diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json
index 7b3e2ccf..66a4762d 100644
--- a/internal/locale/translations/en_US.json
+++ b/internal/locale/translations/en_US.json
@@ -381,6 +381,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.shiori_activate": "Save articles to Shiori",
+ "form.integration.shiori_endpoint": "Shiori API Endpoint",
+ "form.integration.shiori_username": "Shiori Username",
+ "form.integration.shiori_password": "Shiori Password",
"form.api_key.label.description": "API Key Label",
"form.submit.loading": "Loading…",
"form.submit.saving": "Saving…",
diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json
index d09be909..09a28fd4 100644
--- a/internal/locale/translations/es_ES.json
+++ b/internal/locale/translations/es_ES.json
@@ -381,6 +381,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.shiori_activate": "Guardar artículos a Shiori",
+ "form.integration.shiori_endpoint": "Extremo de API de Shiori",
+ "form.integration.shiori_username": "Nombre de usuario de Shiori",
+ "form.integration.shiori_password": "Contraseña de Shiori",
"form.api_key.label.description": "Etiqueta de clave API",
"form.submit.loading": "Cargando...",
"form.submit.saving": "Guardando...",
diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json
index 81fdb5e6..00c731ef 100644
--- a/internal/locale/translations/fi_FI.json
+++ b/internal/locale/translations/fi_FI.json
@@ -381,6 +381,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.shiori_activate": "Save articles to Shiori",
+ "form.integration.shiori_endpoint": "Shiori API Endpoint",
+ "form.integration.shiori_username": "Shiori Username",
+ "form.integration.shiori_password": "Shiori Password",
"form.api_key.label.description": "API Key Label",
"form.submit.loading": "Ladataan...",
"form.submit.saving": "Tallennetaan...",
diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json
index cc024e18..23044dd9 100644
--- a/internal/locale/translations/fr_FR.json
+++ b/internal/locale/translations/fr_FR.json
@@ -381,6 +381,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.shiori_activate": "Sauvegarder les articles vers Shiori",
+ "form.integration.shiori_endpoint": "URL de l'API de Shiori",
+ "form.integration.shiori_username": "Nom d'utilisateur de Shiori",
+ "form.integration.shiori_password": "Mot de passe de Shiori",
"form.api_key.label.description": "Libellé de la clé d'API",
"form.submit.loading": "Chargement...",
"form.submit.saving": "Sauvegarde en cours...",
diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json
index c56b275d..888e6a3a 100644
--- a/internal/locale/translations/hi_IN.json
+++ b/internal/locale/translations/hi_IN.json
@@ -381,6 +381,10 @@
"form.integration.matrix_bot_password": "मैट्रिक्स उपयोगकर्ता के लिए पासवर्ड",
"form.integration.matrix_bot_url": "मैट्रिक्स सर्वर URL",
"form.integration.matrix_bot_chat_id": "मैट्रिक्स रूम की आईडी",
+ "form.integration.shiori_activate": "Save articles to Shiori",
+ "form.integration.shiori_endpoint": "Shiori API Endpoint",
+ "form.integration.shiori_username": "Shiori Username",
+ "form.integration.shiori_password": "Shiori Password",
"form.api_key.label.description": "एपीआई कुंजी लेबल",
"form.submit.loading": "लोड हो रहा है...",
"form.submit.saving": "सहेजा जा रहा है...",
diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json
index f0c62fd5..4934ed57 100644
--- a/internal/locale/translations/id_ID.json
+++ b/internal/locale/translations/id_ID.json
@@ -378,6 +378,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.shiori_activate": "Save articles to Shiori",
+ "form.integration.shiori_endpoint": "Shiori API Endpoint",
+ "form.integration.shiori_username": "Shiori Username",
+ "form.integration.shiori_password": "Shiori Password",
"form.api_key.label.description": "Label Kunci API",
"form.submit.loading": "Memuat...",
"form.submit.saving": "Menyimpan...",
diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json
index e45754a7..f292f8c2 100644
--- a/internal/locale/translations/it_IT.json
+++ b/internal/locale/translations/it_IT.json
@@ -381,6 +381,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.shiori_activate": "Salva gli articoli su Shiori",
+ "form.integration.shiori_endpoint": "Endpoint dell'API di Shiori",
+ "form.integration.shiori_username": "Nome utente dell'account Shiori",
+ "form.integration.shiori_password": "Password dell'account Shiori",
"form.api_key.label.description": "Etichetta chiave API",
"form.submit.loading": "Caricamento in corso...",
"form.submit.saving": "Salvataggio in corso...",
diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json
index a7e88a40..18044a71 100644
--- a/internal/locale/translations/ja_JP.json
+++ b/internal/locale/translations/ja_JP.json
@@ -381,6 +381,10 @@
"form.integration.matrix_bot_password": "Matrixユーザ用パスワード",
"form.integration.matrix_bot_url": "MatrixサーバーのURL",
"form.integration.matrix_bot_chat_id": "MatrixルームのID",
+ "form.integration.shiori_activate": "Shiori に記事を保存する",
+ "form.integration.shiori_endpoint": "Shiori の API Endpoint",
+ "form.integration.shiori_username": "Shiori の ユーザー名",
+ "form.integration.shiori_password": "Shiori の パスワード",
"form.api_key.label.description": "API キーラベル",
"form.submit.loading": "読み込み中…",
"form.submit.saving": "保存中…",
diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json
index d401f98d..033c58ed 100644
--- a/internal/locale/translations/nl_NL.json
+++ b/internal/locale/translations/nl_NL.json
@@ -381,6 +381,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.shiori_activate": "Opslaan naar Shiori",
+ "form.integration.shiori_endpoint": "Shiori URL",
+ "form.integration.shiori_username": "Shiori gebruikersnaam",
+ "form.integration.shiori_password": "Shiori wachtwoord",
"form.api_key.label.description": "API-sleutellabel",
"form.submit.loading": "Laden...",
"form.submit.saving": "Opslaag...",
diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json
index 21f0c339..c8e22131 100644
--- a/internal/locale/translations/pl_PL.json
+++ b/internal/locale/translations/pl_PL.json
@@ -383,6 +383,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.shiori_activate": "Zapisz artykuły do Shiori",
+ "form.integration.shiori_endpoint": "Shiori URL",
+ "form.integration.shiori_username": "Login do Shiori",
+ "form.integration.shiori_password": "Hasło do Shiori",
"form.api_key.label.description": "Etykieta klucza API",
"form.submit.loading": "Ładowanie...",
"form.submit.saving": "Zapisywanie...",
diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json
index e97089df..0b796060 100644
--- a/internal/locale/translations/pt_BR.json
+++ b/internal/locale/translations/pt_BR.json
@@ -381,6 +381,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.shiori_activate": "Salvar itens no Shiori",
+ "form.integration.shiori_endpoint": "Endpoint da API do Shiori",
+ "form.integration.shiori_username": "Nome de usuário do Shiori",
+ "form.integration.shiori_password": "Senha do Shiori",
"form.api_key.label.description": "Etiqueta da chave de API",
"form.submit.loading": "Carregando...",
"form.submit.saving": "Salvando...",
diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json
index a679cf81..8ad3af8e 100644
--- a/internal/locale/translations/ru_RU.json
+++ b/internal/locale/translations/ru_RU.json
@@ -383,6 +383,10 @@
"form.integration.matrix_bot_password": "Пароль пользователя Matrix",
"form.integration.matrix_bot_url": "Ссылка на сервер Matrix",
"form.integration.matrix_bot_chat_id": "ID комнаты Matrix",
+ "form.integration.shiori_activate": "Сохранять статьи в Shiori",
+ "form.integration.shiori_endpoint": "Конечная точка Shiori API",
+ "form.integration.shiori_username": "Имя пользователя Shiori",
+ "form.integration.shiori_password": "Пароль Shiori",
"form.api_key.label.description": "Описание API-ключа",
"form.submit.loading": "Загрузка…",
"form.submit.saving": "Сохранение…",
diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json
index 3fd475a4..d4774b91 100644
--- a/internal/locale/translations/tr_TR.json
+++ b/internal/locale/translations/tr_TR.json
@@ -381,6 +381,10 @@
"form.integration.matrix_bot_password": "Matrix kullanıcısı için şifre",
"form.integration.matrix_bot_url": "Matris sunucusu URL'si",
"form.integration.matrix_bot_chat_id": "Matris odasının kimliği",
+ "form.integration.shiori_activate": "Makaleleri Shiori'e kaydet",
+ "form.integration.shiori_endpoint": "Shiori API Uç Noktası",
+ "form.integration.shiori_username": "Shiori Kullanıcı Adı",
+ "form.integration.shiori_password": "Shiori Parolası",
"form.api_key.label.description": "API Anahtar Etiketi",
"form.submit.loading": "Yükleniyor...",
"form.submit.saving": "Kaydediliyor...",
diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json
index 5ba751d4..b0d3c569 100644
--- a/internal/locale/translations/uk_UA.json
+++ b/internal/locale/translations/uk_UA.json
@@ -380,6 +380,10 @@
"form.integration.matrix_bot_password": "Пароль для користувача Matrix",
"form.integration.matrix_bot_url": "URL-адреса сервера Матриці",
"form.integration.matrix_bot_chat_id": "Ідентифікатор кімнати Матриці",
+ "form.integration.shiori_activate": "Save articles to Shiori",
+ "form.integration.shiori_endpoint": "Shiori API Endpoint",
+ "form.integration.shiori_username": "Shiori Username",
+ "form.integration.shiori_password": "Shiori Password",
"form.api_key.label.description": "Назва ключа API",
"form.submit.loading": "Завантаження...",
"form.submit.saving": "Зберігаю...",
diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json
index a107a523..6034e23b 100644
--- a/internal/locale/translations/zh_CN.json
+++ b/internal/locale/translations/zh_CN.json
@@ -379,6 +379,10 @@
"form.integration.matrix_bot_password": "矩阵用户密码",
"form.integration.matrix_bot_url": "矩阵服务器 URL",
"form.integration.matrix_bot_chat_id": "Matrix房间ID",
+ "form.integration.shiori_activate": "保存文章到 Shiori",
+ "form.integration.shiori_endpoint": "Shiori API Endpoint",
+ "form.integration.shiori_username": "Shiori 用户名",
+ "form.integration.shiori_password": "Shiori 密码",
"form.api_key.label.description": "API密钥标签",
"form.submit.loading": "载入中…",
"form.submit.saving": "保存中…",
diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json
index e9c5f285..b32f8758 100644
--- a/internal/locale/translations/zh_TW.json
+++ b/internal/locale/translations/zh_TW.json
@@ -381,6 +381,10 @@
"form.integration.matrix_bot_password": "矩陣用戶密碼",
"form.integration.matrix_bot_url": "矩陣服務器 URL",
"form.integration.matrix_bot_chat_id": "Matrix房間ID",
+ "form.integration.shiori_activate": "Save articles to Shiori",
+ "form.integration.shiori_endpoint": "Shiori API Endpoint",
+ "form.integration.shiori_username": "Shiori Username",
+ "form.integration.shiori_password": "Shiori Password",
"form.api_key.label.description": "API金鑰標籤",
"form.submit.loading": "載入中…",
"form.submit.saving": "儲存中…",
diff --git a/internal/model/integration.go b/internal/model/integration.go
index edfad601..28a0da9a 100644
--- a/internal/model/integration.go
+++ b/internal/model/integration.go
@@ -57,4 +57,8 @@ type Integration struct {
AppriseEnabled bool
AppriseURL string
AppriseServicesURL string
+ ShioriEnabled bool
+ ShioriURL string
+ ShioriUsername string
+ ShioriPassword string
}
diff --git a/internal/storage/integration.go b/internal/storage/integration.go
index b0a10128..61ecc679 100644
--- a/internal/storage/integration.go
+++ b/internal/storage/integration.go
@@ -160,7 +160,11 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
matrix_bot_chat_id,
apprise_enabled,
apprise_url,
- apprise_services_url
+ apprise_services_url,
+ shiori_enabled,
+ shiori_url,
+ shiori_username,
+ shiori_password
FROM
integrations
WHERE
@@ -220,6 +224,10 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
&integration.AppriseEnabled,
&integration.AppriseURL,
&integration.AppriseServicesURL,
+ &integration.ShioriEnabled,
+ &integration.ShioriURL,
+ &integration.ShioriUsername,
+ &integration.ShioriPassword,
)
switch {
case err == sql.ErrNoRows:
@@ -287,9 +295,13 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
readwise_api_key=$48,
apprise_enabled=$49,
apprise_url=$50,
- apprise_services_url=$51
+ apprise_services_url=$51,
+ shiori_enabled=$52,
+ shiori_url=$53,
+ shiori_username=$54,
+ shiori_password=$55
WHERE
- user_id=$52
+ user_id=$56
`
_, err := s.db.Exec(
query,
@@ -344,11 +356,15 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
integration.AppriseEnabled,
integration.AppriseURL,
integration.AppriseServicesURL,
+ integration.ShioriEnabled,
+ integration.ShioriURL,
+ integration.ShioriUsername,
+ integration.ShioriPassword,
integration.UserID,
)
if err != nil {
- return fmt.Errorf(`store: unable to update integration row: %v`, err)
+ return fmt.Errorf(`store: unable to update integration record: %v`, err)
}
return nil
@@ -364,7 +380,19 @@ func (s *Storage) HasSaveEntry(userID int64) (result bool) {
WHERE
user_id=$1
AND
- (pinboard_enabled='t' OR instapaper_enabled='t' OR wallabag_enabled='t' OR notion_enabled='t' OR nunux_keeper_enabled='t' OR espial_enabled='t' OR readwise_enabled='t' OR pocket_enabled='t' OR linkding_enabled='t' OR apprise_enabled='t')
+ (
+ pinboard_enabled='t' OR
+ instapaper_enabled='t' OR
+ wallabag_enabled='t' OR
+ notion_enabled='t' OR
+ nunux_keeper_enabled='t' OR
+ espial_enabled='t' OR
+ readwise_enabled='t' OR
+ pocket_enabled='t' OR
+ linkding_enabled='t' OR
+ apprise_enabled='t' OR
+ shiori_enabled='t'
+ )
`
if err := s.db.QueryRow(query, userID).Scan(&result); err != nil {
result = false
diff --git a/internal/template/templates/views/integrations.html b/internal/template/templates/views/integrations.html
index 01f6e31e..f26d399f 100644
--- a/internal/template/templates/views/integrations.html
+++ b/internal/template/templates/views/integrations.html
@@ -324,6 +324,28 @@
+
+ Shiori
+