From 3df6f896fce8fd2262194917e612e84716f4afb5 Mon Sep 17 00:00:00 2001 From: Aldino Kemal Date: Thu, 7 Jul 2022 08:08:20 +0700 Subject: [PATCH] feat: add send contact (#18) * feat: add send contact backend service * feat: add UI for send contact * chore: update docs * chore: update openapi & upgrade app version --- docs/openapi.yaml | 96 ++++++++++++++ readme.md | 5 +- src/config/settings.go | 2 +- src/controllers/send_controller.go | 25 ++++ src/services/send_service.go | 1 + src/services/send_service_impl.go | 22 ++++ src/structs/send_struct.go | 11 ++ src/validations/send_validation.go | 14 ++ src/views/index.html | 197 +++++++++++++++++++++++------ 9 files changed, 334 insertions(+), 39 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 69f745d..febf58e 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -791,4 +791,100 @@ paths: code: 500 message: you are not loggin results: null + /send/contact: + post: + tags: + - send + summary: Send Contact + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + phone: + type: integer + example: '6289685024051' + contact_name: + type: string + example: Aldino Kemal + contact_phone: + type: string + example: '6289685024992' + type: + type: string + example: 'user' + description: 'user/group | default: user' + responses: + '200': + description: OK + headers: + Date: + schema: + type: string + example: Fri, 11 Feb 2022 03:42:57 GMT + Content-Type: + schema: + type: string + example: application/json + Content-Length: + schema: + type: integer + example: '123' + content: + application/json: + schema: + type: object + example: + code: 200 + message: Success + results: + status: >- + Contact sent to 6289685024051@s.whatsapp.net (server timestamp: 2022-05-17 14:39:29 +0700 WIB) + '400': + description: Bad Request + headers: + Date: + schema: + type: string + example: Fri, 11 Feb 2022 03:02:17 GMT + Content-Type: + schema: + type: string + example: application/json + Content-Length: + schema: + type: integer + example: '70' + content: + application/json: + schema: + type: object + example: + code: 400 + message: 'phone: cannot be blank.' + results: null + '500': + description: Internal Server Error + headers: + Date: + schema: + type: string + example: Fri, 11 Feb 2022 03:02:48 GMT + Content-Type: + schema: + type: string + example: application/json + Content-Length: + schema: + type: integer + example: '58' + content: + application/json: + schema: + type: object + example: + code: 500 + message: you are not loggin + results: null diff --git a/readme.md b/readme.md index 45cb5e6..bf6fd98 100644 --- a/readme.md +++ b/readme.md @@ -82,7 +82,7 @@ You can check [docs/openapi.yml](./docs/openapi.yaml) for detail API | ✅ | Send Image | POST | /send/image | | ✅ | Send File | POST | /send/file | | ✅ | Send Video | POST | /send/video | -| ❌ | Send Contact | POST | /send/contact | +| ✅ | Send Contact | POST | /send/contact | ``` ✅ = Available @@ -91,12 +91,13 @@ You can check [docs/openapi.yml](./docs/openapi.yaml) for detail API ### App User Interface -1. Homepage ![Homepage](https://i.ibb.co/nCK9w1W/Screen-Shot-2022-05-22-at-13-39-28.png) +1. Homepage ![Homepage](https://i.ibb.co/ScYLjw8/Screen-Shot-2022-07-07-at-07-57-46.png) 2. Login ![Login](https://i.ibb.co/Yp3YJKM/Screen-Shot-2022-02-13-at-12-55-54.png) 3. Send Message ![Send Message](https://i.ibb.co/Bng57Ry/Screen-Shot-2022-05-22-at-13-51-13.png) 4. Send Image ![Send Image](https://i.ibb.co/gJj3SrQ/Screen-Shot-2022-05-22-at-13-49-21.png) 5. Send File ![Send File](https://i.ibb.co/nCwhysd/Screen-Shot-2022-05-22-at-13-43-16.png) 6. Send Video ![Send File](https://i.ibb.co/yBXsWXX/Screen-Shot-2022-05-22-at-13-43-24.png) +6. Send Contact ![Send File](https://i.ibb.co/fqwwGK5/Screen-Shot-2022-07-07-at-07-59-26.png) 7. User Info ![User Info](https://i.ibb.co/BC0mNT7/Screen-Shot-2022-02-13-at-13-00-57.png) 8. User Avatar ![User Avatar](https://i.ibb.co/TkzPbLZ/Screen-Shot-2022-02-13-at-13-01-39.png) 9. User Privacy ![User My Privacy](https://i.ibb.co/RQcC5m9/Screen-Shot-2022-02-13-at-12-58-47.png) diff --git a/src/config/settings.go b/src/config/settings.go index 04049fd..15cd319 100644 --- a/src/config/settings.go +++ b/src/config/settings.go @@ -3,7 +3,7 @@ package config type Browser string var ( - AppVersion string = "3.3.1" + AppVersion string = "3.4.0" AppPort string = "3000" AppDebug bool = false diff --git a/src/controllers/send_controller.go b/src/controllers/send_controller.go index a7c28a1..80be317 100644 --- a/src/controllers/send_controller.go +++ b/src/controllers/send_controller.go @@ -21,6 +21,7 @@ func (controller *SendController) Route(app *fiber.App) { app.Post("/send/image", controller.SendImage) app.Post("/send/file", controller.SendFile) app.Post("/send/video", controller.SendVideo) + app.Post("/send/contact", controller.SendContact) } func (controller *SendController) SendText(c *fiber.Ctx) error { @@ -135,3 +136,27 @@ func (controller *SendController) SendVideo(c *fiber.Ctx) error { Results: response, }) } + +func (controller SendController) SendContact(c *fiber.Ctx) error { + var request structs.SendContactRequest + err := c.BodyParser(&request) + utils.PanicIfNeeded(err) + + // add validation send contect + validations.ValidateSendContact(request) + + if request.Type == structs.TypeGroup { + request.Phone = request.Phone + "@g.us" + } else { + request.Phone = request.Phone + "@s.whatsapp.net" + } + + response, err := controller.Service.SendContact(c, request) + utils.PanicIfNeeded(err) + + return c.JSON(utils.ResponseData{ + Code: 200, + Message: response.Status, + Results: response, + }) +} diff --git a/src/services/send_service.go b/src/services/send_service.go index 0ad41dc..f28dd0c 100644 --- a/src/services/send_service.go +++ b/src/services/send_service.go @@ -10,4 +10,5 @@ type SendService interface { SendImage(c *fiber.Ctx, request structs.SendImageRequest) (response structs.SendImageResponse, err error) SendFile(c *fiber.Ctx, request structs.SendFileRequest) (response structs.SendFileResponse, err error) SendVideo(c *fiber.Ctx, request structs.SendVideoRequest) (response structs.SendVideoResponse, err error) + SendContact(c *fiber.Ctx, request structs.SendContactRequest) (response structs.SendContactResponse, err error) } diff --git a/src/services/send_service_impl.go b/src/services/send_service_impl.go index ef390f7..0476f0f 100644 --- a/src/services/send_service_impl.go +++ b/src/services/send_service_impl.go @@ -286,3 +286,25 @@ func (service SendServiceImpl) SendVideo(c *fiber.Ctx, request structs.SendVideo return response, nil } } + +func (service SendServiceImpl) SendContact(_ *fiber.Ctx, request structs.SendContactRequest) (response structs.SendContactResponse, err error) { + utils.MustLogin(service.WaCli) + + recipient, ok := utils.ParseJID(request.Phone) + if !ok { + return response, errors.New("invalid JID " + request.Phone) + } + msgVCard := fmt.Sprintf("BEGIN:VCARD\nVERSION:3.0\nN:;%v;;;\nFN:%v\nTEL;type=CELL;waid=%v:+%v\nEND:VCARD", + request.ContactName, request.ContactName, request.ContactPhone, request.ContactPhone) + msg := &waProto.Message{ContactMessage: &waProto.ContactMessage{ + DisplayName: proto.String(request.ContactName), + Vcard: proto.String(msgVCard), + }} + ts, err := service.WaCli.SendMessage(recipient, "", msg) + if err != nil { + return response, err + } else { + response.Status = fmt.Sprintf("Contact sent to %s (server timestamp: %s)", request.Phone, ts) + } + return response, nil +} diff --git a/src/structs/send_struct.go b/src/structs/send_struct.go index 980ee49..85484ee 100644 --- a/src/structs/send_struct.go +++ b/src/structs/send_struct.go @@ -54,3 +54,14 @@ type SendVideoRequest struct { type SendVideoResponse struct { Status string `json:"status"` } + +type SendContactRequest struct { + Phone string `json:"phone" form:"phone"` + ContactName string `json:"contact_name" form:"contact_name"` + ContactPhone string `json:"contact_phone" form:"contact_phone"` + Type SendType `json:"type" form:"type"` +} + +type SendContactResponse struct { + Status string `json:"status"` +} diff --git a/src/validations/send_validation.go b/src/validations/send_validation.go index d479fce..6117bb2 100644 --- a/src/validations/send_validation.go +++ b/src/validations/send_validation.go @@ -99,3 +99,17 @@ func ValidateSendVideo(request structs.SendVideoRequest) { }) } } + +func ValidateSendContact(request structs.SendContactRequest) { + err := validation.ValidateStruct(&request, + validation.Field(&request.Phone, validation.Required, validation.Length(10, 25)), + validation.Field(&request.ContactName, validation.Required), + validation.Field(&request.ContactPhone, validation.Required), + ) + + if err != nil { + panic(utils.ValidationError{ + Message: err.Error(), + }) + } +} diff --git a/src/views/index.html b/src/views/index.html index 45f19de..1430a60 100644 --- a/src/views/index.html +++ b/src/views/index.html @@ -27,6 +27,11 @@

[[ app_name ]]

Features

+ +
+ App +
+
@@ -55,42 +60,11 @@
-
-
-
-
User Info
-
- You can search someone user info by phone -
-
-
-
-
-
User Avatar
-
- You can search someone avatar by phone -
-
-
-
-
-
User List Groups
-
- Display all groups you joined -
-
-
-
-
-
User Privacy Setting
-
- Get your privacy settings -
-
-
+
+ Send Private Message
-
+
Private @@ -133,9 +107,22 @@
+
+
+ Contact +
Send Contact
+
+ Send contact to any whatsapp number +
+
+
-
+
+ Send Group Message +
+ +
Group @@ -178,6 +165,54 @@
+
+
+ Contact +
Send Contact
+
+ Send contact to any whatsapp number +
+
+
+
+ +
+ User +
+ +
+
+
+
User Info
+
+ You can search someone user info by phone +
+
+
+
+
+
User Avatar
+
+ You can search someone avatar by phone +
+
+
+
+
+
User List Groups
+
+ Display all groups you joined +
+
+
+
+
+
User Privacy Setting
+
+ Get your privacy settings +
+
+
@@ -369,6 +404,39 @@
+ + +