Skip to content

Expose SubscribePresence (contact online) + decrypt edited messages (new text arrives encrypted) #146

Description

@nicolasnovis

Summary

Two whatsmeow capabilities are effectively present in the codebase but not surfaced to API consumers, so CRMs built on top of Evolution Go can't reach feature parity with the Baileys-based Evolution API for them:

  1. Contact presence ("online" / last-seen) — there is no way to SubscribePresence, so events.Presence never fires.
  2. Edited messages arrive encrypted and undecrypted — the new text is delivered as a raw secretEncryptedMessage envelope, so consumers can't read what the message was edited to.

Both are small, additive changes. Happy to open a PR for either/both if the approach looks right to you.


1. Expose SubscribePresence → enables contact "online"/last-seen

whatsmeow only emits events.Presence for JIDs you've explicitly subscribed to via Client.SubscribePresence(ctx, jid). A grep of the repo shows SubscribePresence is never called, and there's no route to trigger it. The rest of the plumbing already exists:

  • the Presence event dispatcher → webhook ({event:"Presence", state, data:{From, Unavailable, LastSeen}}) is already implemented in pkg/whatsmeow/service/whatsmeow.go;
  • the PRESENCE subscription filter already exists.

Request: a new instance-scoped route, e.g. POST /user/presence/subscribe with body { "number": "5521..." } (nice-to-have: also accept { "numbers": [...] } for batching the top N conversations of an inbox):

  • normalize to a canonical JID (same helper used by /message/presence);
  • send our own presence first — client.SendPresence(types.PresenceAvailable) — since whatsmeow only receives presence updates after you've broadcast your own (same rationale already noted in pkg/message/service/message_service.go around the ChatPresence handler);
  • call client.SubscribePresence(ctx, jid) and return {data:{subscribed:true}}.

With the subscribe in place, the existing Presence → webhook path just starts flowing. No other change needed.


2. Decrypt edited messages (currently the new text is unreadable)

When a contact edits a text message, the event arrives with Info.Edit == "1" and the new text encrypted inside Message.secretEncryptedMessage (secretEncType: 2), with the original message key under secretEncryptedMessage.targetMessageKey. Because this is never decrypted, downstream consumers receive an opaque envelope instead of the edited text.

Real captured payload (redacted):

{
  "event": "Message",
  "data": {
    "Info": { "Edit": "1", "ID": "3A3EFD...", "IsFromMe": false, "Type": "text", "Timestamp": "..." },
    "IsEdit": false,
    "Message": {
      "secretEncryptedMessage": {
        "encIV": "", "encPayload": "", "secretEncType": 2,
        "targetMessageKey": { "ID": "3A35AE...", "fromMe": true, "remoteJID": "" }
      }
    }
  }
}

Two observations:

  • data.IsEdit is false even for an edit — the only reliable signal is Info.Edit == "1". If that's intended, it would help to document it; if not, it may be a small bug worth fixing.
  • The message handler already decrypts poll votes with DecryptPollVote (in pkg/whatsmeow/service/whatsmeow.go, in the same event-processing block that handles PollUpdateMessage). The edit path could mirror that: when evt.Info.Edit indicates an edit (or secretEncryptedMessage is present), decrypt the secret message and emit the resulting editedMessage / plaintext in the webhook (e.g. as protocolMessage.editedMessage or a decoded Message), so consumers can update the original bubble.

Request: decrypt the secretEncryptedMessage for edits (as already done for poll votes) and surface the plaintext new text in the webhook payload.


Environment

  • Evolution Go build "Evolution GO 1.0" (self-hosted), consumed by an external CRM via webhooks + REST.
  • Baileys-based Evolution API already surfaces both of these (contact online + decoded edits), so this is purely about reaching parity on the Go engine.

Thanks for the project! Glad to send PRs for these if you'd point me at the preferred approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions