125 lines
3.5 KiB
PHP
125 lines
3.5 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\Core;
|
||
|
||
use App\Errors\PlaylistNotFoundException;
|
||
use Exception;
|
||
|
||
/**
|
||
* Класс для работы со списком плейлистов
|
||
*/
|
||
class IniFile
|
||
{
|
||
/**
|
||
* @var array[] Коллекция подгруженных плейлистов
|
||
*/
|
||
protected array $playlists;
|
||
|
||
/**
|
||
* @var string Дата последнего обновления списка
|
||
*/
|
||
protected string $updatedAt;
|
||
|
||
/**
|
||
* Считывает ini-файл и инициализирует плейлисты
|
||
*
|
||
* @return array
|
||
* @throws Exception
|
||
*/
|
||
public function load(): array
|
||
{
|
||
$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) {
|
||
try {
|
||
$data = @redis()->get($code);
|
||
} catch (Throwable) {
|
||
$data = false;
|
||
}
|
||
if ($data === false) {
|
||
$raw = $ini[$code];
|
||
$data = [
|
||
'code' => $code,
|
||
'name' => $raw['name'] ?? "Playlist #$code",
|
||
'description' => $raw['desc'] ?? null,
|
||
'url' => $raw['pls'],
|
||
'source' => $raw['src'] ?? null,
|
||
'content' => null,
|
||
'isOnline' => null,
|
||
'attributes' => [],
|
||
'groups' => [],
|
||
'channels' => [],
|
||
'onlineCount' => 0,
|
||
'offlineCount' => 0,
|
||
'checkedAt' => null,
|
||
];
|
||
} elseif (!isset($data['attributes'])) {
|
||
$data['attributes'] = [];
|
||
}
|
||
|
||
$data['hasCatchup'] = str_contains($data['content'] ?? '', 'catchup');
|
||
$data['hasTvg'] = !empty($data['attributes']['url-tvg'])
|
||
|| !empty($data['attributes']['x-tvg-url']);
|
||
|
||
$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;
|
||
}
|
||
|
||
return $this->playlists;
|
||
}
|
||
|
||
/**
|
||
* Возвращает плейлисты
|
||
*
|
||
* @return array[]
|
||
* @throws Exception
|
||
*/
|
||
public function getPlaylists(): array
|
||
{
|
||
return $this->playlists ??= $this->load();
|
||
}
|
||
|
||
/**
|
||
* Возвращает дату обновления ini-файла
|
||
*
|
||
* @return string
|
||
*/
|
||
public function updatedAt(): string
|
||
{
|
||
return $this->updatedAt;
|
||
}
|
||
|
||
/**
|
||
* Возвращает плейлист по его коду
|
||
*
|
||
* @param string $code Код плейлиста
|
||
* @return array|null
|
||
* @throws PlaylistNotFoundException
|
||
* @throws Exception
|
||
*/
|
||
public function getPlaylist(string $code): ?array
|
||
{
|
||
if (empty($this->playlists)) {
|
||
$this->load();
|
||
}
|
||
|
||
return $this->playlists[$code] ?? throw new PlaylistNotFoundException($code);
|
||
}
|
||
}
|