Browse Source

feat: Add group participant request management functionality

- Introduced new endpoints for handling requested participants in groups:
  - GET /group/participants/requested to retrieve requested participants.
  - POST /group/participants/requested/approve to approve participant requests.
  - POST /group/participants/requested/reject to reject participant requests.

- Added corresponding methods in the group service to manage participant requests.
- Implemented validation for new request types to ensure proper data handling.
pull/276/head
Aldino Kemal 11 months ago
parent
commit
2509e742d7
  1. 13
      src/domains/group/group.go
  2. 75
      src/internal/rest/group.go
  3. 55
      src/services/group.go
  4. 27
      src/validations/group_validation.go

13
src/domains/group/group.go

@ -2,6 +2,7 @@ package group
import ( import (
"context" "context"
"go.mau.fi/whatsmeow" "go.mau.fi/whatsmeow"
) )
@ -10,6 +11,8 @@ type IGroupService interface {
LeaveGroup(ctx context.Context, request LeaveGroupRequest) (err error) LeaveGroup(ctx context.Context, request LeaveGroupRequest) (err error)
CreateGroup(ctx context.Context, request CreateGroupRequest) (groupID string, err error) CreateGroup(ctx context.Context, request CreateGroupRequest) (groupID string, err error)
ManageParticipant(ctx context.Context, request ParticipantRequest) (result []ParticipantStatus, err error) ManageParticipant(ctx context.Context, request ParticipantRequest) (result []ParticipantStatus, err error)
GetGroupRequestParticipants(ctx context.Context, request GetGroupRequestParticipantsRequest) (result []string, err error)
ManageGroupRequestParticipants(ctx context.Context, request GroupRequestParticipantsRequest) (result []ParticipantStatus, err error)
} }
type JoinGroupWithLinkRequest struct { type JoinGroupWithLinkRequest struct {
@ -36,3 +39,13 @@ type ParticipantStatus struct {
Status string `json:"status"` Status string `json:"status"`
Message string `json:"message"` Message string `json:"message"`
} }
type GetGroupRequestParticipantsRequest struct {
GroupID string `json:"group_id" query:"group_id"`
}
type GroupRequestParticipantsRequest struct {
GroupID string `json:"group_id" form:"group_id"`
Participants []string `json:"participants" form:"participants"`
Action whatsmeow.ParticipantRequestChange `json:"action" form:"action"`
}

75
src/internal/rest/group.go

@ -2,6 +2,7 @@ package rest
import ( import (
"fmt" "fmt"
domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group" domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group"
"github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/utils" "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/utils"
"github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/whatsapp" "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/whatsapp"
@ -22,6 +23,9 @@ func InitRestGroup(app *fiber.App, service domainGroup.IGroupService) Group {
app.Post("/group/participants/remove", rest.DeleteParticipants) app.Post("/group/participants/remove", rest.DeleteParticipants)
app.Post("/group/participants/promote", rest.PromoteParticipants) app.Post("/group/participants/promote", rest.PromoteParticipants)
app.Post("/group/participants/demote", rest.DemoteParticipants) app.Post("/group/participants/demote", rest.DemoteParticipants)
app.Get("/group/participants/requested", rest.RequestedParticipants)
app.Post("/group/participants/requested/approve", rest.ApproveRequestedParticipants)
app.Post("/group/participants/requested/reject", rest.RejectRequestedParticipants)
return rest return rest
} }
@ -77,83 +81,78 @@ func (controller *Group) CreateGroup(c *fiber.Ctx) error {
}, },
}) })
} }
func (controller *Group) AddParticipants(c *fiber.Ctx) error { func (controller *Group) AddParticipants(c *fiber.Ctx) error {
var request domainGroup.ParticipantRequest
err := c.BodyParser(&request)
utils.PanicIfNeeded(err)
whatsapp.SanitizePhone(&request.GroupID)
return controller.manageParticipants(c, whatsmeow.ParticipantChangeAdd, "Success add participants")
}
request.Action = whatsmeow.ParticipantChangeAdd
func (controller *Group) DeleteParticipants(c *fiber.Ctx) error {
return controller.manageParticipants(c, whatsmeow.ParticipantChangeRemove, "Success delete participants")
}
result, err := controller.Service.ManageParticipant(c.UserContext(), request)
utils.PanicIfNeeded(err)
func (controller *Group) PromoteParticipants(c *fiber.Ctx) error {
return controller.manageParticipants(c, whatsmeow.ParticipantChangePromote, "Success promote participants")
}
return c.JSON(utils.ResponseData{
Status: 200,
Code: "SUCCESS",
Message: "Success add participants",
Results: result,
})
func (controller *Group) DemoteParticipants(c *fiber.Ctx) error {
return controller.manageParticipants(c, whatsmeow.ParticipantChangeDemote, "Success demote participants")
} }
func (controller *Group) DeleteParticipants(c *fiber.Ctx) error {
var request domainGroup.ParticipantRequest
err := c.BodyParser(&request)
func (controller *Group) RequestedParticipants(c *fiber.Ctx) error {
var request domainGroup.GetGroupRequestParticipantsRequest
err := c.QueryParser(&request)
utils.PanicIfNeeded(err) utils.PanicIfNeeded(err)
whatsapp.SanitizePhone(&request.GroupID) whatsapp.SanitizePhone(&request.GroupID)
request.Action = whatsmeow.ParticipantChangeRemove
result, err := controller.Service.ManageParticipant(c.UserContext(), request)
result, err := controller.Service.GetGroupRequestParticipants(c.UserContext(), request)
utils.PanicIfNeeded(err) utils.PanicIfNeeded(err)
return c.JSON(utils.ResponseData{ return c.JSON(utils.ResponseData{
Status: 200, Status: 200,
Code: "SUCCESS", Code: "SUCCESS",
Message: "Success delete participants",
Message: "Success getting list requested participants",
Results: result, Results: result,
}) })
} }
func (controller *Group) PromoteParticipants(c *fiber.Ctx) error {
func (controller *Group) ApproveRequestedParticipants(c *fiber.Ctx) error {
return controller.handleRequestedParticipants(c, whatsmeow.ParticipantChangeApprove, "Success approve requested participants")
}
func (controller *Group) RejectRequestedParticipants(c *fiber.Ctx) error {
return controller.handleRequestedParticipants(c, whatsmeow.ParticipantChangeReject, "Success reject requested participants")
}
// Generalized participant management handler
func (controller *Group) manageParticipants(c *fiber.Ctx, action whatsmeow.ParticipantChange, successMsg string) error {
var request domainGroup.ParticipantRequest var request domainGroup.ParticipantRequest
err := c.BodyParser(&request) err := c.BodyParser(&request)
utils.PanicIfNeeded(err) utils.PanicIfNeeded(err)
whatsapp.SanitizePhone(&request.GroupID) whatsapp.SanitizePhone(&request.GroupID)
request.Action = whatsmeow.ParticipantChangePromote
request.Action = action
result, err := controller.Service.ManageParticipant(c.UserContext(), request) result, err := controller.Service.ManageParticipant(c.UserContext(), request)
utils.PanicIfNeeded(err) utils.PanicIfNeeded(err)
return c.JSON(utils.ResponseData{ return c.JSON(utils.ResponseData{
Status: 200, Status: 200,
Code: "SUCCESS", Code: "SUCCESS",
Message: "Success promote participants",
Message: successMsg,
Results: result, Results: result,
}) })
} }
func (controller *Group) DemoteParticipants(c *fiber.Ctx) error {
var request domainGroup.ParticipantRequest
// Generalized requested participants handler
func (controller *Group) handleRequestedParticipants(c *fiber.Ctx, action whatsmeow.ParticipantRequestChange, successMsg string) error {
var request domainGroup.GroupRequestParticipantsRequest
err := c.BodyParser(&request) err := c.BodyParser(&request)
utils.PanicIfNeeded(err) utils.PanicIfNeeded(err)
whatsapp.SanitizePhone(&request.GroupID) whatsapp.SanitizePhone(&request.GroupID)
request.Action = whatsmeow.ParticipantChangeDemote
result, err := controller.Service.ManageParticipant(c.UserContext(), request)
request.Action = action
result, err := controller.Service.ManageGroupRequestParticipants(c.UserContext(), request)
utils.PanicIfNeeded(err) utils.PanicIfNeeded(err)
return c.JSON(utils.ResponseData{ return c.JSON(utils.ResponseData{
Status: 200, Status: 200,
Code: "SUCCESS", Code: "SUCCESS",
Message: "Success demote participants",
Message: successMsg,
Results: result, Results: result,
}) })
} }

55
src/services/group.go

@ -2,6 +2,8 @@ package services
import ( import (
"context" "context"
"fmt"
"github.com/aldinokemal/go-whatsapp-web-multidevice/config" "github.com/aldinokemal/go-whatsapp-web-multidevice/config"
domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group" domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group"
pkgError "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/error" pkgError "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/error"
@ -113,6 +115,59 @@ func (service groupService) ManageParticipant(ctx context.Context, request domai
return result, nil return result, nil
} }
func (service groupService) GetGroupRequestParticipants(ctx context.Context, request domainGroup.GetGroupRequestParticipantsRequest) (result []string, err error) {
if err = validations.ValidateGetGroupRequestParticipants(ctx, request); err != nil {
return result, err
}
groupJID, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.GroupID)
if err != nil {
return result, err
}
participants, err := service.WaCli.GetGroupRequestParticipants(groupJID)
if err != nil {
return result, err
}
for _, participant := range participants {
result = append(result, participant.JID.String())
}
return result, nil
}
func (service groupService) ManageGroupRequestParticipants(ctx context.Context, request domainGroup.GroupRequestParticipantsRequest) (result []domainGroup.ParticipantStatus, err error) {
if err = validations.ValidateManageGroupRequestParticipants(ctx, request); err != nil {
return result, err
}
groupJID, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.GroupID)
if err != nil {
return result, err
}
participantsJID, err := service.participantToJID(request.Participants)
if err != nil {
return result, err
}
participants, err := service.WaCli.UpdateGroupRequestParticipants(groupJID, participantsJID, request.Action)
if err != nil {
return result, err
}
for _, participant := range participants {
result = append(result, domainGroup.ParticipantStatus{
Participant: participant.JID.String(),
Status: "success",
Message: fmt.Sprintf("Action %s success", request.Action),
})
}
return result, nil
}
func (service groupService) participantToJID(participants []string) ([]types.JID, error) { func (service groupService) participantToJID(participants []string) ([]types.JID, error) {
var participantsJID []types.JID var participantsJID []types.JID
for _, participant := range participants { for _, participant := range participants {

27
src/validations/group_validation.go

@ -2,6 +2,7 @@ package validations
import ( import (
"context" "context"
domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group" domainGroup "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/group"
pkgError "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/error" pkgError "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/error"
validation "github.com/go-ozzo/ozzo-validation/v4" validation "github.com/go-ozzo/ozzo-validation/v4"
@ -58,3 +59,29 @@ func ValidateParticipant(ctx context.Context, request domainGroup.ParticipantReq
return nil return nil
} }
func ValidateGetGroupRequestParticipants(ctx context.Context, request domainGroup.GetGroupRequestParticipantsRequest) error {
err := validation.ValidateStructWithContext(ctx, &request,
validation.Field(&request.GroupID, validation.Required),
)
if err != nil {
return pkgError.ValidationError(err.Error())
}
return nil
}
func ValidateManageGroupRequestParticipants(ctx context.Context, request domainGroup.GroupRequestParticipantsRequest) error {
err := validation.ValidateStructWithContext(ctx, &request,
validation.Field(&request.GroupID, validation.Required),
validation.Field(&request.Participants, validation.Required),
validation.Field(&request.Participants, validation.Each(validation.Required)),
)
if err != nil {
return pkgError.ValidationError(err.Error())
}
return nil
}
Loading…
Cancel
Save