Skip to content

Commit 35bed29

Browse files
authored
Merge pull request #721 from nyaruka/fix-WA-button-component-type
Use templating component type
2 parents d9467e3 + 980a8e1 commit 35bed29

File tree

4 files changed

+91
-59
lines changed

4 files changed

+91
-59
lines changed

Diff for: handlers/dialog360/handler_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ var SendTestCasesD3C = []OutgoingTestCase{
425425
MsgText: "templated message",
426426
MsgURN: "whatsapp:250788123123",
427427
MsgLocale: "eng",
428-
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"}}`),
428+
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"}}`),
429429
MockResponses: map[string][]*httpx.MockResponse{
430430
"https://waba-v2.360dialog.io/messages": {
431431
httpx.NewMockResponse(200, nil, []byte(`{ "messages": [{"id": "157b5e14568e8"}] }`)),

Diff for: handlers/meta/whataspp_test.go

+36-27
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ var whatsappOutgoingTests = []OutgoingTestCase{
394394
MsgText: "templated message",
395395
MsgURN: "whatsapp:250788123123",
396396
MsgLocale: "eng",
397-
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"}}`),
397+
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"}}`),
398398
MockResponses: map[string][]*httpx.MockResponse{
399399
"*/12345_ID/messages": {
400400
httpx.NewMockResponse(201, nil, []byte(`{ "messages": [{"id": "157b5e14568e8"}] }`)),
@@ -410,7 +410,7 @@ var whatsappOutgoingTests = []OutgoingTestCase{
410410
MsgText: "templated message",
411411
MsgURN: "whatsapp:250788123123",
412412
MsgLocale: "eng",
413-
MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "params": {}, "variables": [], "language": "en_US"}}`),
413+
MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "components": [], "variables": [], "language": "en_US"}}`),
414414
MockResponses: map[string][]*httpx.MockResponse{
415415
"*/12345_ID/messages": {
416416
httpx.NewMockResponse(200, nil, []byte(`{ "messages": [{"id": "157b5e14568e8"}] }`)),
@@ -426,37 +426,46 @@ var whatsappOutgoingTests = []OutgoingTestCase{
426426
MsgText: "templated message",
427427
MsgURN: "whatsapp:250788123123",
428428
MsgLocale: "eng",
429-
MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" }, "params": {
430-
"body": [
431-
{
432-
"type": "text",
433-
"value": "Ryan Lewis"
434-
},
435-
{
436-
"type": "text",
437-
"value": "niño"
438-
}
439-
],
440-
"button.0": [
441-
{
442-
"type": "text",
443-
"value": "Sip"
444-
}
445-
],
446-
"button.1": [
447-
{
448-
"type": "url",
449-
"value": "id00231"
450-
}
451-
]
452-
}, "language": "en_US"}}`),
429+
MsgMetadata: json.RawMessage(`{ "templating": { "template": { "name": "revive_issue", "uuid": "171f8a4d-f725-46d7-85a6-11aceff0bfe3" },"components": [
430+
{
431+
"type": "body",
432+
"params": [
433+
{
434+
"type": "text",
435+
"value": "Ryan Lewis"
436+
},
437+
{
438+
"type": "text",
439+
"value": "niño"
440+
}
441+
]
442+
},
443+
{
444+
"type": "button/quick_reply",
445+
"params": [
446+
{
447+
"type": "text",
448+
"value": "Sip"
449+
}
450+
]
451+
},
452+
{
453+
"type": "button/url",
454+
"params": [
455+
{
456+
"type": "url",
457+
"value": "id00231"
458+
}
459+
]
460+
}
461+
], "language": "en_US"}}`),
453462
MockResponses: map[string][]*httpx.MockResponse{
454463
"*/12345_ID/messages": {
455464
httpx.NewMockResponse(201, nil, []byte(`{ "messages": [{"id": "157b5e14568e8"}] }`)),
456465
},
457466
},
458467
ExpectedRequests: []ExpectedRequest{{
459-
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"}]}]}}`,
468+
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"}]}]}}`,
460469
}},
461470
ExpectedExtIDs: []string{"157b5e14568e8"},
462471
},

Diff for: handlers/meta/whatsapp/templates.go

+23-22
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,27 @@ package whatsapp
22

33
import (
44
"encoding/json"
5-
"sort"
5+
"fmt"
66
"strings"
77

88
"github.com/nyaruka/courier"
99
"github.com/nyaruka/courier/utils"
1010
"github.com/pkg/errors"
11-
"golang.org/x/exp/maps"
1211
)
1312

1413
type MsgTemplating struct {
1514
Template struct {
1615
Name string `json:"name" validate:"required"`
1716
UUID string `json:"uuid" validate:"required"`
1817
} `json:"template" validate:"required,dive"`
19-
Namespace string `json:"namespace"`
20-
Params map[string][]struct {
21-
Type string `json:"type"`
22-
Value string `json:"value"`
23-
} `json:"params"`
18+
Namespace string `json:"namespace"`
19+
Components []struct {
20+
Type string `json:"type"`
21+
Params []struct {
22+
Type string `json:"type"`
23+
Value string `json:"value"`
24+
} `json:"params"`
25+
} `json:"components"`
2426
Language string `json:"language"`
2527
}
2628

@@ -54,17 +56,14 @@ func GetTemplatePayload(templating *MsgTemplating) *Template {
5456
Components: []*Component{},
5557
}
5658

57-
compKeys := maps.Keys(templating.Params)
58-
sort.Strings(compKeys) // so that final component order is deterministic
59-
60-
for _, k := range compKeys {
61-
v := templating.Params[k]
59+
buttonIndex := -1
60+
for _, comp := range templating.Components {
6261
var component *Component
6362

64-
if k == "header" {
65-
component = &Component{Type: "header"}
63+
if comp.Type == "header" {
64+
component = &Component{Type: comp.Type}
6665

67-
for _, p := range v {
66+
for _, p := range comp.Params {
6867
if p.Type == "image" {
6968
component.Params = append(component.Params, &Param{Type: p.Type, Image: &struct {
7069
Link string "json:\"link,omitempty\""
@@ -81,17 +80,19 @@ func GetTemplatePayload(templating *MsgTemplating) *Template {
8180
component.Params = append(component.Params, &Param{Type: p.Type, Text: p.Value})
8281
}
8382
}
84-
} else if k == "body" {
85-
component = &Component{Type: "body"}
83+
} else if comp.Type == "body" {
84+
component = &Component{Type: comp.Type}
8685

87-
for _, p := range v {
86+
for _, p := range comp.Params {
8887
component.Params = append(component.Params, &Param{Type: p.Type, Text: p.Value})
8988
}
90-
} else if strings.HasPrefix(k, "button.") {
91-
component = &Component{Type: "button", Index: strings.TrimPrefix(k, "button."), SubType: "quick_reply", Params: []*Param{}}
89+
} else if strings.HasPrefix(comp.Type, "button/") {
90+
buttonIndex += 1
91+
92+
component = &Component{Type: "button", Index: fmt.Sprint(buttonIndex), SubType: strings.TrimPrefix(comp.Type, "button/"), Params: []*Param{}}
9293

93-
for _, p := range v {
94-
if p.Type == "url" {
94+
for _, p := range comp.Params {
95+
if comp.Type == "button/url" {
9596
component.Params = append(component.Params, &Param{Type: "text", Text: p.Value})
9697
} else {
9798
component.Params = append(component.Params, &Param{Type: "payload", Payload: p.Value})

Diff for: handlers/meta/whatsapp/templates_test.go

+31-9
Original file line numberDiff line numberDiff line change
@@ -64,35 +64,57 @@ func TestGetTemplatePayload(t *testing.T) {
6464
templating: `{
6565
"template": {"uuid": "4ed5000f-5c94-4143-9697-b7cbd230a381", "name": "Update"},
6666
"language": "en",
67-
"params": {
68-
"header": [{"type": "text", "value": "Welome"}],
69-
"body": [{"type": "text", "value": "Hello"}, {"type": "text", "value": "Bob"}]
70-
}
67+
"components": [
68+
{
69+
"type": "header",
70+
"name": "header",
71+
"params": [{"type": "text", "value": "Welcome"}]
72+
},
73+
{
74+
"type": "body",
75+
"name": "body",
76+
"params": [{"type": "text", "value": "Hello"}, {"type": "text", "value": "Bob"}]
77+
}
78+
]
7179
}`,
7280
expected: &whatsapp.Template{
7381
Name: "Update",
7482
Language: &whatsapp.Language{Policy: "deterministic", Code: "en"},
7583
Components: []*whatsapp.Component{
84+
{Type: "header", Params: []*whatsapp.Param{{Type: "text", Text: "Welcome"}}},
7685
{Type: "body", Params: []*whatsapp.Param{{Type: "text", Text: "Hello"}, {Type: "text", Text: "Bob"}}},
77-
{Type: "header", Params: []*whatsapp.Param{{Type: "text", Text: "Welome"}}},
7886
},
7987
},
8088
},
8189
{
8290
templating: `{
8391
"template": {"uuid": "4ed5000f-5c94-4143-9697-b7cbd230a381", "name": "Update"},
8492
"language": "en",
85-
"params": {
86-
"button.1": [{"type": "text", "value": "No"}],
87-
"button.0": [{"type": "text", "value": "Yes"}, {"type": "text", "value": "Bob"}]
88-
}
93+
"components": [
94+
{
95+
"type": "button/quick_reply",
96+
"name": "button.0",
97+
"params": [{"type": "text", "value": "Yes"}, {"type": "text", "value": "Bob"}]
98+
},
99+
{
100+
"type": "button/quick_reply",
101+
"name": "button.1",
102+
"params" : [{"type": "text", "value": "No"}]
103+
},
104+
{
105+
"type": "button/url",
106+
"name": "button.2",
107+
"params": [{"type": "url", "value": "id0023"}]
108+
}
109+
]
89110
}`,
90111
expected: &whatsapp.Template{
91112
Name: "Update",
92113
Language: &whatsapp.Language{Policy: "deterministic", Code: "en"},
93114
Components: []*whatsapp.Component{
94115
{Type: "button", SubType: "quick_reply", Index: "0", Params: []*whatsapp.Param{{Type: "payload", Payload: "Yes"}, {Type: "payload", Payload: "Bob"}}},
95116
{Type: "button", SubType: "quick_reply", Index: "1", Params: []*whatsapp.Param{{Type: "payload", Payload: "No"}}},
117+
{Type: "button", SubType: "url", Index: "2", Params: []*whatsapp.Param{{Type: "text", Text: "id0023"}}},
96118
},
97119
},
98120
},

0 commit comments

Comments
 (0)