Переработка под iptvc

This commit is contained in:
2025-05-12 00:07:43 +08:00
parent f43843bb07
commit 252af50239
29 changed files with 1662 additions and 1268 deletions

View File

@@ -1,4 +1,9 @@
<?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);
@@ -8,7 +13,7 @@ use App\Errors\PlaylistNotFoundException;
use Exception;
/**
* Класс для работы с ini-файлом плейлистов
* Класс для работы со списком плейлистов
*/
class IniFile
{
@@ -18,65 +23,76 @@ class IniFile
protected array $ini;
/**
* @var Playlist[] Коллекция подгруженных плейлистов
* @var array[] Коллекция подгруженных плейлистов
*/
protected array $playlists = [];
/**
* @var string[] Карта переадресаций плейлистов
*/
protected array $redirections = [];
protected array $playlists;
/**
* @var string Дата последнего обновления списка
*/
protected string $updated_at;
protected string $updatedAt;
/**
* Считывает ini-файл и инициализирует объекты плейлистов
* Считывает ini-файл и инициализирует плейлисты
*
* @return void
* @return array
* @throws Exception
*/
public function load(): void
public function load(): array
{
$ini = redis()->hGetAll('_playlists_');
if (empty($ini)) {
$filepath = config_path('playlists.ini');
$ini = parse_ini_file($filepath, true);
$this->updated_at = date('d.m.Y h:i', filemtime($filepath));
$order = array_keys($ini);
$filepath = config_path('playlists.ini');
$ini = parse_ini_file($filepath, true);
$this->updatedAt = date('d.m.Y h:i', filemtime($filepath));
// сохраняем порядок
foreach (array_keys($ini) as $code) {
$data = redis()->get($code);
if ($data === false) {
$raw = $ini[$code];
$data = [
'code' => $code,
'name' => $raw['name'],
'description' => $raw['desc'],
'url' => $raw['pls'],
'source' => $raw['src'],
'content' => null,
'isOnline' => null,
'attributes' => [],
'groups' => [],
'channels' => [],
'onlineCount' => 0,
'offlineCount' => 0,
'checkedAt' => null,
];
} else if (!isset($data['attributes'])) {
$data['attributes'] = [];
}
$data['hasTvg'] = !empty($data['asttributes']['url-tvg']);
$data['hasCatchup'] = str_contains($data['content'] ?? '', 'catchup');
$data['tags'] = [];
foreach ($data['channels'] ?? [] as $channel) {
$data['tags'] = array_merge($data['tags'], $channel['tags']);
}
$data['tags'] = array_values(array_unique($data['tags']));
sort($data['tags']);
$this->playlists[$code] = $data;
}
$order ??= redis()->get('_order_');
$this->ini ??= $ini;
$this->updated_at ??= redis()->get('_updated_at_');
$transaction = redis()->multi();
foreach ($order as $id) {
$data = $this->ini[$id];
$this->playlists[(string)$id] = $pls = $this->makePlaylist($id, $data);
$transaction->hSet('_playlists_', $id, $pls);
}
$expireAfter = config('redis.ttl_days');
$transaction
->expire('_playlists_', $expireAfter)
->set('_order_', $order, ['EX' => $expireAfter])
->set('_updated_at_', $this->updated_at, ['EX' => $expireAfter])
->exec();
return $this->playlists;
}
/**
* Возвращает объекты плейлистов
* Возвращает плейлисты
*
* @param bool $all true - получить все, false - получить только НЕпереадресованные
* @return Playlist[]
* @return array[]
* @throws Exception
*/
public function playlists(bool $all = true): array
public function getPlaylists(): array
{
return $all
? $this->playlists
: array_filter($this->playlists, static fn ($playlist) => is_null($playlist->redirectId));
return $this->playlists ??= $this->load();
}
/**
@@ -86,50 +102,23 @@ class IniFile
*/
public function updatedAt(): string
{
return $this->updated_at;
return $this->updatedAt;
}
/**
* Возвращает ID плейлиста, на который нужно переадресовать указанный
* Возвращает плейлист по его коду
*
* @param string $id ID плейлиста
* @return string|null
*/
public function getRedirection(string $id): ?string
{
return $this->redirections[$id] ?? null;
}
/**
* Возвращает объект плейлиста
*
* @param string $id ID плейлиста
* @return Playlist|null
* @param string $code Код плейлиста
* @return array|null
* @throws PlaylistNotFoundException
*/
public function getPlaylist(string $id): ?Playlist
{
return $this->playlists[$id] ?? throw new PlaylistNotFoundException($id);
}
/**
* Создаёт объекты плейлистов, рекурсивно определяя переадресации
*
* @param int|string $id ID плейлиста
* @param array $params Описание плейлиста
* @param string|null $redirectId ID для переадресации
* @return Playlist
* @throws Exception
*/
protected function makePlaylist(int|string $id, array $params, ?string $redirectId = null): Playlist
public function getPlaylist(string $code): ?array
{
$id = (string)$id;
if (isset($params['redirect'])) {
$this->redirections[$id] = $redirectId = (string)$params['redirect'];
$params = $this->ini[$redirectId];
return $this->makePlaylist($id, $params, $redirectId);
if (empty($this->playlists)) {
$this->load();
}
return new Playlist($id, $params, $redirectId);
return $this->playlists[$code] ?? throw new PlaylistNotFoundException($code);
}
}