diff --git a/handlers/dialog360/handler.go b/handlers/dialog360/handler.go index 8f946f525..0db5ec2e1 100644 --- a/handlers/dialog360/handler.go +++ b/handlers/dialog360/handler.go @@ -323,7 +323,7 @@ func (h *handler) Send(ctx context.Context, msg courier.MsgOut, res *courier.Sen } if templating != nil { payload.Type = "template" - payload.Template = whatsapp.GetTemplatePayload(*templating) + payload.Template = whatsapp.GetTemplatePayload(templating) } else { if i < (len(msgParts) + len(msg.Attachments()) - 1) { // this is still a msg part diff --git a/handlers/meta/handlers.go b/handlers/meta/handlers.go index 27ce1cd4a..7609f8dd9 100644 --- a/handlers/meta/handlers.go +++ b/handlers/meta/handlers.go @@ -811,7 +811,7 @@ func (h *handler) sendWhatsAppMsg(ctx context.Context, msg courier.MsgOut, res * } if templating != nil { payload.Type = "template" - payload.Template = whatsapp.GetTemplatePayload(*templating) + payload.Template = whatsapp.GetTemplatePayload(templating) } else { if i < (len(msgParts) + len(msg.Attachments()) - 1) { diff --git a/handlers/meta/whatsapp/templates.go b/handlers/meta/whatsapp/templates.go index afe776daf..a01ec7969 100644 --- a/handlers/meta/whatsapp/templates.go +++ b/handlers/meta/whatsapp/templates.go @@ -47,31 +47,23 @@ func GetTemplating(msg courier.MsgOut) (*MsgTemplating, error) { return metadata.Templating, nil } -func GetTemplatePayload(templating MsgTemplating) *Template { - template := &Template{Name: templating.Template.Name, Language: &Language{Policy: "deterministic", Code: templating.Language}} +func GetTemplatePayload(templating *MsgTemplating) *Template { + template := &Template{ + Name: templating.Template.Name, + Language: &Language{Policy: "deterministic", Code: templating.Language}, + Components: []*Component{}, + } compKeys := maps.Keys(templating.Params) sort.Strings(compKeys) // so that final component order is deterministic for _, k := range compKeys { v := templating.Params[k] + var component *Component - if strings.HasPrefix(k, "button.") { - - for _, p := range v { - if p.Type == "url" { - component := &Component{Type: "button", Index: strings.TrimPrefix(k, "button."), SubType: "quick_reply"} - component.Params = append(component.Params, &Param{Type: "text", Text: p.Value}) - template.Components = append(template.Components, component) - } else { - component := &Component{Type: "button", Index: strings.TrimPrefix(k, "button."), SubType: "quick_reply"} - component.Params = append(component.Params, &Param{Type: "payload", Payload: p.Value}) - template.Components = append(template.Components, component) - } - } + if k == "header" { + component = &Component{Type: "header"} - } else if k == "header" { - component := &Component{Type: "header"} for _, p := range v { if p.Type == "image" { component.Params = append(component.Params, &Param{Type: p.Type, Image: &struct { @@ -89,17 +81,27 @@ func GetTemplatePayload(templating MsgTemplating) *Template { component.Params = append(component.Params, &Param{Type: p.Type, Text: p.Value}) } } - template.Components = append(template.Components, component) + } else if k == "body" { + component = &Component{Type: "body"} - } else { - component := &Component{Type: "body"} for _, p := range v { component.Params = append(component.Params, &Param{Type: p.Type, Text: p.Value}) } - template.Components = append(template.Components, component) + } else if strings.HasPrefix(k, "button.") { + component = &Component{Type: "button", Index: strings.TrimPrefix(k, "button."), SubType: "quick_reply", Params: []*Param{}} + for _, p := range v { + if p.Type == "url" { + component.Params = append(component.Params, &Param{Type: "text", Text: p.Value}) + } else { + component.Params = append(component.Params, &Param{Type: "payload", Payload: p.Value}) + } + } } + if component != nil { + template.Components = append(template.Components, component) + } } return template diff --git a/handlers/meta/whatsapp/templates_test.go b/handlers/meta/whatsapp/templates_test.go index 34000cf60..ee234650d 100644 --- a/handlers/meta/whatsapp/templates_test.go +++ b/handlers/meta/whatsapp/templates_test.go @@ -2,11 +2,13 @@ package whatsapp_test import ( "encoding/json" + "fmt" "testing" "github.com/nyaruka/courier/handlers/meta/whatsapp" "github.com/nyaruka/courier/test" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGetTemplating(t *testing.T) { @@ -39,3 +41,71 @@ func TestGetTemplating(t *testing.T) { assert.Equal(t, "4ed5000f-5c94-4143-9697-b7cbd230a381", tpl.Template.UUID) assert.Equal(t, "Update", tpl.Template.Name) } + +func TestGetTemplatePayload(t *testing.T) { + tcs := []struct { + templating string + expected *whatsapp.Template + }{ + { + templating: `{ + "template": {"uuid": "4ed5000f-5c94-4143-9697-b7cbd230a381", "name": "Update"}, + "namespace": "12345", + "language": "en", + "params": {} + }`, + expected: &whatsapp.Template{ + Name: "Update", + Language: &whatsapp.Language{Policy: "deterministic", Code: "en"}, + Components: []*whatsapp.Component{}, + }, + }, + { + templating: `{ + "template": {"uuid": "4ed5000f-5c94-4143-9697-b7cbd230a381", "name": "Update"}, + "language": "en", + "params": { + "header": [{"type": "text", "value": "Welome"}], + "body": [{"type": "text", "value": "Hello"}, {"type": "text", "value": "Bob"}] + } + }`, + expected: &whatsapp.Template{ + Name: "Update", + Language: &whatsapp.Language{Policy: "deterministic", Code: "en"}, + Components: []*whatsapp.Component{ + {Type: "body", Params: []*whatsapp.Param{{Type: "text", Text: "Hello"}, {Type: "text", Text: "Bob"}}}, + {Type: "header", Params: []*whatsapp.Param{{Type: "text", Text: "Welome"}}}, + }, + }, + }, + { + templating: `{ + "template": {"uuid": "4ed5000f-5c94-4143-9697-b7cbd230a381", "name": "Update"}, + "language": "en", + "params": { + "button.1": [{"type": "text", "value": "No"}], + "button.0": [{"type": "text", "value": "Yes"}, {"type": "text", "value": "Bob"}] + } + }`, + expected: &whatsapp.Template{ + Name: "Update", + Language: &whatsapp.Language{Policy: "deterministic", Code: "en"}, + Components: []*whatsapp.Component{ + {Type: "button", SubType: "quick_reply", Index: "0", Params: []*whatsapp.Param{{Type: "payload", Payload: "Yes"}, {Type: "payload", Payload: "Bob"}}}, + {Type: "button", SubType: "quick_reply", Index: "1", Params: []*whatsapp.Param{{Type: "payload", Payload: "No"}}}, + }, + }, + }, + } + + for _, tc := range tcs { + metadata := json.RawMessage(fmt.Sprintf(`{"templating": %s}`, tc.templating)) + msg := test.NewMockMsg(1, "87995844-2017-4ba0-bc73-f3da75b32f9b", nil, "tel:+1234567890", "hi", nil).WithMetadata(metadata) + templating, err := whatsapp.GetTemplating(msg) + require.NoError(t, err) + + actual := whatsapp.GetTemplatePayload(templating) + + assert.Equal(t, tc.expected, actual) + } +}