diff --git a/README.md b/README.md index bc1bd5f..f3f5013 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ The build result will shown in build directory You can access any endpoint under **BASE_URL** environment variable which by default located at *.env* file. +Integrated API Documentation can be accessed in **BASE_URL**/docs/index.html or by default it's in `127.0.0.1:3000/api/v1/whatsapp/docs/index.html` + ## Built With * [Go](https://golang.org/) - Go Programming Languange diff --git a/docs/docs.go b/docs/docs.go index bd12b37..ea1abee 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -23,9 +23,6 @@ const docTemplate = `{ "/api/v1/whatsapp": { "get": { "description": "Get The Server Status", - "consumes": [ - "*/*" - ], "produces": [ "application/json" ], @@ -48,9 +45,6 @@ const docTemplate = `{ } ], "description": "Get Authentication Token", - "consumes": [ - "*/*" - ], "produces": [ "application/json" ], @@ -74,7 +68,7 @@ const docTemplate = `{ ], "description": "Get QR Code for WhatsApp Multi-Device Login", "consumes": [ - "*/*" + "multipart/form-data" ], "produces": [ "application/json", @@ -94,7 +88,7 @@ const docTemplate = `{ "default": "html", "description": "Change Output Format in HTML or JSON", "name": "output", - "in": "query" + "in": "formData" } ], "responses": { @@ -112,8 +106,30 @@ const docTemplate = `{ } ], "description": "Make Device Logout from WhatsApp Multi-Device", + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Logout Device from WhatsApp Multi-Device", + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/audio": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Audio Message to Spesific Phone Number", "consumes": [ - "*/*" + "multipart/form-data" ], "produces": [ "application/json" @@ -121,7 +137,160 @@ const docTemplate = `{ "tags": [ "WhatsApp" ], - "summary": "Logout Device from WhatsApp Multi-Device", + "summary": "Send Audio Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Audio File", + "name": "audio", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/document": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Document Message to Spesific Phone Number", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Send Document Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Document File", + "name": "document", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/image": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Image Message to Spesific Phone Number", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Send Image Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Caption Image Message", + "name": "caption", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Image File", + "name": "image", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/location": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Location Message to Spesific Phone Number", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Send Location Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "number", + "description": "Location Latitude", + "name": "latitude", + "in": "formData", + "required": true + }, + { + "type": "number", + "description": "Location Longitude", + "name": "longitude", + "in": "formData", + "required": true + } + ], "responses": { "200": { "description": "" @@ -136,9 +305,9 @@ const docTemplate = `{ "BearerAuth": [] } ], - "description": "Make Device Logout from WhatsApp Multi-Device", + "description": "Send Text Message to Spesific Phone Number", "consumes": [ - "*/*" + "multipart/form-data" ], "produces": [ "application/json" @@ -146,20 +315,68 @@ const docTemplate = `{ "tags": [ "WhatsApp" ], - "summary": "Logout Device from WhatsApp Multi-Device", + "summary": "Send Text Message", "parameters": [ { "type": "string", "description": "Destination Phone Number", "name": "msisdn", - "in": "query", + "in": "formData", "required": true }, { "type": "string", - "description": "Text Message Content", + "description": "Text Message", "name": "message", - "in": "query", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/video": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Video Message to Spesific Phone Number", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Send Video Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Caption Video Message", + "name": "caption", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Video File", + "name": "video", + "in": "formData", "required": true } ], diff --git a/docs/swagger.json b/docs/swagger.json index bce5654..fad08c2 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -18,9 +18,6 @@ "/api/v1/whatsapp": { "get": { "description": "Get The Server Status", - "consumes": [ - "*/*" - ], "produces": [ "application/json" ], @@ -43,9 +40,6 @@ } ], "description": "Get Authentication Token", - "consumes": [ - "*/*" - ], "produces": [ "application/json" ], @@ -69,7 +63,7 @@ ], "description": "Get QR Code for WhatsApp Multi-Device Login", "consumes": [ - "*/*" + "multipart/form-data" ], "produces": [ "application/json", @@ -89,7 +83,7 @@ "default": "html", "description": "Change Output Format in HTML or JSON", "name": "output", - "in": "query" + "in": "formData" } ], "responses": { @@ -107,8 +101,30 @@ } ], "description": "Make Device Logout from WhatsApp Multi-Device", + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Logout Device from WhatsApp Multi-Device", + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/audio": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Audio Message to Spesific Phone Number", "consumes": [ - "*/*" + "multipart/form-data" ], "produces": [ "application/json" @@ -116,7 +132,160 @@ "tags": [ "WhatsApp" ], - "summary": "Logout Device from WhatsApp Multi-Device", + "summary": "Send Audio Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Audio File", + "name": "audio", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/document": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Document Message to Spesific Phone Number", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Send Document Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Document File", + "name": "document", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/image": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Image Message to Spesific Phone Number", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Send Image Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Caption Image Message", + "name": "caption", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Image File", + "name": "image", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/location": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Location Message to Spesific Phone Number", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Send Location Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "number", + "description": "Location Latitude", + "name": "latitude", + "in": "formData", + "required": true + }, + { + "type": "number", + "description": "Location Longitude", + "name": "longitude", + "in": "formData", + "required": true + } + ], "responses": { "200": { "description": "" @@ -131,9 +300,9 @@ "BearerAuth": [] } ], - "description": "Make Device Logout from WhatsApp Multi-Device", + "description": "Send Text Message to Spesific Phone Number", "consumes": [ - "*/*" + "multipart/form-data" ], "produces": [ "application/json" @@ -141,20 +310,68 @@ "tags": [ "WhatsApp" ], - "summary": "Logout Device from WhatsApp Multi-Device", + "summary": "Send Text Message", "parameters": [ { "type": "string", "description": "Destination Phone Number", "name": "msisdn", - "in": "query", + "in": "formData", "required": true }, { "type": "string", - "description": "Text Message Content", + "description": "Text Message", "name": "message", - "in": "query", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "" + } + } + } + }, + "/api/v1/whatsapp/send/video": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Send Video Message to Spesific Phone Number", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "WhatsApp" + ], + "summary": "Send Video Message", + "parameters": [ + { + "type": "string", + "description": "Destination Phone Number", + "name": "msisdn", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Caption Video Message", + "name": "caption", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Video File", + "name": "video", + "in": "formData", "required": true } ], diff --git a/docs/swagger.yaml b/docs/swagger.yaml index ee83633..dcf8400 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -10,8 +10,6 @@ info: paths: /api/v1/whatsapp: get: - consumes: - - '*/*' description: Get The Server Status produces: - application/json @@ -23,8 +21,6 @@ paths: - Root /api/v1/whatsapp/auth: get: - consumes: - - '*/*' description: Get Authentication Token produces: - application/json @@ -39,7 +35,7 @@ paths: /api/v1/whatsapp/login: post: consumes: - - '*/*' + - multipart/form-data description: Get QR Code for WhatsApp Multi-Device Login parameters: - default: html @@ -47,7 +43,7 @@ paths: enum: - html - json - in: query + in: formData name: output type: string produces: @@ -63,8 +59,6 @@ paths: - WhatsApp /api/v1/whatsapp/logout: post: - consumes: - - '*/*' description: Make Device Logout from WhatsApp Multi-Device produces: - application/json @@ -76,19 +70,133 @@ paths: summary: Logout Device from WhatsApp Multi-Device tags: - WhatsApp + /api/v1/whatsapp/send/audio: + post: + consumes: + - multipart/form-data + description: Send Audio Message to Spesific Phone Number + parameters: + - description: Destination Phone Number + in: formData + name: msisdn + required: true + type: string + - description: Audio File + in: formData + name: audio + required: true + type: file + produces: + - application/json + responses: + "200": + description: "" + security: + - BearerAuth: [] + summary: Send Audio Message + tags: + - WhatsApp + /api/v1/whatsapp/send/document: + post: + consumes: + - multipart/form-data + description: Send Document Message to Spesific Phone Number + parameters: + - description: Destination Phone Number + in: formData + name: msisdn + required: true + type: string + - description: Document File + in: formData + name: document + required: true + type: file + produces: + - application/json + responses: + "200": + description: "" + security: + - BearerAuth: [] + summary: Send Document Message + tags: + - WhatsApp + /api/v1/whatsapp/send/image: + post: + consumes: + - multipart/form-data + description: Send Image Message to Spesific Phone Number + parameters: + - description: Destination Phone Number + in: formData + name: msisdn + required: true + type: string + - description: Caption Image Message + in: formData + name: caption + required: true + type: string + - description: Image File + in: formData + name: image + required: true + type: file + produces: + - application/json + responses: + "200": + description: "" + security: + - BearerAuth: [] + summary: Send Image Message + tags: + - WhatsApp + /api/v1/whatsapp/send/location: + post: + consumes: + - multipart/form-data + description: Send Location Message to Spesific Phone Number + parameters: + - description: Destination Phone Number + in: formData + name: msisdn + required: true + type: string + - description: Location Latitude + in: formData + name: latitude + required: true + type: number + - description: Location Longitude + in: formData + name: longitude + required: true + type: number + produces: + - application/json + responses: + "200": + description: "" + security: + - BearerAuth: [] + summary: Send Location Message + tags: + - WhatsApp /api/v1/whatsapp/send/text: post: consumes: - - '*/*' - description: Make Device Logout from WhatsApp Multi-Device + - multipart/form-data + description: Send Text Message to Spesific Phone Number parameters: - description: Destination Phone Number - in: query + in: formData name: msisdn required: true type: string - - description: Text Message Content - in: query + - description: Text Message + in: formData name: message required: true type: string @@ -99,7 +207,38 @@ paths: description: "" security: - BearerAuth: [] - summary: Logout Device from WhatsApp Multi-Device + summary: Send Text Message + tags: + - WhatsApp + /api/v1/whatsapp/send/video: + post: + consumes: + - multipart/form-data + description: Send Video Message to Spesific Phone Number + parameters: + - description: Destination Phone Number + in: formData + name: msisdn + required: true + type: string + - description: Caption Video Message + in: formData + name: caption + required: true + type: string + - description: Video File + in: formData + name: video + required: true + type: file + produces: + - application/json + responses: + "200": + description: "" + security: + - BearerAuth: [] + summary: Send Video Message tags: - WhatsApp schemes: diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 1db829b..4bf8924 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -17,7 +17,6 @@ import ( // @Summary Generate Authentication Token // @Description Get Authentication Token // @Tags Root -// @Accept */* // @Produce json // @Success 200 // @Security BasicAuth diff --git a/internal/index/index.go b/internal/index/index.go index 36e2523..596851d 100644 --- a/internal/index/index.go +++ b/internal/index/index.go @@ -10,7 +10,6 @@ import ( // @Summary Show The Status of The Server // @Description Get The Server Status // @Tags Root -// @Accept */* // @Produce json // @Success 200 // @Router /api/v1/whatsapp [get] diff --git a/internal/whatsapp/whatsapp.go b/internal/whatsapp/whatsapp.go index 8ee6cdb..731a9a1 100644 --- a/internal/whatsapp/whatsapp.go +++ b/internal/whatsapp/whatsapp.go @@ -44,10 +44,10 @@ func convertFileToBytes(file multipart.File) ([]byte, error) { // @Summary Generate QR Code for WhatsApp Multi-Device Login // @Description Get QR Code for WhatsApp Multi-Device Login // @Tags WhatsApp -// @Accept */* +// @Accept multipart/form-data // @Produce json // @Produce html -// @Param output query string false "Change Output Format in HTML or JSON" Enums(html, json) default(html) +// @Param output formData string false "Change Output Format in HTML or JSON" Enums(html, json) default(html) // @Success 200 // @Security BearerAuth // @Router /api/v1/whatsapp/login [post] @@ -108,7 +108,6 @@ func Login(c echo.Context) error { // @Summary Logout Device from WhatsApp Multi-Device // @Description Make Device Logout from WhatsApp Multi-Device // @Tags WhatsApp -// @Accept */* // @Produce json // @Success 200 // @Security BearerAuth @@ -126,13 +125,13 @@ func Logout(c echo.Context) error { } // SendText -// @Summary Logout Device from WhatsApp Multi-Device -// @Description Make Device Logout from WhatsApp Multi-Device +// @Summary Send Text Message +// @Description Send Text Message to Spesific Phone Number // @Tags WhatsApp -// @Accept */* +// @Accept multipart/form-data // @Produce json -// @Param msisdn query string true "Destination Phone Number" -// @Param message query string true "Text Message Content" +// @Param msisdn formData string true "Destination Phone Number" +// @Param message formData string true "Text Message" // @Success 200 // @Security BearerAuth // @Router /api/v1/whatsapp/send/text [post] @@ -157,6 +156,18 @@ func SendText(c echo.Context) error { return router.ResponseSuccessWithData(c, "Successfully Send Text Message", resSendMessage) } +// SendLocation +// @Summary Send Location Message +// @Description Send Location Message to Spesific Phone Number +// @Tags WhatsApp +// @Accept multipart/form-data +// @Produce json +// @Param msisdn formData string true "Destination Phone Number" +// @Param latitude formData number true "Location Latitude" +// @Param longitude formData number true "Location Longitude" +// @Success 200 +// @Security BearerAuth +// @Router /api/v1/whatsapp/send/location [post] func SendLocation(c echo.Context) error { var err error jid := jwtPayload(c).JID @@ -187,18 +198,64 @@ func SendLocation(c echo.Context) error { return router.ResponseSuccessWithData(c, "Successfully Send Location Message", resSendMessage) } +// SendDocument +// @Summary Send Document Message +// @Description Send Document Message to Spesific Phone Number +// @Tags WhatsApp +// @Accept multipart/form-data +// @Produce json +// @Param msisdn formData string true "Destination Phone Number" +// @Param document formData file true "Document File" +// @Success 200 +// @Security BearerAuth +// @Router /api/v1/whatsapp/send/document [post] func SendDocument(c echo.Context) error { return sendMedia(c, "document") } +// SendImage +// @Summary Send Image Message +// @Description Send Image Message to Spesific Phone Number +// @Tags WhatsApp +// @Accept multipart/form-data +// @Produce json +// @Param msisdn formData string true "Destination Phone Number" +// @Param caption formData string true "Caption Image Message" +// @Param image formData file true "Image File" +// @Success 200 +// @Security BearerAuth +// @Router /api/v1/whatsapp/send/image [post] func SendImage(c echo.Context) error { return sendMedia(c, "image") } +// SendAudio +// @Summary Send Audio Message +// @Description Send Audio Message to Spesific Phone Number +// @Tags WhatsApp +// @Accept multipart/form-data +// @Produce json +// @Param msisdn formData string true "Destination Phone Number" +// @Param audio formData file true "Audio File" +// @Success 200 +// @Security BearerAuth +// @Router /api/v1/whatsapp/send/audio [post] func SendAudio(c echo.Context) error { return sendMedia(c, "audio") } +// SendVideo +// @Summary Send Video Message +// @Description Send Video Message to Spesific Phone Number +// @Tags WhatsApp +// @Accept multipart/form-data +// @Produce json +// @Param msisdn formData string true "Destination Phone Number" +// @Param caption formData string true "Caption Video Message" +// @Param video formData file true "Video File" +// @Success 200 +// @Security BearerAuth +// @Router /api/v1/whatsapp/send/video [post] func SendVideo(c echo.Context) error { return sendMedia(c, "video") } diff --git a/pkg/whatsapp/whatsapp.go b/pkg/whatsapp/whatsapp.go index 9b17573..3b09002 100644 --- a/pkg/whatsapp/whatsapp.go +++ b/pkg/whatsapp/whatsapp.go @@ -174,29 +174,34 @@ func WhatsAppReconnect(jid string) error { func WhatsAppLogout(jid string) error { if WhatsAppClient[jid] != nil { - var err error - - // Set WhatsApp Client Presence to Unavailable - _ = WhatsAppClient[jid].SendPresence(types.PresenceUnavailable) + // Make Sure Store ID is not Empty + if WhatsAppClient[jid].Store.ID != nil { + var err error - // Logout WhatsApp Client and Disconnect from WebSocket - err = WhatsAppClient[jid].Logout() - if err != nil { - // Force Disconnect - WhatsAppClient[jid].Disconnect() + // Set WhatsApp Client Presence to Unavailable + _ = WhatsAppClient[jid].SendPresence(types.PresenceUnavailable) - // Manually Delete Device from Datastore Store - err = WhatsAppClient[jid].Store.Delete() + // Logout WhatsApp Client and Disconnect from WebSocket + err = WhatsAppClient[jid].Logout() if err != nil { - return err + // Force Disconnect + WhatsAppClient[jid].Disconnect() + + // Manually Delete Device from Datastore Store + err = WhatsAppClient[jid].Store.Delete() + if err != nil { + return err + } } - } - // Free WhatsApp Client Map - WhatsAppClient[jid] = nil - delete(WhatsAppClient, jid) + // Free WhatsApp Client Map + WhatsAppClient[jid] = nil + delete(WhatsAppClient, jid) - return nil + return nil + } + + return errors.New("WhatsApp Client Store ID is Empty, Please Re-Login and Scan QR Code Again") } // Return Error WhatsApp Client is not Valid