diff --git a/handlers/dialog360/handler_test.go b/handlers/dialog360/handler_test.go index b2e8083ed..60e7bfa55 100644 --- a/handlers/dialog360/handler_test.go +++ b/handlers/dialog360/handler_test.go @@ -425,7 +425,7 @@ var SendTestCasesD3C = []OutgoingTestCase{ MsgText: "templated message", MsgURN: "whatsapp:250788123123", MsgLocale: "eng", - MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "params": {"body": [{"type":"text", "value":"Chef"}, {"type": "text" , "value": "tomorrow"}]}, "language": "en_US"}}`), + MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "components": [{"type": "body", "params": [{"type":"text", "value":"Chef"}, {"type": "text" , "value": "tomorrow"}]}], "language": "en_US"}}`), MockResponses: map[string][]*httpx.MockResponse{ "https://waba-v2.360dialog.io/messages": { httpx.NewMockResponse(200, nil, []byte(`{ "messages": [{"id": "157b5e14568e8"}] }`)), diff --git a/handlers/meta/whataspp_test.go b/handlers/meta/whataspp_test.go index e55b50c7f..95dac2e4e 100644 --- a/handlers/meta/whataspp_test.go +++ b/handlers/meta/whataspp_test.go @@ -394,7 +394,7 @@ var whatsappOutgoingTests = []OutgoingTestCase{ MsgText: "templated message", MsgURN: "whatsapp:250788123123", MsgLocale: "eng", - MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "params": {"body": [{"type":"text", "value":"Chef"}, {"type": "text" , "value": "tomorrow"}]}, "language": "en_US"}}`), + MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "components": [{"type":"body", "params": [{"type":"text", "value":"Chef"}, {"type": "text" , "value": "tomorrow"}]}], "language": "en_US"}}`), MockResponses: map[string][]*httpx.MockResponse{ "*/12345_ID/messages": { httpx.NewMockResponse(201, nil, []byte(`{ "messages": [{"id": "157b5e14568e8"}] }`)), @@ -410,7 +410,7 @@ var whatsappOutgoingTests = []OutgoingTestCase{ MsgText: "templated message", MsgURN: "whatsapp:250788123123", MsgLocale: "eng", - MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "params": {}, "variables": [], "language": "en_US"}}`), + MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "components": [], "variables": [], "language": "en_US"}}`), MockResponses: map[string][]*httpx.MockResponse{ "*/12345_ID/messages": { httpx.NewMockResponse(200, nil, []byte(`{ "messages": [{"id": "157b5e14568e8"}] }`)), @@ -426,37 +426,46 @@ var whatsappOutgoingTests = []OutgoingTestCase{ MsgText: "templated message", MsgURN: "whatsapp:250788123123", MsgLocale: "eng", - MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "params": { - "body": [ - { - "type": "text", - "value": "Ryan Lewis" - }, - { - "type": "text", - "value": "niño" - } - ], - "button.0": [ - { - "type": "text", - "value": "Sip" - } - ], - "button.1": [ - { - "type": "url", - "value": "id00231" - } - ] - }, "language": "en_US"}}`), + MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" },"components": [ + { + "type": "body", + "params": [ + { + "type": "text", + "value": "Ryan Lewis" + }, + { + "type": "text", + "value": "niño" + } + ] + }, + { + "type": "button/quick_reply", + "params": [ + { + "type": "text", + "value": "Sip" + } + ] + }, + { + "type": "button/url", + "params": [ + { + "type": "url", + "value": "id00231" + } + ] + } + ], "language": "en_US"}}`), MockResponses: map[string][]*httpx.MockResponse{ "*/12345_ID/messages": { httpx.NewMockResponse(201, nil, []byte(`{ "messages": [{"id": "157b5e14568e8"}] }`)), }, }, ExpectedRequests: []ExpectedRequest{{ - Body: `{"messaging_product":"whatsapp","recipient_type":"individual","to":"250788123123","type":"template","template":{"name":"revive_issue","language":{"policy":"deterministic","code":"en_US"},"components":[{"type":"body","parameters":[{"type":"text","text":"Ryan Lewis"},{"type":"text","text":"niño"}]},{"type":"button","sub_type":"quick_reply","index":"0","parameters":[{"type":"payload","payload":"Sip"}]},{"type":"button","sub_type":"quick_reply","index":"1","parameters":[{"type":"text","text":"id00231"}]}]}}`, + Body: `{"messaging_product":"whatsapp","recipient_type":"individual","to":"250788123123","type":"template","template":{"name":"revive_issue","language":{"policy":"deterministic","code":"en_US"},"components":[{"type":"body","parameters":[{"type":"text","text":"Ryan Lewis"},{"type":"text","text":"niño"}]},{"type":"button","sub_type":"quick_reply","index":"0","parameters":[{"type":"payload","payload":"Sip"}]},{"type":"button","sub_type":"url","index":"1","parameters":[{"type":"text","text":"id00231"}]}]}}`, }}, ExpectedExtIDs: []string{"157b5e14568e8"}, }, diff --git a/handlers/meta/whatsapp/templates.go b/handlers/meta/whatsapp/templates.go index a01ec7969..ff2a763e6 100644 --- a/handlers/meta/whatsapp/templates.go +++ b/handlers/meta/whatsapp/templates.go @@ -2,13 +2,12 @@ package whatsapp import ( "encoding/json" - "sort" + "fmt" "strings" "github.com/nyaruka/courier" "github.com/nyaruka/courier/utils" "github.com/pkg/errors" - "golang.org/x/exp/maps" ) type MsgTemplating struct { @@ -16,11 +15,14 @@ type MsgTemplating struct { Name string `json:"name" validate:"required"` UUID string `json:"uuid" validate:"required"` } `json:"template" validate:"required,dive"` - Namespace string `json:"namespace"` - Params map[string][]struct { - Type string `json:"type"` - Value string `json:"value"` - } `json:"params"` + Namespace string `json:"namespace"` + Components []struct { + Type string `json:"type"` + Params []struct { + Type string `json:"type"` + Value string `json:"value"` + } `json:"params"` + } `json:"components"` Language string `json:"language"` } @@ -54,17 +56,14 @@ func GetTemplatePayload(templating *MsgTemplating) *Template { 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] + buttonIndex := -1 + for _, comp := range templating.Components { var component *Component - if k == "header" { - component = &Component{Type: "header"} + if comp.Type == "header" { + component = &Component{Type: comp.Type} - for _, p := range v { + for _, p := range comp.Params { if p.Type == "image" { component.Params = append(component.Params, &Param{Type: p.Type, Image: &struct { Link string "json:\"link,omitempty\"" @@ -81,17 +80,19 @@ func GetTemplatePayload(templating *MsgTemplating) *Template { component.Params = append(component.Params, &Param{Type: p.Type, Text: p.Value}) } } - } else if k == "body" { - component = &Component{Type: "body"} + } else if comp.Type == "body" { + component = &Component{Type: comp.Type} - for _, p := range v { + for _, p := range comp.Params { component.Params = append(component.Params, &Param{Type: p.Type, Text: p.Value}) } - } else if strings.HasPrefix(k, "button.") { - component = &Component{Type: "button", Index: strings.TrimPrefix(k, "button."), SubType: "quick_reply", Params: []*Param{}} + } else if strings.HasPrefix(comp.Type, "button/") { + buttonIndex += 1 + + component = &Component{Type: "button", Index: fmt.Sprint(buttonIndex), SubType: strings.TrimPrefix(comp.Type, "button/"), Params: []*Param{}} - for _, p := range v { - if p.Type == "url" { + for _, p := range comp.Params { + if comp.Type == "button/url" { component.Params = append(component.Params, &Param{Type: "text", Text: p.Value}) } else { component.Params = append(component.Params, &Param{Type: "payload", Payload: p.Value}) diff --git a/handlers/meta/whatsapp/templates_test.go b/handlers/meta/whatsapp/templates_test.go index ee234650d..e7b7b5ae1 100644 --- a/handlers/meta/whatsapp/templates_test.go +++ b/handlers/meta/whatsapp/templates_test.go @@ -64,17 +64,25 @@ func TestGetTemplatePayload(t *testing.T) { 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"}] - } + "components": [ + { + "type": "header", + "name": "header", + "params": [{"type": "text", "value": "Welcome"}] + }, + { + "type": "body", + "name": "body", + "params": [{"type": "text", "value": "Hello"}, {"type": "text", "value": "Bob"}] + } + ] }`, expected: &whatsapp.Template{ Name: "Update", Language: &whatsapp.Language{Policy: "deterministic", Code: "en"}, Components: []*whatsapp.Component{ + {Type: "header", Params: []*whatsapp.Param{{Type: "text", Text: "Welcome"}}}, {Type: "body", Params: []*whatsapp.Param{{Type: "text", Text: "Hello"}, {Type: "text", Text: "Bob"}}}, - {Type: "header", Params: []*whatsapp.Param{{Type: "text", Text: "Welome"}}}, }, }, }, @@ -82,10 +90,23 @@ func TestGetTemplatePayload(t *testing.T) { 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"}] - } + "components": [ + { + "type": "button/quick_reply", + "name": "button.0", + "params": [{"type": "text", "value": "Yes"}, {"type": "text", "value": "Bob"}] + }, + { + "type": "button/quick_reply", + "name": "button.1", + "params" : [{"type": "text", "value": "No"}] + }, + { + "type": "button/url", + "name": "button.2", + "params": [{"type": "url", "value": "id0023"}] + } + ] }`, expected: &whatsapp.Template{ Name: "Update", @@ -93,6 +114,7 @@ func TestGetTemplatePayload(t *testing.T) { 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"}}}, + {Type: "button", SubType: "url", Index: "2", Params: []*whatsapp.Param{{Type: "text", Text: "id0023"}}}, }, }, },