Skip to content
Merged
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
204 changes: 142 additions & 62 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@ func (s *server) SendDocument() http.HandlerFunc {
Id string
MimeType string
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

return func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -906,10 +907,22 @@ func (s *server) SendDocument() http.HandlerFunc {
}}

if t.ContextInfo.StanzaID != nil {
msg.DocumentMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: &waE2E.Message{Conversation: proto.String("")},
var qm *waE2E.Message

// If QuotedMessage was provided, use it.
if t.QuotedMessage != nil {
qm = t.QuotedMessage
} else {
// Otherwise, it uses the old logic (empty message).
qm = &waE2E.Message{Conversation: proto.String("")}
}

if msg.DocumentMessage.ContextInfo == nil {
msg.DocumentMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: qm,
}
}
}
Comment on lines 909 to 927
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There's significant code duplication across several Send... handlers for building the ContextInfo with a quoted message. This logic is repeated in SendAudio, SendImage, SendSticker, SendVideo, SendContact, and SendLocation.

To improve maintainability and reduce redundancy, you could extract this logic into a helper function. For example, you could create a function that takes a pointer to the message's ContextInfo field and sets it accordingly.

Here's an example of what such a helper function could look like:

func (s *server) setQuotedContextInfo(
	contextInfo **waE2E.ContextInfo,
	reqContextInfo waE2E.ContextInfo,
	quotedMessage *waE2E.Message,
) {
	if reqContextInfo.StanzaID == nil {
		return
	}

	// Don't overwrite if it's already set (e.g., by another part of the handler)
	if *contextInfo != nil {
		return
	}

	qm := quotedMessage
	if qm == nil {
		qm = &waE2E.Message{Conversation: proto.String("")}
	}

	*contextInfo = &waE2E.ContextInfo{
		StanzaID:      proto.String(*reqContextInfo.StanzaID),
		Participant:   proto.String(*reqContextInfo.Participant),
		QuotedMessage: qm,
	}
}

You could then call it from SendDocument like this:

s.setQuotedContextInfo(&msg.DocumentMessage.ContextInfo, t.ContextInfo, t.QuotedMessage)

And similarly for the other 6 handlers, just changing &msg.DocumentMessage.ContextInfo to &msg.AudioMessage.ContextInfo, etc. This would make the code much cleaner and easier to maintain.

if t.ContextInfo.MentionedJID != nil {
Expand Down Expand Up @@ -961,6 +974,7 @@ func (s *server) SendAudio() http.HandlerFunc {
Seconds uint32
Waveform []byte
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

return func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -1059,10 +1073,22 @@ func (s *server) SendAudio() http.HandlerFunc {
}}

if t.ContextInfo.StanzaID != nil {
msg.AudioMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: &waE2E.Message{Conversation: proto.String("")},
var qm *waE2E.Message

// If QuotedMessage was provided, use it.
if t.QuotedMessage != nil {
qm = t.QuotedMessage
} else {
// Otherwise, it uses the old logic (empty message).
qm = &waE2E.Message{Conversation: proto.String("")}
}

if msg.AudioMessage.ContextInfo == nil {
msg.AudioMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: qm,
}
}
}
if t.ContextInfo.MentionedJID != nil {
Expand Down Expand Up @@ -1105,12 +1131,13 @@ func (s *server) SendAudio() http.HandlerFunc {
func (s *server) SendImage() http.HandlerFunc {

type imageStruct struct {
Phone string
Image string
Caption string
Id string
MimeType string
ContextInfo waE2E.ContextInfo
Phone string
Image string
Caption string
Id string
MimeType string
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

return func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -1243,11 +1270,21 @@ func (s *server) SendImage() http.HandlerFunc {
}}

if t.ContextInfo.StanzaID != nil {
var qm *waE2E.Message

// If QuotedMessage was provided, use it.
if t.QuotedMessage != nil {
qm = t.QuotedMessage
} else {
// Otherwise, it uses the old logic (empty message).
qm = &waE2E.Message{Conversation: proto.String("")}
}

if msg.ImageMessage.ContextInfo == nil {
msg.ImageMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: &waE2E.Message{Conversation: proto.String("")},
QuotedMessage: qm,
}
}
}
Expand Down Expand Up @@ -1302,6 +1339,7 @@ func (s *server) SendSticker() http.HandlerFunc {
PackPublisher string
Emojis []string
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

return func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -1382,10 +1420,22 @@ func (s *server) SendSticker() http.HandlerFunc {
}}

if t.ContextInfo.StanzaID != nil {
msg.StickerMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: &waE2E.Message{Conversation: proto.String("")},
var qm *waE2E.Message

// If QuotedMessage was provided, use it.
if t.QuotedMessage != nil {
qm = t.QuotedMessage
} else {
// Otherwise, it uses the old logic (empty message).
qm = &waE2E.Message{Conversation: proto.String("")}
}

if msg.StickerMessage.ContextInfo == nil {
msg.StickerMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: qm,
}
}
}
if t.ContextInfo.MentionedJID != nil {
Expand Down Expand Up @@ -1435,6 +1485,7 @@ func (s *server) SendVideo() http.HandlerFunc {
JPEGThumbnail []byte
MimeType string
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

return func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -1538,10 +1589,22 @@ func (s *server) SendVideo() http.HandlerFunc {
}}

if t.ContextInfo.StanzaID != nil {
msg.VideoMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: &waE2E.Message{Conversation: proto.String("")},
var qm *waE2E.Message

// If QuotedMessage was provided, use it.
if t.QuotedMessage != nil {
qm = t.QuotedMessage
} else {
// Otherwise, it uses the old logic (empty message).
qm = &waE2E.Message{Conversation: proto.String("")}
}

if msg.VideoMessage.ContextInfo == nil {
msg.VideoMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: qm,
}
}
}
if t.ContextInfo.MentionedJID != nil {
Expand Down Expand Up @@ -1589,6 +1652,7 @@ func (s *server) SendContact() http.HandlerFunc {
Name string
Vcard string
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

return func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -1642,10 +1706,22 @@ func (s *server) SendContact() http.HandlerFunc {
}}

if t.ContextInfo.StanzaID != nil {
msg.ContactMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: &waE2E.Message{Conversation: proto.String("")},
var qm *waE2E.Message

// If QuotedMessage was provided, use it.
if t.QuotedMessage != nil {
qm = t.QuotedMessage
} else {
// Otherwise, it uses the old logic (empty message).
qm = &waE2E.Message{Conversation: proto.String("")}
}

if msg.ContactMessage.ContextInfo == nil {
msg.ContactMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: qm,
}
}
}
if t.ContextInfo.MentionedJID != nil {
Expand Down Expand Up @@ -1694,6 +1770,7 @@ func (s *server) SendLocation() http.HandlerFunc {
Latitude float64
Longitude float64
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

return func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -1748,10 +1825,22 @@ func (s *server) SendLocation() http.HandlerFunc {
}}

if t.ContextInfo.StanzaID != nil {
msg.LocationMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: &waE2E.Message{Conversation: proto.String("")},
var qm *waE2E.Message

// If QuotedMessage was provided, use it.
if t.QuotedMessage != nil {
qm = t.QuotedMessage
} else {
// Otherwise, it uses the old logic (empty message).
qm = &waE2E.Message{Conversation: proto.String("")}
}

if msg.LocationMessage.ContextInfo == nil {
msg.LocationMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
QuotedMessage: qm,
}
}
}
if t.ContextInfo.MentionedJID != nil {
Expand Down Expand Up @@ -2100,73 +2189,61 @@ func (s *server) SetStatusMessage() http.HandlerFunc {

// Sends a regular text message
func (s *server) SendMessage() http.HandlerFunc {

type textStruct struct {
Phone string
Body string
LinkPreview bool
Id string
ContextInfo waE2E.ContextInfo
QuotedText string `json:"QuotedText,omitempty"`
Phone string
Body string
LinkPreview bool
Id string
ContextInfo waE2E.ContextInfo
QuotedText string `json:"QuotedText,omitempty"`
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

return func(w http.ResponseWriter, r *http.Request) {

txtid := r.Context().Value("userinfo").(Values).Get("Id")

if clientManager.GetWhatsmeowClient(txtid) == nil {
s.Respond(w, r, http.StatusInternalServerError, errors.New("no session"))
return
}

msgid := ""
var resp whatsmeow.SendResponse

decoder := json.NewDecoder(r.Body)
var t textStruct
err := decoder.Decode(&t)
if err != nil {
s.Respond(w, r, http.StatusBadRequest, errors.New("could not decode Payload"))
return
}

if t.Phone == "" {
s.Respond(w, r, http.StatusBadRequest, errors.New("missing Phone in Payload"))
return
}

if t.Body == "" {
s.Respond(w, r, http.StatusBadRequest, errors.New("missing Body in Payload"))
return
}

recipient, err := validateMessageFields(t.Phone, t.ContextInfo.StanzaID, t.ContextInfo.Participant)
if err != nil {
log.Error().Msg(fmt.Sprintf("%s", err))
s.Respond(w, r, http.StatusBadRequest, err)
return
}

if t.Id == "" {
msgid = clientManager.GetWhatsmeowClient(txtid).GenerateMessageID()
} else {
msgid = t.Id
}

var (
url string
title string
description string
imageData []byte
)

if t.LinkPreview {
url = extractFirstURL(t.Body)
if url != "" {
title, description, imageData = getOpenGraphData(r.Context(), url, txtid)
}
}

msg := &waE2E.Message{
ExtendedTextMessage: &waE2E.ExtendedTextMessage{
Text: proto.String(t.Body),
Expand All @@ -2176,16 +2253,24 @@ func (s *server) SendMessage() http.HandlerFunc {
JPEGThumbnail: imageData,
},
}

if t.ContextInfo.StanzaID != nil {
qm := &waE2E.Message{}
if t.QuotedText != "" {
qm.ExtendedTextMessage = &waE2E.ExtendedTextMessage{
Text: proto.String(t.QuotedText),
}
var qm *waE2E.Message

// If QuotedMessage was provided, use it.
if t.QuotedMessage != nil {
qm = t.QuotedMessage
} else {
qm.Conversation = proto.String("")
// Otherwise, use the old logic with QuotedText.
qm = &waE2E.Message{}
if t.QuotedText != "" {
qm.ExtendedTextMessage = &waE2E.ExtendedTextMessage{
Text: proto.String(t.QuotedText),
}
} else {
qm.Conversation = proto.String("")
}
}
Comment on lines +2257 to 2272
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This logic for determining qm can be simplified by removing the var declaration and the outer if/else structure. This makes the code more concise and easier to read.

qm := t.QuotedMessage
			if qm == nil {
				// Otherwise, use the old logic with QuotedText.
				qm = &waE2E.Message{}
				if t.QuotedText != "" {
					qm.ExtendedTextMessage = &waE2E.ExtendedTextMessage{
						Text: proto.String(t.QuotedText),
					}
				} else {
					qm.Conversation = proto.String("")
				}
			}


msg.ExtendedTextMessage.ContextInfo = &waE2E.ContextInfo{
StanzaID: proto.String(*t.ContextInfo.StanzaID),
Participant: proto.String(*t.ContextInfo.Participant),
Expand All @@ -2198,24 +2283,20 @@ func (s *server) SendMessage() http.HandlerFunc {
}
msg.ExtendedTextMessage.ContextInfo.MentionedJID = t.ContextInfo.MentionedJID
}

if t.ContextInfo.IsForwarded != nil && *t.ContextInfo.IsForwarded {
if msg.ExtendedTextMessage.ContextInfo == nil {
msg.ExtendedTextMessage.ContextInfo = &waE2E.ContextInfo{}
}
msg.ExtendedTextMessage.ContextInfo.IsForwarded = proto.Bool(true)
}

resp, err = clientManager.GetWhatsmeowClient(txtid).SendMessage(context.Background(), recipient, msg, whatsmeow.SendRequestExtra{ID: msgid})
if err != nil {
s.Respond(w, r, http.StatusInternalServerError, errors.New(fmt.Sprintf("error sending message: %v", err)))
return
}

historyStr := r.Context().Value("userinfo").(Values).Get("History")
historyLimit, _ := strconv.Atoi(historyStr)
s.saveOutgoingMessageToHistory(txtid, recipient.String(), msgid, "text", t.Body, "", historyLimit)

log.Info().Str("timestamp", fmt.Sprintf("%v", resp.Timestamp)).Str("id", msgid).Msg("Message sent")
response := map[string]interface{}{"Details": "Sent", "Timestamp": resp.Timestamp.Unix(), "Id": msgid}
responseJson, err := json.Marshal(response)
Expand All @@ -2224,7 +2305,6 @@ func (s *server) SendMessage() http.HandlerFunc {
} else {
s.Respond(w, r, http.StatusOK, string(responseJson))
}

return
}
}
Expand Down
Loading