Use Go templates, update docs

This commit is contained in:
binwiederhier
2026-01-17 04:59:46 -05:00
parent 6bacf7dafc
commit b23f6632b1
6 changed files with 69 additions and 43 deletions

View File

@@ -3,6 +3,7 @@ package server
import (
"io/fs"
"net/netip"
"text/template"
"time"
"heckel.io/ntfy/v2/user"
@@ -128,7 +129,7 @@ type Config struct {
TwilioCallsBaseURL string
TwilioVerifyBaseURL string
TwilioVerifyService string
TwilioCallFormat string
TwilioCallFormat *template.Template
MetricsEnable bool
MetricsListenHTTP string
ProfileListenHTTP string
@@ -227,7 +228,7 @@ func NewConfig() *Config {
TwilioPhoneNumber: "",
TwilioVerifyBaseURL: "https://verify.twilio.com", // Override for tests
TwilioVerifyService: "",
TwilioCallFormat: "",
TwilioCallFormat: nil,
MessageSizeLimit: DefaultMessageSizeLimit,
MessageDelayMin: DefaultMessageDelayMin,
MessageDelayMax: DefaultMessageDelayMax,

View File

@@ -15,14 +15,13 @@ import (
"heckel.io/ntfy/v2/util"
)
const (
// defaultTwilioCallFormat is the default TwiML format used for Twilio calls.
// It can be overridden in the server configuration's twilio-call-format field.
//
// The format uses Go template syntax with the following fields:
// {{.Topic}}, {{.Title}}, {{.Message}}, {{.Priority}}, {{.Tags}}, {{.Sender}}
// String fields are automatically XML-escaped.
defaultTwilioCallFormat = `
// defaultTwilioCallFormatTemplate is the default TwiML template used for Twilio calls.
// It can be overridden in the server configuration's twilio-call-format field.
//
// The format uses Go template syntax with the following fields:
// {{.Topic}}, {{.Title}}, {{.Message}}, {{.Priority}}, {{.Tags}}, {{.Sender}}
// String fields are automatically XML-escaped.
var defaultTwilioCallFormatTemplate = template.Must(template.New("twiml").Parse(`
<Response>
<Pause length="1"/>
<Say loop="3">
@@ -37,8 +36,7 @@ const (
<break time="3s"/>
</Say>
<Say>Goodbye.</Say>
</Response>`
)
</Response>`))
// twilioCallData holds the data passed to the Twilio call format template
type twilioCallData struct {
@@ -83,15 +81,9 @@ func (s *Server) callPhone(v *visitor, r *http.Request, m *message, to string) {
if u != nil {
sender = u.Name
}
templateStr := defaultTwilioCallFormat
if s.config.TwilioCallFormat != "" {
templateStr = s.config.TwilioCallFormat
}
tmpl, err := template.New("twiml").Parse(templateStr)
if err != nil {
logvrm(v, r, m).Tag(tagTwilio).Err(err).Warn("Error parsing Twilio call format template")
minc(metricCallsMadeFailure)
return
tmpl := defaultTwilioCallFormatTemplate
if s.config.TwilioCallFormat != nil {
tmpl = s.config.TwilioCallFormat
}
tags := make([]string, len(m.Tags))
for i, tag := range m.Tags {

View File

@@ -1,14 +1,16 @@
package server
import (
"github.com/stretchr/testify/require"
"heckel.io/ntfy/v2/user"
"heckel.io/ntfy/v2/util"
"io"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"text/template"
"github.com/stretchr/testify/require"
"heckel.io/ntfy/v2/user"
"heckel.io/ntfy/v2/util"
)
func TestServer_Twilio_Call_Add_Verify_Call_Delete_Success(t *testing.T) {
@@ -222,22 +224,22 @@ func TestServer_Twilio_Call_Success_with_custom_twiml(t *testing.T) {
c.TwilioAccount = "AC1234567890"
c.TwilioAuthToken = "AAEAA1234567890"
c.TwilioPhoneNumber = "+1234567890"
c.TwilioCallFormat = `
c.TwilioCallFormat = template.Must(template.New("twiml").Parse(`
<Response>
<Pause length="1"/>
<Say language="de-DE" loop="3">
Du hast eine Nachricht von notify im Thema %s. Nachricht:
Du hast eine Nachricht von notify im Thema {{.Topic}}. Nachricht:
<break time="1s"/>
%s
{{.Message}}
<break time="1s"/>
Ende der Nachricht.
<break time="1s"/>
Diese Nachricht wurde von Benutzer %s gesendet. Sie wird drei Mal wiederholt.
Diese Nachricht wurde von Benutzer {{.Sender}} gesendet. Sie wird drei Mal wiederholt.
Um dich von Anrufen wie diesen abzumelden, entferne deine Telefonnummer in der notify web app.
<break time="3s"/>
</Say>
<Say language="de-DE">Auf Wiederhören.</Say>
</Response>`
</Response>`))
s := newTestServer(t, c)
// Add tier and user
@@ -246,7 +248,7 @@ func TestServer_Twilio_Call_Success_with_custom_twiml(t *testing.T) {
MessageLimit: 10,
CallLimit: 1,
}))
require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser))
require.Nil(t, s.userManager.AddUser("phil", "phil", user.RoleUser, false))
require.Nil(t, s.userManager.ChangeTier("phil", "pro"))
u, err := s.userManager.User("phil")
require.Nil(t, err)