the browser-facing portion of osu!
at master 2.1 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6namespace App\Libraries; 7 8use App\Exceptions\ImageProcessorServiceException; 9use App\Models\Beatmapset; 10use GuzzleHttp\Client; 11use GuzzleHttp\Exception\GuzzleException; 12 13class ImageProcessorService 14{ 15 private string $endpoint; 16 17 public function __construct(?string $endpoint = null) 18 { 19 $this->endpoint = $endpoint ?? $GLOBALS['cfg']['osu']['beatmap_processor']['thumbnailer']; 20 } 21 22 private static function isValidFormat($size) 23 { 24 return in_array($size, Beatmapset::coverSizes(), true); 25 } 26 27 public function optimize($src) 28 { 29 return $this->process('optim', $src); 30 } 31 32 public function resize($src, $format) 33 { 34 if (!self::isValidFormat($format)) { 35 throw new ImageProcessorServiceException('Invalid format requested.'); 36 } 37 38 return $this->process("thumb/$format", $src); 39 } 40 41 // returns a handle instead of a filename to keep tmpfile alive 42 public function process($method, $src) 43 { 44 $src = preg_replace('/https?:\/\//', '', $src); 45 try { 46 $tmpFile = tmpfile(); 47 $bytesWritten = fwrite( 48 $tmpFile, 49 (new Client())->request('GET', "{$this->endpoint}/{$method}/{$src}")->getBody()->getContents(), 50 ); 51 } catch (GuzzleException $e) { 52 if (str_contains($e->getMessage(), 'VipsJpeg: Premature end of input file')) { 53 throw new ImageProcessorServiceException( 54 'Invalid image file', 55 ImageProcessorServiceException::INVALID_IMAGE, 56 $e, 57 ); 58 } 59 throw new ImageProcessorServiceException('HTTP request failed!', 0, $e); 60 } 61 62 if ($bytesWritten === false || $bytesWritten < 100) { 63 throw new ImageProcessorServiceException("Error retrieving processed image: $method."); 64 } 65 66 return $tmpFile; 67 } 68}