118 lines
3.7 KiB
PHP
118 lines
3.7 KiB
PHP
<?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\Controllers;
|
||
|
||
use App\Errors\PlaylistNotFoundException;
|
||
use App\Playlists\ChannelLogo;
|
||
use chillerlan\QRCode\QRCode;
|
||
use chillerlan\QRCode\QROptions;
|
||
use Psr\Http\Message\ResponseInterface;
|
||
use Psr\Http\Message\ServerRequestInterface;
|
||
use Twig\Error\LoaderError;
|
||
|
||
/**
|
||
* Контроллер методов API
|
||
*/
|
||
class ApiController extends BasicController
|
||
{
|
||
/**
|
||
* Возвращает информацию о каналов плейлиста
|
||
*
|
||
* @param ServerRequestInterface $request
|
||
* @param ResponseInterface $response
|
||
* @return ResponseInterface
|
||
* @throws LoaderError
|
||
*/
|
||
public function makeQrCode(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||
{
|
||
$code = $request->getAttribute('code');
|
||
$codes = array_keys(ini()->getPlaylists());
|
||
if (!in_array($code, $codes, true)) {
|
||
return $response->withStatus(404);
|
||
}
|
||
|
||
$filePath = cache_path("qr-codes/$code.jpg");
|
||
if (file_exists($filePath)) {
|
||
$raw = file_get_contents($filePath);
|
||
} else {
|
||
$options = new QROptions([
|
||
'version' => 5,
|
||
'outputType' => QRCode::OUTPUT_IMAGE_JPG,
|
||
'eccLevel' => QRCode::ECC_L,
|
||
]);
|
||
$data = base_url("$code");
|
||
$raw = (new QRCode($options))->render($data, $filePath);
|
||
$raw = base64_decode(str_replace('data:image/jpg;base64,', '', $raw));
|
||
}
|
||
|
||
$mime = mime_content_type($filePath);
|
||
$response->getBody()->write($raw);
|
||
return $response->withStatus(200)
|
||
->withHeader('Content-Type', $mime);
|
||
}
|
||
|
||
/**
|
||
* Возвращает информацию о плейлисте
|
||
*
|
||
* @param ServerRequestInterface $request
|
||
* @param ResponseInterface $response
|
||
* @return ResponseInterface
|
||
* @throws LoaderError
|
||
*/
|
||
public function getPlaylist(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
|
||
{
|
||
$code = $request->getAttributes()['code'];
|
||
|
||
try {
|
||
$playlist = ini()->getPlaylist($code);
|
||
return $this->responseJson($response, 200, $playlist);
|
||
} catch (PlaylistNotFoundException $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);
|
||
}
|
||
}
|