Parse API json payloads. Added new plex discover api endpoint.

This commit is contained in:
Abdulmhsen B. A. A
2024-04-09 00:44:33 +03:00
parent 6963087332
commit fd99950ac0
11 changed files with 208 additions and 167 deletions

View File

@@ -6,23 +6,24 @@ namespace App\API\Backends;
use App\Libs\Attributes\Route\Get;
use App\Libs\Config;
use App\Libs\ConfigFile;
use App\Libs\HTTP_STATUS;
use App\Libs\Options;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface as iResponse;
use Psr\Http\Message\ServerRequestInterface as iRequest;
#[Get(self::URL . '[/]', name: 'backends.index')]
final class Index
{
public const URL = '%{api.prefix}/backends';
public const string URL = '%{api.prefix}/backends';
public const BLACK_LIST = [
public const array BLACK_LIST = [
'token',
'webhook.token',
'options.' . Options::ADMIN_TOKEN
];
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
#[Get(self::URL . '[/]', name: 'backends.index')]
public function backendsIndex(iRequest $request): iResponse
{
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$urlPath = $request->getUri()->getPath();
@@ -34,7 +35,7 @@ final class Index
],
];
foreach (self::getBackends(blacklist: true) as $backend) {
foreach (self::getBackends() as $backend) {
$backend = array_filter(
$backend,
fn($key) => false === in_array($key, ['options', 'webhook'], true),
@@ -51,19 +52,38 @@ final class Index
return api_response(HTTP_STATUS::HTTP_OK, $response);
}
public static function getBackends(string|null $name = null, bool $blacklist = false): array
#[Get(self::URL . '/{id:[a-zA-Z0-9_-]+}[/]', name: 'backends.view')]
public function backendsView(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
$data = Index::getBackends(name: $id);
if (empty($data)) {
return api_error('Backend not found.', HTTP_STATUS::HTTP_NOT_FOUND);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$data = array_pop($data);
$response = [
...$data,
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(self::URL)),
],
];
return api_response(HTTP_STATUS::HTTP_OK, ['backend' => $response]);
}
private function getBackends(string|null $name = null): array
{
$backends = [];
foreach (Config::get('servers', []) as $backendName => $backend) {
$backend = ['name' => $backendName, ...$backend];
if (true === $blacklist) {
foreach (self::BLACK_LIST as $hideValue) {
if (true === ag_exists($backend, $hideValue)) {
$backend = ag_set($backend, $hideValue, '__hidden__');
}
}
}
foreach (ConfigFile::open(Config::get('backends_file'), 'yaml')->getAll() as $backendName => $backend) {
$backend = ['name' => $backendName, ...$backend];
if (null !== ag($backend, 'import.lastSync')) {
$backend = ag_set($backend, 'import.lastSync', makeDate(ag($backend, 'import.lastSync')));

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace App\API\Backends\Plex;
use App\Backends\Plex\PlexClient;
use App\Libs\Attributes\Route\Post;
use App\Libs\DataUtil;
use App\Libs\HTTP_STATUS;
use Psr\Http\Message\ResponseInterface as iResponse;
use Psr\Http\Message\ServerRequestInterface as iRequest;
use Symfony\Contracts\HttpClient\HttpClientInterface as iHttp;
final class Discover
{
public const string URL = '%{api.prefix}/backends/plex/discover';
public function __construct(private iHttp $http)
{
}
#[Post(self::URL . '[/]', name: 'backends.plex.discover')]
public function plexDiscover(iRequest $request): iResponse
{
$data = DataUtil::fromArray($request->getParsedBody());
if (null === ($token = $data->get('token'))) {
return api_error('No token was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
try {
$list = PlexClient::discover($this->http, $token);
} catch (\Throwable $e) {
return api_error($e->getMessage(), HTTP_STATUS::HTTP_INTERNAL_SERVER_ERROR);
}
return api_response(HTTP_STATUS::HTTP_OK, ag($list, 'list', []));
}
}

View File

@@ -1,42 +0,0 @@
<?php
declare(strict_types=1);
namespace App\API\Backends;
use App\Libs\Attributes\Route\Get;
use App\Libs\HTTP_STATUS;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
#[Get(self::URL . '/{id:[a-zA-Z0-9_-]+}[/]', name: 'backends.view')]
final class View
{
public const URL = '%{api.prefix}/backends';
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
{
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
$data = Index::getBackends(name: $id, blacklist: true);
if (empty($data)) {
return api_error('Backend not found.', HTTP_STATUS::HTTP_NOT_FOUND);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$data = array_pop($data);
$response = [
...$data,
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(self::URL)),
],
];
return api_response(HTTP_STATUS::HTTP_OK, ['backend' => $response]);
}
}

View File

@@ -14,13 +14,12 @@ use App\Libs\Guid;
use App\Libs\HTTP_STATUS;
use App\Libs\Uri;
use PDO;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface as iResponse;
use Psr\Http\Message\ServerRequestInterface as iRequest;
#[Get(self::URL . '[/]', name: 'history.index')]
final class Index
{
public const URL = '%{api.prefix}/history';
public const string URL = '%{api.prefix}/history';
private PDO $pdo;
public function __construct(private readonly iDB $db)
@@ -28,7 +27,8 @@ final class Index
$this->pdo = $this->db->getPDO();
}
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
#[Get(self::URL . '[/]', name: 'history.index')]
public function historyIndex(iRequest $request): iResponse
{
$es = fn(string $val) => $this->db->identifier($val);
$data = DataUtil::fromArray($request->getQueryParams());
@@ -316,4 +316,36 @@ final class Index
return api_response(HTTP_STATUS::HTTP_OK, $response);
}
#[Get(self::URL . '/{id:\d+}[/]', name: 'history.view')]
public function historyView(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
$entity = Container::get(iState::class)::fromArray([iState::COLUMN_ID => $id]);
if (null === ($item = $this->db->get($entity))) {
return api_error('Not found', HTTP_STATUS::HTTP_NOT_FOUND);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$item = $item->getAll();
$item[iState::COLUMN_WATCHED] = $entity->isWatched();
$item[iState::COLUMN_UPDATED] = makeDate($entity->updated);
$item = [
...$item,
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
],
];
return api_response(HTTP_STATUS::HTTP_OK, ['history' => $item]);
}
}

View File

@@ -1,51 +0,0 @@
<?php
declare(strict_types=1);
namespace App\API\History;
use App\Libs\Attributes\Route\Get;
use App\Libs\Container;
use App\Libs\Database\DatabaseInterface as iDB;
use App\Libs\Entity\StateInterface as iState;
use App\Libs\HTTP_STATUS;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
#[Get(Index::URL . '/{id:\d+}[/]', name: 'history.view')]
final readonly class View
{
public function __construct(private iDB $db)
{
}
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
{
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
$entity = Container::get(iState::class)::fromArray([iState::COLUMN_ID => $id]);
if (null === ($item = $this->db->get($entity))) {
return api_error('Not found', HTTP_STATUS::HTTP_NOT_FOUND);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$item = $item->getAll();
$item[iState::COLUMN_WATCHED] = $entity->isWatched();
$item[iState::COLUMN_UPDATED] = makeDate($entity->updated);
$item = [
...$item,
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
],
];
return api_response(HTTP_STATUS::HTTP_OK, ['history' => $item]);
}
}

View File

@@ -14,11 +14,13 @@ use Throwable;
#[Get(self::URL . '[/]', name: 'system.env')]
final class Env
{
public const URL = '%{api.prefix}/system/env';
private const BLACKLIST = [
public const string URL = '%{api.prefix}/system/env';
private const array BLACKLIST = [
'WS_API_KEY'
];
private const BLACKLIST_PARSE_URL = [
private const array BLACKLIST_PARSE_URL = [
'WS_CACHE_URL' => [
'password',
],

View File

@@ -7,15 +7,15 @@ namespace App\API\Tasks;
use App\Commands\System\TasksCommand;
use App\Libs\Attributes\Route\Get;
use App\Libs\HTTP_STATUS;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface as iResponse;
use Psr\Http\Message\ServerRequestInterface as iRequest;
#[Get(self::URL . '[/]', name: 'tasks.index')]
final class Index
{
public const URL = '%{api.prefix}/tasks';
public const string URL = '%{api.prefix}/tasks';
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
#[Get(self::URL . '[/]', name: 'tasks.index')]
public function tasksIndex(iRequest $request): iResponse
{
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$urlPath = rtrim($request->getUri()->getPath(), '/');
@@ -44,14 +44,40 @@ final class Index
return api_response(HTTP_STATUS::HTTP_OK, $response);
}
public static function formatTask(array $task): array
#[Get(self::URL . '/{id:[a-zA-Z0-9_-]+}[/]', name: 'tasks.view')]
public function __invoke(iRequest $request, array $args = []): iResponse
{
if (null === ($id = ag($args, 'id'))) {
return api_error('No id was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$task = TasksCommand::getTasks($id);
if (empty($task)) {
return api_error('Task not found.', HTTP_STATUS::HTTP_NOT_FOUND);
}
$response = [
...Index::formatTask($task),
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
],
];
return api_response(HTTP_STATUS::HTTP_OK, ['task' => $response]);
}
private function formatTask(array $task): array
{
$isEnabled = (bool)ag($task, 'enabled', false);
$item = [
'name' => ag($task, 'name'),
'description' => ag($task, 'description'),
'enabled' => $isEnabled,
'enabled' => true === $isEnabled,
'timer' => ag($task, 'timer')->getexpression(),
'next_run' => null,
'prev_run' => null,
@@ -63,7 +89,7 @@ final class Index
$item['command'] = get_debug_type($item['command']);
}
if ($isEnabled) {
if (true === $isEnabled) {
$item['next_run'] = makeDate(ag($task, 'timer')->getNextRunDate());
$item['prev_run'] = makeDate(ag($task, 'timer')->getPreviousRunDate());
}

View File

@@ -1,40 +0,0 @@
<?php
declare(strict_types=1);
namespace App\API\Tasks;
use App\Commands\System\TasksCommand;
use App\Libs\Attributes\Route\Get;
use App\Libs\HTTP_STATUS;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
#[Get(Index::URL . '/{id:[a-zA-Z0-9_-]+}[/]', name: 'tasks.view')]
final class View
{
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
{
if (null === ($id = ag($args, 'id'))) {
return api_error('No id was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$task = TasksCommand::getTasks($id);
if (empty($task)) {
return api_error('Task not found.', HTTP_STATUS::HTTP_NOT_FOUND);
}
$response = [
...Index::formatTask($task),
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
],
];
return api_response(HTTP_STATUS::HTTP_OK, ['task' => $response]);
}
}