"context"
"errors"
"fmt"
+ "net/http"
+ "time"
"go.mau.fi/whatsmeow"
"go.mau.fi/whatsmeow/proto/waE2E"
)
+// whatsappImageUploadTimeout limits one image upload to WhatsApp.
+const whatsappImageUploadTimeout = 2 * time.Minute
+
// whatsappImage downloads only supported images and stores them before the
// event can be acknowledged. Both the declared size and the downloaded bytes
// must fit the image store. Decoded bytes determine the stored format.
return errors.New("media download failed")
}
+
+// whatsappImageMessage uploads stored pixels and uses the upload keys only in
+// the outgoing message. The text is the caption, not a separate message.
+func whatsappImageMessage(ctx context.Context, client WhatsAppClient, data []byte, text string) (*waE2E.Message, error) {
+ ctx, cancel := context.WithTimeout(ctx, whatsappImageUploadTimeout)
+ defer cancel()
+
+ upload, err := client.Upload(ctx, data, whatsmeow.MediaImage)
+ if err != nil {
+ return nil, fmt.Errorf("upload image: %w", whatsappImageSendError(err))
+ }
+
+ return &waE2E.Message{ImageMessage: &waE2E.ImageMessage{
+ Caption: new(text),
+ Mimetype: new(http.DetectContentType(data)),
+ URL: &upload.URL,
+ DirectPath: &upload.DirectPath,
+ MediaKey: upload.MediaKey,
+ FileEncSHA256: upload.FileEncSHA256,
+ FileSHA256: upload.FileSHA256,
+ FileLength: &upload.FileLength,
+ }}, nil
+}
+
+// whatsappImageSendError drops arbitrary upload and send errors, which can hold
+// media URLs and keys. Cancellation and deadline causes are safe to keep.
+func whatsappImageSendError(err error) error {
+ switch {
+ case errors.Is(err, context.Canceled):
+ return context.Canceled
+ case errors.Is(err, context.DeadlineExceeded):
+ return context.DeadlineExceeded
+ default:
+ return errors.New("media send failed")
+ }
+}