From aaa9f5ee44677e4f16bec186c2bf25a5498326d1 Mon Sep 17 00:00:00 2001 From: Norbert Kwizera Date: Wed, 16 Aug 2023 14:33:41 +0200 Subject: [PATCH] Fix retrieve media files for D3C --- handlers/dialog360/dialog360.go | 26 ++++++++++++++-- handlers/dialog360/dialog360_test.go | 46 ++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/handlers/dialog360/dialog360.go b/handlers/dialog360/dialog360.go index 52377f320..efd7bb911 100644 --- a/handlers/dialog360/dialog360.go +++ b/handlers/dialog360/dialog360.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/buger/jsonparser" "github.com/nyaruka/courier" "github.com/nyaruka/courier/handlers" "github.com/nyaruka/courier/utils" @@ -375,16 +376,35 @@ func resolveMediaURL(channel courier.Channel, mediaID string, clog *courier.Chan return "", nil } + token := channel.StringConfigForKey(courier.ConfigAuthToken, "") + if token == "" { + return "", fmt.Errorf("missing token for D3C channel") + } + urlStr := channel.StringConfigForKey(courier.ConfigBaseURL, "") url, err := url.Parse(urlStr) if err != nil { return "", fmt.Errorf("invalid base url set for D3C channel: %s", err) } - mediaPath, _ := url.Parse("/whatsapp_business/attachments/") - mediaEndpoint := url.ResolveReference(mediaPath).String() + mediaPath, _ := url.Parse(mediaID) + mediaURL := url.ResolveReference(mediaPath).String() + + req, _ := http.NewRequest(http.MethodGet, mediaURL, nil) + req.Header.Set("User-Agent", utils.HTTPUserAgent) + req.Header.Set(d3AuthorizationKey, token) + + resp, respBody, err := handlers.RequestHTTP(req, clog) + if err != nil || resp.StatusCode/100 != 2 { + return "", fmt.Errorf("failed to request media URL for D3C channel: %s", err) + } + + fbFileURL, err := jsonparser.GetString(respBody, "url") + if err != nil { + return "", fmt.Errorf("missing url field in response for D3C media: %s", err) + } - fileURL := fmt.Sprintf("%s?mid=%s", mediaEndpoint, mediaID) + fileURL := strings.ReplaceAll(fbFileURL, "https://lookaside.fbsbx.com", urlStr) return fileURL, nil } diff --git a/handlers/dialog360/dialog360_test.go b/handlers/dialog360/dialog360_test.go index 23bfcb8a2..4368dd43a 100644 --- a/handlers/dialog360/dialog360_test.go +++ b/handlers/dialog360/dialog360_test.go @@ -3,7 +3,10 @@ package dialog360 import ( "context" "encoding/json" + "fmt" + "net/http" "net/http/httptest" + "strings" "testing" "time" @@ -252,11 +255,54 @@ var testCasesD3C = []ChannelHandleTestCase{ }, } +func buildMockD3MediaService(testChannels []courier.Channel, testCases []ChannelHandleTestCase) *httptest.Server { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fileURL := "" + + if strings.HasSuffix(r.URL.Path, "id_voice") { + fileURL = "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=id_voice" + } + if strings.HasSuffix(r.URL.Path, "id_document") { + fileURL = "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=id_document" + } + if strings.HasSuffix(r.URL.Path, "id_image") { + fileURL = "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=id_image" + } + if strings.HasSuffix(r.URL.Path, "id_video") { + fileURL = "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=id_video" + } + if strings.HasSuffix(r.URL.Path, "id_audio") { + fileURL = "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=id_audio" + } + + w.WriteHeader(http.StatusOK) + w.Write([]byte(fmt.Sprintf(`{ "url": "%s" }`, fileURL))) + })) + testChannels[0].(*test.MockChannel).SetConfig("base_url", server.URL) + + // update our tests media urls + for _, tc := range testCases { + for i := range tc.ExpectedAttachments { + if !strings.HasPrefix(tc.ExpectedAttachments[i], "geo:") { + tc.ExpectedAttachments[i] = strings.ReplaceAll(tc.ExpectedAttachments[i], "https://waba-v2.360dialog.io", server.URL) + } + } + } + + return server +} + func TestHandler(t *testing.T) { + + d3MediaService := buildMockD3MediaService(testChannels, testCasesD3C) + defer d3MediaService.Close() + RunChannelTestCases(t, testChannels, newWAHandler(courier.ChannelType("D3C"), "360Dialog"), testCasesD3C) } func BenchmarkHandler(b *testing.B) { + d3MediaService := buildMockD3MediaService(testChannels, testCasesD3C) + defer d3MediaService.Close() RunChannelBenchmarks(b, testChannels, newWAHandler(courier.ChannelType("D3C"), "360Dialog"), testCasesD3C) }