From 0806e9c5490c488e12d071c3ea14016a214d79b5 Mon Sep 17 00:00:00 2001 From: Dimas Restu H Date: Tue, 14 Jun 2022 16:35:32 +0700 Subject: [PATCH] update logic to validate and construct jid server type --- .env.default | 4 +- .env.development | 4 +- .env.production | 4 +- docs/docs.go | 31 +++++++++ docs/swagger.json | 31 +++++++++ docs/swagger.yaml | 19 ++++++ go.mod | 2 +- go.sum | 4 +- internal/route.go | 2 + internal/whatsapp/whatsapp.go | 27 ++++++++ pkg/whatsapp/whatsapp.go | 116 +++++++++++++++++++++++++--------- 11 files changed, 204 insertions(+), 40 deletions(-) diff --git a/.env.default b/.env.default index dbfcbb2..4a8aae9 100644 --- a/.env.default +++ b/.env.default @@ -34,8 +34,8 @@ WHATSAPP_DATASTORE_URI=file:dbs/WhatsApp.db?_foreign_keys=on WHATSAPP_MEDIA_IMAGE_COMPRESSION=true WHATSAPP_MEDIA_IMAGE_CONVERT_WEBP=true -# WHATSAPP_VERSION_MAJOR=2 -# WHATSAPP_VERSION_MINOR=2216 +# WHATSAPP_VERSION_MAJOR=2. +# WHATSAPP_VERSION_MINOR=2220 # WHATSAPP_VERSION_PATCH=8 # ----------------------------------- diff --git a/.env.development b/.env.development index 4ca3fe8..e54c0bd 100644 --- a/.env.development +++ b/.env.development @@ -34,8 +34,8 @@ WHATSAPP_DATASTORE_URI=file:dbs/WhatsApp.db?_foreign_keys=on WHATSAPP_MEDIA_IMAGE_COMPRESSION=true WHATSAPP_MEDIA_IMAGE_CONVERT_WEBP=true -# WHATSAPP_VERSION_MAJOR=2 -# WHATSAPP_VERSION_MINOR=2216 +# WHATSAPP_VERSION_MAJOR=2. +# WHATSAPP_VERSION_MINOR=2220 # WHATSAPP_VERSION_PATCH=8 # ----------------------------------- diff --git a/.env.production b/.env.production index 1d3d8f8..d586164 100644 --- a/.env.production +++ b/.env.production @@ -34,8 +34,8 @@ WHATSAPP_DATASTORE_URI=file:dbs/WhatsApp.db?_foreign_keys=on WHATSAPP_MEDIA_IMAGE_COMPRESSION=true WHATSAPP_MEDIA_IMAGE_CONVERT_WEBP=true -# WHATSAPP_VERSION_MAJOR=2 -# WHATSAPP_VERSION_MINOR=2216 +# WHATSAPP_VERSION_MAJOR=2. +# WHATSAPP_VERSION_MINOR=2220 # WHATSAPP_VERSION_PATCH=8 # ----------------------------------- diff --git a/docs/docs.go b/docs/docs.go index bd45e8c..160f6cb 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -120,6 +120,37 @@ const docTemplate = `{ } } }, + "/api/v1/whatsapp/registered": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Check Phone Number is Registered in WhatsApp", + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp Authentication" + ], + "summary": "Check If Phone Number is Registered in WhatsApp", + "parameters": [ + { + "type": "string", + "description": "Phone Number to Check", + "name": "msisdn", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, "/api/v1/whatsapp/send/audio": { "post": { "security": [ diff --git a/docs/swagger.json b/docs/swagger.json index 0091a0c..c2c1938 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -115,6 +115,37 @@ } } }, + "/api/v1/whatsapp/registered": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Check Phone Number is Registered in WhatsApp", + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp Authentication" + ], + "summary": "Check If Phone Number is Registered in WhatsApp", + "parameters": [ + { + "type": "string", + "description": "Phone Number to Check", + "name": "msisdn", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, "/api/v1/whatsapp/send/audio": { "post": { "security": [ diff --git a/docs/swagger.yaml b/docs/swagger.yaml index fe7953a..9051f80 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -70,6 +70,25 @@ paths: summary: Logout Device from WhatsApp Multi-Device tags: - WhatsApp Authentication + /api/v1/whatsapp/registered: + get: + description: Check Phone Number is Registered in WhatsApp + parameters: + - description: Phone Number to Check + in: query + name: msisdn + required: true + type: string + produces: + - application/json + responses: + "200": + description: "" + security: + - BearerAuth: [] + summary: Check If Phone Number is Registered in WhatsApp + tags: + - WhatsApp Authentication /api/v1/whatsapp/send/audio: post: consumes: diff --git a/go.mod b/go.mod index 82716bc..396e1f5 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/sunshineplan/imgconv v1.0.5 github.com/swaggo/echo-swagger v1.3.2 github.com/swaggo/swag v1.8.1 - go.mau.fi/whatsmeow v0.0.0-20220517205516-246a2007ca7f + go.mau.fi/whatsmeow v0.0.0-20220604174810-f28d984f1b9a google.golang.org/protobuf v1.28.0 modernc.org/sqlite v1.17.0 ) diff --git a/go.sum b/go.sum index d3fe018..36675bd 100644 --- a/go.sum +++ b/go.sum @@ -220,8 +220,8 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.mau.fi/libsignal v0.0.0-20220425070825-c40c839ee6a0 h1:3IQF2bgAyibdo77hTejwuJe4jlypj9QaE4xCQuxrThM= go.mau.fi/libsignal v0.0.0-20220425070825-c40c839ee6a0/go.mod h1:kBOXTvYyDG/q1Ihgvd4J6WenGPh7wtEGvPKF6vmf5ak= -go.mau.fi/whatsmeow v0.0.0-20220517205516-246a2007ca7f h1:0eo1TMJBx2pv7vNh/sPAl8bXPpn+HwrVJntuOnejMfs= -go.mau.fi/whatsmeow v0.0.0-20220517205516-246a2007ca7f/go.mod h1:iUBgOLNaqShLrR17u0kIiRptIGFH+nbT1tRhaWBEX/c= +go.mau.fi/whatsmeow v0.0.0-20220604174810-f28d984f1b9a h1:kLIh5zAEvEMK8k8Qg2aU6aMDfJmrf5+XJ3t3Q3ZCV7o= +go.mau.fi/whatsmeow v0.0.0-20220604174810-f28d984f1b9a/go.mod h1:iUBgOLNaqShLrR17u0kIiRptIGFH+nbT1tRhaWBEX/c= go.opentelemetry.io/otel v0.5.0/go.mod h1:jzBIgIzK43Iu1BpDAXwqOd6UPsSAk+ewVZ5ofSXw4Ek= go.opentelemetry.io/otel v0.6.0/go.mod h1:jzBIgIzK43Iu1BpDAXwqOd6UPsSAk+ewVZ5ofSXw4Ek= go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo= diff --git a/internal/route.go b/internal/route.go index ee5b86f..f45d813 100644 --- a/internal/route.go +++ b/internal/route.go @@ -35,6 +35,8 @@ func Routes(e *echo.Echo) { SigningKey: []byte(auth.AuthJWTSecret), } + e.GET(router.BaseURL+"/registered", ctlWhatsApp.Registered, middleware.JWTWithConfig(authJWTConfig)) + 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)) diff --git a/internal/whatsapp/whatsapp.go b/internal/whatsapp/whatsapp.go index 06c6298..355ffb8 100644 --- a/internal/whatsapp/whatsapp.go +++ b/internal/whatsapp/whatsapp.go @@ -121,6 +121,33 @@ func Logout(c echo.Context) error { return router.ResponseSuccess(c, "Successfully Logged Out") } +// Registered +// @Summary Check If Phone Number is Registered in WhatsApp +// @Description Check Phone Number is Registered in WhatsApp +// @Tags WhatsApp Authentication +// @Produce json +// @Param msisdn query string true "Phone Number to Check" +// @Success 200 +// @Security BearerAuth +// @Router /api/v1/whatsapp/registered [get] +func Registered(c echo.Context) error { + jid := jwtPayload(c).JID + rjid := strings.TrimSpace(c.QueryParam("msisdn")) + + if len(rjid) == 0 { + return router.ResponseInternalError(c, "Missing Param Value MSISDN") + } + + rjid = pkgWhatsApp.WhatsAppDecomposeJID(rjid) + + _, isJIDRegistered := pkgWhatsApp.WhatsAppCheckJID(jid, rjid) + if !isJIDRegistered { + return router.ResponseNotFound(c, "Phone Number is Not Registered") + } + + return router.ResponseSuccess(c, "Phone Number is Registered") +} + // SendText // @Summary Send Text Message // @Description Send Text Message to Spesific Phone Number diff --git a/pkg/whatsapp/whatsapp.go b/pkg/whatsapp/whatsapp.go index 8796636..632a859 100644 --- a/pkg/whatsapp/whatsapp.go +++ b/pkg/whatsapp/whatsapp.go @@ -224,39 +224,66 @@ func WhatsAppClientIsOK(jid string) error { return nil } -func WhatsAppComposeJID(jid string) types.JID { - // Decompose JID First Before Recomposing - jid = WhatsAppDecomposeJID(jid) - - // Check if JID Contains '-' Symbol - if strings.ContainsRune(jid, '-') { - // Check if the JID is a Group ID - if len(strings.SplitN(jid, "-", 2)) == 2 { +func WhatsAppCheckJID(jid string, phone string) (types.JID, bool) { + if WhatsAppClient[jid] != nil { + var phones []string + + phones = append(phones, "+"+phone) + jidInfos, err := WhatsAppClient[jid].IsOnWhatsApp(phones) + if err == nil { + // If Phone Number is Registered in WhatsApp + if jidInfos[0].IsIn { + // Return JID Information + return jidInfos[0].JID, true + } + } + } + + // Return Empty JID Information + return types.EmptyJID, false +} + +func WhatsAppComposeJID(jid string, phone string) types.JID { + // Decompose Phone Number First Before Recomposing + phone = WhatsAppDecomposeJID(phone) + + // Check if Phone Number is Registered in WhatsApp + jidInfo, jidOK := WhatsAppCheckJID(jid, phone) + + // If Phone Number Registered Then + // Check if JID Server is in Group Server + // Or it's Default User Server + if jidOK { + // Check if JID Info is in Group Server + if jidInfo.Server == types.GroupServer { // Return JID as Group Server (@g.us) - return types.NewJID(jid, types.GroupServer) + return types.NewJID(phone, types.GroupServer) } + + // Return JID as Default User Server (@s.whatsapp.net) + return types.NewJID(phone, types.DefaultUserServer) } - // Return JID as Default User Server (@s.whatsapp.net) - return types.NewJID(jid, types.DefaultUserServer) + // Return Empty JID + return types.EmptyJID } -func WhatsAppDecomposeJID(jid string) string { - // Check if JID Contains '@' Symbol - if strings.ContainsRune(jid, '@') { - // Split JID Based on '@' Symbol +func WhatsAppDecomposeJID(phone string) string { + // Check if Phone Number Contains '@' Symbol + if strings.ContainsRune(phone, '@') { + // Split Phone Number Based on '@' Symbol // and Get Only The First Section Before The Symbol - buffers := strings.Split(jid, "@") - jid = buffers[0] + buffers := strings.Split(phone, "@") + phone = buffers[0] } - // Check if JID First Character is '+' Symbol - if jid[0] == '+' { - // Remove '+' Symbol from JID - jid = jid[1:] + // Check if Phone Number First Character is '+' Symbol + if phone[0] == '+' { + // Remove '+' Symbol from Phone Number + phone = phone[1:] } - return jid + return phone } func WhatsAppComposeStatus(jid string, rjid types.JID, isComposing bool, isAudio bool) { @@ -291,7 +318,10 @@ func WhatsAppSendText(jid string, rjid string, message string) (string, error) { } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, false) @@ -327,7 +357,10 @@ func WhatsAppSendLocation(jid string, rjid string, latitude float64, longitude f } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, false) @@ -366,7 +399,10 @@ func WhatsAppSendDocument(jid string, rjid string, fileBytes []byte, fileType st } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, false) @@ -418,7 +454,10 @@ func WhatsAppSendImage(jid string, rjid string, imageBytes []byte, imageType str } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, false) @@ -538,7 +577,10 @@ func WhatsAppSendAudio(jid string, rjid string, audioBytes []byte, audioType str } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, true) @@ -588,7 +630,10 @@ func WhatsAppSendVideo(jid string, rjid string, videoBytes []byte, videoType str } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, false) @@ -640,7 +685,10 @@ func WhatsAppSendContact(jid string, rjid string, contactName string, contactNum } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, false) @@ -681,7 +729,10 @@ func WhatsAppSendLink(jid string, rjid string, linkCaption string, linkURL strin } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, false) @@ -734,7 +785,10 @@ func WhatsAppSendSticker(jid string, rjid string, stickerBytes []byte) (string, } // Make Sure Remote JID is Proper JID Type - remoteJID := WhatsAppComposeJID(rjid) + remoteJID := WhatsAppComposeJID(jid, rjid) + if remoteJID.IsEmpty() { + return "", errors.New("Phone Number is Not Registered") + } // Set Chat Presence WhatsAppComposeStatus(jid, remoteJID, true, false)