From 9f1cf7ac37dc1c4eced6311e1775e672834711fa Mon Sep 17 00:00:00 2001 From: luan Date: Fri, 19 Jun 2026 20:49:19 -0300 Subject: [PATCH] feat: add forwardingScore support to send text/media WhatsApp renders the Encaminhada badge when ContextInfo.ForwardingScore > 0. Evolution Go v1 did not expose this field, so forwarded messages arrived without the badge in the recipient's WhatsApp. Changes: - TextStruct and MediaStruct accept optional forwardingScore (uint32) - SendDataStruct carries it through to SendMessage - SendMessage applies it to the ContextInfo of every message type (text, image, video, ptv, audio, document, poll, sticker, location, contact, interactive, list) --- pkg/sendMessage/service/send_service.go | 163 ++++++++++++++++-------- 1 file changed, 113 insertions(+), 50 deletions(-) diff --git a/pkg/sendMessage/service/send_service.go b/pkg/sendMessage/service/send_service.go index c6ecdcdd..907938c1 100644 --- a/pkg/sendMessage/service/send_service.go +++ b/pkg/sendMessage/service/send_service.go @@ -58,14 +58,15 @@ type sendService struct { } type SendDataStruct struct { - Id string - Number string - Delay int32 - MentionAll bool - MentionedJID []string - FormatJid *bool - Quoted QuotedStruct - MediaHandle string + Id string + Number string + Delay int32 + MentionAll bool + MentionedJID []string + FormatJid *bool + Quoted QuotedStruct + MediaHandle string + ForwardingScore *uint32 } type QuotedStruct struct { @@ -74,14 +75,15 @@ type QuotedStruct struct { } type TextStruct struct { - Number string `json:"number"` - Text string `json:"text"` - Id string `json:"id"` - Delay int32 `json:"delay"` - MentionedJID []string `json:"mentionedJid"` - MentionAll bool `json:"mentionAll"` - FormatJid *bool `json:"formatJid,omitempty"` - Quoted QuotedStruct `json:"quoted"` + Number string `json:"number"` + Text string `json:"text"` + Id string `json:"id"` + Delay int32 `json:"delay"` + MentionedJID []string `json:"mentionedJid"` + MentionAll bool `json:"mentionAll"` + FormatJid *bool `json:"formatJid,omitempty"` + Quoted QuotedStruct `json:"quoted"` + ForwardingScore *uint32 `json:"forwardingScore,omitempty"` } type LinkStruct struct { @@ -100,17 +102,18 @@ type LinkStruct struct { } type MediaStruct struct { - Number string `json:"number"` - Url string `json:"url"` - Type string `json:"type"` - Caption string `json:"caption"` - Filename string `json:"filename"` - Id string `json:"id"` - Delay int32 `json:"delay"` - MentionedJID []string `json:"mentionedJid"` - MentionAll bool `json:"mentionAll"` - FormatJid *bool `json:"formatJid,omitempty"` - Quoted QuotedStruct `json:"quoted"` + Number string `json:"number"` + Url string `json:"url"` + Type string `json:"type"` + Caption string `json:"caption"` + Filename string `json:"filename"` + Id string `json:"id"` + Delay int32 `json:"delay"` + MentionedJID []string `json:"mentionedJid"` + MentionAll bool `json:"mentionAll"` + FormatJid *bool `json:"formatJid,omitempty"` + Quoted QuotedStruct `json:"quoted"` + ForwardingScore *uint32 `json:"forwardingScore,omitempty"` } type PollStruct struct { @@ -614,13 +617,14 @@ func (s *sendService) sendTextWithRetry(data *TextStruct, instance *instance_mod } message, err := s.SendMessage(instance, msg, "ExtendedTextMessage", &SendDataStruct{ - Id: data.Id, - Number: data.Number, - Quoted: data.Quoted, - Delay: data.Delay, - MentionAll: data.MentionAll, - MentionedJID: data.MentionedJID, - FormatJid: data.FormatJid, + Id: data.Id, + Number: data.Number, + Quoted: data.Quoted, + Delay: data.Delay, + MentionAll: data.MentionAll, + MentionedJID: data.MentionedJID, + FormatJid: data.FormatJid, + ForwardingScore: data.ForwardingScore, }) if err != nil { @@ -1161,14 +1165,15 @@ func (s *sendService) sendMediaFileWithRetry(data *MediaStruct, fileData []byte, } message, err := s.SendMessage(instance, media, mediaType, &SendDataStruct{ - Id: data.Id, - Number: data.Number, - Quoted: data.Quoted, - Delay: data.Delay, - MentionAll: data.MentionAll, - MentionedJID: data.MentionedJID, - FormatJid: data.FormatJid, - MediaHandle: uploaded.Handle, + Id: data.Id, + Number: data.Number, + Quoted: data.Quoted, + Delay: data.Delay, + MentionAll: data.MentionAll, + MentionedJID: data.MentionedJID, + FormatJid: data.FormatJid, + MediaHandle: uploaded.Handle, + ForwardingScore: data.ForwardingScore, }) if err != nil { @@ -1450,14 +1455,15 @@ func (s *sendService) sendMediaUrlWithRetry(data *MediaStruct, instance *instanc messageStart := time.Now() message, err := s.SendMessage(instance, media, mediaType, &SendDataStruct{ - Id: data.Id, - Number: data.Number, - Quoted: data.Quoted, - Delay: data.Delay, - MentionAll: data.MentionAll, - MentionedJID: data.MentionedJID, - FormatJid: data.FormatJid, - MediaHandle: uploaded.Handle, + Id: data.Id, + Number: data.Number, + Quoted: data.Quoted, + Delay: data.Delay, + MentionAll: data.MentionAll, + MentionedJID: data.MentionedJID, + FormatJid: data.FormatJid, + MediaHandle: uploaded.Handle, + ForwardingScore: data.ForwardingScore, }) if err != nil { @@ -2192,6 +2198,63 @@ func (s *sendService) SendMessage(instance *instance_model.Instance, msg *waE2E. } } + // Apply ForwardingScore to whichever ContextInfo was set above. + // WhatsApp renders "Encaminhada" when ContextInfo.ForwardingScore > 0. + if data.ForwardingScore != nil && *data.ForwardingScore > 0 { + switch messageType { + case "ExtendedTextMessage": + if msg.ExtendedTextMessage != nil && msg.ExtendedTextMessage.ContextInfo != nil { + msg.ExtendedTextMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "ImageMessage": + if msg.ImageMessage != nil && msg.ImageMessage.ContextInfo != nil { + msg.ImageMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "VideoMessage": + if msg.VideoMessage != nil && msg.VideoMessage.ContextInfo != nil { + msg.VideoMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "PtvMessage": + if msg.PtvMessage != nil && msg.PtvMessage.ContextInfo != nil { + msg.PtvMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "AudioMessage": + if msg.AudioMessage != nil && msg.AudioMessage.ContextInfo != nil { + msg.AudioMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "DocumentMessage": + if msg.DocumentMessage != nil && msg.DocumentMessage.ContextInfo != nil { + msg.DocumentMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } else if msg.DocumentWithCaptionMessage != nil && msg.DocumentWithCaptionMessage.Message != nil && msg.DocumentWithCaptionMessage.Message.DocumentMessage != nil && msg.DocumentWithCaptionMessage.Message.DocumentMessage.ContextInfo != nil { + msg.DocumentWithCaptionMessage.Message.DocumentMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "PollCreationMessage": + if msg.PollCreationMessage != nil && msg.PollCreationMessage.ContextInfo != nil { + msg.PollCreationMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "StickerMessage": + if msg.StickerMessage != nil && msg.StickerMessage.ContextInfo != nil { + msg.StickerMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "LocationMessage": + if msg.LocationMessage != nil && msg.LocationMessage.ContextInfo != nil { + msg.LocationMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "ContactMessage": + if msg.ContactMessage != nil && msg.ContactMessage.ContextInfo != nil { + msg.ContactMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "InteractiveMessage": + if msg.InteractiveMessage != nil && msg.InteractiveMessage.ContextInfo != nil { + msg.InteractiveMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + case "ListMessage": + if msg.ListMessage != nil && msg.ListMessage.ContextInfo != nil { + msg.ListMessage.ContextInfo.ForwardingScore = data.ForwardingScore + } + } + } + isGroup := strings.Contains(data.Number, "@g.us") isNewsletter := strings.Contains(data.Number, "@newsletter")