Browse Source

feat(ntfy): Add option to use internal links

Brieuc Dubois 1 year ago
parent
commit
a702bf0342

+ 5 - 0
internal/database/migrations.go

@@ -977,4 +977,9 @@ var migrations = []func(tx *sql.Tx, driver string) error{
 		_, err = tx.Exec(sql)
 		return err
 	},
+	func(tx *sql.Tx, _ string) (err error) {
+		sql := `ALTER TABLE integrations ADD COLUMN ntfy_internal_links bool default 'f';`
+		_, err = tx.Exec(sql)
+		return err
+	},
 }

+ 1 - 0
internal/integration/integration.go

@@ -506,6 +506,7 @@ func PushEntries(feed *model.Feed, entries model.Entries, userIntegrations *mode
 			userIntegrations.NtfyUsername,
 			userIntegrations.NtfyPassword,
 			userIntegrations.NtfyIconURL,
+			userIntegrations.NtfyInternalLinks,
 			feed.NtfyPriority,
 		)
 

+ 15 - 3
internal/integration/ntfy/ntfy.go

@@ -9,8 +9,10 @@ import (
 	"fmt"
 	"log/slog"
 	"net/http"
+	"net/url"
 	"time"
 
+	"miniflux.app/v2/internal/config"
 	"miniflux.app/v2/internal/model"
 	"miniflux.app/v2/internal/version"
 )
@@ -22,14 +24,15 @@ const (
 
 type Client struct {
 	ntfyURL, ntfyTopic, ntfyApiToken, ntfyUsername, ntfyPassword, ntfyIconURL string
+	ntfyInternalLinks                                                         bool
 	ntfyPriority                                                              int
 }
 
-func NewClient(ntfyURL, ntfyTopic, ntfyApiToken, ntfyUsername, ntfyPassword, ntfyIconURL string, ntfyPriority int) *Client {
+func NewClient(ntfyURL, ntfyTopic, ntfyApiToken, ntfyUsername, ntfyPassword, ntfyIconURL string, ntfyInternalLinks bool, ntfyPriority int) *Client {
 	if ntfyURL == "" {
 		ntfyURL = defaultNtfyURL
 	}
-	return &Client{ntfyURL, ntfyTopic, ntfyApiToken, ntfyUsername, ntfyPassword, ntfyIconURL, ntfyPriority}
+	return &Client{ntfyURL, ntfyTopic, ntfyApiToken, ntfyUsername, ntfyPassword, ntfyIconURL, ntfyInternalLinks, ntfyPriority}
 }
 
 func (c *Client) SendMessages(feed *model.Feed, entries model.Entries) error {
@@ -46,12 +49,21 @@ func (c *Client) SendMessages(feed *model.Feed, entries model.Entries) error {
 			ntfyMessage.Icon = c.ntfyIconURL
 		}
 
+		if c.ntfyInternalLinks {
+			url, err := url.Parse(config.Opts.BaseURL())
+			if err != nil {
+				slog.Error("Unable to parse base URL", slog.Any("error", err))
+			} else {
+				ntfyMessage.Click = fmt.Sprintf("%s%s%d", url, "/unread/entry/", entry.ID)
+			}
+		}
+
 		slog.Debug("Sending Ntfy message",
 			slog.String("url", c.ntfyURL),
 			slog.String("topic", c.ntfyTopic),
 			slog.Int("priority", ntfyMessage.Priority),
 			slog.String("message", ntfyMessage.Message),
-			slog.String("entry_url", entry.URL),
+			slog.String("entry_url", ntfyMessage.Click),
 		)
 
 		if err := c.makeRequest(ntfyMessage); err != nil {

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

@@ -513,6 +513,7 @@
     "form.integration.ntfy_username": "Ntfy-Benutzername (optional)",
     "form.integration.ntfy_password": "Ntfy-Passwort (optional)",
     "form.integration.ntfy_icon_url": "Ntfy-Symbol-URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Einträge zu Discord pushen",
     "form.integration.discord_webhook_link": "Discord-Webhook-URL",
     "form.api_key.label.description": "API-Schlüsselbezeichnung",

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

@@ -513,6 +513,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Push entries to Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "Ετικέτα κλειδιού API",

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

@@ -511,6 +511,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.cubox_activate": "Save entries to Cubox",
     "form.integration.cubox_api_link": "Cubox API link",
     "form.integration.discord_activate": "Push entries to Discord",

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

@@ -513,6 +513,7 @@
     "form.integration.ntfy_username": "Nombre de usuario de Ntfy (opcional)",
     "form.integration.ntfy_password": "Contraseña de Ntfy (opcional)",
     "form.integration.ntfy_icon_url": "URL del icono de Ntfy (opcional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Enviar artículos a Discord",
     "form.integration.discord_webhook_link": "URL de la Webhook de Discord",
     "form.api_key.label.description": "Etiqueta de clave API",

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

@@ -513,6 +513,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Push entries to Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "API Key Label",

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

@@ -513,6 +513,7 @@
     "form.integration.ntfy_username": "Nom d'utilisateur Ntfy (optionnel)",
     "form.integration.ntfy_password": "Mot de passe Ntfy (facultatif)",
     "form.integration.ntfy_icon_url": "URL de l'icône Ntfy (facultatif)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Envoyer les articles vers Discord",
     "form.integration.discord_webhook_link": "URL du Webhook Discord",
     "form.api_key.label.description": "Libellé de la clé d'API",

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

@@ -513,6 +513,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Push entries to Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "एपीआई कुंजी लेबल",

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

@@ -503,6 +503,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Push entries to Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "Label Kunci API",

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

@@ -514,6 +514,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Push entries to Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.submit.loading": "Caricamento in corso...",

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

@@ -503,6 +503,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Push entries to Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "API キーラベル",

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

@@ -513,6 +513,7 @@
     "form.integration.ntfy_username": "Ntfy gebruikersnaam (optioneel)",
     "form.integration.ntfy_password": "Ntfy wachtwoord (optioneel)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optioneel)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Artikelen opslaan in Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "API-sleutel omschrijving",

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

@@ -523,6 +523,7 @@
     "form.integration.ntfy_username": "Login do ntfy (opcjonalny)",
     "form.integration.ntfy_password": "Hasło do ntfy (opcjonalne)",
     "form.integration.ntfy_icon_url": "Adres URL ikony ntfy (opcjonalny)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Przesyłaj wpisy do Discord",
     "form.integration.discord_webhook_link": "Adres URL Webhook Discord",
     "form.api_key.label.description": "Etykieta klucza API",

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

@@ -513,6 +513,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Push entries to Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "Etiqueta da chave de API",

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

@@ -523,6 +523,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Отправить статьи в Discord",
     "form.integration.discord_webhook_link": "Ссылка на Discord Webhook",
     "form.api_key.label.description": "Описание API-ключа",

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

@@ -279,6 +279,7 @@
   "form.integration.ntfy_username": "Ntfy Username (optional)",
   "form.integration.ntfy_password": "Ntfy Password (optional)",
   "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+  "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
   "form.feed.label.ntfy_activate": "Push entries to ntfy",
   "form.feed.label.ntfy_priority": "Ntfy priority",
   "form.feed.label.ntfy_max_priority": "Ntfy max priority",

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

@@ -523,6 +523,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "Push entries to Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "Назва ключа API",

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

@@ -503,6 +503,7 @@
     "form.integration.ntfy_username": "Ntfy用户名(可选)",
     "form.integration.ntfy_password": "Ntfy密码(可选)",
     "form.integration.ntfy_icon_url": "Ntfy图标URL(可选)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "将新文章推送到 Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "API密钥标签",

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

@@ -503,6 +503,7 @@
     "form.integration.ntfy_username": "Ntfy Username (optional)",
     "form.integration.ntfy_password": "Ntfy Password (optional)",
     "form.integration.ntfy_icon_url": "Ntfy Icon URL (optional)",
+    "form.integration.ntfy_internal_links": "Use internal links on click (optional)",
     "form.integration.discord_activate": "推送文章到 Discord",
     "form.integration.discord_webhook_link": "Discord Webhook link",
     "form.api_key.label.description": "API金鑰標籤",

+ 1 - 0
internal/model/integration.go

@@ -104,6 +104,7 @@ type Integration struct {
 	NtfyUsername                     string
 	NtfyPassword                     string
 	NtfyIconURL                      string
+	NtfyInternalLinks                bool
 	CuboxEnabled                     bool
 	CuboxAPILink                     string
 	DiscordEnabled                   bool

+ 9 - 5
internal/storage/integration.go

@@ -208,6 +208,7 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
 			ntfy_username,
 			ntfy_password,
 			ntfy_icon_url,
+			ntfy_internal_links,
 			cubox_enabled,
 			cubox_api_link,
 			discord_enabled,
@@ -318,6 +319,7 @@ func (s *Storage) Integration(userID int64) (*model.Integration, error) {
 		&integration.NtfyUsername,
 		&integration.NtfyPassword,
 		&integration.NtfyIconURL,
+		&integration.NtfyInternalLinks,
 		&integration.CuboxEnabled,
 		&integration.CuboxAPILink,
 		&integration.DiscordEnabled,
@@ -437,12 +439,13 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
 			ntfy_username=$96,
 			ntfy_password=$97,
 			ntfy_icon_url=$98,
-			cubox_enabled=$99,
-			cubox_api_link=$100,
-			discord_enabled=$101,
-			discord_webhook_link=$102
+			ntfy_internal_links=$99,
+			cubox_enabled=$100,
+			cubox_api_link=$101,
+			discord_enabled=$102,
+			discord_webhook_link=$103
 		WHERE
-			user_id=$103
+			user_id=$104
 	`
 	_, err := s.db.Exec(
 		query,
@@ -544,6 +547,7 @@ func (s *Storage) UpdateIntegration(integration *model.Integration) error {
 		integration.NtfyUsername,
 		integration.NtfyPassword,
 		integration.NtfyIconURL,
+		integration.NtfyInternalLinks,
 		integration.CuboxEnabled,
 		integration.CuboxAPILink,
 		integration.DiscordEnabled,

+ 4 - 0
internal/template/templates/views/integrations.html

@@ -316,6 +316,10 @@
             <label for="form-ntfy-icon-url">{{ t "form.integration.ntfy_icon_url" }}</label>
             <input type="url" name="ntfy_icon_url" id="form-ntfy-icon-url" value="{{ .form.NtfyIconURL }}" spellcheck="false">
 
+            <label>
+                <input type="checkbox" name="ntfy_internal_links" value="1" {{ if .form.NtfyInternalLinks }}checked{{ end }}> {{ t "form.integration.ntfy_internal_links" }}
+            </label>
+
             <div class="buttons">
                 <button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
             </div>

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

@@ -110,6 +110,7 @@ type IntegrationForm struct {
 	NtfyUsername                     string
 	NtfyPassword                     string
 	NtfyIconURL                      string
+	NtfyInternalLinks                bool
 	CuboxEnabled                     bool
 	CuboxAPILink                     string
 	DiscordEnabled                   bool
@@ -213,6 +214,7 @@ func (i IntegrationForm) Merge(integration *model.Integration) {
 	integration.NtfyUsername = i.NtfyUsername
 	integration.NtfyPassword = i.NtfyPassword
 	integration.NtfyIconURL = i.NtfyIconURL
+	integration.NtfyInternalLinks = i.NtfyInternalLinks
 	integration.CuboxEnabled = i.CuboxEnabled
 	integration.CuboxAPILink = i.CuboxAPILink
 	integration.DiscordEnabled = i.DiscordEnabled
@@ -319,6 +321,7 @@ func NewIntegrationForm(r *http.Request) *IntegrationForm {
 		NtfyUsername:                     r.FormValue("ntfy_username"),
 		NtfyPassword:                     r.FormValue("ntfy_password"),
 		NtfyIconURL:                      r.FormValue("ntfy_icon_url"),
+		NtfyInternalLinks:                r.FormValue("ntfy_internal_links") == "1",
 		CuboxEnabled:                     r.FormValue("cubox_enabled") == "1",
 		CuboxAPILink:                     r.FormValue("cubox_api_link"),
 		DiscordEnabled:                   r.FormValue("discord_enabled") == "1",

+ 1 - 0
internal/ui/integration_show.go

@@ -124,6 +124,7 @@ func (h *handler) showIntegrationPage(w http.ResponseWriter, r *http.Request) {
 		NtfyUsername:                     integration.NtfyUsername,
 		NtfyPassword:                     integration.NtfyPassword,
 		NtfyIconURL:                      integration.NtfyIconURL,
+		NtfyInternalLinks:                integration.NtfyInternalLinks,
 		CuboxEnabled:                     integration.CuboxEnabled,
 		CuboxAPILink:                     integration.CuboxAPILink,
 		DiscordEnabled:                   integration.DiscordEnabled,