Skip to content

send: add BuildReply helper for quoting messages#1147

Open
jobasfernandes wants to merge 1 commit into
tulir:mainfrom
jobasfernandes:feat/build-reply
Open

send: add BuildReply helper for quoting messages#1147
jobasfernandes wants to merge 1 commit into
tulir:mainfrom
jobasfernandes:feat/build-reply

Conversation

@jobasfernandes
Copy link
Copy Markdown

@jobasfernandes jobasfernandes commented May 14, 2026

Adds Client.BuildReply, following the same pattern as BuildRevoke/BuildEdit/BuildPollVote. Today callers have to hand-build ContextInfo, pick the right field per message type, promote Conversation to ExtendedTextMessage, and remember to strip the nested QuotedMessage to avoid transitive quote chains. BuildReply does all of that, matching what the official WhatsApp clients do before embedding a quoted message.

  • Embeds a stripped copy of the quoted message: principal content only, nested ContextInfo.QuotedMessage cleared. When an ExtendedTextMessage ends up with only Text after the strip, it is downgraded to Conversation to match what the official client emits.
  • Promotes plain Conversation reply content to ExtendedTextMessage.
  • Preserves any ContextInfo already on the reply content (mentions, forwarding flags).
  • Resolves Participant to the bot's own JID (PN or LID, matching the quoted message's server) for self-quotes, otherwise Sender.ToNonAD().
  • Returns ErrUnsupportedReplyType for content types with no ContextInfo field (reactions, protocol messages, etc.).

Purely additive - callers that build ContextInfo manually are unaffected.

Example:

client.AddEventHandler(func(evt any) {
    msg, ok := evt.(*events.Message)
    if !ok {
        return
    }
    reply, err := client.BuildReply(&msg.Info, msg.Message, &waE2E.Message{
        Conversation: proto.String("got it"),
    })
    if err != nil {
        return
    }
    _, _ = client.SendMessage(context.Background(), msg.Info.Chat, reply)
})

The same helper works for media replies - set ImageMessage/VideoMessage/DocumentMessage/etc. on the reply content and BuildReply injects the ContextInfo into the right field.

If you prefer something simpler, I can do it like this:

func (cli *Client) BuildQuotedContext(info *types.MessageInfo, quotedMsg *waE2E.Message) *waE2E.ContextInfo

which builds the ContextInfo only, with the caller setting it on whichever message field they choose. No per-type switch, no auto promotion/downgrade, no field injection.

Checklist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant