-
Notifications
You must be signed in to change notification settings - Fork 20
/
template.go
126 lines (102 loc) · 3.54 KB
/
template.go
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package flows
import (
"fmt"
"regexp"
"strings"
"github.com/nyaruka/goflow/assets"
"github.com/nyaruka/goflow/utils"
)
// Template represents messaging templates used by channels types such as WhatsApp
type Template struct {
assets.Template
}
// NewTemplate returns a new template objects based on the passed in asset
func NewTemplate(t assets.Template) *Template {
return &Template{Template: t}
}
// Asset returns the underlying asset
func (t *Template) Asset() assets.Template { return t.Template }
// Reference returns the reference for this template
func (t *Template) Reference() *assets.TemplateReference {
if t == nil {
return nil
}
return assets.NewTemplateReference(t.UUID(), t.Name())
}
// FindTranslation finds the matching translation for the passed in channel and languages (in priority order)
func (t *Template) FindTranslation(channel assets.ChannelUUID, langs []utils.Language) *TemplateTranslation {
// first iterate through and find all translations that are for this channel
matches := make(map[utils.Language]assets.TemplateTranslation)
for _, tr := range t.Template.Translations() {
if tr.Channel().UUID == channel {
matches[tr.Language()] = tr
}
}
// now find the first that matches our language
for _, lang := range langs {
tr := matches[lang]
if tr != nil {
return NewTemplateTranslation(tr)
}
}
return nil
}
// TemplateTranslation represents a single translation for a template
type TemplateTranslation struct {
assets.TemplateTranslation
}
// NewTemplateTranslation returns a new TemplateTranslation for the passed in asset
func NewTemplateTranslation(t assets.TemplateTranslation) *TemplateTranslation {
return &TemplateTranslation{TemplateTranslation: t}
}
// Asset returns the underlying asset
func (t *TemplateTranslation) Asset() assets.TemplateTranslation { return t.TemplateTranslation }
var templateRegex = regexp.MustCompile(`({{\d+}})`)
// Substitute substitutes the passed in variables in our template
func (t *TemplateTranslation) Substitute(vars []string) string {
s := string(t.Content())
for i, v := range vars {
s = strings.ReplaceAll(s, fmt.Sprintf("{{%d}}", i+1), v)
}
// replace any remaining unmatched items
s = templateRegex.ReplaceAllString(s, "")
return s
}
// TemplateAssets is our type for all the templates in an environment
type TemplateAssets struct {
templates []*Template
byUUID map[assets.TemplateUUID]*Template
}
// NewTemplateAssets creates a new template list
func NewTemplateAssets(ts []assets.Template) *TemplateAssets {
templates := make([]*Template, len(ts))
byUUID := make(map[assets.TemplateUUID]*Template)
for i, t := range ts {
template := NewTemplate(t)
templates[i] = template
byUUID[t.UUID()] = template
}
return &TemplateAssets{
templates: templates,
byUUID: byUUID,
}
}
// Get returns the template with the passed in UUID if any
func (a *TemplateAssets) Get(uuid assets.TemplateUUID) *Template {
return a.byUUID[uuid]
}
// FindTranslation looks through our list of templates to find the template matching the passed in uuid
// If no template or translation is found then empty string is returned
func (a *TemplateAssets) FindTranslation(uuid assets.TemplateUUID, channel *assets.ChannelReference, langs []utils.Language) *TemplateTranslation {
// no channel, can't match to a template
if channel == nil {
return nil
}
template := a.byUUID[uuid]
// not found, no template
if template == nil {
return nil
}
// look through our translations looking for a match by both channel and translation
return template.FindTranslation(channel.UUID, langs)
}