]> git.giacomolli.uk - onechat/blob - whatsapp_image.go
Name timeouts for the operations they limit
[onechat] / whatsapp_image.go
1 package main
2
3 import (
4 "context"
5 "errors"
6 "fmt"
7
8 "go.mau.fi/whatsmeow"
9 "go.mau.fi/whatsmeow/proto/waE2E"
10 )
11
12 // whatsappImage downloads only supported images and stores them before the
13 // event can be acknowledged. Both the declared size and the downloaded bytes
14 // must fit the image store. Decoded bytes determine the stored format.
15 func whatsappImage(ctx context.Context, client WhatsAppClient, store *ImageStore, message *waE2E.ImageMessage) (string, error) {
16 if message.GetFileLength() > imageMaxBytes {
17 return "", errImageSize
18 }
19
20 switch message.GetMimetype() {
21 case "image/jpeg", "image/png", "image/webp":
22 default:
23 return "", errImageFormat
24 }
25
26 if client == nil {
27 return "", errors.New("WhatsApp client is not available")
28 }
29
30 data, err := client.Download(ctx, message)
31 if err != nil {
32 return "", fmt.Errorf("download image: %w", whatsappImageDownloadError(err))
33 }
34
35 name, err := store.Save(data)
36 if err != nil {
37 return "", fmt.Errorf("store image: %w", err)
38 }
39
40 return name, nil
41 }
42
43 // whatsappImageDownloadError keeps only known safe causes. Library errors can
44 // contain signed URLs or direct paths even when request preparation fails, so
45 // arbitrary error text cannot go to the daemon log.
46 func whatsappImageDownloadError(err error) error {
47 switch {
48 case errors.Is(err, context.Canceled):
49 return context.Canceled
50 case errors.Is(err, context.DeadlineExceeded):
51 return context.DeadlineExceeded
52 }
53
54 var response whatsmeow.DownloadHTTPError
55
56 if errors.As(err, &response) && response.Response != nil {
57 return fmt.Errorf("media server returned HTTP %d", response.StatusCode)
58 }
59
60 return errors.New("media download failed")
61 }