From aa2f10dd3bc6c29521c6b1841304ab08f5930fcf Mon Sep 17 00:00:00 2001 From: Aldino Kemal Date: Sun, 10 Mar 2024 21:39:02 +0700 Subject: [PATCH] feat: add send poll message --- readme.md | 12 ++++++++---- src/config/settings.go | 2 +- src/domains/send/poll.go | 8 ++++++++ src/domains/send/send.go | 1 + src/internal/rest/send.go | 19 +++++++++++++++++++ src/services/send.go | 20 ++++++++++++++++++++ src/validations/send_validation.go | 30 ++++++++++++++++++++++++++++++ 7 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 src/domains/send/poll.go diff --git a/readme.md b/readme.md index b914abc..e861f71 100644 --- a/readme.md +++ b/readme.md @@ -8,13 +8,15 @@ ![release linux](https://github.com/aldinokemal/go-whatsapp-web-multidevice/actions/workflows/release-linux.yml/badge.svg) ![release macos](https://github.com/aldinokemal/go-whatsapp-web-multidevice/actions/workflows/release-mac.yml/badge.svg) -### Support `ARM` Architecture -Now that we support ARM64 for Linux: -- [Release](https://github.com/aldinokemal/go-whatsapp-web-multidevice/releases/latest) for ARM64 -- [Docker Image](https://hub.docker.com/r/aldinokemal2104/go-whatsapp-web-multidevice/tags) for ARM64. +### Support `ARM` Architecture + +Now that we support ARM64 for Linux: +- [Release](https://github.com/aldinokemal/go-whatsapp-web-multidevice/releases/latest) for ARM64 +- [Docker Image](https://hub.docker.com/r/aldinokemal2104/go-whatsapp-web-multidevice/tags) for ARM64. ### Feature + - Send whatsapp via http API, [docs/openapi.yml](./docs/openapi.yaml) for more details - Compress image before send - Compress video before send @@ -84,6 +86,7 @@ Now that we support ARM64 for Linux: 7. open `http://localhost:3000` in browser ### Production Mode (docker) + ``` docker run --detach --publish=3000:3000 --name=whatsapp --restart=always --volume=$(docker volume create --name=whatsapp):/app/storages aldinokemal2104/go-whatsapp-web-multidevice --autoreply="Dont't reply this message please" ``` @@ -116,6 +119,7 @@ API using [openapi-generator](https://openapi-generator.tech/#try) | ✅ | Send Contact | POST | /send/contact | | ✅ | Send Link | POST | /send/link | | ✅ | Send Location | POST | /send/location | +| ✅ | Send Poll / Vote | POST | /send/poll | | ✅ | Revoke Message | POST | /message/:message_id/revoke | | ✅ | React Message | POST | /message/:message_id/react | | ✅ | Join Group With Link | POST | /group/join-with-link | diff --git a/src/config/settings.go b/src/config/settings.go index 9005d6c..2459a21 100644 --- a/src/config/settings.go +++ b/src/config/settings.go @@ -6,7 +6,7 @@ import ( ) var ( - AppVersion = "v4.10.0" + AppVersion = "v4.11.0" AppPort = "3000" AppDebug = false AppOs = fmt.Sprintf("AldinoKemal") diff --git a/src/domains/send/poll.go b/src/domains/send/poll.go new file mode 100644 index 0000000..09ba34b --- /dev/null +++ b/src/domains/send/poll.go @@ -0,0 +1,8 @@ +package send + +type PollRequest struct { + Phone string `json:"phone" form:"phone"` + Question string `json:"question" form:"question"` + Options []string `json:"options[]" form:"options[]"` + MaxAnswer int `json:"max_answer" form:"max_answer"` +} diff --git a/src/domains/send/send.go b/src/domains/send/send.go index c848050..0e270c2 100644 --- a/src/domains/send/send.go +++ b/src/domains/send/send.go @@ -13,6 +13,7 @@ type ISendService interface { SendLink(ctx context.Context, request LinkRequest) (response GenericResponse, err error) SendLocation(ctx context.Context, request LocationRequest) (response GenericResponse, err error) SendAudio(ctx context.Context, request AudioRequest) (response GenericResponse, err error) + SendPoll(ctx context.Context, request PollRequest) (response GenericResponse, err error) } type GenericResponse struct { diff --git a/src/internal/rest/send.go b/src/internal/rest/send.go index a27cfbe..e0eb827 100644 --- a/src/internal/rest/send.go +++ b/src/internal/rest/send.go @@ -21,6 +21,7 @@ func InitRestSend(app *fiber.App, service domainSend.ISendService) Send { app.Post("/send/link", rest.SendLink) app.Post("/send/location", rest.SendLocation) app.Post("/send/audio", rest.SendAudio) + app.Post("/send/poll", rest.SendPoll) return rest } @@ -185,3 +186,21 @@ func (controller *Send) SendAudio(c *fiber.Ctx) error { Results: response, }) } + +func (controller *Send) SendPoll(c *fiber.Ctx) error { + var request domainSend.PollRequest + err := c.BodyParser(&request) + utils.PanicIfNeeded(err) + + whatsapp.SanitizePhone(&request.Phone) + + response, err := controller.Service.SendPoll(c.UserContext(), request) + utils.PanicIfNeeded(err) + + return c.JSON(utils.ResponseData{ + Status: 200, + Code: "SUCCESS", + Message: response.Status, + Results: response, + }) +} diff --git a/src/services/send.go b/src/services/send.go index 57b04c7..6ad4006 100644 --- a/src/services/send.go +++ b/src/services/send.go @@ -457,3 +457,23 @@ func (service serviceSend) SendAudio(ctx context.Context, request domainSend.Aud response.Status = fmt.Sprintf("Send audio success %s (server timestamp: %s)", request.Phone, ts.Timestamp.String()) return response, nil } + +func (service serviceSend) SendPoll(ctx context.Context, request domainSend.PollRequest) (response domainSend.GenericResponse, err error) { + err = validations.ValidateSendPoll(ctx, request) + if err != nil { + return response, err + } + dataWaRecipient, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.Phone) + if err != nil { + return response, err + } + + ts, err := service.WaCli.SendMessage(ctx, dataWaRecipient, service.WaCli.BuildPollCreation(request.Question, request.Options, request.MaxAnswer)) + if err != nil { + return response, err + } + + response.MessageID = ts.ID + response.Status = fmt.Sprintf("Send poll success %s (server timestamp: %s)", request.Phone, ts.Timestamp.String()) + return response, nil +} diff --git a/src/validations/send_validation.go b/src/validations/send_validation.go index 344589c..137704c 100644 --- a/src/validations/send_validation.go +++ b/src/validations/send_validation.go @@ -175,3 +175,33 @@ func ValidateSendAudio(ctx context.Context, request domainSend.AudioRequest) err return nil } + +func ValidateSendPoll(ctx context.Context, request domainSend.PollRequest) error { + err := validation.ValidateStructWithContext(ctx, &request, + validation.Field(&request.Phone, validation.Required), + validation.Field(&request.Question, validation.Required), + + validation.Field(&request.Options, validation.Required), + validation.Field(&request.Options, validation.Each(validation.Required)), + + validation.Field(&request.MaxAnswer, validation.Required), + validation.Field(&request.MaxAnswer, validation.Min(1)), + validation.Field(&request.MaxAnswer, validation.Max(len(request.Options))), + ) + + if err != nil { + return pkgError.ValidationError(err.Error()) + } + + // validate options should be unique each other + uniqueOptions := make(map[string]bool) + for _, option := range request.Options { + if _, ok := uniqueOptions[option]; ok { + return pkgError.ValidationError("options should be unique") + } + uniqueOptions[option] = true + } + + return nil + +}