Skip to content
Open
Show file tree
Hide file tree
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
164 changes: 103 additions & 61 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,18 +177,18 @@ func (s *server) authalice(next http.Handler) http.Handler {
log.Debug().Str("userId", txtid).Bool("historyValid", history.Valid).Int64("historyValue", history.Int64).Str("historyStr", historyStr).Msg("User authentication - history debug")

v := Values{map[string]string{
"Id": txtid,
"Name": name,
"Jid": jid,
"Webhook": webhook,
"Token": token,
"Proxy": proxy_url,
"Events": events,
"Qrcode": qrcode,
"History": historyStr,
"HasHmac": strconv.FormatBool(hasHmac),
"S3Enabled": s3Enabled,
"MediaDelivery": mediaDelivery,
"Id": txtid,
"Name": name,
"Jid": jid,
"Webhook": webhook,
"Token": token,
"Proxy": proxy_url,
"Events": events,
"Qrcode": qrcode,
"History": historyStr,
"HasHmac": strconv.FormatBool(hasHmac),
"S3Enabled": s3Enabled,
"MediaDelivery": mediaDelivery,
}}

userinfocache.Set(token, v, cache.NoExpiration)
Expand Down Expand Up @@ -813,13 +813,13 @@ func (s *server) GetStatus() http.HandlerFunc {
func (s *server) SendDocument() http.HandlerFunc {

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

Expand Down Expand Up @@ -874,21 +874,36 @@ func (s *server) SendDocument() http.HandlerFunc {
var uploaded whatsmeow.UploadResponse
var filedata []byte

if t.Document[0:29] == "data:application/octet-stream" {
if strings.HasPrefix(t.Document, "data:") {
var dataURL, err = dataurl.DecodeString(t.Document)
if err != nil {
s.Respond(w, r, http.StatusBadRequest, errors.New("could not decode base64 encoded data from payload"))
return
} else {
filedata = dataURL.Data
uploaded, err = clientManager.GetWhatsmeowClient(txtid).Upload(context.Background(), filedata, whatsmeow.MediaDocument)
if err != nil {
s.Respond(w, r, http.StatusInternalServerError, errors.New(fmt.Sprintf("failed to upload file: %v", err)))
return
}
}
filedata = dataURL.Data
} else if isHTTPURL(t.Document) {
data, ct, err := fetchURLBytes(r.Context(), t.Document, fetchDocumentMaxBytes)
if err != nil {
s.Respond(w, r, http.StatusBadRequest, errors.New(fmt.Sprintf("failed to fetch document from url: %v", err)))
return
}
if t.MimeType == "" {
t.MimeType = ct
}
filedata = data
} else {
s.Respond(w, r, http.StatusBadRequest, errors.New("document data should start with \"data:application/octet-stream;base64,\""))
s.Respond(w, r, http.StatusBadRequest, errors.New("document data should start with \"data:\" or be a valid HTTP URL"))
return
}

uploaded, err = mediaCache.GetOrUploadDocument(context.Background(), clientManager.GetWhatsmeowClient(txtid), filedata, func() string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Use r.Context() instead of context.Background() when calling mediaCache.GetOrUploadDocument. This allows the upload process to be cancelled if the HTTP request is closed by the client, which is a best practice for handling long-running operations in web handlers.

Suggested change
uploaded, err = mediaCache.GetOrUploadDocument(context.Background(), clientManager.GetWhatsmeowClient(txtid), filedata, func() string {
uploaded, err = mediaCache.GetOrUploadDocument(r.Context(), clientManager.GetWhatsmeowClient(txtid), filedata, func() string {

if t.MimeType != "" {
return t.MimeType
}
return http.DetectContentType(filedata)
}())
if err != nil {
s.Respond(w, r, http.StatusInternalServerError, errors.New(fmt.Sprintf("failed to upload file: %v", err)))
return
}

Expand Down Expand Up @@ -973,15 +988,15 @@ func (s *server) SendDocument() http.HandlerFunc {
func (s *server) SendAudio() http.HandlerFunc {

type audioStruct struct {
Phone string
Audio string
Caption string
Id string
PTT *bool `json:"ptt,omitempty"`
MimeType string `json:"mimetype,omitempty"`
Seconds uint32
Waveform []byte
ContextInfo waE2E.ContextInfo
Phone string
Audio string
Caption string
Id string
PTT *bool `json:"ptt,omitempty"`
MimeType string `json:"mimetype,omitempty"`
Seconds uint32
Waveform []byte
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

Expand Down Expand Up @@ -1035,16 +1050,29 @@ func (s *server) SendAudio() http.HandlerFunc {
if err != nil {
s.Respond(w, r, http.StatusBadRequest, errors.New("could not decode base64 encoded data from payload"))
return
} else {
filedata = dataURL.Data
uploaded, err = clientManager.GetWhatsmeowClient(txtid).Upload(context.Background(), filedata, whatsmeow.MediaAudio)
if err != nil {
s.Respond(w, r, http.StatusInternalServerError, errors.New(fmt.Sprintf("failed to upload file: %v", err)))
return
}
filedata = dataURL.Data
} else if isHTTPURL(t.Audio) {
data, ct, err := fetchURLBytes(r.Context(), t.Audio, fetchAudioMaxBytes)
if err != nil {
s.Respond(w, r, http.StatusBadRequest, errors.New(fmt.Sprintf("failed to fetch audio from url: %v", err)))
return
}
if t.MimeType == "" {
if strings.HasPrefix(strings.ToLower(ct), "audio/") {
mime = ct
}
// else mantém o default já definido (ogg ou mpeg)
}
filedata = data
} else {
s.Respond(w, r, http.StatusBadRequest, errors.New("audio data should start with \"data:audio/\""))
s.Respond(w, r, http.StatusBadRequest, errors.New("audio data should start with \"data:audio/\" or be a valid HTTP URL"))
return
}

uploaded, err = mediaCache.GetOrUploadAudio(context.Background(), clientManager.GetWhatsmeowClient(txtid), filedata, mime)
Comment on lines +1063 to +1073
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

This block contains a critical issue: the variable mime is used at lines 1063 and 1073 but is not declared until line 1086. This will result in a compilation error (undefined: mime).

Furthermore, the mime type resolution logic (including the defaults based on the PTT setting) should be executed before the mediaCache.GetOrUploadAudio call to ensure the correct metadata is used during the upload. Also, consider using r.Context() instead of context.Background() for the upload call to respect request cancellation.

if err != nil {
s.Respond(w, r, http.StatusInternalServerError, errors.New(fmt.Sprintf("failed to upload file: %v", err)))
return
}

Expand Down Expand Up @@ -1208,7 +1236,7 @@ func (s *server) SendImage() http.HandlerFunc {
filedata = dataURL.Data
}
} else if isHTTPURL(t.Image) {
data, ct, err := fetchURLBytes(r.Context(), t.Image, openGraphImageMaxBytes)
data, ct, err := fetchURLBytes(r.Context(), t.Image, fetchImageMaxBytes)
if err != nil {
s.Respond(w, r, http.StatusBadRequest, errors.New(fmt.Sprintf("failed to fetch image from url: %v", err)))
return
Expand Down Expand Up @@ -1402,6 +1430,20 @@ func (s *server) SendSticker() http.HandlerFunc {
msgid = t.Id
}

if isHTTPURL(t.Sticker) {
data, ct, err := fetchURLBytes(r.Context(), t.Sticker, fetchImageMaxBytes)
if err != nil {
s.Respond(w, r, http.StatusBadRequest, errors.New(fmt.Sprintf("failed to fetch sticker from url: %v", err)))
return
}
mimeType := ct
if !strings.HasPrefix(strings.ToLower(mimeType), "image/") {
mimeType = "image/webp"
}
imgDataURL := dataurl.New(data, mimeType)
t.Sticker = imgDataURL.String()
}

processedData, detectedMimeType, err := processStickerData(
t.Sticker,
t.MimeType,
Expand Down Expand Up @@ -1566,7 +1608,7 @@ func (s *server) SendVideo() http.HandlerFunc {

}
} else if isHTTPURL(t.Video) {
data, ct, err := fetchURLBytes(r.Context(), t.Video, openGraphImageMaxBytes)
data, ct, err := fetchURLBytes(r.Context(), t.Video, fetchVideoMaxBytes)
if err != nil {
s.Respond(w, r, http.StatusBadRequest, errors.New(fmt.Sprintf("failed to fetch image from url: %v", err)))
return
Expand Down Expand Up @@ -1675,11 +1717,11 @@ func (s *server) SendVideo() http.HandlerFunc {
func (s *server) SendContact() http.HandlerFunc {

type contactStruct struct {
Phone string
Id string
Name string
Vcard string
ContextInfo waE2E.ContextInfo
Phone string
Id string
Name string
Vcard string
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

Expand Down Expand Up @@ -1797,12 +1839,12 @@ func (s *server) SendContact() http.HandlerFunc {
func (s *server) SendLocation() http.HandlerFunc {

type locationStruct struct {
Phone string
Id string
Name string
Latitude float64
Longitude float64
ContextInfo waE2E.ContextInfo
Phone string
Id string
Name string
Latitude float64
Longitude float64
ContextInfo waE2E.ContextInfo
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
}

Expand Down Expand Up @@ -2244,8 +2286,8 @@ func (s *server) SendMessage() http.HandlerFunc {
LinkPreview bool
Id string
ContextInfo waE2E.ContextInfo
QuotedText string `json:"QuotedText,omitempty"`
QuotedMessage *waE2E.Message `json:"QuotedMessage,omitempty"`
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")
Expand Down Expand Up @@ -6701,14 +6743,14 @@ func (s *server) publishSentMessageEvent(token, userID, txtid string, recipient
var recipientLID types.JID
if client.Store != nil && client.Store.LIDs != nil {
ctx := context.Background()

// Get sender LID
if !senderJID.IsEmpty() {
if lid, err := client.Store.LIDs.GetLIDForPN(ctx, senderJID); err == nil && !lid.IsEmpty() {
senderLID = lid
}
}

// Get recipient LID (only for non-group chats)
if !isGroup && !recipient.IsEmpty() {
if lid, err := client.Store.LIDs.GetLIDForPN(ctx, recipient); err == nil && !lid.IsEmpty() {
Expand Down
9 changes: 7 additions & 2 deletions helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,12 @@ import (

const (
openGraphFetchTimeout = 5 * time.Second
openGraphPageMaxBytes = 2 * 1024 * 1024 // 2MB
openGraphImageMaxBytes = 10 * 1024 * 1024 // 10MB
fetchImageMaxBytes = 16 * 1024 * 1024 // 16MB
fetchVideoMaxBytes = 100 * 1024 * 1024 // 100MB
fetchAudioMaxBytes = 16 * 1024 * 1024 // 16MB
fetchDocumentMaxBytes = 100 * 1024 * 1024 // 100MB
openGraphPageMaxBytes = 2 * 1024 * 1024 // 2MB
openGraphImageMaxBytes = 10 * 1024 * 1024 // 10MB
openGraphThumbnailWidth = 100
openGraphThumbnailHeight = 100
openGraphJpegQuality = 80
Expand Down Expand Up @@ -136,6 +140,7 @@ func isHTTPURL(input string) bool {
}
return parsed.Host != ""
}

func fetchURLBytes(ctx context.Context, resourceURL string, limit int64) ([]byte, string, error) {
req, err := http.NewRequestWithContext(ctx, "GET", resourceURL, nil)
if err != nil {
Expand Down
Loading