Browse Source

feat: mark as read (#208)

* feat: add mark as read

feat(message.go): add MarkAsRead functionality to IMessageService for marking messages as read
feat(go.mod): update dependencies to newer versions for improved functionality and security
feat(rest): add endpoint for MarkAsRead to handle marking messages as read through the API
feat(service): implement MarkAsRead logic in serviceMessage to mark messages as read in WhatsApp
feat(validations): add validation for MarkAsRead request to ensure required fields are present

* chore(settings.go): bump AppVersion to v4.21.0 for new release

feat(message.go): add logging for MarkAsRead function using logrus for better traceability

fix(GroupManageParticipants.js): remove redundant '@' from group_id computation
pull/225/head v4.21.0
Aldino Kemal 1 year ago
committed by GitHub
parent
commit
1e173b2212
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 46
      docs/openapi.yaml
  2. 1
      readme.md
  3. 2
      src/config/settings.go
  4. 6
      src/domains/message/message.go
  5. 6
      src/go.mod
  6. 6
      src/go.sum
  7. 20
      src/internal/rest/message.go
  8. 27
      src/services/message.go
  9. 14
      src/validations/message_validation.go
  10. 2
      src/views/components/GroupManageParticipants.js

46
docs/openapi.yaml

@ -1,7 +1,7 @@
openapi: 3.0.0
info:
title: WhatsApp API MultiDevice
version: 4.3.0
version: 4.4.0
description: This API is used for sending whatsapp via API
servers:
- url: http://localhost:3000
@ -835,6 +835,50 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorInternalServer'
/message/{message_id}/read:
post:
operationId: readMessage
tags:
- message
summary: Mark as read message
parameters:
- in: path
name: message_id
schema:
type: string
required: true
description: Message ID
requestBody:
content:
application/json:
schema:
type: object
properties:
phone:
type: string
example: '62819273192397132@s.whatsapp.net'
description: Phone number with country code
required:
- phone
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/SendResponse'
'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'
/group:
post:
operationId: createGroup

1
readme.md

@ -128,6 +128,7 @@ You can fork or edit this source code !
| ✅ | React Message | POST | /message/:message_id/reaction |
| ✅ | Delete Message | POST | /message/:message_id/delete |
| ✅ | Edit Message | POST | /message/:message_id/update |
| ✅ | Read Message (DM) | POST | /message/:message_id/read |
| ❌ | Star message | POST | /message/:message_id/star |
| ✅ | Join Group With Link | POST | /group/join-with-link |
| ✅ | Leave Group | POST | /group/leave |

2
src/config/settings.go

@ -5,7 +5,7 @@ import (
)
var (
AppVersion = "v4.20.0"
AppVersion = "v4.21.0"
AppPort = "3000"
AppDebug = false
AppOs = "AldinoKemal"

6
src/domains/message/message.go

@ -3,6 +3,7 @@ package message
import "context"
type IMessageService interface {
MarkAsRead(ctx context.Context, request MarkAsReadRequest) (response GenericResponse, 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)
@ -35,3 +36,8 @@ type UpdateMessageRequest struct {
Message string `json:"message" form:"message"`
Phone string `json:"phone" form:"phone"`
}
type MarkAsReadRequest struct {
MessageID string `json:"message_id" uri:"message_id"`
Phone string `json:"phone" form:"phone"`
}

6
src/go.mod

@ -18,9 +18,9 @@ require (
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
github.com/valyala/fasthttp v1.56.0
github.com/valyala/fasthttp v1.57.0
go.mau.fi/libsignal v0.1.1
go.mau.fi/whatsmeow v0.0.0-20241009112614-70d73b690a8d
go.mau.fi/whatsmeow v0.0.0-20241027175758-cd900353e4a7
google.golang.org/protobuf v1.35.1
)
@ -47,7 +47,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
go.mau.fi/util v0.8.0 // indirect
go.mau.fi/util v0.8.1 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/image v0.21.0 // indirect
golang.org/x/net v0.30.0 // indirect

6
src/go.sum

@ -101,6 +101,8 @@ github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
github.com/valyala/fasthttp v1.56.0 h1:bEZdJev/6LCBlpdORfrLu/WOZXXxvrUQSiyniuaoW8U=
github.com/valyala/fasthttp v1.56.0/go.mod h1:sReBt3XZVnudxuLOx4J/fMrJVorWRiWY2koQKgABiVI=
github.com/valyala/fasthttp v1.57.0 h1:Xw8SjWGEP/+wAAgyy5XTvgrWlOD1+TxbbvNADYCm1Tg=
github.com/valyala/fasthttp v1.57.0/go.mod h1:h6ZBaPRlzpZ6O3H5t2gEk1Qi33+TmLvfwgLLp0t9CpE=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
@ -111,6 +113,8 @@ go.mau.fi/util v0.7.0 h1:l31z+ivrSQw+cv/9eFebEqtQW2zhxivGypn+JT0h/ws=
go.mau.fi/util v0.7.0/go.mod h1:bWYreIoTULL/UiRbZdfddPh7uWDFW5yX4YCv5FB0eE0=
go.mau.fi/util v0.8.0 h1:MiSny8jgQq4XtCLAT64gDJhZVhqiDeMVIEBDFVw+M0g=
go.mau.fi/util v0.8.0/go.mod h1:1Ixb8HWoVbl3rT6nAX6nV4iMkzn7KU/KXwE0Rn5RmsQ=
go.mau.fi/util v0.8.1 h1:Ga43cz6esQBYqcjZ/onRoVnYWoUwjWbsxVeJg2jOTSo=
go.mau.fi/util v0.8.1/go.mod h1:T1u/rD2rzidVrBLyaUdPpZiJdP/rsyi+aTzn0D+Q6wc=
go.mau.fi/whatsmeow v0.0.0-20240821142752-3d63c6fcc1a7 h1:Aa4uov0rM0SQQ7Fc/TZZpmQEGksie2SVTv/UuCJwViI=
go.mau.fi/whatsmeow v0.0.0-20240821142752-3d63c6fcc1a7/go.mod h1:BhHKalSq0qNtSCuGIUIvoJyU5KbT4a7k8DQ5yw1Ssk4=
go.mau.fi/whatsmeow v0.0.0-20240911102933-bb3364aa3986 h1:7X+3826qoRBHPCtxY89tqMcYEsi9+OuWE6hHZfRc0qI=
@ -119,6 +123,8 @@ go.mau.fi/whatsmeow v0.0.0-20240927134544-69ba055bef0f h1:+gT0NSk50HaAagtyj6J/a/
go.mau.fi/whatsmeow v0.0.0-20240927134544-69ba055bef0f/go.mod h1:UvaXcdb8y5Mryj2LSXAMw7u4/exnWJIXn8Gvpmf6ndI=
go.mau.fi/whatsmeow v0.0.0-20241009112614-70d73b690a8d h1:0OV2Ula2IGaoHVfvv7ns+Gn3xGT0SHn5yDecJBB8FQY=
go.mau.fi/whatsmeow v0.0.0-20241009112614-70d73b690a8d/go.mod h1:UvaXcdb8y5Mryj2LSXAMw7u4/exnWJIXn8Gvpmf6ndI=
go.mau.fi/whatsmeow v0.0.0-20241027175758-cd900353e4a7 h1:0qujZcpt0G1QFCrTgrXvnVg6yQU1IG1VbmHRHkWV0iY=
go.mau.fi/whatsmeow v0.0.0-20241027175758-cd900353e4a7/go.mod h1:UvaXcdb8y5Mryj2LSXAMw7u4/exnWJIXn8Gvpmf6ndI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=

20
src/internal/rest/message.go

@ -18,6 +18,7 @@ func InitRestMessage(app *fiber.App, service domainMessage.IMessageService) Mess
app.Post("/message/:message_id/revoke", rest.RevokeMessage)
app.Post("/message/:message_id/delete", rest.DeleteMessage)
app.Post("/message/:message_id/update", rest.UpdateMessage)
app.Post("/message/:message_id/read", rest.MarkAsRead)
return rest
}
@ -96,3 +97,22 @@ func (controller *Message) ReactMessage(c *fiber.Ctx) error {
Results: response,
})
}
func (controller *Message) MarkAsRead(c *fiber.Ctx) error {
var request message.MarkAsReadRequest
err := c.BodyParser(&request)
utils.PanicIfNeeded(err)
request.MessageID = c.Params("message_id")
whatsapp.SanitizePhone(&request.Phone)
response, err := controller.Service.MarkAsRead(c.UserContext(), request)
utils.PanicIfNeeded(err)
return c.JSON(utils.ResponseData{
Status: 200,
Code: "SUCCESS",
Message: response.Status,
Results: response,
})
}

27
src/services/message.go

@ -7,6 +7,7 @@ import (
domainMessage "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message"
"github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/whatsapp"
"github.com/aldinokemal/go-whatsapp-web-multidevice/validations"
"github.com/sirupsen/logrus"
"go.mau.fi/whatsmeow"
"go.mau.fi/whatsmeow/appstate"
"go.mau.fi/whatsmeow/proto/waCommon"
@ -27,6 +28,32 @@ func NewMessageService(waCli *whatsmeow.Client) domainMessage.IMessageService {
}
}
func (service serviceMessage) MarkAsRead(ctx context.Context, request domainMessage.MarkAsReadRequest) (response domainMessage.GenericResponse, err error) {
if err = validations.ValidateMarkAsRead(ctx, request); err != nil {
return response, err
}
dataWaRecipient, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.Phone)
if err != nil {
return response, err
}
ids := []types.MessageID{request.MessageID}
if err = service.WaCli.MarkRead(ids, time.Now(), dataWaRecipient, *service.WaCli.Store.ID); err != nil {
return response, err
}
logrus.Info(map[string]interface{}{
"phone": request.Phone,
"message_id": request.MessageID,
"chat": dataWaRecipient.String(),
"sender": service.WaCli.Store.ID.String(),
})
response.MessageID = request.MessageID
response.Status = fmt.Sprintf("Mark as read success %s", request.MessageID)
return response, nil
}
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

14
src/validations/message_validation.go

@ -8,6 +8,20 @@ import (
validation "github.com/go-ozzo/ozzo-validation/v4"
)
func ValidateMarkAsRead(ctx context.Context, request domainMessage.MarkAsReadRequest) error {
err := validation.ValidateStructWithContext(ctx, &request,
validation.Field(&request.MessageID, validation.Required),
validation.Field(&request.Phone, validation.Required),
)
if err != nil {
return pkgError.ValidationError(err.Error())
}
return nil
}
func ValidateRevokeMessage(ctx context.Context, request domainMessage.RevokeRequest) error {
err := validation.ValidateStructWithContext(ctx, &request,
validation.Field(&request.Phone, validation.Required),

2
src/views/components/GroupManageParticipants.js

@ -10,7 +10,7 @@ export default {
},
computed: {
group_id() {
return `${this.group}@${window.TYPEGROUP}`;
return `${this.group}${window.TYPEGROUP}`;
},
},
methods: {

Loading…
Cancel
Save