]> git.giacomolli.uk - onechat/blobdiff - whatsapp_image.go
Send stored images to WhatsApp chats
[onechat] / whatsapp_image.go
index d4b88d8303a6c2a2aed12fb59d780fbb4825acbc..5ce13a8b7f1d391d73377ab56aee127bf6d06925 100644 (file)
@@ -4,11 +4,16 @@ import (
        "context"
        "errors"
        "fmt"
        "context"
        "errors"
        "fmt"
+       "net/http"
+       "time"
 
        "go.mau.fi/whatsmeow"
        "go.mau.fi/whatsmeow/proto/waE2E"
 )
 
 
        "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.
 // 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.
@@ -59,3 +64,39 @@ func whatsappImageDownloadError(err error) error {
 
        return errors.New("media download failed")
 }
 
        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")
+       }
+}