From f1e5fbc318f706c4d0137fcc4e9ba3075569b1c3 Mon Sep 17 00:00:00 2001 From: Dimas Restu H Date: Thu, 21 Apr 2022 17:31:01 +0700 Subject: [PATCH] add capabilities to send document --- README.md | 2 +- internal/route.go | 2 +- internal/whatsapp/whatsapp.go | 77 +++++++++++++++++++++++++++++++++-- pkg/whatsapp/whatsapp.go | 39 ++++++++++++++++++ 4 files changed, 114 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2b43750..bc1bd5f 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ The build result will shown in build directory ## API Access -You can access any endpoint under **API_BASE_URL** environment variable which by default located at */*. +You can access any endpoint under **BASE_URL** environment variable which by default located at *.env* file. ## Built With diff --git a/internal/route.go b/internal/route.go index 5b2865c..92b328f 100644 --- a/internal/route.go +++ b/internal/route.go @@ -33,7 +33,7 @@ func Routes(e *echo.Echo) { e.POST(router.BaseURL+"/login", ctlWhatsApp.Login, middleware.JWTWithConfig(authJWTConfig)) e.POST(router.BaseURL+"/send/text", ctlWhatsApp.SendText, middleware.JWTWithConfig(authJWTConfig)) e.POST(router.BaseURL+"/send/location", ctlWhatsApp.SendLocation, middleware.JWTWithConfig(authJWTConfig)) - // e.POST(router.BaseURL+"/send/document", ctlWhatsApp.SendDocument, middleware.JWTWithConfig(authJWTConfig)) + e.POST(router.BaseURL+"/send/document", ctlWhatsApp.SendDocument, middleware.JWTWithConfig(authJWTConfig)) // e.POST(router.BaseURL+"/send/audio", ctlWhatsApp.SendAudio, middleware.JWTWithConfig(authJWTConfig)) // e.POST(router.BaseURL+"/send/image", ctlWhatsApp.SendImage, middleware.JWTWithConfig(authJWTConfig)) // e.POST(router.BaseURL+"/send/video", ctlWhatsApp.SendVideo, middleware.JWTWithConfig(authJWTConfig)) diff --git a/internal/whatsapp/whatsapp.go b/internal/whatsapp/whatsapp.go index bf95dc9..5baa80c 100644 --- a/internal/whatsapp/whatsapp.go +++ b/internal/whatsapp/whatsapp.go @@ -1,6 +1,9 @@ package whatsapp import ( + "bytes" + "io" + "mime/multipart" "strconv" "strings" @@ -21,6 +24,72 @@ func jwtPayload(c echo.Context) typAuth.AuthJWTClaimsPayload { return jwtClaims.Data } +func convertFileToBuffer(file multipart.File) ([]byte, error) { + buffer := bytes.NewBuffer(nil) + _, err := io.Copy(buffer, file) + if err != nil { + return bytes.NewBuffer(nil).Bytes(), err + } + + return buffer.Bytes(), nil +} + +func sendContent(c echo.Context, mediaType string) error { + var err error + jid := jwtPayload(c).JID + + var reqSendMessage typWhatsApp.RequestSendMessage + reqSendMessage.RJID = strings.TrimSpace(c.FormValue("msisdn")) + + // Read Uploaded File Based on Send Media Type + var fileStream multipart.File + var fileHeader *multipart.FileHeader + + switch mediaType { + case "document": + fileStream, fileHeader, err = c.Request().FormFile("document") + reqSendMessage.Message = fileHeader.Filename + } + + // Don't Forget to Close The File Stream + defer fileStream.Close() + + // Get Uploaded File MIME Type + fileType := fileHeader.Header.Get("Content-Type") + + // If There are Some Errors While Opeening The File Stream + // Return Bad Request with Original Error Message + if err != nil { + return router.ResponseBadRequest(c, err.Error()) + } + + // Make Sure RJID is Filled + if len(reqSendMessage.RJID) == 0 { + return router.ResponseBadRequest(c, "Missing Form Value MSISDN") + } + + // Convert File Stream in to Bytes + // Since WhatsApp Proto for Media is only Accepting Bytes format + fileBytes, err := convertFileToBuffer(fileStream) + if err != nil { + return router.ResponseInternalError(c, err.Error()) + } + + // Send Media Message Based on Media Type + switch mediaType { + case "document": + err = pkgWhatsApp.WhatsAppSendDocument(jid, reqSendMessage.RJID, fileBytes, fileType, reqSendMessage.Message) + } + + // Return Internal Server Error + // When Detected There are Some Errors While Sending The Media Message + if err != nil { + return router.ResponseInternalError(c, err.Error()) + } + + return router.ResponseSuccess(c, "Successfully Send Media Message") +} + func Login(c echo.Context) error { var err error jid := jwtPayload(c).JID @@ -133,15 +202,15 @@ func SendLocation(c echo.Context) error { return router.ResponseSuccess(c, "Successfully Send Location Message") } +func SendDocument(c echo.Context) error { + return sendContent(c, "document") +} + /* TODO: Send Media */ /* -func SendDocument(c echo.Context) error { - return router.ResponseSuccess(c, "Successfully Send Document Message") -} - func SendImage(c echo.Context) error { return router.ResponseSuccess(c, "Successfully Send Image Message") } diff --git a/pkg/whatsapp/whatsapp.go b/pkg/whatsapp/whatsapp.go index 3de1fac..693b933 100644 --- a/pkg/whatsapp/whatsapp.go +++ b/pkg/whatsapp/whatsapp.go @@ -269,3 +269,42 @@ func WhatsAppSendLocation(jid string, rjid string, latitude float64, longitude f // Return Error WhatsApp Client is not Valid return errors.New("WhatsApp Client is not Valid") } + +func WhatsAppSendDocument(jid string, rjid string, fileBytes []byte, fileType string, fileName string) error { + if WhatsAppClient[jid] != nil { + // Make Sure WhatsApp Client is OK + err := WhatsAppClientIsOK(jid) + if err != nil { + return err + } + + // Upload File to WhatsApp Storage Server + fileUploaded, err := WhatsAppClient[jid].Upload(context.Background(), fileBytes, whatsmeow.MediaDocument) + + // Compose WhatsApp Proto + content := &waproto.Message{ + DocumentMessage: &waproto.DocumentMessage{ + Url: proto.String(fileUploaded.URL), + DirectPath: proto.String(fileUploaded.DirectPath), + Mimetype: proto.String(fileType), + Title: proto.String(fileName), + FileName: proto.String(fileName), + FileLength: proto.Uint64(fileUploaded.FileLength), + FileSha256: fileUploaded.FileSHA256, + FileEncSha256: fileUploaded.FileEncSHA256, + MediaKey: fileUploaded.MediaKey, + }, + } + + // Send WhatsApp Message Proto + _, err = WhatsAppClient[jid].SendMessage(WhatsAppComposeJID(rjid), "", content) + if err != nil { + return err + } + + return nil + } + + // Return Error WhatsApp Client is not Valid + return errors.New("WhatsApp Client is not Valid") +}