Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1944,6 +1944,52 @@ const docTemplate = `{
}
}
},
"/message/markplayed": {
"post": {
"description": "Mark an audio message as played",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Message"
],
"summary": "Mark an audio message as played",
"parameters": [
{
"description": "Mark an audio message as played",
"name": "message",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct"
}
}
],
"responses": {
"200": {
"description": "success",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"400": {
"description": "Error on validation",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
}
},
"/message/markread": {
"post": {
"description": "Mark a message as read",
Expand Down Expand Up @@ -3849,6 +3895,20 @@ const docTemplate = `{
}
}
},
"github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct": {
"type": "object",
"properties": {
"id": {
"type": "array",
"items": {
"type": "string"
}
},
"number": {
"type": "string"
}
}
},
"github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct": {
"type": "object",
"properties": {
Expand Down
60 changes: 60 additions & 0 deletions docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1936,6 +1936,52 @@
}
}
},
"/message/markplayed": {
"post": {
"description": "Mark an audio message as played",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Message"
],
"summary": "Mark an audio message as played",
"parameters": [
{
"description": "Mark an audio message as played",
"name": "message",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct"
}
}
],
"responses": {
"200": {
"description": "success",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"400": {
"description": "Error on validation",
"schema": {
"$ref": "#/definitions/gin.H"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/gin.H"
}
}
}
}
},
"/message/markread": {
"post": {
"description": "Mark a message as read",
Expand Down Expand Up @@ -3841,6 +3887,20 @@
}
}
},
"github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct": {
"type": "object",
"properties": {
"id": {
"type": "array",
"items": {
"type": "string"
}
},
"number": {
"type": "string"
}
}
},
"github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct": {
"type": "object",
"properties": {
Expand Down
39 changes: 39 additions & 0 deletions docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ definitions:
messageId:
type: string
type: object
github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct:
properties:
id:
items:
type: string
type: array
number:
type: string
type: object
github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkReadStruct:
properties:
id:
Expand Down Expand Up @@ -7870,6 +7879,36 @@ paths:
summary: Edit a message
tags:
- Message
/message/markplayed:
post:
consumes:
- application/json
description: Mark an audio message as played
parameters:
- description: Mark an audio message as played
in: body
name: message
required: true
schema:
$ref: '#/definitions/github_com_EvolutionAPI_evolution-go_pkg_message_service.MarkPlayedStruct'
produces:
- application/json
responses:
"200":
description: success
schema:
$ref: '#/definitions/gin.H'
"400":
description: Error on validation
schema:
$ref: '#/definitions/gin.H'
"500":
description: Internal server error
schema:
$ref: '#/definitions/gin.H'
summary: Mark an audio message as played
tags:
- Message
/message/markread:
post:
consumes:
Expand Down
51 changes: 51 additions & 0 deletions pkg/message/handler/message_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type MessageHandler interface {
React(ctx *gin.Context)
ChatPresence(ctx *gin.Context)
MarkRead(ctx *gin.Context)
MarkPlayed(ctx *gin.Context)
DownloadMedia(ctx *gin.Context)
GetMessageStatus(ctx *gin.Context)
DeleteMessageEveryone(ctx *gin.Context)
Expand Down Expand Up @@ -168,6 +169,56 @@ func (m *messageHandler) MarkRead(ctx *gin.Context) {
ctx.JSON(http.StatusOK, gin.H{"message": "success", "data": responseData})
}

// MarkPlayed mark an audio message as played (blue mic icon)
// @Summary Mark an audio message as played
// @Description Mark an audio message as played
// @Tags Message
// @Accept json
// @Produce json
// @Param message body message_service.MarkPlayedStruct true "Mark an audio message as played"
// @Success 200 {object} gin.H "success"
// @Failure 400 {object} gin.H "Error on validation"
// @Failure 500 {object} gin.H "Internal server error"
// @Router /message/markplayed [post]
func (m *messageHandler) MarkPlayed(ctx *gin.Context) {
getInstance := ctx.MustGet("instance")

instance, ok := getInstance.(*instance_model.Instance)
if !ok {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"})
return
}

var data *message_service.MarkPlayedStruct
err := ctx.ShouldBindBodyWithJSON(&data)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

if data.Number == "" {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "phone number is required"})
return
}

if len(data.Id) < 1 {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "id is required"})
return
}

ts, err := m.messageService.MarkPlayed(data, instance)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

responseData := gin.H{
"timestamp": ts,
}

ctx.JSON(http.StatusOK, gin.H{"message": "success", "data": responseData})
}

// DownloadImage download an image
// @Summary Download an image
// @Description Download an image
Expand Down
29 changes: 29 additions & 0 deletions pkg/message/service/message_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type MessageService interface {
React(data *ReactStruct, instance *instance_model.Instance) (*MessageSendStruct, error)
ChatPresence(data *ChatPresenceStruct, instance *instance_model.Instance) (string, error)
MarkRead(data *MarkReadStruct, instance *instance_model.Instance) (string, error)
MarkPlayed(data *MarkPlayedStruct, instance *instance_model.Instance) (string, error)
DownloadMedia(data *DownloadMediaStruct, instance *instance_model.Instance, request *http.Request) (*dataurl.DataURL, string, error)
GetMessageStatus(data *MessageStatusStruct, instance *instance_model.Instance) (*message_model.Message, string, error)
DeleteMessageEveryone(data *MessageStruct, instance *instance_model.Instance) (string, string, error)
Expand Down Expand Up @@ -59,6 +60,11 @@ type MarkReadStruct struct {
Number string `json:"number"`
}

type MarkPlayedStruct struct {
Id []string `json:"id"`
Number string `json:"number"`
}

type DownloadMediaStruct struct {
Message *waE2E.Message `json:"message"`
}
Expand Down Expand Up @@ -258,6 +264,29 @@ func (m *messageService) MarkRead(data *MarkReadStruct, instance *instance_model
return ts.String(), nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Return value for timestamp is always zero-time because ts is never set.

In MarkPlayed, ts is declared but never assigned, so ts.String() will always return the zero time (0001-01-01 ...), which is inconsistent with MarkRead and likely incorrect. If you need to return the time the message was marked as played, set ts := time.Now() and use it both in the MarkRead call and for the return value. If no timestamp is needed, remove ts and adjust the return accordingly.

}

func (m *messageService) MarkPlayed(data *MarkPlayedStruct, instance *instance_model.Instance) (string, error) {
client, err := m.ensureClientConnected(instance.Id)
if err != nil {
return "", err
}

var ts time.Time

jid, ok := utils.ParseJID(data.Number)
if !ok {
m.loggerWrapper.GetLogger(instance.Id).LogError("[%s] Error validating message fields", instance.Id)
return "", errors.New("invalid phone number")
}

err = client.MarkRead(context.Background(), data.Id, time.Now(), jid, jid, types.ReceiptTypePlayed)
if err != nil {
m.loggerWrapper.GetLogger(instance.Id).LogError("[%s] error marking message as played: %v", instance.Id, err)
return "", errors.New("error marking message as played")
}

return ts.String(), nil
}

func (m *messageService) DownloadMedia(data *DownloadMediaStruct, instance *instance_model.Instance, request *http.Request) (*dataurl.DataURL, string, error) {
client, err := m.ensureClientConnected(instance.Id)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ func (r *Routes) AssignRoutes(eng *gin.Engine) {
routes.POST("/react", r.jidValidationMiddleware.ValidateJIDFields("number"), r.messageHandler.React)
routes.POST("/presence", r.jidValidationMiddleware.ValidateNumberField(), r.messageHandler.ChatPresence)
routes.POST("/markread", r.jidValidationMiddleware.ValidateNumberField(), r.messageHandler.MarkRead)
routes.POST("/markplayed", r.jidValidationMiddleware.ValidateNumberField(), r.messageHandler.MarkPlayed)
routes.POST("/downloadmedia", r.messageHandler.DownloadMedia)
routes.POST("/status", r.messageHandler.GetMessageStatus)
routes.POST("/delete", r.jidValidationMiddleware.ValidateNumberField(), r.messageHandler.DeleteMessageEveryone)
Expand Down