diff --git a/internal/api/subscription.go b/internal/api/subscription.go
index 315db6f2..eb744419 100644
--- a/internal/api/subscription.go
+++ b/internal/api/subscription.go
@@ -7,6 +7,7 @@ import (
json_parser "encoding/json"
"net/http"
+ "miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/json"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/reader/subscription"
@@ -25,6 +26,12 @@ func (h *handler) discoverSubscriptions(w http.ResponseWriter, r *http.Request)
return
}
+ var rssbridgeURL string
+ intg, err := h.store.Integration(request.UserID(r))
+ if err == nil && intg != nil && intg.RSSBridgeEnabled {
+ rssbridgeURL = intg.RSSBridgeURL
+ }
+
subscriptions, finderErr := subscription.FindSubscriptions(
subscriptionDiscoveryRequest.URL,
subscriptionDiscoveryRequest.UserAgent,
@@ -33,6 +40,7 @@ func (h *handler) discoverSubscriptions(w http.ResponseWriter, r *http.Request)
subscriptionDiscoveryRequest.Password,
subscriptionDiscoveryRequest.FetchViaProxy,
subscriptionDiscoveryRequest.AllowSelfSignedCertificates,
+ rssbridgeURL,
)
if finderErr != nil {
json.ServerError(w, r, finderErr)
diff --git a/internal/database/migrations.go b/internal/database/migrations.go
index 1b4f44dd..ba356217 100644
--- a/internal/database/migrations.go
+++ b/internal/database/migrations.go
@@ -799,4 +799,12 @@ var migrations = []func(tx *sql.Tx) error{
_, err = tx.Exec(sql)
return err
},
+ func(tx *sql.Tx) (err error) {
+ sql := `
+ ALTER TABLE integrations ADD COLUMN rssbridge_enabled bool default 'f';
+ ALTER TABLE integrations ADD COLUMN rssbridge_url text default '';
+ `
+ _, err = tx.Exec(sql)
+ return
+ },
}
diff --git a/internal/googlereader/handler.go b/internal/googlereader/handler.go
index 2312a20e..681bed4c 100644
--- a/internal/googlereader/handler.go
+++ b/internal/googlereader/handler.go
@@ -673,7 +673,7 @@ func (h *handler) quickAddHandler(w http.ResponseWriter, r *http.Request) {
return
}
- subscriptions, s_err := mfs.FindSubscriptions(url, "", "", "", "", false, false)
+ subscriptions, s_err := mfs.FindSubscriptions(url, "", "", "", "", false, false, "")
if s_err != nil {
json.ServerError(w, r, s_err)
return
diff --git a/internal/integration/rssbridge/rssbridge.go b/internal/integration/rssbridge/rssbridge.go
new file mode 100644
index 00000000..117b9c84
--- /dev/null
+++ b/internal/integration/rssbridge/rssbridge.go
@@ -0,0 +1,45 @@
+package rssbridge // import "miniflux.app/integration/rssbridge"
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+)
+
+type Bridge struct {
+ URL string `json:"url"`
+ BridgeMeta BridgeMeta `json:"bridgeMeta"`
+}
+
+type BridgeMeta struct {
+ Name string `json:"name"`
+}
+
+func DetectBridges(rssbridgeURL, websiteURL string) (bridgeResponse []Bridge, err error) {
+ u, err := url.Parse(rssbridgeURL)
+ if err != nil {
+ return nil, err
+ }
+ values := u.Query()
+ values.Add("action", "findfeed")
+ values.Add("format", "atom")
+ values.Add("url", websiteURL)
+ u.RawQuery = values.Encode()
+
+ response, err := http.Get(u.String())
+ if err != nil {
+ return nil, err
+ }
+ defer response.Body.Close()
+ if response.StatusCode == http.StatusNotFound {
+ return
+ }
+ if response.StatusCode > 400 {
+ return nil, fmt.Errorf("RSS-Bridge: server failure (%d)", response.StatusCode)
+ }
+ if err := json.NewDecoder(response.Body).Decode(&bridgeResponse); err != nil {
+ return nil, fmt.Errorf("RSS-Bridge: unable to decode bridge response: %w", err)
+ }
+ return
+}
diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json
index 15851aa4..abcddc1b 100644
--- a/internal/locale/translations/de_DE.json
+++ b/internal/locale/translations/de_DE.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 cbacf37b..6a4d87e4 100644
--- a/internal/locale/translations/el_EL.json
+++ b/internal/locale/translations/el_EL.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 89f16821..e553b5b1 100644
--- a/internal/locale/translations/en_US.json
+++ b/internal/locale/translations/en_US.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 3e9198b8..5db848b4 100644
--- a/internal/locale/translations/es_ES.json
+++ b/internal/locale/translations/es_ES.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 2a950314..a83a43c9 100644
--- a/internal/locale/translations/fi_FI.json
+++ b/internal/locale/translations/fi_FI.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 0b3b27d2..a27de069 100644
--- a/internal/locale/translations/fr_FR.json
+++ b/internal/locale/translations/fr_FR.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Activer le webhook",
"form.integration.webhook_url": "URL du webhook",
"form.integration.webhook_secret": "Secret du webhook",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 50cf7753..278d78c6 100644
--- a/internal/locale/translations/hi_IN.json
+++ b/internal/locale/translations/hi_IN.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 8d3c7f9a..62ea5c76 100644
--- a/internal/locale/translations/id_ID.json
+++ b/internal/locale/translations/id_ID.json
@@ -401,6 +401,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 13ad90f2..dd4a33e8 100644
--- a/internal/locale/translations/it_IT.json
+++ b/internal/locale/translations/it_IT.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 3bae562d..3eadf836 100644
--- a/internal/locale/translations/ja_JP.json
+++ b/internal/locale/translations/ja_JP.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 ddc280d6..2b887f95 100644
--- a/internal/locale/translations/nl_NL.json
+++ b/internal/locale/translations/nl_NL.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 e27614d6..08ff54c0 100644
--- a/internal/locale/translations/pl_PL.json
+++ b/internal/locale/translations/pl_PL.json
@@ -406,6 +406,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 ce019f4e..bb9d40a0 100644
--- a/internal/locale/translations/pt_BR.json
+++ b/internal/locale/translations/pt_BR.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 fd542255..2ad084c3 100644
--- a/internal/locale/translations/ru_RU.json
+++ b/internal/locale/translations/ru_RU.json
@@ -406,6 +406,8 @@
"form.integration.webhook_activate": "Включить вебхуки",
"form.integration.webhook_url": "Адрес вебхуков",
"form.integration.webhook_secret": "Секретный ключ для вебхуков",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 4515c569..d896b8f7 100644
--- a/internal/locale/translations/tr_TR.json
+++ b/internal/locale/translations/tr_TR.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 c7a7b2b0..22d69d77 100644
--- a/internal/locale/translations/uk_UA.json
+++ b/internal/locale/translations/uk_UA.json
@@ -407,6 +407,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 63697de0..da90de6b 100644
--- a/internal/locale/translations/zh_CN.json
+++ b/internal/locale/translations/zh_CN.json
@@ -402,6 +402,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 d7da6d62..52b75745 100644
--- a/internal/locale/translations/zh_TW.json
+++ b/internal/locale/translations/zh_TW.json
@@ -404,6 +404,8 @@
"form.integration.webhook_activate": "Enable Webhook",
"form.integration.webhook_url": "Webhook URL",
"form.integration.webhook_secret": "Webhook Secret",
+ "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
+ "form.integration.rssbridge_url": "RSS-Bridge server URL",
"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 49b6be07..e31ae8fe 100644
--- a/internal/model/integration.go
+++ b/internal/model/integration.go
@@ -71,4 +71,6 @@ type Integration struct {
WebhookEnabled bool
WebhookURL string
WebhookSecret string
+ RSSBridgeEnabled bool
+ RSSBridgeURL string
}
diff --git a/internal/reader/subscription/finder.go b/internal/reader/subscription/finder.go
index 1683f393..f20d272a 100644
--- a/internal/reader/subscription/finder.go
+++ b/internal/reader/subscription/finder.go
@@ -12,6 +12,7 @@ import (
"miniflux.app/v2/internal/config"
"miniflux.app/v2/internal/errors"
"miniflux.app/v2/internal/http/client"
+ "miniflux.app/v2/internal/integration/rssbridge"
"miniflux.app/v2/internal/reader/browser"
"miniflux.app/v2/internal/reader/parser"
"miniflux.app/v2/internal/urllib"
@@ -26,7 +27,25 @@ var (
)
// FindSubscriptions downloads and try to find one or more subscriptions from an URL.
-func FindSubscriptions(websiteURL, userAgent, cookie, username, password string, fetchViaProxy, allowSelfSignedCertificates bool) (Subscriptions, *errors.LocalizedError) {
+func FindSubscriptions(websiteURL, userAgent, cookie, username, password string, fetchViaProxy, allowSelfSignedCertificates bool, rssbridgeURL string) (Subscriptions, *errors.LocalizedError) {
+ if rssbridgeURL != "" {
+ bridges, err := rssbridge.DetectBridges(rssbridgeURL, websiteURL)
+ if err != nil {
+ return nil, errors.NewLocalizedError("RSS-Bridge: %v", err)
+ }
+ if len(bridges) > 0 {
+ var subscriptions Subscriptions
+ for _, bridge := range bridges {
+ subscriptions = append(subscriptions, &Subscription{
+ Title: bridge.BridgeMeta.Name,
+ URL: bridge.URL,
+ Type: "atom",
+ })
+ }
+ return subscriptions, nil
+ }
+ }
+
websiteURL = findYoutubeChannelFeed(websiteURL)
websiteURL = parseYoutubeVideoPage(websiteURL)
diff --git a/internal/storage/integration.go b/internal/storage/integration.go
index 56bcea4b..54e4f7a4 100644
--- a/internal/storage/integration.go
+++ b/internal/storage/integration.go
@@ -174,7 +174,9 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
shaarli_api_secret,
webhook_enabled,
webhook_url,
- webhook_secret
+ webhook_secret,
+ rssbridge_enabled,
+ rssbridge_url
FROM
integrations
WHERE
@@ -248,6 +250,8 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
&integration.WebhookEnabled,
&integration.WebhookURL,
&integration.WebhookSecret,
+ &integration.RSSBridgeEnabled,
+ &integration.RSSBridgeURL,
)
switch {
case err == sql.ErrNoRows:
@@ -329,9 +333,11 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
shaarli_api_secret=$62,
webhook_enabled=$63,
webhook_url=$64,
- webhook_secret=$65
+ webhook_secret=$65,
+ rssbridge_enabled=$66,
+ rssbridge_url=$67
WHERE
- user_id=$66
+ user_id=$68
`
_, err := s.db.Exec(
query,
@@ -400,6 +406,8 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
integration.WebhookEnabled,
integration.WebhookURL,
integration.WebhookSecret,
+ integration.RSSBridgeEnabled,
+ integration.RSSBridgeURL,
integration.UserID,
)
diff --git a/internal/template/templates/views/integrations.html b/internal/template/templates/views/integrations.html
index 761cec17..faffb3b7 100644
--- a/internal/template/templates/views/integrations.html
+++ b/internal/template/templates/views/integrations.html
@@ -401,6 +401,22 @@
+
+ RSS-Bridge
+