Răsfoiți Sursa

feat(integration): add webhook URL per feed

Wesley van Tilburg 1 an în urmă
părinte
comite
459284ab96

+ 4 - 0
internal/database/migrations.go

@@ -990,4 +990,8 @@ var migrations = []func(tx *sql.Tx, driver string) error{
 		_, err = tx.Exec(sql)
 		return err
 	},
+	func(tx *sql.Tx, _ string) (err error) {
+		_, err = tx.Exec(`ALTER TABLE feeds ADD COLUMN webhook_url text default '';`)
+		return err
+	},
 }

+ 10 - 3
internal/integration/integration.go

@@ -474,20 +474,27 @@ func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *mode
 	}
 
 	if userIntegrations.WebhookEnabled {
+		var webhookURL string
+		if feed.WebhookURL != "" {
+			webhookURL = feed.WebhookURL
+		} else {
+			webhookURL = userIntegrations.WebhookURL
+		}
+
 		slog.Debug("Sending new entries to Webhook",
 			slog.Int64("user_id", userIntegrations.UserID),
 			slog.Int("nb_entries", len(entries)),
 			slog.Int64("feed_id", feed.ID),
-			slog.String("webhook_url", userIntegrations.WebhookURL),
+			slog.String("webhook_url", webhookURL),
 		)
 
-		webhookClient := webhook.NewClient(userIntegrations.WebhookURL, userIntegrations.WebhookSecret)
+		webhookClient := webhook.NewClient(webhookURL, userIntegrations.WebhookSecret)
 		if err := webhookClient.SendNewEntriesWebhookEvent(feed, entries); err != nil {
 			slog.Debug("Unable to send new entries to Webhook",
 				slog.Int64("user_id", userIntegrations.UserID),
 				slog.Int("nb_entries", len(entries)),
 				slog.Int64("feed_id", feed.ID),
-				slog.String("webhook_url", userIntegrations.WebhookURL),
+				slog.String("webhook_url", webhookURL),
 				slog.Any("error", err),
 			)
 		}

+ 3 - 2
internal/locale/translations/de_DE.json

@@ -339,6 +339,7 @@
     "form.feed.label.scraper_rules": "Extraktionsregeln",
     "form.feed.label.rewrite_rules": "Umschreiberegeln",
     "form.feed.label.apprise_service_urls": "Kommaseparierte Liste der Apprise-Service-URLs",
+    "form.feed.label.webhook_url": "Webhook-URL überschreiben",
     "form.feed.label.blocklist_rules": "Blockierregeln",
     "form.feed.label.keeplist_rules": "Erlaubnisregeln",
     "form.feed.label.urlrewrite_rules": "Umschreibregeln für URL",
@@ -501,8 +502,8 @@
     "form.integration.shaarli_activate": "Artikel in Shaarli speichern",
     "form.integration.shaarli_endpoint": "Shaarli-URL",
     "form.integration.shaarli_api_secret": "Shaarli-API-Geheimnis",
-    "form.integration.webhook_activate": "Webhook aktivieren",
-    "form.integration.webhook_url": "Webhook-URL",
+    "form.integration.webhook_activate": "Webhooks aktivieren",
+    "form.integration.webhook_url": "Standard Webhook-URL",
     "form.integration.webhook_secret": "Webhook-Geheimnis",
     "form.integration.rssbridge_activate": "Beim Hinzufügen von Abonnements RSS-Bridge prüfen.",
     "form.integration.rssbridge_url": "RSS-Bridge-Server-URL",

+ 4 - 3
internal/locale/translations/el_EL.json

@@ -325,6 +325,7 @@
     "error.feed_invalid_keeplist_rule": "Ο κανόνας keep list δεν είναι έγκυρος.",
     "form.feed.label.urlrewrite_rules": "επανεγγραφή κανόνων για τη διεύθυνση URL.",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "error.user_mandatory_fields": "Το όνομα χρήστη είναι υποχρεωτικό.",
     "error.api_key_already_exists": "Αυτό το κλειδί API υπάρχει ήδη.",
     "error.unable_to_create_api_key": "Δεν είναι δυνατή η δημιουργία αυτού του κλειδιού API.",
@@ -501,9 +502,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Push entries to ntfy",

+ 4 - 3
internal/locale/translations/en_US.json

@@ -339,6 +339,7 @@
     "form.feed.label.scraper_rules": "Scraper Rules",
     "form.feed.label.rewrite_rules": "Rewrite Rules",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.blocklist_rules": "Block Rules",
     "form.feed.label.keeplist_rules": "Keep Rules",
     "form.feed.label.urlrewrite_rules": "URL Rewrite Rules",
@@ -499,9 +500,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Push entries to ntfy",

+ 4 - 3
internal/locale/translations/es_ES.json

@@ -339,6 +339,7 @@
     "form.feed.label.scraper_rules": "Reglas de extracción de información",
     "form.feed.label.rewrite_rules": "Reglas de reescribir",
     "form.feed.label.apprise_service_urls": "Lista separada por comas de las URL del servicio Apprise",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.blocklist_rules": "Reglas de Filtrado (Bloquear)",
     "form.feed.label.keeplist_rules": "Reglas de Filtrado (Permitir)",
     "form.feed.label.urlrewrite_rules": "Reglas de Filtrado (Reescritura)",
@@ -501,9 +502,9 @@
     "form.integration.shaarli_activate": "Guardar artículos en Shaarli",
     "form.integration.shaarli_endpoint": "URL de Shaarli",
     "form.integration.shaarli_api_secret": "Secreto API de Shaarli",
-    "form.integration.webhook_activate": "Habilitar Webhook",
-    "form.integration.webhook_url": "URL de Webhook",
-    "form.integration.webhook_secret": "Secreto de Webhook",
+    "form.integration.webhook_activate": "Habilitar Webhooks",
+    "form.integration.webhook_url": "Defecto URL de Webhook",
+    "form.integration.webhook_secret": "Secreto de Webhooks",
     "form.integration.rssbridge_activate": "Vericar RSS-Bridge al agregar suscripciones",
     "form.integration.rssbridge_url": "URL del servidro RSS-Bridge",
     "form.integration.ntfy_activate": "Enviar artículos a ntfy",

+ 4 - 3
internal/locale/translations/fi_FI.json

@@ -325,6 +325,7 @@
     "error.feed_invalid_keeplist_rule": "The keep list rule is invalid.",
     "form.feed.label.urlrewrite_rules": "URL-osoitteen uudelleenkirjoitussäännöt",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "error.user_mandatory_fields": "Käyttäjätunnus on pakollinen.",
     "error.api_key_already_exists": "API-avain on jo olemassa.",
     "error.unable_to_create_api_key": "API-avainta ei voi luoda.",
@@ -501,9 +502,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Push entries to ntfy",

+ 1 - 0
internal/locale/translations/fr_FR.json

@@ -339,6 +339,7 @@
     "form.feed.label.scraper_rules": "Règles pour récupérer le contenu original",
     "form.feed.label.rewrite_rules": "Règles de réécriture",
     "form.feed.label.apprise_service_urls": "Liste séparée par des virgules des URL du service Apprise",
+    "form.feed.label.webhook_url": "Remplacer l'URL du webhook",
     "form.feed.label.blocklist_rules": "Règles de blocage",
     "form.feed.label.keeplist_rules": "Règles d'autorisation",
     "form.feed.label.urlrewrite_rules": "Règles de réécriture d'URL",

+ 4 - 3
internal/locale/translations/hi_IN.json

@@ -339,6 +339,7 @@
     "form.feed.label.scraper_rules": "खुरचनी नियम",
     "form.feed.label.rewrite_rules": "नियम फिर से लिखें",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.blocklist_rules": "ब्लॉक नियम",
     "form.feed.label.keeplist_rules": "नियम बनाए रखें",
     "form.feed.label.urlrewrite_rules": " यूआरएल पुनर्लेखन नियम",
@@ -501,9 +502,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Push entries to ntfy",

+ 4 - 3
internal/locale/translations/id_ID.json

@@ -329,6 +329,7 @@
     "form.feed.label.scraper_rules": "Aturan Pengambil Data",
     "form.feed.label.rewrite_rules": "Aturan Tulis Ulang",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.blocklist_rules": "Aturan Blokir",
     "form.feed.label.keeplist_rules": "Aturan Simpan",
     "form.feed.label.urlrewrite_rules": "Aturan Tulis Ulang URL",
@@ -491,9 +492,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Push entries to ntfy",

+ 4 - 3
internal/locale/translations/it_IT.json

@@ -339,6 +339,7 @@
     "form.feed.label.scraper_rules": "Regole di estrazione del contenuto",
     "form.feed.label.rewrite_rules": "Regole di impaginazione del contenuto",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.blocklist_rules": "Regole di blocco",
     "form.feed.label.keeplist_rules": "Regole di autorizzazione",
     "form.feed.label.urlrewrite_rules": "Regole di riscrittura URL",
@@ -501,9 +502,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks 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",

+ 4 - 3
internal/locale/translations/ja_JP.json

@@ -332,6 +332,7 @@
     "form.feed.label.keeplist_rules": "Keep ルール",
     "form.feed.label.urlrewrite_rules": "Rewrite URL ルール",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.ignore_http_cache": "HTTPキャッシュを無視",
     "form.feed.label.allow_self_signed_certificates": "自己署名証明書または無効な証明書を許可する",
     "form.feed.label.disable_http2": "Disable HTTP/2 to avoid fingerprinting",
@@ -491,9 +492,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Push entries to ntfy",

+ 4 - 3
internal/locale/translations/nl_NL.json

@@ -342,6 +342,7 @@
     "form.feed.label.keeplist_rules": "Bewaarregels",
     "form.feed.label.urlrewrite_rules": "Herschrijfregels voor URL's",
     "form.feed.label.apprise_service_urls": "Door komma's gescheiden lijst van Apprise service URL's",
+    "form.feed.label.webhook_url": "Overschrijf webhook URL",
     "form.feed.label.ignore_http_cache": "Negeer HTTP-cache",
     "form.feed.label.allow_self_signed_certificates": "Zelfondertekende of ongeldige certificaten toestaan",
     "form.feed.label.disable_http2": "HTTP/2 uitschakelen om fingerprinting te voorkomen",
@@ -501,9 +502,9 @@
     "form.integration.shaarli_activate": "Artikelen opslaan in Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Webhook activeren",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Webhooks activeren",
+    "form.integration.webhook_url": "Standard Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Controleer RSS-Bridge bij het toevoegen van abonnementen",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Stuur artikelen naar ntfy",

+ 4 - 3
internal/locale/translations/pl_PL.json

@@ -352,6 +352,7 @@
     "form.feed.label.keeplist_rules": "Reguły utrzymywania",
     "form.feed.label.urlrewrite_rules": "Reguły przepisywania adresów URL",
     "form.feed.label.apprise_service_urls": "Rozdzielana przecinkami lista adresów URL usług Appprise",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.ignore_http_cache": "Zignoruj pamięć podręczną HTTP",
     "form.feed.label.allow_self_signed_certificates": "Zezwalaj na samopodpisane lub nieprawidłowe certyfikaty",
     "form.feed.label.disable_http2": "Wyłącz protokół HTTP/2, aby uniknąć identyfikowania",
@@ -511,9 +512,9 @@
     "form.integration.shaarli_activate": "Zapisuj artykuły w Shaarli",
     "form.integration.shaarli_endpoint": "Adres URL Shaarli",
     "form.integration.shaarli_api_secret": "Tajny klucz API do Shaarli",
-    "form.integration.webhook_activate": "Włącz Webhook",
-    "form.integration.webhook_url": "Adres URL Webhook",
-    "form.integration.webhook_secret": "Tajny klucz do Webhook",
+    "form.integration.webhook_activate": "Włącz Webhooks",
+    "form.integration.webhook_url": "Default Adres URL Webhook",
+    "form.integration.webhook_secret": "Tajny klucz do Webhooks",
     "form.integration.rssbridge_activate": "Sprawdź RSS-Bridge podczas dodawania subskrypcji",
     "form.integration.rssbridge_url": "Adres URL serwera RSS-Bridge",
     "form.integration.ntfy_activate": "Przesyłaj wpisy do ntfy",

+ 4 - 3
internal/locale/translations/pt_BR.json

@@ -342,6 +342,7 @@
     "form.feed.label.keeplist_rules": "Regras de permissão",
     "form.feed.label.urlrewrite_rules": "Regras de reescrita de URL",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.ignore_http_cache": "Ignorar cache HTTP",
     "form.feed.label.allow_self_signed_certificates": "Permitir certificados autoassinados ou inválidos",
     "form.feed.label.disable_http2": "Disable HTTP/2 to avoid fingerprinting",
@@ -501,9 +502,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Push entries to ntfy",

+ 1 - 0
internal/locale/translations/ru_RU.json

@@ -352,6 +352,7 @@
     "form.feed.label.keeplist_rules": "Правила белого списка",
     "form.feed.label.urlrewrite_rules": "Правила перезаписи URL",
     "form.feed.label.apprise_service_urls": "Список ссылок сервисов Apprise, разделенный запятой",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.ignore_http_cache": "Игнорировать HTTP кеш",
     "form.feed.label.allow_self_signed_certificates": "Разрешить самоподписанные или недействительные сертификаты",
     "form.feed.label.disable_http2": "Disable HTTP/2 to avoid fingerprinting",

+ 3 - 2
internal/locale/translations/tr_TR.json

@@ -154,6 +154,7 @@
   "form.feed.fieldset.rules": "Kurallar",
   "form.feed.label.allow_self_signed_certificates": "Kendinden imzalı veya geçersiz sertifikalara izin ver",
   "form.feed.label.apprise_service_urls": "Apprise hizmet URL'lerinin virgülle ayrılmış listesi",
+  "form.feed.label.webhook_url": "Override webhook url",
   "form.feed.label.blocklist_rules": "Engelleme Kuralları",
   "form.feed.label.category": "Kategori",
   "form.feed.label.cookie": "Çerezleri Ayarla",
@@ -270,8 +271,8 @@
   "form.integration.wallabag_password": "Wallabag Parolası",
   "form.integration.wallabag_username": "Wallabag Kullanıcı Adı",
   "form.integration.webhook_activate": "Webhook'u etkinleştir",
-  "form.integration.webhook_secret": "Webhook Secret",
-  "form.integration.webhook_url": "Webhook URL",
+  "form.integration.webhook_secret": "Webhooks Secret",
+  "form.integration.webhook_url": "Default Webhook URL",
   "form.integration.ntfy_activate": "Push entries to ntfy",
   "form.integration.ntfy_topic": "Ntfy topic",
   "form.integration.ntfy_url": "Ntfy URL (optional, default is ntfy.sh)",

+ 4 - 3
internal/locale/translations/uk_UA.json

@@ -352,6 +352,7 @@
     "form.feed.label.keeplist_rules": "Правила дозволення",
     "form.feed.label.urlrewrite_rules": "Правила перезапису URL-адрес",
     "form.feed.label.apprise_service_urls": "Comma separated list of Apprise service URLs",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.ignore_http_cache": "Ігнорувати кеш HTTP",
     "form.feed.label.allow_self_signed_certificates": "Дозволити сертифікати з власним підписом або недійсні",
     "form.feed.label.disable_http2": "Disable HTTP/2 to avoid fingerprinting",
@@ -511,9 +512,9 @@
     "form.integration.shaarli_activate": "Save articles to Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API Secret",
-    "form.integration.webhook_activate": "Enable Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "Enable Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "Check RSS-Bridge when adding subscriptions",
     "form.integration.rssbridge_url": "RSS-Bridge server URL",
     "form.integration.ntfy_activate": "Push entries to ntfy",

+ 4 - 3
internal/locale/translations/zh_CN.json

@@ -332,6 +332,7 @@
     "form.feed.label.keeplist_rules": "保留规则",
     "form.feed.label.urlrewrite_rules": "URL 重写规则",
     "form.feed.label.apprise_service_urls": "使用逗号分隔的 Apprise 服务 URL 列表",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.ignore_http_cache": "忽略 HTTP 缓存",
     "form.feed.label.allow_self_signed_certificates": "允许自签名证书或无效证书",
     "form.feed.label.disable_http2": "关闭 HTTP/2 避免记录指纹",
@@ -491,9 +492,9 @@
     "form.integration.shaarli_activate": "保存文章到 Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli URL",
     "form.integration.shaarli_api_secret": "Shaarli API 密钥",
-    "form.integration.webhook_activate": "启用 Webhook",
-    "form.integration.webhook_url": "Webhook URL",
-    "form.integration.webhook_secret": "Webhook 密钥",
+    "form.integration.webhook_activate": "启用 Webhooks",
+    "form.integration.webhook_url": "Default Webhook URL",
+    "form.integration.webhook_secret": "Webhooks 密钥",
     "form.integration.rssbridge_activate": "添加订阅时检查 RSS-Bridge",
     "form.integration.rssbridge_url": "RSS-Bridge 服务器 URL",
     "form.integration.ntfy_activate": "推送条目到ntfy",

+ 4 - 3
internal/locale/translations/zh_TW.json

@@ -332,6 +332,7 @@
     "form.feed.label.keeplist_rules": "保留規則",
     "form.feed.label.urlrewrite_rules": "網址重寫規則",
     "form.feed.label.apprise_service_urls": "使用逗號分隔的 Apprise 服務網址列表",
+    "form.feed.label.webhook_url": "Override webhook url",
     "form.feed.label.ignore_http_cache": "忽略 HTTP 快取",
     "form.feed.label.allow_self_signed_certificates": "允許自簽或無效的憑證",
     "form.feed.label.disable_http2": "停用 HTTP/2 以避免指紋追蹤",
@@ -491,9 +492,9 @@
     "form.integration.shaarli_activate": "儲存文章到 Shaarli",
     "form.integration.shaarli_endpoint": "Shaarli 網址",
     "form.integration.shaarli_api_secret": "Shaarli API 金鑰",
-    "form.integration.webhook_activate": "啟用 Webhook",
-    "form.integration.webhook_url": "Webhook 網址",
-    "form.integration.webhook_secret": "Webhook Secret",
+    "form.integration.webhook_activate": "啟用 Webhooks",
+    "form.integration.webhook_url": "Default Webhook 網址",
+    "form.integration.webhook_secret": "Webhooks Secret",
     "form.integration.rssbridge_activate": "新增訂閱時檢查 RSS-Bridge",
     "form.integration.rssbridge_url": "RSS-Bridge 伺服器的網址",
     "form.integration.ntfy_activate": "推送文章到 Ntfy",

+ 1 - 0
internal/model/feed.go

@@ -53,6 +53,7 @@ type Feed struct {
 	HideGlobally                bool      `json:"hide_globally"`
 	DisableHTTP2                bool      `json:"disable_http2"`
 	AppriseServiceURLs          string    `json:"apprise_service_urls"`
+	WebhookURL                  string    `json:"webhook_url"`
 	NtfyEnabled                 bool      `json:"ntfy_enabled"`
 	NtfyPriority                int       `json:"ntfy_priority"`
 

+ 10 - 6
internal/storage/feed.go

@@ -246,11 +246,12 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
 			url_rewrite_rules,
 			no_media_player,
 			apprise_service_urls,
+			webhook_url,
 			disable_http2,
 			description
 		)
 		VALUES
-			($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26)
+			($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27)
 		RETURNING
 			id
 	`
@@ -280,6 +281,7 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
 		feed.UrlRewriteRules,
 		feed.NoMediaPlayer,
 		feed.AppriseServiceURLs,
+		feed.WebhookURL,
 		feed.DisableHTTP2,
 		feed.Description,
 	).Scan(&feed.ID)
@@ -354,12 +356,13 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
 			url_rewrite_rules=$25,
 			no_media_player=$26,
 			apprise_service_urls=$27,
-			disable_http2=$28,
-			description=$29,
-			ntfy_enabled=$30,
-			ntfy_priority=$31
+			webhook_url=$28,
+			disable_http2=$29,
+			description=$30,
+			ntfy_enabled=$31,
+			ntfy_priority=$32
 		WHERE
-			id=$32 AND user_id=$33
+			id=$33 AND user_id=$34
 	`
 	_, err = s.db.Exec(query,
 		feed.FeedURL,
@@ -389,6 +392,7 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
 		feed.UrlRewriteRules,
 		feed.NoMediaPlayer,
 		feed.AppriseServiceURLs,
+		feed.WebhookURL,
 		feed.DisableHTTP2,
 		feed.Description,
 		feed.NtfyEnabled,

+ 2 - 0
internal/storage/feed_query_builder.go

@@ -165,6 +165,7 @@ func (f *FeedQueryBuilder) GetFeeds() (model.Feeds, error) {
 			fi.icon_id,
 			u.timezone,
 			f.apprise_service_urls,
+			f.webhook_url,
 			f.disable_http2,
 			f.ntfy_enabled,
 			f.ntfy_priority
@@ -235,6 +236,7 @@ func (f *FeedQueryBuilder) GetFeeds() (model.Feeds, error) {
 			&iconID,
 			&tz,
 			&feed.AppriseServiceURLs,
+			&feed.WebhookURL,
 			&feed.DisableHTTP2,
 			&feed.NtfyEnabled,
 			&feed.NtfyPriority,

+ 10 - 0
internal/template/templates/views/edit_feed.html

@@ -209,6 +209,16 @@
                 </select>
             </details>
 
+            <details>
+                <summary>Webhook</summary>
+                <div class="form-label-row">
+                    <label for="form-webhook-url">
+                        {{ t "form.feed.label.webhook_url" }}
+                    </label>
+                </div>
+                <input type="url" name="webhook_url" id="form-webhook-url" value="{{ .form.WebhookURL }}" spellcheck="false">
+            </details>
+
             <div class="buttons">
                 <button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
             </div>

+ 1 - 0
internal/ui/feed_edit.go

@@ -63,6 +63,7 @@ func (h *handler) showEditFeedPage(w http.ResponseWriter, r *http.Request) {
 		HideGlobally:                feed.HideGlobally,
 		CategoryHidden:              feed.Category.HideGlobally,
 		AppriseServiceURLs:          feed.AppriseServiceURLs,
+		WebhookURL:                  feed.WebhookURL,
 		DisableHTTP2:                feed.DisableHTTP2,
 		NtfyEnabled:                 feed.NtfyEnabled,
 		NtfyPriority:                feed.NtfyPriority,

+ 3 - 0
internal/ui/form/feed.go

@@ -35,6 +35,7 @@ type FeedForm struct {
 	HideGlobally                bool
 	CategoryHidden              bool // Category has "hide_globally"
 	AppriseServiceURLs          string
+	WebhookURL                  string
 	DisableHTTP2                bool
 	NtfyEnabled                 bool
 	NtfyPriority                int
@@ -66,6 +67,7 @@ func (f FeedForm) Merge(feed *model.Feed) *model.Feed {
 	feed.NoMediaPlayer = f.NoMediaPlayer
 	feed.HideGlobally = f.HideGlobally
 	feed.AppriseServiceURLs = f.AppriseServiceURLs
+	feed.WebhookURL = f.WebhookURL
 	feed.DisableHTTP2 = f.DisableHTTP2
 	feed.NtfyEnabled = f.NtfyEnabled
 	feed.NtfyPriority = f.NtfyPriority
@@ -105,6 +107,7 @@ func NewFeedForm(r *http.Request) *FeedForm {
 		NoMediaPlayer:               r.FormValue("no_media_player") == "1",
 		HideGlobally:                r.FormValue("hide_globally") == "1",
 		AppriseServiceURLs:          r.FormValue("apprise_service_urls"),
+		WebhookURL:                  r.FormValue("webhook_url"),
 		DisableHTTP2:                r.FormValue("disable_http2") == "1",
 		NtfyEnabled:                 r.FormValue("ntfy_enabled") == "1",
 		NtfyPriority:                ntfyPriority,