package main import ( "context" "errors" "fmt" "go.mau.fi/whatsmeow" "go.mau.fi/whatsmeow/proto/waE2E" ) // 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. func whatsappImage(ctx context.Context, client WhatsAppClient, store *ImageStore, message *waE2E.ImageMessage) (string, error) { if message.GetFileLength() > imageMaxBytes { return "", errImageSize } switch message.GetMimetype() { case "image/jpeg", "image/png", "image/webp": default: return "", errImageFormat } if client == nil { return "", errors.New("WhatsApp client is not available") } data, err := client.Download(ctx, message) if err != nil { return "", fmt.Errorf("download image: %w", whatsappImageDownloadError(err)) } name, err := store.Save(data) if err != nil { return "", fmt.Errorf("store image: %w", err) } return name, nil } // whatsappImageDownloadError keeps only known safe causes. Library errors can // contain signed URLs or direct paths even when request preparation fails, so // arbitrary error text cannot go to the daemon log. func whatsappImageDownloadError(err error) error { switch { case errors.Is(err, context.Canceled): return context.Canceled case errors.Is(err, context.DeadlineExceeded): return context.DeadlineExceeded } var response whatsmeow.DownloadHTTPError if errors.As(err, &response) && response.Response != nil { return fmt.Errorf("media server returned HTTP %d", response.StatusCode) } return errors.New("media download failed") }