From f0d5392e9e7c365d27217e9a6b4f8a6a4b09f8e0 Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Sat, 19 Jul 2025 21:32:05 +0200 Subject: [PATCH] Self-review --- docs/releases.md | 3 ++- server/server.go | 25 +++++++++++++++---------- server/templates/alertmanager.yml | 2 -- server/templates/github.yml | 1 - server/templates/grafana.yml | 1 - 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/docs/releases.md b/docs/releases.md index fe91f580..6171dcff 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1456,7 +1456,8 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release **Features:** -* You can now use a subset of [Sprig](https://github.com/Masterminds/sprig) functions in message/title templates ([#1121](https://github.com/binwiederhier/ntfy/issues/1121), thanks to [@davidatkinsondoyle](https://github.com/davidatkinsondoyle) for reporting and to [@wunter8](https://github.com/wunter8) for implementing) +* Enhanced JSON webhook support via [pre-defined](publish.md#pre-defined-templates) and [custom templates](publish.md#custom-templates) ([#1390](https://github.com/binwiederhier/ntfy/pull/1390)) +* Support of advanced [template functions](publish.md#template-functions) based on the [Sprig](https://github.com/Masterminds/sprig) library ([#1121](https://github.com/binwiederhier/ntfy/issues/1121), thanks to [@davidatkinsondoyle](https://github.com/davidatkinsondoyle) for reporting, to [@wunter8](https://github.com/wunter8) for implementing, and to the Sprig team for their work) ### ntfy Android app v1.16.1 (UNRELEASED) diff --git a/server/server.go b/server/server.go index 0d69e068..f3d2ac51 100644 --- a/server/server.go +++ b/server/server.go @@ -57,7 +57,7 @@ type Server struct { userManager *user.Manager // Might be nil! messageCache *messageCache // Database that stores the messages webPush *webPushStore // Database that stores web push subscriptions - fileCache *fileCache // Name system based cache that stores attachments + fileCache *fileCache // File system based cache that stores attachments stripe stripeAPI // Stripe API, can be replaced with a mock priceCache *util.LookupCache[map[string]int64] // Stripe price ID -> price as cents (USD implied!) metricsHandler http.Handler // Handles /metrics if enable-metrics set, and listen-metrics-http not set @@ -1120,11 +1120,11 @@ func (s *Server) handleBodyAsTemplatedTextMessage(m *message, template templateM } peekedBody := strings.TrimSpace(string(body.PeekedBytes)) if templateName := template.Name(); templateName != "" { - if err := s.replaceTemplateFromFile(m, templateName, peekedBody); err != nil { + if err := s.renderTemplateFromFile(m, templateName, peekedBody); err != nil { return err } } else { - if err := s.replaceTemplateFromParams(m, peekedBody); err != nil { + if err := s.renderTemplateFromParams(m, peekedBody); err != nil { return err } } @@ -1134,7 +1134,9 @@ func (s *Server) handleBodyAsTemplatedTextMessage(m *message, template templateM return nil } -func (s *Server) replaceTemplateFromFile(m *message, templateName, peekedBody string) error { +// renderTemplateFromFile transforms the JSON message body according to a template from the filesystem. +// The template file must be in the templates directory, or in the configured template directory. +func (s *Server) renderTemplateFromFile(m *message, templateName, peekedBody string) error { if !templateNameRegex.MatchString(templateName) { return errHTTPBadRequestTemplateFileNotFound } @@ -1153,30 +1155,33 @@ func (s *Server) replaceTemplateFromFile(m *message, templateName, peekedBody st } var err error if tpl.Message != nil { - if m.Message, err = s.replaceTemplate(*tpl.Message, peekedBody); err != nil { + if m.Message, err = s.renderTemplate(*tpl.Message, peekedBody); err != nil { return err } } if tpl.Title != nil { - if m.Title, err = s.replaceTemplate(*tpl.Title, peekedBody); err != nil { + if m.Title, err = s.renderTemplate(*tpl.Title, peekedBody); err != nil { return err } } return nil } -func (s *Server) replaceTemplateFromParams(m *message, peekedBody string) error { +// renderTemplateFromParams transforms the JSON message body according to the inline template in the +// message and title parameters. +func (s *Server) renderTemplateFromParams(m *message, peekedBody string) error { var err error - if m.Message, err = s.replaceTemplate(m.Message, peekedBody); err != nil { + if m.Message, err = s.renderTemplate(m.Message, peekedBody); err != nil { return err } - if m.Title, err = s.replaceTemplate(m.Title, peekedBody); err != nil { + if m.Title, err = s.renderTemplate(m.Title, peekedBody); err != nil { return err } return nil } -func (s *Server) replaceTemplate(tpl string, source string) (string, error) { +// renderTemplate renders a template with the given JSON source data. +func (s *Server) renderTemplate(tpl string, source string) (string, error) { if templateDisallowedRegex.MatchString(tpl) { return "", errHTTPBadRequestTemplateDisallowedFunctionCalls } diff --git a/server/templates/alertmanager.yml b/server/templates/alertmanager.yml index 803bbfcb..a63a756c 100644 --- a/server/templates/alertmanager.yml +++ b/server/templates/alertmanager.yml @@ -25,5 +25,3 @@ message: | Source: {{ .generatorURL }} {{ end }} - - diff --git a/server/templates/github.yml b/server/templates/github.yml index 2c2922a2..aee95b42 100644 --- a/server/templates/github.yml +++ b/server/templates/github.yml @@ -55,4 +55,3 @@ message: | {{- else }} {{ fail "Unsupported GitHub event type or action." }} {{- end }} - diff --git a/server/templates/grafana.yml b/server/templates/grafana.yml index 658aa550..bdb64e45 100644 --- a/server/templates/grafana.yml +++ b/server/templates/grafana.yml @@ -8,4 +8,3 @@ title: | {{- end }} message: | {{ .message | trunc 2000 }} -