Skip to content
Open
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
163 changes: 113 additions & 50 deletions pkg/sendMessage/service/send_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Comment on lines +2201 to +2210

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: The large switch for setting ForwardingScore is repetitive and may be brittle as new message types are added.

Consider extracting a helper like getContextInfo(msg *waE2E.Message, messageType string) *waE2E.ContextInfo that encapsulates the mapping (including the DocumentWithCaptionMessage special case), and then set ctx.ForwardingScore only if the returned context is non-nil. Centralizing this logic would reduce duplication and make it easier to keep in sync as new message types are added.

Suggested implementation:

	// Apply ForwardingScore to whichever ContextInfo was set above.
	// WhatsApp renders "Encaminhada" when ContextInfo.ForwardingScore > 0.
	if data.ForwardingScore != nil && *data.ForwardingScore > 0 {
		if ctxInfo := getContextInfo(msg, messageType); ctxInfo != nil {
			ctxInfo.ForwardingScore = data.ForwardingScore
		}

To fully implement the refactor:

  1. Define the helper in pkg/sendMessage/service/send_service.go (near the other send helpers / below this function):
func getContextInfo(msg *waE2E.Message, messageType string) *waE2E.ContextInfo {
	switch messageType {
	case "ExtendedTextMessage":
		if msg.ExtendedTextMessage != nil {
			return msg.ExtendedTextMessage.ContextInfo
		}
	case "ImageMessage":
		if msg.ImageMessage != nil {
			return msg.ImageMessage.ContextInfo
		}
	case "DocumentWithCaptionMessage":
		// Use the same logic that currently exists in the large switch, e.g.:
		// - If the DocumentWithCaptionMessage has its own ContextInfo, return it
		// - Otherwise, return the underlying DocumentMessage.ContextInfo (or whatever the current special-case logic is)
		// Example skeleton (adjust field names to match the existing code):
		if msg.DocumentWithCaptionMessage != nil {
			if msg.DocumentWithCaptionMessage.ContextInfo != nil {
				return msg.DocumentWithCaptionMessage.ContextInfo
			}
			if msg.DocumentWithCaptionMessage.DocumentMessage != nil {
				return msg.DocumentWithCaptionMessage.DocumentMessage.ContextInfo
			}
		}
	// Add remaining message types currently handled in the big ForwardingScore switch:
	//   - VideoMessage
	//   - AudioMessage
	//   - DocumentMessage
	//   - etc.
	// Each case should mirror the existing logic used to select which ContextInfo gets ForwardingScore.
	}
	return nil
}
  1. For every case that was previously present in the large switch messageType { ... } (that set ForwardingScore directly on msg.<Type>.ContextInfo), add a corresponding case in getContextInfo that returns the same ContextInfo pointer instead of setting the score.

  2. Ensure the special DocumentWithCaptionMessage handling in getContextInfo exactly mirrors the current behavior from the old switch (including any fallback to DocumentMessage.ContextInfo or other fields).

Once this helper contains all the cases, the call site you edited will correctly centralize the mapping and reduce duplication.

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":

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nitpick: The nested DocumentWithCaptionMessage condition is quite dense and could be made more readable.

Consider extracting msg.DocumentWithCaptionMessage.Message.DocumentMessage into a local variable (and/or splitting the checks into separate if blocks or early returns) to simplify the condition and make future changes less error‑prone.

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
}
Comment on lines +2247 to +2250
case "ListMessage":
if msg.ListMessage != nil && msg.ListMessage.ContextInfo != nil {
msg.ListMessage.ContextInfo.ForwardingScore = data.ForwardingScore
}
Comment on lines +2251 to +2254
}
}

isGroup := strings.Contains(data.Number, "@g.us")
isNewsletter := strings.Contains(data.Number, "@newsletter")

Expand Down