From 74a4011bf6312fab7fc028de13761aa7858accef Mon Sep 17 00:00:00 2001 From: Dimas Restu H Date: Thu, 21 Mar 2024 09:57:05 +0700 Subject: [PATCH] add feature message react --- docs/docs.go | 48 ++++++++++++++++++++++++ docs/swagger.json | 48 ++++++++++++++++++++++++ docs/swagger.yaml | 31 ++++++++++++++++ go.mod | 3 +- go.sum | 2 + internal/route.go | 1 + internal/whatsapp/types/request.go | 1 + internal/whatsapp/whatsapp.go | 42 +++++++++++++++++++++ pkg/whatsapp/whatsapp.go | 59 ++++++++++++++++++++++++++++++ 9 files changed, 234 insertions(+), 1 deletion(-) diff --git a/docs/docs.go b/docs/docs.go index d5d3296..fb72c30 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -318,6 +318,54 @@ const docTemplate = `{ } } }, + "/message/react": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "React Message to Spesific WhatsApp Personal ID or Group ID", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp Message" + ], + "summary": "React Message", + "parameters": [ + { + "type": "string", + "description": "Destination WhatsApp Personal ID or Group ID", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Message ID", + "name": "messageid", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Reaction Emoji", + "name": "emoji", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, "/registered": { "get": { "security": [ diff --git a/docs/swagger.json b/docs/swagger.json index 1673ae9..99cd3eb 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -309,6 +309,54 @@ } } }, + "/message/react": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "React Message to Spesific WhatsApp Personal ID or Group ID", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp Message" + ], + "summary": "React Message", + "parameters": [ + { + "type": "string", + "description": "Destination WhatsApp Personal ID or Group ID", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Message ID", + "name": "messageid", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Reaction Emoji", + "name": "emoji", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, "/registered": { "get": { "security": [ diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 886d5fa..d1db7c8 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -192,6 +192,37 @@ paths: summary: Update Message tags: - WhatsApp Message + /message/react: + post: + consumes: + - multipart/form-data + description: React Message to Spesific WhatsApp Personal ID or Group ID + parameters: + - description: Destination WhatsApp Personal ID or Group ID + in: formData + name: msisdn + required: true + type: string + - description: Message ID + in: formData + name: messageid + required: true + type: string + - description: Reaction Emoji + in: formData + name: emoji + required: true + type: string + produces: + - application/json + responses: + "200": + description: "" + security: + - BearerAuth: [] + summary: React Message + tags: + - WhatsApp Message /registered: get: description: Check WhatsApp Personal ID is Registered diff --git a/go.mod b/go.mod index 3cefffb..85f1ae6 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,14 @@ go 1.21 require ( github.com/PuerkitoBio/goquery v1.9.1 github.com/SporkHubr/echo-http-cache v0.0.0-20200706100054-1d7ae9f38029 + github.com/forPelevin/gomoji v1.1.8 github.com/go-playground/validator/v10 v10.19.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/joho/godotenv v1.5.1 github.com/labstack/echo/v4 v4.11.4 github.com/lib/pq v1.10.9 github.com/nickalie/go-webpbin v0.0.0-20220110095747-f10016bf2dc1 + github.com/rivo/uniseg v0.4.4 github.com/robfig/cron/v3 v3.0.1 github.com/sirupsen/logrus v1.9.3 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e @@ -60,7 +62,6 @@ require ( github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect - github.com/rivo/uniseg v0.4.4 // indirect github.com/rs/zerolog v1.32.0 // indirect github.com/sunshineplan/pdf v1.0.7 // indirect github.com/swaggo/files/v2 v2.0.0 // indirect diff --git a/go.sum b/go.sum index 6aab5b2..6a03b90 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/forPelevin/gomoji v1.1.8 h1:JElzDdt0TyiUlecy6PfITDL6eGvIaxqYH1V52zrd0qQ= +github.com/forPelevin/gomoji v1.1.8/go.mod h1:8+Z3KNGkdslmeGZBC3tCrwMrcPy5GRzAD+gL9NAwMXg= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/internal/route.go b/internal/route.go index 996bc9b..6cd6256 100644 --- a/internal/route.go +++ b/internal/route.go @@ -63,5 +63,6 @@ func Routes(e *echo.Echo) { e.POST(router.BaseURL+"/send/poll", ctlWhatsApp.SendPoll, middleware.JWTWithConfig(authJWTConfig)) e.POST(router.BaseURL+"/message/edit", ctlWhatsApp.MessageEdit, middleware.JWTWithConfig(authJWTConfig)) + e.POST(router.BaseURL+"/message/react", ctlWhatsApp.MessageEdit, middleware.JWTWithConfig(authJWTConfig)) e.POST(router.BaseURL+"/message/delete", ctlWhatsApp.MessageDelete, middleware.JWTWithConfig(authJWTConfig)) } diff --git a/internal/whatsapp/types/request.go b/internal/whatsapp/types/request.go index 5bf6218..f2011ee 100644 --- a/internal/whatsapp/types/request.go +++ b/internal/whatsapp/types/request.go @@ -39,6 +39,7 @@ type RequestMessage struct { RJID string MSGID string Message string + Emoji string } type RequestGroupJoin struct { diff --git a/internal/whatsapp/whatsapp.go b/internal/whatsapp/whatsapp.go index 6621f1e..4d869f3 100644 --- a/internal/whatsapp/whatsapp.go +++ b/internal/whatsapp/whatsapp.go @@ -701,6 +701,48 @@ func MessageEdit(c echo.Context) error { return router.ResponseSuccessWithData(c, "Successfully Update Message", resSendMessage) } +// MessageReact +// @Summary React Message +// @Description React Message to Spesific WhatsApp Personal ID or Group ID +// @Tags WhatsApp Message +// @Accept multipart/form-data +// @Produce json +// @Param msisdn formData string true "Destination WhatsApp Personal ID or Group ID" +// @Param messageid formData string true "Message ID" +// @Param emoji formData string true "Reaction Emoji" +// @Success 200 +// @Security BearerAuth +// @Router /message/react [post] +func MessageReact(c echo.Context) error { + var err error + jid := jwtPayload(c).JID + + var reqMessageUpdate typWhatsApp.RequestMessage + reqMessageUpdate.RJID = strings.TrimSpace(c.FormValue("msisdn")) + reqMessageUpdate.MSGID = strings.TrimSpace(c.FormValue("messageid")) + reqMessageUpdate.Emoji = strings.TrimSpace(c.FormValue("emoji")) + + if len(reqMessageUpdate.RJID) == 0 { + return router.ResponseBadRequest(c, "Missing Form Value MSISDN") + } + + if len(reqMessageUpdate.MSGID) == 0 { + return router.ResponseBadRequest(c, "Missing Form Value Message ID") + } + + if len(reqMessageUpdate.Emoji) == 0 { + return router.ResponseBadRequest(c, "Missing Form Value Emoji") + } + + var resSendMessage typWhatsApp.ResponseSendMessage + resSendMessage.MsgID, err = pkgWhatsApp.WhatsAppMessageReact(c.Request().Context(), jid, reqMessageUpdate.RJID, reqMessageUpdate.MSGID, reqMessageUpdate.Emoji) + if err != nil { + return router.ResponseInternalError(c, err.Error()) + } + + return router.ResponseSuccessWithData(c, "Successfully React Message", resSendMessage) +} + // MessageDelete // @Summary Delete Message // @Description Delete Message to Spesific WhatsApp Personal ID or Group ID diff --git a/pkg/whatsapp/whatsapp.go b/pkg/whatsapp/whatsapp.go index 902a913..8b8daff 100644 --- a/pkg/whatsapp/whatsapp.go +++ b/pkg/whatsapp/whatsapp.go @@ -9,9 +9,12 @@ import ( "net/http" "runtime" "strings" + "time" "github.com/PuerkitoBio/goquery" + "github.com/forPelevin/gomoji" webp "github.com/nickalie/go-webpbin" + "github.com/rivo/uniseg" "github.com/sunshineplan/imgconv" qrCode "github.com/skip2/go-qrcode" @@ -1165,6 +1168,62 @@ func WhatsAppMessageEdit(ctx context.Context, jid string, rjid string, msgid str return "", errors.New("WhatsApp Client is not Valid") } +func WhatsAppMessageReact(ctx context.Context, jid string, rjid string, msgid string, emoji string) (string, error) { + if WhatsAppClient[jid] != nil { + var err error + + // Make Sure WhatsApp Client is OK + err = WhatsAppIsClientOK(jid) + if err != nil { + return "", err + } + + // Make Sure WhatsApp ID is Registered + remoteJID, err := WhatsAppCheckJID(jid, rjid) + if err != nil { + return "", err + } + + // Set Chat Presence + WhatsAppPresence(jid, true) + WhatsAppComposeStatus(jid, remoteJID, true, false) + defer func() { + WhatsAppComposeStatus(jid, remoteJID, false, false) + WhatsAppPresence(jid, false) + }() + + // Check Emoji Must Be Contain Only 1 Emoji Character + if !gomoji.ContainsEmoji(emoji) && uniseg.GraphemeClusterCount(emoji) == 1 { + return "", errors.New("WhatsApp Message React Emoji Must Be Contain Only 1 Emoji Character") + } + + // Compose WhatsApp Proto + msgReact := &waproto.Message{ + ReactionMessage: &waproto.ReactionMessage{ + Key: &waproto.MessageKey{ + FromMe: proto.Bool(true), + Id: proto.String(msgid), + RemoteJid: proto.String(remoteJID.String()), + }, + Text: proto.String(emoji), + SenderTimestampMs: proto.Int64(time.Now().UnixMilli()), + }, + } + + // Send WhatsApp Message Proto + _, err = WhatsAppClient[jid].SendMessage(ctx, remoteJID, msgReact) + if err != nil { + return "", err + } + + return msgid, nil + } + + // Return Error WhatsApp Client is not Valid + return "", errors.New("WhatsApp Client is not Valid") + +} + func WhatsAppMessageDelete(ctx context.Context, jid string, rjid string, msgid string) error { if WhatsAppClient[jid] != nil { var err error