-
Notifications
You must be signed in to change notification settings - Fork 20
/
template.go
140 lines (114 loc) · 3.87 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package flows
import (
"fmt"
"regexp"
"strings"
"github.com/nyaruka/gocommon/i18n"
"github.com/nyaruka/goflow/assets"
)
// 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, locales []i18n.Locale) *TemplateTranslation {
// first iterate through and find all translations that are for this channel
candidatesByLocale := make(map[i18n.Locale]*TemplateTranslation)
candidatesByLang := make(map[i18n.Language]*TemplateTranslation)
for _, tr := range t.Template.Translations() {
if tr.Channel().UUID == channel {
tt := NewTemplateTranslation(tr)
lang, _ := tt.Locale().Split()
candidatesByLocale[tt.Locale()] = tt
candidatesByLang[lang] = tt
}
}
// first look for exact locale match
for _, locale := range locales {
tt := candidatesByLocale[locale]
if tt != nil {
return tt
}
}
// if that fails look for language match
for _, locale := range locales {
lang, _ := locale.Split()
tt := candidatesByLang[lang]
if tt != nil {
return tt
}
}
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, locales []i18n.Locale) *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, locales)
}