Skip to content

[Feature] Novo endpoint POST /message/markplayed (microfone azul em áudios) #45

@brunohenriquecontente

Description

@brunohenriquecontente

Bem-vindo!

  • Sim, pesquisei solicitações semelhantes no GitHub e não encontrei nenhum.

Qual tipo de recurso?

Endpoint

Qual a motivação para a solicitação?

Hoje só existe POST /message/markread, que chama client.MarkRead(...) da whatsmeow sem passar o parâmetro ReceiptType — então sempre envia o default types.ReceiptTypeRead (✓✓ azul).

Para mensagens de áudio (notas de voz / PTT), o WhatsApp tem um indicador visual separado: o ícone do microfone fica azul no aparelho de quem enviou — esse efeito é acionado especificamente por types.ReceiptTypePlayed. Como a API não expõe esse tipo de receipt, mesmo depois do áudio ser ouvido pelo destinatário, o remetente continua vendo o microfone cinza e fica com a impressão de que ninguém escutou a mensagem.

Isso aparece como uma lacuna em qualquer integração que queira sinalizar "o áudio foi consumido" — seja por um usuário humano numa interface custom, seja por um pipeline automatizado que processa o áudio (transcrição, análise, etc.).

Vale lembrar que read e played são receipts distintos no protocolo do WhatsApp: read corresponde aos checks azuis (✓✓), enquanto played corresponde ao microfone azul. Eles podem ser enviados de forma independente.

Exemplos de Uso

Cenário típico:

  1. Cliente envia uma nota de voz.
  2. Backend recebe via webhook MESSAGES_UPSERT e baixa os bytes.
  3. Backend processa o áudio (player custom, transcrição, etc.).
  4. Backend chama POST /message/markread para marcar como lido → ✓✓ azul ✅.
  5. Mesmo após o passo 4, o microfone permanece cinza ❌ no WhatsApp do remetente, dando a impressão de que o áudio não foi escutado.

Esperado: cliente vê o microfone azul, confirmando que o áudio foi de fato consumido.

Como o recurso deve ser desenvolvido?

Sugestão: novo endpoint POST /message/markplayed, simétrico ao markread existente, que envia o receipt types.ReceiptTypePlayed. Seguindo o padrão da API atual (um handler por ação).

pkg/message/service/message_service.go:

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

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

    jid, ok := utils.ParseJID(data.Number)
    if !ok {
        return "", errors.New("invalid phone number")
    }

    if err := client.MarkRead(context.Background(), data.Id, time.Now(), jid, jid, types.ReceiptTypePlayed); 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 time.Time{}.String(), nil
}

Rota equivalente à markread em pkg/routes/routes.go:

routes.POST("/markplayed", r.jidValidationMiddleware.ValidateNumberField(), r.messageHandler.MarkPlayed)

Handler (pkg/message/handler/message_handler.go) segue o mesmo formato dos demais handlers do package (parsing JSON → service → response padrão), incluindo as anotações Swagger no estilo já adotado.

Assinatura da whatsmeow para referência:

func (cli *Client) MarkRead(ids []types.MessageID, timestamp time.Time, chat, sender types.JID, receiptType ...types.ReceiptType) error

whatsmeow/types/ReceiptType

Alternativa considerada: adicionar campo opcional receiptType no próprio MarkReadStruct. Optei pelo endpoint separado para manter consistência com o padrão da API (um endpoint por ação, swagger mais claro, validação dedicada).

Notas Adicionais

Posso enviar o PR com a implementação — já tenho o patch testado num fork e validado em ambiente real (microfone azul confirmado no WhatsApp do remetente após chamada do endpoint).

Versão observada: 0.7.0 (Docker evoapicloud/evolution-go:0.7.0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions