From fb28568b694bae2fbbae6910a6db40bf75adc297 Mon Sep 17 00:00:00 2001 From: Aldino Kemal Date: Fri, 5 May 2023 08:31:48 +0700 Subject: [PATCH] feat: add ui leave group --- docs/openapi.yaml | 38 +++++++++++++++++++++++-- src/domains/group/group.go | 6 ++-- src/go.sum | 7 ----- src/internal/rest/group.go | 20 ++++++++++++- src/pkg/whatsapp/whatsapp.go | 4 +-- src/services/group.go | 14 +++++++-- src/validations/group_validation.go | 32 +++++++++++++++++++++ src/views/index.html | 44 ++++++++++++++++++++++++++--- 8 files changed, 143 insertions(+), 22 deletions(-) create mode 100644 src/validations/group_validation.go diff --git a/docs/openapi.yaml b/docs/openapi.yaml index e94224b..155a5dd 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: title: WhatsApp API MultiDevice - version: 3.5.0 + version: 3.6.0 description: This API is used for sending whatsapp via API servers: - url: http://localhost:3000 @@ -627,6 +627,40 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorInternalServer' + /group/leave: + post: + operationId: leaveGroup + tags: + - group + summary: Leave group + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + group_id: + type: string + example: '120363024512399999@g.us' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GenericResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBadRequest' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorInternalServer' components: schemas: @@ -854,7 +888,7 @@ components: description: 'HTTP Status Code' message: type: string - example: phone cannot be blank + example: field cannot be blank description: 'Detail error message' results: type: object diff --git a/src/domains/group/group.go b/src/domains/group/group.go index a562b02..33a6c9b 100644 --- a/src/domains/group/group.go +++ b/src/domains/group/group.go @@ -4,13 +4,13 @@ import "context" type IGroupService interface { JoinGroupWithLink(ctx context.Context, request JoinGroupWithLinkRequest) (groupID string, err error) - LeaveGroup(ctx context.Context, groupID string) (err error) + LeaveGroup(ctx context.Context, request LeaveGroupRequest) (err error) } type JoinGroupWithLinkRequest struct { Link string `json:"link" form:"link"` } -type JoinGroupWithLinkResponse struct { - JID string `json:"jid"` +type LeaveGroupRequest struct { + GroupID string `json:"group_id" form:"group_id"` } diff --git a/src/go.sum b/src/go.sum index fe5d91c..883a3a3 100644 --- a/src/go.sum +++ b/src/go.sum @@ -120,8 +120,6 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= -github.com/fasthttp/websocket v1.5.2 h1:KdCb0EpLpdJpfE3IPA5YLK/aYBO3dhZcvwxz6tXe2LQ= -github.com/fasthttp/websocket v1.5.2/go.mod h1:S0KC1VBlx1SaXGXq7yi1wKz4jMub58qEnHQG9oHuqBw= github.com/fasthttp/websocket v1.5.3 h1:TPpQuLwJYfd4LJPXvHDYPMFWbLjsT91n3GpWtCQtdek= github.com/fasthttp/websocket v1.5.3/go.mod h1:46gg/UBmTU1kUaTcwQXpUxtRwG2PvIZYeA8oL6vF3Fs= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -409,8 +407,6 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.45.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= -github.com/valyala/fasthttp v1.46.0 h1:6ZRhrFg8zBXTRYY6vdzbFhqsBd7FVv123pV2m9V87U4= -github.com/valyala/fasthttp v1.46.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c= github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= @@ -428,8 +424,6 @@ go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3 go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= go.mau.fi/libsignal v0.1.0 h1:vAKI/nJ5tMhdzke4cTK1fb0idJzz1JuEIpmjprueC+c= go.mau.fi/libsignal v0.1.0/go.mod h1:R8ovrTezxtUNzCQE5PH30StOQWWeBskBsWE55vMfY9I= -go.mau.fi/whatsmeow v0.0.0-20230421200254-eb71a6b59083 h1:9m92f4MviAPv/PQgLZ7AO0E15goh/4B8uzvS3kyDpeg= -go.mau.fi/whatsmeow v0.0.0-20230421200254-eb71a6b59083/go.mod h1:+ObGpFE6cbbY4hKc1FmQH9MVfqaemmlXGXSnwDvCOyE= go.mau.fi/whatsmeow v0.0.0-20230427180258-7f679583b39b h1:VSSc37LfKMt7HYeu9NibbSRwELFN5wc/hreGyY+z+o4= go.mau.fi/whatsmeow v0.0.0-20230427180258-7f679583b39b/go.mod h1:+ObGpFE6cbbY4hKc1FmQH9MVfqaemmlXGXSnwDvCOyE= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -647,7 +641,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/src/internal/rest/group.go b/src/internal/rest/group.go index 1583bfa..1d7f2d9 100644 --- a/src/internal/rest/group.go +++ b/src/internal/rest/group.go @@ -13,6 +13,7 @@ type Group struct { func InitRestGroup(app *fiber.App, service domainGroup.IGroupService) Group { rest := Group{Service: service} app.Post("/group/join-with-link", rest.JoinGroupWithLink) + app.Post("/group/leave", rest.LeaveGroup) return rest } @@ -28,6 +29,23 @@ func (controller *Group) JoinGroupWithLink(c *fiber.Ctx) error { Status: 200, Code: "SUCCESS", Message: "Success joined group", - Results: response, + Results: map[string]string{ + "group_id": response, + }, + }) +} + +func (controller *Group) LeaveGroup(c *fiber.Ctx) error { + var request domainGroup.LeaveGroupRequest + err := c.BodyParser(&request) + utils.PanicIfNeeded(err) + + err = controller.Service.LeaveGroup(c.UserContext(), request) + utils.PanicIfNeeded(err) + + return c.JSON(utils.ResponseData{ + Status: 200, + Code: "SUCCESS", + Message: "Success leave group", }) } diff --git a/src/pkg/whatsapp/whatsapp.go b/src/pkg/whatsapp/whatsapp.go index f372f53..92c776c 100644 --- a/src/pkg/whatsapp/whatsapp.go +++ b/src/pkg/whatsapp/whatsapp.go @@ -98,9 +98,9 @@ func ParseJID(arg string) (types.JID, error) { } } -func ValidateJidWithLogin(waCli *whatsmeow.Client, phone string) (types.JID, error) { +func ValidateJidWithLogin(waCli *whatsmeow.Client, jid string) (types.JID, error) { MustLogin(waCli) - return ParseJID(phone) + return ParseJID(jid) } func InitWaDB() *sqlstore.Container { diff --git a/src/services/group.go b/src/services/group.go index d6c2c25..ba57f68 100644 --- a/src/services/group.go +++ b/src/services/group.go @@ -4,6 +4,7 @@ import ( "context" domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group" "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/whatsapp" + "github.com/aldinokemal/go-whatsapp-web-multidevice/validations" "go.mau.fi/whatsmeow" ) @@ -17,7 +18,10 @@ func NewGroupService(waCli *whatsmeow.Client) domainGroup.IGroupService { } } -func (service groupService) JoinGroupWithLink(_ context.Context, request domainGroup.JoinGroupWithLinkRequest) (groupID string, err error) { +func (service groupService) JoinGroupWithLink(ctx context.Context, request domainGroup.JoinGroupWithLinkRequest) (groupID string, err error) { + if err = validations.ValidateJoinGroupWithLink(ctx, request); err != nil { + return groupID, err + } whatsapp.MustLogin(service.WaCli) jid, err := service.WaCli.JoinGroupWithLink(request.Link) @@ -27,8 +31,12 @@ func (service groupService) JoinGroupWithLink(_ context.Context, request domainG return jid.String(), nil } -func (service groupService) LeaveGroup(_ context.Context, groupID string) (err error) { - JID, err := whatsapp.ValidateJidWithLogin(service.WaCli, groupID) +func (service groupService) LeaveGroup(ctx context.Context, request domainGroup.LeaveGroupRequest) (err error) { + if err = validations.ValidateLeaveGroup(ctx, request); err != nil { + return err + } + + JID, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.GroupID) if err != nil { return err } diff --git a/src/validations/group_validation.go b/src/validations/group_validation.go new file mode 100644 index 0000000..35d35b6 --- /dev/null +++ b/src/validations/group_validation.go @@ -0,0 +1,32 @@ +package validations + +import ( + "context" + domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group" + pkgError "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/error" + validation "github.com/go-ozzo/ozzo-validation/v4" +) + +func ValidateJoinGroupWithLink(ctx context.Context, request domainGroup.JoinGroupWithLinkRequest) error { + err := validation.ValidateStructWithContext(ctx, &request, + validation.Field(&request.Link, validation.Required), + ) + + if err != nil { + return pkgError.ValidationError(err.Error()) + } + + return nil +} + +func ValidateLeaveGroup(ctx context.Context, request domainGroup.LeaveGroupRequest) error { + err := validation.ValidateStructWithContext(ctx, &request, + validation.Field(&request.GroupID, validation.Required), + ) + + if err != nil { + return pkgError.ValidationError(err.Error()) + } + + return nil +} diff --git a/src/views/index.html b/src/views/index.html index a0bb810..ccf6fd7 100644 --- a/src/views/index.html +++ b/src/views/index.html @@ -605,6 +605,7 @@ Name Participants Created At + Action @@ -613,6 +614,9 @@ [[ g.Name ]] [[ g.Participants.length ]] [[ formatDate(g.GroupCreated) ]] + + + @@ -1374,15 +1378,47 @@ try { await this.groupApi(); $('#modalUserGroup').modal('show'); - $('#user_groups_table').DataTable().destroy(); - $('#user_groups_table').DataTable({ - "pageLength": 100, - }); + this.rebuildModal() showSuccessInfo("Groups fetched") } catch (err) { showErrorInfo(err) } }, + rebuildModal() { + $('#user_groups_table').DataTable({ + "pageLength": 100, + "reloadData": true, + }); + }, + async handleLeaveGroup(group_id) { + try { + const ok = confirm("Are you sure to leave this group?"); + if (!ok) return; + + await this.leaveGroupApi(group_id); + await this.groupApi(); + location.reload() + showSuccessInfo("Group left") + } catch (err) { + showErrorInfo(err) + } + }, + leaveGroupApi(group_id) { + return new Promise(async (resolve, reject) => { + try { + let payload = new FormData(); + payload.append("group_id", group_id) + await http.post(`/group/leave`, payload) + resolve() + } catch (error) { + if (error.response) { + reject(error.response.data.message) + } else { + reject(error.message) + } + } + }) + }, groupApi() { return new Promise(async (resolve, reject) => { try {