From 4abcb2852ce0c4610f639783cdce61b08a7fb600 Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Fri, 6 Dec 2019 22:40:30 +0530 Subject: [PATCH] Refactor template functions. - Better template function shorthand substitution. - Make `UnsubscribeURL` a function consitent with TrackLink. This is a breaking change that makes the old `.UnsubscrbeURL` obsolete. --- email-templates/default.tpl | 2 +- main.go | 2 +- manager/manager.go | 37 ++++++++++++++++++--------------- models/models.go | 41 +++++++++++++++++++++++++------------ 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/email-templates/default.tpl b/email-templates/default.tpl index f76dc97..e553d0c 100644 --- a/email-templates/default.tpl +++ b/email-templates/default.tpl @@ -63,7 +63,7 @@
 {{ TrackView }}
diff --git a/main.go b/main.go index b4d9ca8..1258b37 100644 --- a/main.go +++ b/main.go @@ -313,7 +313,7 @@ func main() { FromEmail: app.Constants.FromEmail, // url.com/unsubscribe/{campaign_uuid}/{subscriber_uuid} - UnsubscribeURL: fmt.Sprintf("%s/subscription/%%s/%%s", app.Constants.RootURL), + UnsubURL: fmt.Sprintf("%s/subscription/%%s/%%s", app.Constants.RootURL), // url.com/link/{campaign_uuid}/{subscriber_uuid}/{link_uuid} LinkTrackURL: fmt.Sprintf("%s/link/%%s/%%s/%%s", app.Constants.RootURL), diff --git a/manager/manager.go b/manager/manager.go index 4e21ca7..1a642b7 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -59,12 +59,13 @@ type Manager struct { // Message represents an active subscriber that's being processed. type Message struct { - Campaign *models.Campaign - Subscriber *models.Subscriber - UnsubscribeURL string - Body []byte - from string - to string + Campaign *models.Campaign + Subscriber *models.Subscriber + Body []byte + + unsubURL string + from string + to string } // Config has parameters for configuring the manager. @@ -74,7 +75,7 @@ type Config struct { RequeueOnError bool FromEmail string LinkTrackURL string - UnsubscribeURL string + UnsubURL string ViewTrackURL string } @@ -104,11 +105,12 @@ func New(cfg Config, src DataSource, notifCB models.AdminNotifCallback, l *log.L // to message templates while they're compiled. func (m *Manager) NewMessage(c *models.Campaign, s *models.Subscriber) *Message { return &Message{ - from: c.FromEmail, - to: s.Email, - Campaign: c, - Subscriber: s, - UnsubscribeURL: fmt.Sprintf(m.cfg.UnsubscribeURL, c.UUID, s.UUID), + Campaign: c, + Subscriber: s, + + from: c.FromEmail, + to: s.Email, + unsubURL: fmt.Sprintf(m.cfg.UnsubURL, c.UUID, s.UUID), } } @@ -413,12 +415,15 @@ func (m *Manager) sendNotif(c *models.Campaign, status, reason string) error { // compiled campaign templates. func (m *Manager) TemplateFuncs(c *models.Campaign) template.FuncMap { return template.FuncMap{ - "TrackLink": func(url, campUUID, subUUID string) string { - return m.trackLink(url, campUUID, subUUID) + "TrackLink": func(url string, msg *Message) string { + return m.trackLink(url, msg.Campaign.UUID, msg.Subscriber.UUID) }, - "TrackView": func(campUUID, subUUID string) template.HTML { + "TrackView": func(msg *Message) template.HTML { return template.HTML(fmt.Sprintf(``, - fmt.Sprintf(m.cfg.ViewTrackURL, campUUID, subUUID))) + fmt.Sprintf(m.cfg.ViewTrackURL, msg.Campaign.UUID, msg.Subscriber.UUID))) + }, + "UnsubscribeURL": func(msg *Message) string { + return msg.unsubURL }, "Date": func(layout string) string { if layout == "" { diff --git a/models/models.go b/models/models.go index 60c77e2..17cab99 100644 --- a/models/models.go +++ b/models/models.go @@ -48,16 +48,27 @@ const ( ContentTpl = "content" ) +// regTplFunc represents contains a regular expression for wrapping and +// substituting a Go template function from the user's shorthand to a full +// function call. +type regTplFunc struct { + regExp *regexp.Regexp + replace string +} + // Regular expression for matching {{ Track "http://link.com" }} in the template // and substituting it with {{ Track "http://link.com" .Campaign.UUID .Subscriber.UUID }} // before compilation. This string gimmick is to make linking easier for users. -var ( - regexpLinkTag = regexp.MustCompile("{{(\\s+)?TrackLink\\s+?(\"|`)(.+?)(\"|`)(\\s+)?}}") - regexpLinkTagReplace = `{{ TrackLink "$3" .Campaign.UUID .Subscriber.UUID }}` - - regexpViewTag = regexp.MustCompile(`{{(\s+)?TrackView(\s+)?}}`) - regexpViewTagReplace = `{{ TrackView .Campaign.UUID .Subscriber.UUID }}` -) +var regTplFuncs = []regTplFunc{ + regTplFunc{ + regExp: regexp.MustCompile("{{(\\s+)?TrackLink\\s+?(\"|`)(.+?)(\"|`)(\\s+)?}}"), + replace: `{{ TrackLink "$3" . }}`, + }, + regTplFunc{ + regExp: regexp.MustCompile(`{{(\s+)?(TrackView|UnsubscribeURL|OptinURL)(\s+)?}}`), + replace: `{{ $2 . }}`, + }, +} // AdminNotifCallback is a callback function that's called // when a campaign's status changes. @@ -264,17 +275,21 @@ func (camps Campaigns) LoadStats(stmt *sqlx.Stmt) error { // template and sets the resultant template to Campaign.Tpl. func (c *Campaign) CompileTemplate(f template.FuncMap) error { // Compile the base template. - t := regexpLinkTag.ReplaceAllString(c.TemplateBody, regexpLinkTagReplace) - t = regexpViewTag.ReplaceAllString(t, regexpViewTagReplace) - baseTPL, err := template.New(BaseTpl).Funcs(f).Parse(t) + body := c.TemplateBody + for _, r := range regTplFuncs { + body = r.regExp.ReplaceAllString(body, r.replace) + } + baseTPL, err := template.New(BaseTpl).Funcs(f).Parse(body) if err != nil { return fmt.Errorf("error compiling base template: %v", err) } // Compile the campaign message. - t = regexpLinkTag.ReplaceAllString(c.Body, regexpLinkTagReplace) - t = regexpViewTag.ReplaceAllString(t, regexpViewTagReplace) - msgTpl, err := template.New(ContentTpl).Funcs(f).Parse(t) + body = c.Body + for _, r := range regTplFuncs { + body = r.regExp.ReplaceAllString(body, r.replace) + } + msgTpl, err := template.New(ContentTpl).Funcs(f).Parse(body) if err != nil { return fmt.Errorf("error compiling message: %v", err) }