Удалена обработка логотипов
This commit is contained in:
@@ -76,41 +76,4 @@ class ApiController extends BasicController
|
|||||||
return $this->responseJsonError($response, 404, $e);
|
return $this->responseJsonError($response, 404, $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает логотип канала
|
|
||||||
*
|
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return ResponseInterface
|
|
||||||
* @throws LoaderError
|
|
||||||
* @throws PlaylistNotFoundException
|
|
||||||
* @todo логотипы каналов
|
|
||||||
*/
|
|
||||||
public function logo(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
|
||||||
{
|
|
||||||
$code = $request->getAttributes()['code'];
|
|
||||||
$playlist = ini()->getPlaylist($code);
|
|
||||||
$channelHash = $request->getAttributes()['hash'];
|
|
||||||
$channel = $playlist['channels'][$channelHash];
|
|
||||||
$url = $channel['attributes']['tvg-logo'] ?? '';
|
|
||||||
|
|
||||||
$logo = new ChannelLogo($url);
|
|
||||||
if (!$logo->readFile()) {
|
|
||||||
$logo->fetch();
|
|
||||||
if ($logo->size() === 0) {
|
|
||||||
$logo->setDefault();
|
|
||||||
} else {
|
|
||||||
$logo->store();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$body = $logo->raw();
|
|
||||||
$size = $logo->size();
|
|
||||||
$mime = $logo->mimeType();
|
|
||||||
|
|
||||||
$response->getBody()->write($body);
|
|
||||||
return $response->withHeader('Content-Type', $mime)
|
|
||||||
->withHeader('Content-Length', $size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,200 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2025, Антон Аксенов
|
|
||||||
* This file is part of iptv.axenov.dev web interface
|
|
||||||
* MIT License: https://git.axenov.dev/IPTV/web/src/branch/master/LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Playlists;
|
|
||||||
|
|
||||||
class ChannelLogo implements \Stringable
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var string Валидированная ссылка на изображение
|
|
||||||
*/
|
|
||||||
public readonly string $url;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string|null Хэш от ссылки на изображение
|
|
||||||
*/
|
|
||||||
public readonly ?string $hash;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string|null Путь к файлу изображению на диске
|
|
||||||
*/
|
|
||||||
protected ?string $path = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string|null MIME-тип изображения
|
|
||||||
*/
|
|
||||||
protected ?string $mimeType = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var false|string|null Сырое изображение:
|
|
||||||
* null -- не загружалось;
|
|
||||||
* false -- ошибка загрузки;
|
|
||||||
* string -- бинарные данные.
|
|
||||||
*/
|
|
||||||
protected false|string|null $rawData = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Конструктор
|
|
||||||
*
|
|
||||||
* @param string $url Внешняя ссылка на изображение
|
|
||||||
*/
|
|
||||||
public function __construct(string $url)
|
|
||||||
{
|
|
||||||
$url = empty($url) ? base_url('public/no-tvg-logo.png') : $this->prepareUrl($url);
|
|
||||||
if (is_string($url)) {
|
|
||||||
$this->url = $url;
|
|
||||||
$this->hash = md5($url);
|
|
||||||
$this->path = cache_path("tv-logos/$this->hash");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Валидирует и очищает ссылку на изображение
|
|
||||||
*
|
|
||||||
* @param string $url
|
|
||||||
* @return false|string
|
|
||||||
*/
|
|
||||||
protected function prepareUrl(string $url): false|string
|
|
||||||
{
|
|
||||||
$parts = parse_url(trim($url));
|
|
||||||
if (!is_array($parts) || count($parts) < 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $parts['scheme'] . '://' . $parts['host'];
|
|
||||||
$result .= (empty($parts['port']) ? '' : ':' . $parts['port']);
|
|
||||||
|
|
||||||
return $result . $parts['path'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Загружает сырое изображение по ссылке и определяет его MIME-тип
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function fetch(): bool
|
|
||||||
{
|
|
||||||
$this->rawData = @file_get_contents($this->url);
|
|
||||||
$isFetched = is_string($this->rawData);
|
|
||||||
if (!$isFetched) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->mimeType = $this->mimeType();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Сохраняет сырое изображение в кэш
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function store(): bool
|
|
||||||
{
|
|
||||||
return is_string($this->rawData)
|
|
||||||
&& $this->prepareCacheDir()
|
|
||||||
&& @file_put_contents($this->path, $this->rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Считывает изображение из кэша
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function readFile(): bool
|
|
||||||
{
|
|
||||||
if (!file_exists($this->path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->rawData = @file_get_contents($this->path);
|
|
||||||
return is_string($this->rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Считывает дефолтный эскиз вместо логотипа
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function setDefault(): bool
|
|
||||||
{
|
|
||||||
$this->path = root_path('public/no-tvg-logo.png');
|
|
||||||
return $this->readFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает base64-кодированное изображение
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function asBase64(): ?string
|
|
||||||
{
|
|
||||||
if (!is_string($this->rawData)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "data:$this->mimeType;base64," . base64_encode($this->rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает сырое изображение
|
|
||||||
*
|
|
||||||
* @return false|string|null
|
|
||||||
*/
|
|
||||||
public function raw(): false|string|null
|
|
||||||
{
|
|
||||||
return $this->rawData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверяет готовность директории кэша изображений, создавая её при необходимости
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function prepareCacheDir(): bool
|
|
||||||
{
|
|
||||||
$cacheFileDir = cache_path('tv-logos');
|
|
||||||
|
|
||||||
return is_dir($cacheFileDir)
|
|
||||||
|| @mkdir($cacheFileDir, 0775, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает MIME-тип сырого изображения
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function mimeType(): ?string
|
|
||||||
{
|
|
||||||
if (!is_string($this->rawData)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$finfo = new \finfo(FILEINFO_MIME_TYPE);
|
|
||||||
return $finfo->buffer($this->rawData) ?: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает размер сырого изображения в байтах
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function size(): int
|
|
||||||
{
|
|
||||||
return strlen((string)$this->rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function __toString(): string
|
|
||||||
{
|
|
||||||
return $this->asBase64();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user