Skip to content

Commit fe66ad4

Browse files
committed
Support sending and receiving stickers for WAC and D3C
1 parent d7ec130 commit fe66ad4

File tree

6 files changed

+197
-14
lines changed

6 files changed

+197
-14
lines changed

handlers/dialog360/dialog360.go

+26-7
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ type wacMedia struct {
9292
Mimetype string `json:"mime_type"`
9393
SHA256 string `json:"sha256"`
9494
}
95+
96+
type wacSticker struct {
97+
Animated bool `json:"animated"`
98+
ID string `json:"id"`
99+
Mimetype string `json:"mime_type"`
100+
SHA256 string `json:"sha256"`
101+
}
95102
type moPayload struct {
96103
Object string `json:"object"`
97104
Entry []struct {
@@ -125,11 +132,12 @@ type moPayload struct {
125132
Text struct {
126133
Body string `json:"body"`
127134
} `json:"text"`
128-
Image *wacMedia `json:"image"`
129-
Audio *wacMedia `json:"audio"`
130-
Video *wacMedia `json:"video"`
131-
Document *wacMedia `json:"document"`
132-
Voice *wacMedia `json:"voice"`
135+
Image *wacMedia `json:"image"`
136+
Audio *wacMedia `json:"audio"`
137+
Video *wacMedia `json:"video"`
138+
Document *wacMedia `json:"document"`
139+
Voice *wacMedia `json:"voice"`
140+
Sticker *wacSticker `json:"sticker"`
133141
Location *struct {
134142
Latitude float64 `json:"latitude"`
135143
Longitude float64 `json:"longitude"`
@@ -273,6 +281,8 @@ func (h *handler) processCloudWhatsAppPayload(ctx context.Context, channel couri
273281
} else if msg.Type == "image" && msg.Image != nil {
274282
text = msg.Image.Caption
275283
mediaURL, err = resolveMediaURL(channel, msg.Image.ID, clog)
284+
} else if msg.Type == "sticker" && msg.Sticker != nil {
285+
mediaURL, err = resolveMediaURL(channel, msg.Sticker.ID, clog)
276286
} else if msg.Type == "video" && msg.Video != nil {
277287
text = msg.Video.Caption
278288
mediaURL, err = resolveMediaURL(channel, msg.Video.ID, clog)
@@ -490,6 +500,7 @@ type wacMTPayload struct {
490500
Image *wacMTMedia `json:"image,omitempty"`
491501
Audio *wacMTMedia `json:"audio,omitempty"`
492502
Video *wacMTMedia `json:"video,omitempty"`
503+
Sticker *wacMTMedia `json:"sticker,omitempty"`
493504

494505
Interactive *wacInteractive `json:"interactive,omitempty"`
495506

@@ -636,7 +647,9 @@ func (h *handler) Send(ctx context.Context, msg courier.Msg, clog *courier.Chann
636647

637648
} else if i < len(msg.Attachments()) && (len(qrs) == 0 || len(qrs) > 3) {
638649
attType, attURL := handlers.SplitAttachment(msg.Attachments()[i])
639-
attType = strings.Split(attType, "/")[0]
650+
splitedAttType := strings.Split(attType, "/")
651+
attType = splitedAttType[0]
652+
attFormat := splitedAttType[1]
640653
if attType == "application" {
641654
attType = "document"
642655
}
@@ -649,7 +662,13 @@ func (h *handler) Send(ctx context.Context, msg courier.Msg, clog *courier.Chann
649662
}
650663

651664
if attType == "image" {
652-
payload.Image = &media
665+
if attFormat == "webp" {
666+
payload.Type = "sticker"
667+
payload.Sticker = &media
668+
} else {
669+
payload.Image = &media
670+
}
671+
653672
} else if attType == "audio" {
654673
payload.Audio = &media
655674
} else if attType == "video" {

handlers/dialog360/dialog360_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,20 @@ var testCasesD3C = []ChannelHandleTestCase{
115115
ExpectedAttachments: []string{"https://waba-v2.360dialog.io/whatsapp_business/attachments/?mid=id_image"},
116116
ExpectedDate: time.Date(2016, 1, 30, 1, 57, 9, 0, time.UTC),
117117
},
118+
{
119+
Label: "Receive Valid Sticker Message",
120+
URL: d3CReceiveURL,
121+
Data: string(test.ReadFile("./testdata/wac/stickerWAC.json")),
122+
ExpectedRespStatus: 200,
123+
ExpectedBodyContains: "Handled",
124+
NoQueueErrorCheck: true,
125+
NoInvalidChannelCheck: true,
126+
ExpectedMsgText: Sp(""),
127+
ExpectedURN: "whatsapp:5678",
128+
ExpectedExternalID: "external_id",
129+
ExpectedAttachments: []string{"https://waba-v2.360dialog.io/whatsapp_business/attachments/?mid=id_sticker"},
130+
ExpectedDate: time.Date(2016, 1, 30, 1, 57, 9, 0, time.UTC),
131+
},
118132
{
119133
Label: "Receive Valid Video Message",
120134
URL: d3CReceiveURL,
@@ -393,6 +407,19 @@ var SendTestCasesD3C = []ChannelSendTestCase{
393407
ExpectedExternalID: "157b5e14568e8",
394408
SendPrep: setSendURL,
395409
},
410+
{
411+
Label: "Sticker Send",
412+
MsgText: "sticker caption",
413+
MsgURN: "whatsapp:250788123123",
414+
MsgAttachments: []string{"image/webp:https://foo.bar/sticker.webp"},
415+
MockResponseBody: `{ "messages": [{"id": "157b5e14568e8"}] }`,
416+
MockResponseStatus: 201,
417+
ExpectedRequestBody: `{"messaging_product":"whatsapp","recipient_type":"individual","to":"250788123123","type":"sticker","sticker":{"link":"https://foo.bar/sticker.webp","caption":"sticker caption"}}`,
418+
ExpectedRequestPath: "/messages",
419+
ExpectedMsgStatus: "W",
420+
ExpectedExternalID: "157b5e14568e8",
421+
SendPrep: setSendURL,
422+
},
396423
{
397424
Label: "Video Send",
398425
MsgText: "video caption",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"object": "whatsapp_business_account",
3+
"entry": [
4+
{
5+
"id": "8856996819413533",
6+
"changes": [
7+
{
8+
"value": {
9+
"messaging_product": "whatsapp",
10+
"metadata": {
11+
"display_phone_number": "+250 788 123 200",
12+
"phone_number_id": "12345"
13+
},
14+
"contacts": [
15+
{
16+
"profile": {
17+
"name": "Kerry Fisher"
18+
},
19+
"wa_id": "5678"
20+
}
21+
],
22+
"messages": [
23+
{
24+
"from": "5678",
25+
"id": "external_id",
26+
"sticker": {
27+
"file": "/usr/local/wamedia/shared/b1cf38-8734-4ad3-b4a1-ef0c10d0d683",
28+
"id": "id_sticker",
29+
"mime_type": "image/webp",
30+
"sha256": "29ed500fa64eb55fc19dc4124acb300e5dcc54a0f822a301ae99944db"
31+
},
32+
"timestamp": "1454119029",
33+
"type": "sticker"
34+
}
35+
]
36+
},
37+
"field": "messages"
38+
}
39+
]
40+
}
41+
]
42+
}

handlers/facebookapp/facebookapp.go

+27-7
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,14 @@ type wacMedia struct {
127127
Mimetype string `json:"mime_type"`
128128
SHA256 string `json:"sha256"`
129129
}
130+
131+
type wacSticker struct {
132+
Animated bool `json:"animated"`
133+
ID string `json:"id"`
134+
Mimetype string `json:"mime_type"`
135+
SHA256 string `json:"sha256"`
136+
}
137+
130138
type moPayload struct {
131139
Object string `json:"object"`
132140
Entry []struct {
@@ -160,11 +168,12 @@ type moPayload struct {
160168
Text struct {
161169
Body string `json:"body"`
162170
} `json:"text"`
163-
Image *wacMedia `json:"image"`
164-
Audio *wacMedia `json:"audio"`
165-
Video *wacMedia `json:"video"`
166-
Document *wacMedia `json:"document"`
167-
Voice *wacMedia `json:"voice"`
171+
Image *wacMedia `json:"image"`
172+
Audio *wacMedia `json:"audio"`
173+
Video *wacMedia `json:"video"`
174+
Document *wacMedia `json:"document"`
175+
Voice *wacMedia `json:"voice"`
176+
Sticker *wacSticker `json:"sticker"`
168177
Location *struct {
169178
Latitude float64 `json:"latitude"`
170179
Longitude float64 `json:"longitude"`
@@ -469,6 +478,8 @@ func (h *handler) processCloudWhatsAppPayload(ctx context.Context, channel couri
469478
} else if msg.Type == "image" && msg.Image != nil {
470479
text = msg.Image.Caption
471480
mediaURL, err = resolveMediaURL(msg.Image.ID, token, clog)
481+
} else if msg.Type == "sticker" && msg.Sticker != nil {
482+
mediaURL, err = resolveMediaURL(msg.Sticker.ID, token, clog)
472483
} else if msg.Type == "video" && msg.Video != nil {
473484
text = msg.Video.Caption
474485
mediaURL, err = resolveMediaURL(msg.Video.ID, token, clog)
@@ -1082,6 +1093,7 @@ type wacMTPayload struct {
10821093
Image *wacMTMedia `json:"image,omitempty"`
10831094
Audio *wacMTMedia `json:"audio,omitempty"`
10841095
Video *wacMTMedia `json:"video,omitempty"`
1096+
Sticker *wacMTMedia `json:"sticker,omitempty"`
10851097

10861098
Interactive *wacInteractive `json:"interactive,omitempty"`
10871099

@@ -1217,7 +1229,10 @@ func (h *handler) sendCloudAPIWhatsappMsg(ctx context.Context, msg courier.Msg,
12171229

12181230
} else if i < len(msg.Attachments()) && (len(qrs) == 0 || len(qrs) > 3) {
12191231
attType, attURL := handlers.SplitAttachment(msg.Attachments()[i])
1220-
attType = strings.Split(attType, "/")[0]
1232+
splitedAttType := strings.Split(attType, "/")
1233+
attType = splitedAttType[0]
1234+
attFormat := splitedAttType[1]
1235+
12211236
if attType == "application" {
12221237
attType = "document"
12231238
}
@@ -1230,7 +1245,12 @@ func (h *handler) sendCloudAPIWhatsappMsg(ctx context.Context, msg courier.Msg,
12301245
}
12311246

12321247
if attType == "image" {
1233-
payload.Image = &media
1248+
if attFormat == "webp" {
1249+
payload.Type = "sticker"
1250+
payload.Sticker = &media
1251+
} else {
1252+
payload.Image = &media
1253+
}
12341254
} else if attType == "audio" {
12351255
payload.Audio = &media
12361256
} else if attType == "video" {

handlers/facebookapp/facebookapp_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,21 @@ var testCasesWAC = []ChannelHandleTestCase{
627627
ExpectedDate: time.Date(2016, 1, 30, 1, 57, 9, 0, time.UTC),
628628
PrepRequest: addValidSignature,
629629
},
630+
{
631+
Label: "Receive Valid Sticker Message",
632+
URL: wacReceiveURL,
633+
Data: string(test.ReadFile("./testdata/wac/stickerWAC.json")),
634+
ExpectedRespStatus: 200,
635+
ExpectedBodyContains: "Handled",
636+
NoQueueErrorCheck: true,
637+
NoInvalidChannelCheck: true,
638+
ExpectedMsgText: Sp(""),
639+
ExpectedURN: "whatsapp:5678",
640+
ExpectedExternalID: "external_id",
641+
ExpectedAttachments: []string{"https://foo.bar/attachmentURL_Sticker"},
642+
ExpectedDate: time.Date(2016, 1, 30, 1, 57, 9, 0, time.UTC),
643+
PrepRequest: addValidSignature,
644+
},
630645
{
631646
Label: "Receive Valid Video Message",
632647
URL: wacReceiveURL,
@@ -828,6 +843,11 @@ func TestHandler(t *testing.T) {
828843
return
829844
}
830845

846+
if strings.HasSuffix(r.URL.Path, "sticker") {
847+
w.Write([]byte(`{"url": "https://foo.bar/attachmentURL_Sticker"}`))
848+
return
849+
}
850+
831851
// valid token
832852
w.Write([]byte(`{"url": "https://foo.bar/attachmentURL"}`))
833853

@@ -1311,6 +1331,19 @@ var SendTestCasesWAC = []ChannelSendTestCase{
13111331
ExpectedExternalID: "157b5e14568e8",
13121332
SendPrep: setSendURL,
13131333
},
1334+
{
1335+
Label: "Sticker Send",
1336+
MsgText: "sticker caption",
1337+
MsgURN: "whatsapp:250788123123",
1338+
MsgAttachments: []string{"image/webp:https://foo.bar/sticker.webp"},
1339+
MockResponseBody: `{ "messages": [{"id": "157b5e14568e8"}] }`,
1340+
MockResponseStatus: 201,
1341+
ExpectedRequestBody: `{"messaging_product":"whatsapp","recipient_type":"individual","to":"250788123123","type":"sticker","sticker":{"link":"https://foo.bar/sticker.webp","caption":"sticker caption"}}`,
1342+
ExpectedRequestPath: "/12345_ID/messages",
1343+
ExpectedMsgStatus: "W",
1344+
ExpectedExternalID: "157b5e14568e8",
1345+
SendPrep: setSendURL,
1346+
},
13141347
{
13151348
Label: "Video Send",
13161349
MsgText: "video caption",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"object": "whatsapp_business_account",
3+
"entry": [
4+
{
5+
"id": "8856996819413533",
6+
"changes": [
7+
{
8+
"value": {
9+
"messaging_product": "whatsapp",
10+
"metadata": {
11+
"display_phone_number": "+250 788 123 200",
12+
"phone_number_id": "12345"
13+
},
14+
"contacts": [
15+
{
16+
"profile": {
17+
"name": "Kerry Fisher"
18+
},
19+
"wa_id": "5678"
20+
}
21+
],
22+
"messages": [
23+
{
24+
"from": "5678",
25+
"id": "external_id",
26+
"sticker": {
27+
"file": "/usr/local/wamedia/shared/b1cf38-8734-4ad3-b4a1-ef0c10d0d683",
28+
"id": "id_sticker",
29+
"mime_type": "image/webp",
30+
"sha256": "29ed500fa64eb55fc19dc4124acb300e5dcc54a0f822a301ae99944db"
31+
},
32+
"timestamp": "1454119029",
33+
"type": "sticker"
34+
}
35+
]
36+
},
37+
"field": "messages"
38+
}
39+
]
40+
}
41+
]
42+
}

0 commit comments

Comments
 (0)