diff --git a/src/domains/message/message.go b/src/domains/message/message.go index a65a44f..282781f 100644 --- a/src/domains/message/message.go +++ b/src/domains/message/message.go @@ -3,7 +3,35 @@ package message import "context" type IMessageService interface { - ReactMessage(ctx context.Context, request ReactionRequest) (response ReactionResponse, err error) - RevokeMessage(ctx context.Context, request RevokeRequest) (response RevokeResponse, err error) - UpdateMessage(ctx context.Context, request UpdateMessageRequest) (response UpdateMessageResponse, err error) + ReactMessage(ctx context.Context, request ReactionRequest) (response GenericResponse, err error) + RevokeMessage(ctx context.Context, request RevokeRequest) (response GenericResponse, err error) + UpdateMessage(ctx context.Context, request UpdateMessageRequest) (response GenericResponse, err error) + DeleteMessage(ctx context.Context, request DeleteRequest) (err error) +} + +type GenericResponse struct { + MessageID string `json:"message_id"` + Status string `json:"status"` +} + +type RevokeRequest struct { + MessageID string `json:"message_id" uri:"message_id"` + Phone string `json:"phone" form:"phone"` +} + +type DeleteRequest struct { + MessageID string `json:"message_id" uri:"message_id"` + Phone string `json:"phone" form:"phone"` +} + +type ReactionRequest struct { + MessageID string `json:"message_id" form:"message_id"` + Phone string `json:"phone" form:"phone"` + Emoji string `json:"emoji" form:"emoji"` +} + +type UpdateMessageRequest struct { + MessageID string `json:"message_id" uri:"message_id"` + Message string `json:"message" form:"message"` + Phone string `json:"phone" form:"phone"` } diff --git a/src/domains/message/reaction.go b/src/domains/message/reaction.go deleted file mode 100644 index 45a5c8f..0000000 --- a/src/domains/message/reaction.go +++ /dev/null @@ -1,12 +0,0 @@ -package message - -type ReactionRequest struct { - MessageID string `json:"message_id" form:"message_id"` - Phone string `json:"phone" form:"phone"` - Emoji string `json:"emoji" form:"emoji"` -} - -type ReactionResponse struct { - MessageID string `json:"message_id"` - Status string `json:"status"` -} diff --git a/src/domains/message/revoke.go b/src/domains/message/revoke.go deleted file mode 100644 index e7567e9..0000000 --- a/src/domains/message/revoke.go +++ /dev/null @@ -1,11 +0,0 @@ -package message - -type RevokeRequest struct { - MessageID string `json:"message_id" uri:"message_id"` - Phone string `json:"phone" form:"phone"` -} - -type RevokeResponse struct { - MessageID string `json:"message_id"` - Status string `json:"status"` -} diff --git a/src/domains/message/update.go b/src/domains/message/update.go deleted file mode 100644 index 5321055..0000000 --- a/src/domains/message/update.go +++ /dev/null @@ -1,12 +0,0 @@ -package message - -type UpdateMessageRequest struct { - MessageID string `json:"message_id" uri:"message_id"` - Message string `json:"message" form:"message"` - Phone string `json:"phone" form:"phone"` -} - -type UpdateMessageResponse struct { - MessageID string `json:"message_id"` - Status string `json:"status"` -} diff --git a/src/internal/rest/message.go b/src/internal/rest/message.go index 71e6329..c14d223 100644 --- a/src/internal/rest/message.go +++ b/src/internal/rest/message.go @@ -16,6 +16,7 @@ func InitRestMessage(app *fiber.App, service domainMessage.IMessageService) Mess rest := Message{Service: service} app.Post("/message/:message_id/reaction", rest.ReactMessage) app.Post("/message/:message_id/revoke", rest.RevokeMessage) + app.Post("/message/:message_id/delete", rest.DeleteMessage) app.Post("/message/:message_id/update", rest.UpdateMessage) return rest } @@ -39,6 +40,25 @@ func (controller *Message) RevokeMessage(c *fiber.Ctx) error { }) } +func (controller *Message) DeleteMessage(c *fiber.Ctx) error { + var request domainMessage.DeleteRequest + err := c.BodyParser(&request) + utils.PanicIfNeeded(err) + + request.MessageID = c.Params("message_id") + whatsapp.SanitizePhone(&request.Phone) + + err = controller.Service.DeleteMessage(c.UserContext(), request) + utils.PanicIfNeeded(err) + + return c.JSON(utils.ResponseData{ + Status: 200, + Code: "SUCCESS", + Message: "Message deleted successfully", + Results: nil, + }) +} + func (controller *Message) UpdateMessage(c *fiber.Ctx) error { var request domainMessage.UpdateMessageRequest err := c.BodyParser(&request) diff --git a/src/pkg/whatsapp/whatsapp.go b/src/pkg/whatsapp/whatsapp.go index 97d0a66..5c01437 100644 --- a/src/pkg/whatsapp/whatsapp.go +++ b/src/pkg/whatsapp/whatsapp.go @@ -188,6 +188,8 @@ func MustLogin(waCli *whatsmeow.Client) { func handler(rawEvt interface{}) { switch evt := rawEvt.(type) { + case *events.DeleteForMe: + log.Infof("Deleted message %s for %s", evt.MessageID, evt.SenderJID.String()) case *events.AppStateSyncComplete: if len(cli.Store.PushName) > 0 && evt.Name == appstate.WAPatchCriticalBlock { err := cli.SendPresence(types.PresenceAvailable) diff --git a/src/services/message.go b/src/services/message.go index 9ba678a..8afed92 100644 --- a/src/services/message.go +++ b/src/services/message.go @@ -8,6 +8,7 @@ import ( "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/whatsapp" "github.com/aldinokemal/go-whatsapp-web-multidevice/validations" "go.mau.fi/whatsmeow" + "go.mau.fi/whatsmeow/appstate" waProto "go.mau.fi/whatsmeow/binary/proto" "go.mau.fi/whatsmeow/types" "google.golang.org/protobuf/proto" @@ -24,7 +25,7 @@ func NewMessageService(waCli *whatsmeow.Client) domainMessage.IMessageService { } } -func (service serviceMessage) ReactMessage(ctx context.Context, request message.ReactionRequest) (response message.ReactionResponse, err error) { +func (service serviceMessage) ReactMessage(ctx context.Context, request message.ReactionRequest) (response message.GenericResponse, err error) { if err = validations.ValidateReactMessage(ctx, request); err != nil { return response, err } @@ -54,7 +55,7 @@ func (service serviceMessage) ReactMessage(ctx context.Context, request message. return response, nil } -func (service serviceMessage) RevokeMessage(ctx context.Context, request domainMessage.RevokeRequest) (response domainMessage.RevokeResponse, err error) { +func (service serviceMessage) RevokeMessage(ctx context.Context, request domainMessage.RevokeRequest) (response domainMessage.GenericResponse, err error) { if err = validations.ValidateRevokeMessage(ctx, request); err != nil { return response, err } @@ -73,7 +74,41 @@ func (service serviceMessage) RevokeMessage(ctx context.Context, request domainM return response, nil } -func (service serviceMessage) UpdateMessage(ctx context.Context, request domainMessage.UpdateMessageRequest) (response domainMessage.UpdateMessageResponse, err error) { +func (service serviceMessage) DeleteMessage(ctx context.Context, request domainMessage.DeleteRequest) (err error) { + if err = validations.ValidateDeleteMessage(ctx, request); err != nil { + return err + } + dataWaRecipient, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.Phone) + if err != nil { + return err + } + + isFromMe := "1" + if len(request.MessageID) > 22 { + isFromMe = "0" + } + + patchInfo := appstate.PatchInfo{ + Timestamp: time.Now(), + Type: appstate.WAPatchRegularHigh, + Mutations: []appstate.MutationInfo{{ + Index: []string{appstate.IndexDeleteMessageForMe, dataWaRecipient.String(), request.MessageID, isFromMe, service.WaCli.Store.ID.String()}, + Value: &waProto.SyncActionValue{ + DeleteMessageForMeAction: &waProto.DeleteMessageForMeAction{ + DeleteMedia: proto.Bool(true), + MessageTimestamp: proto.Int64(time.Now().UnixMilli()), + }, + }, + }}, + } + + if err = service.WaCli.SendAppState(patchInfo); err != nil { + return err + } + return nil +} + +func (service serviceMessage) UpdateMessage(ctx context.Context, request domainMessage.UpdateMessageRequest) (response domainMessage.GenericResponse, err error) { if err = validations.ValidateUpdateMessage(ctx, request); err != nil { return response, err } diff --git a/src/validations/message_validation.go b/src/validations/message_validation.go index b7caabe..6e268fd 100644 --- a/src/validations/message_validation.go +++ b/src/validations/message_validation.go @@ -48,3 +48,16 @@ func ValidateReactMessage(ctx context.Context, request message.ReactionRequest) return nil } + +func ValidateDeleteMessage(ctx context.Context, request domainMessage.DeleteRequest) error { + err := validation.ValidateStructWithContext(ctx, &request, + validation.Field(&request.Phone, validation.Required), + validation.Field(&request.MessageID, validation.Required), + ) + + if err != nil { + return pkgError.ValidationError(err.Error()) + } + + return nil +}