Jacek Kowalski
4 hours ago 6b9278a5d57091fce636dbb640b380cfb990db6c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?php
declare(strict_types=1);
 
namespace App\Service;
 
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\Attribute\Target;
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
 
/**
 * Downloads covers from LibraryThing (https://www.librarything.com/services/covers.php).
 */
class LibraryThingCovers {
    private const int MAX_BYTES = 10 * 1024 * 1024;
 
    public function __construct(
        #[Target('librarything.client')]
        private readonly HttpClientInterface $libraryThingClient,
        private readonly LoggerInterface     $logger,
        #[Autowire('%app.librarything_api_key%')]
        private readonly ?string             $apiKey,
    ) {
    }
 
    public function isEnabled(): bool {
        return trim((string)$this->apiKey) !== '';
    }
 
    /**
     * @return string|null the image data, or null when there is no cover or it could not be fetched
     */
    public function download(string $isbn): ?string {
        if (!$this->isEnabled() || preg_match('/^[\dX]{10,13}$/', $isbn) !== 1) {
            return null;
        }
 
        try {
            $response = $this->libraryThingClient->request(
                'GET',
                \sprintf('/devkey/%s/large/isbn/%s', rawurlencode(trim((string)$this->apiKey)), $isbn),
            );
 
            if ($response->getStatusCode() !== 200) {
                $this->logger->warning('LibraryThing returned HTTP {status} for ISBN {isbn}.', [
                    'status' => $response->getStatusCode(),
                    'isbn' => $isbn,
                ]);
 
                return null;
            }
 
            $data = $response->getContent();
        } catch (ExceptionInterface $exception) {
            // The message would contain the URL, and with it the key.
            $this->logger->warning('The LibraryThing cover for ISBN {isbn} could not be downloaded.', ['isbn' => $isbn]);
 
            return null;
        }
 
        if (\strlen($data) > self::MAX_BYTES) {
            return null;
        }
 
        $size = @getimagesizefromstring($data);
 
        return $size === false || $size[0] <= 1 || $size[1] <= 1 ? null : $data;
    }
}