From 0b41503131fab2026fda6ce199def7db616a41ab Mon Sep 17 00:00:00 2001 From: AnthonyAxenov Date: Sat, 19 Jul 2025 14:58:30 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=D0=A0=D0=B5=D1=81=D1=82=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D1=8B=20404?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controllers/BasicController.php | 3 ++- views/notfound.twig | 33 ++++++++++++++++++----------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/app/Controllers/BasicController.php b/app/Controllers/BasicController.php index aab299f..c5feb2f 100644 --- a/app/Controllers/BasicController.php +++ b/app/Controllers/BasicController.php @@ -34,8 +34,9 @@ class BasicController */ public function notFound(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { + $code = $request->getAttributes()['code']; $response->withStatus(404); - $this->view($request, $response, 'notfound.twig'); + $this->view($request, $response, 'notfound.twig', ['code' => $code]); return $response; } diff --git a/views/notfound.twig b/views/notfound.twig index 6c5a71a..8f535c0 100644 --- a/views/notfound.twig +++ b/views/notfound.twig @@ -6,19 +6,28 @@ {% extends "template.twig" %} -{% block header %} -

Плейлист не найден

-{% endblock %} - {% block content %} -
-
-

- Плейлист {{ id }} не найден -

- - Перейти к списку - +
+
+
+
+ +

Плейлист не найден

+

+ Плейлист с кодом {{ code }} не найден в системе. +

+

+ Возможно, его здесь никогда не было, либо он уже был удалён. +
+ Если хочешь, чтобы здесь был плейлист, предложи его к добавлению. +
+ Как это сделать? +

+ + Перейти к списку плейлистов + +
+
{% endblock %} From 1e188be6f369a14bae1ec228bc61e5f34cb2b5a6 Mon Sep 17 00:00:00 2001 From: AnthonyAxenov Date: Sat, 19 Jul 2025 15:10:37 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=D0=A0=D0=B5=D1=81=D1=82=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=20=D0=BE=D0=B1=D1=89=D0=B5=D0=B3=D0=BE=20=D1=88=D0=B0=D0=B1?= =?UTF-8?q?=D0=BB=D0=BE=D0=BD=D0=B0=20=D0=B8=20=D0=B3=D0=BB=D0=B0=D0=B2?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- views/list.twig | 196 +++++++++++++++++++++++--------------------- views/template.twig | 156 ++++++++++++++++++++++------------- 2 files changed, 200 insertions(+), 152 deletions(-) diff --git a/views/list.twig b/views/list.twig index 5574b4f..bf29f37 100644 --- a/views/list.twig +++ b/views/list.twig @@ -10,119 +10,127 @@ {% block metakeywords %}самообновляемые,бесплатные,iptv-плейлисты,iptv,плейлисты{% endblock %} +{% block head %} + + +{% endblock %} + {% block header %} -
-
- Список изменён: {{ updatedAt }} МСК
- Плейлистов в списке: {{ count }} +
+
+

Список плейлистов ({{ count }})

+
Изменён {{ updatedAt }} МСК
-
- Состояние проверки:
- - online{{ onlineCount }} - - - offline{{ offlineCount }} - - - unknown{{ uncheckedCount }} - +
+ online: {{ onlineCount }} + offline: {{ offlineCount }} + unknown: {{ uncheckedCount }}
-
{% endblock %} {% block content %} -
- - - - - - - - - - +
{% for code, playlist in playlists %} -
- - - - - +
+ + {{ mirror_url(playlist.code) }} + + +
+ + + + + {% endfor %} - -
КодИнформация о плейлистеКаналовСсылка для ТВ
{{ code }} - {% if playlist.isOnline is same as(true) %} - online - {% elseif playlist.isOnline is same as(false) %} - offline - {% elseif playlist.isOnline is same as(null) %} - unknown - {% endif %} - {% if "adult" in playlist.tags %} - 18+ - {% endif %} - {{ playlist.name }} -
-

+ {% set statusClass = 'secondary' %} + {% if playlist.isOnline is same as(true) %} + {% set statusClass = 'success' %} + {% elseif playlist.isOnline is same as(false) %} + {% set statusClass = 'danger' %} + {% endif %} + +

+
+ +
+ {{ code }} + + {% if playlist.isOnline is same as(true) %}online + {% elseif playlist.isOnline is same as(false) %}offline + {% elseif playlist.isOnline is same as(null) %}unknown + {% endif %} + + {% if "adult" in playlist.tags %} + 18+ + {% endif %} +
+
+ +
+ +
{{ playlist.name }}
+
+

{{ playlist.description }}

+
+ + + {% if playlist.isOnline is not same as(null) %} + {{ playlist.channels|length }} каналов + {% endif %} + {% if playlist.groups|length > 0 %} - + +  {{ playlist.groups|length }} групп + {% endif %} {% if playlist.hasTvg %} - + +  ТВ-программа + {% endif %} {% if playlist.hasCatchup %} - + +  Архив + {% endif %} - {{ playlist.description }} -

- {% if playlist.tags|length > 0 %} -

- - {% for tag in playlist.tags %} - #{{ tag }} - {% endfor %} -

- {% endif %} - Подробнее... +
-
- {% if (playlist.isOnline is not same as(null)) %} - {{ playlist.channels|length }} - {% else %} - ? - {% endif %} - - - {{ mirror_url(playlist.code) }} - -
- {% if pageCount > 1 %} -
-
    - {% for page in range(1, pageCount) %} - {% if page == pageCurrent %} -
  • - {{ page }} -
  • - {% else %} -
  • - {{ page }} -
  • - {% endif %} - {% endfor %} -
+ + {% if pageCount > 1 %} + {% endif %} -
{% endblock %} {% block footer %} diff --git a/views/template.twig b/views/template.twig index 81bf47f..3acc477 100644 --- a/views/template.twig +++ b/views/template.twig @@ -5,7 +5,7 @@ ###########################################################################} - + {% block title %}{{ config('app.title') }}{% endblock %} @@ -30,67 +30,107 @@ {% block head %}{% endblock %} - - + - -
+ + {% block footer %}{% endblock %} {% include("custom.twig") ignore missing %} From 48d8a00b136d8486efdbaea2088726753565b477 Mon Sep 17 00:00:00 2001 From: AnthonyAxenov Date: Sat, 19 Jul 2025 15:34:31 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=B1=D0=B5?= =?UTF-8?q?=D0=B9=D0=B4=D0=B6=D0=B0=20=D0=BA=D0=BE=D0=BB-=D0=B2=D0=B0=20?= =?UTF-8?q?=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=D0=BE=D0=B2=20=D1=83=20unknown-?= =?UTF-8?q?=D0=BB=D0=B8=D1=81=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- views/list.twig | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/views/list.twig b/views/list.twig index bf29f37..51d04bc 100644 --- a/views/list.twig +++ b/views/list.twig @@ -72,12 +72,11 @@

{{ playlist.description }}

+ {% if playlist.isOnline is not same as(null) %} - - {% if playlist.isOnline is not same as(null) %} - {{ playlist.channels|length }} каналов - {% endif %} +  {{ playlist.channels|length }} каналов + {% endif %} {% if playlist.groups|length > 0 %}  {{ playlist.groups|length }} групп From 80586d14897cb1d3d717b604344774c4d16f3b4a Mon Sep 17 00:00:00 2001 From: AnthonyAxenov Date: Sat, 19 Jul 2025 19:28:37 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D1=91=D0=BD=20?= =?UTF-8?q?=D1=80=D0=BE=D1=83=D1=82=20faq=20(#5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/config/routes.php b/config/routes.php index 1dc3031..59c3eea 100644 --- a/config/routes.php +++ b/config/routes.php @@ -35,12 +35,6 @@ return [ 'handler' => [WebController::class, 'home'], 'name' => 'home', ], - [ - 'method' => 'GET', - 'path' => '/faq', - 'handler' => [WebController::class, 'faq'], - 'name' => 'faq', - ], [ 'method' => 'GET', 'path' => '/{code:[0-9a-zA-Z]+}[.m3u[8]]', From 9083a9656475b9688dae65e4e3dcd0a0275e0552 Mon Sep 17 00:00:00 2001 From: AnthonyAxenov Date: Sat, 19 Jul 2025 21:10:48 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BE=D1=87=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D0=B5?= =?UTF-8?q?=20404?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- views/notfound.twig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/views/notfound.twig b/views/notfound.twig index 8f535c0..0140965 100644 --- a/views/notfound.twig +++ b/views/notfound.twig @@ -12,13 +12,11 @@
-

Плейлист не найден

+

Плейлист {{ code }} не найден

- Плейлист с кодом {{ code }} не найден в системе. + Возможно, его здесь никогда не было, либо он уже был удалён.

- Возможно, его здесь никогда не было, либо он уже был удалён. -
Если хочешь, чтобы здесь был плейлист, предложи его к добавлению.
Как это сделать? From 36c3570e0593e5402847f579f847150bff80fe72 Mon Sep 17 00:00:00 2001 From: AnthonyAxenov Date: Sat, 19 Jul 2025 21:11:33 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BE=D1=87=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D0=B0=D0=B4=D0=B0=D0=BF=D1=82=D0=B8=D0=B2=D1=83?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BC=D0=BE=D0=B1=D0=B8=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=8D=D0=BA=D1=80=D0=B0=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- views/list.twig | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/views/list.twig b/views/list.twig index 51d04bc..a5aae4f 100644 --- a/views/list.twig +++ b/views/list.twig @@ -70,26 +70,28 @@

{{ playlist.name }}
-

{{ playlist.description }}

+ {% if playlist.description is not same as(null) %} +

{{ playlist.description }}

+ {% endif %}
{% if playlist.isOnline is not same as(null) %} -  {{ playlist.channels|length }} каналов +  {{ playlist.channels|length }} каналов {% endif %} {% if playlist.groups|length > 0 %} -  {{ playlist.groups|length }} групп +  {{ playlist.groups|length }} групп {% endif %} {% if playlist.hasTvg %} -  ТВ-программа +  ТВ-программа {% endif %} {% if playlist.hasCatchup %} -  Архив +  Архив {% endif %}
From 5c4554b9f9c56645aefcb9763aac3ab8569070ca Mon Sep 17 00:00:00 2001 From: AnthonyAxenov Date: Sat, 19 Jul 2025 21:20:30 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=D0=A0=D0=BE=D1=83=D1=82=D1=8B=20/api/=20?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B5=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5?= =?UTF-8?q?=20=D0=BC=D0=B5=D0=BB=D0=BE=D1=87=D0=B8=20=D0=BF=D0=BE=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=BB=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controllers/ApiController.php | 44 ++++++++++++++++------------- app/Controllers/BasicController.php | 2 +- app/Controllers/WebController.php | 15 ---------- app/Core/IniFile.php | 6 +++- config/routes.php | 9 +++--- views/details.twig | 2 +- 6 files changed, 36 insertions(+), 42 deletions(-) diff --git a/app/Controllers/ApiController.php b/app/Controllers/ApiController.php index dfc274a..ab4dd7c 100644 --- a/app/Controllers/ApiController.php +++ b/app/Controllers/ApiController.php @@ -21,6 +21,30 @@ use Psr\Http\Message\ServerRequestInterface; */ class ApiController extends BasicController { + /** + * Возвращает информацию о плейлисте + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface + * @throws Exception + */ + public function getOne(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface + { + try { + $code = $request->getAttributes()['code'] ?? null; + empty($code) && throw new PlaylistNotFoundException(''); + + $playlist = ini()->getPlaylist($code); + if ($playlist['isOnline'] === true) { + unset($playlist['content']); + } + return $this->responseJson($response, 200, $playlist); + } catch (PlaylistNotFoundException $e) { + return $this->responseJsonError($response, 404, $e); + } + } + /** * Возвращает информацию о каналов плейлиста * @@ -56,24 +80,4 @@ class ApiController extends BasicController return $response->withStatus(200) ->withHeader('Content-Type', $mime); } - - /** - * Возвращает информацию о плейлисте - * - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @return ResponseInterface - * @throws Exception - */ - public function json(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); - } - } } diff --git a/app/Controllers/BasicController.php b/app/Controllers/BasicController.php index c5feb2f..4f422fe 100644 --- a/app/Controllers/BasicController.php +++ b/app/Controllers/BasicController.php @@ -34,7 +34,7 @@ class BasicController */ public function notFound(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { - $code = $request->getAttributes()['code']; + $code = $request->getAttributes()['code'] ?? ''; $response->withStatus(404); $this->view($request, $response, 'notfound.twig', ['code' => $code]); diff --git a/app/Controllers/WebController.php b/app/Controllers/WebController.php index c2b6622..0d2a956 100644 --- a/app/Controllers/WebController.php +++ b/app/Controllers/WebController.php @@ -63,21 +63,6 @@ class WebController extends BasicController ]); } - /** - * Возвращает страницу FAQ - * - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @return ResponseInterface - * @throws LoaderError - * @throws RuntimeError - * @throws SyntaxError - */ - public function faq(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface - { - return $this->view($request, $response, 'faq.twig'); - } - /** * Переадресует запрос на прямую ссылку плейлиста * diff --git a/app/Core/IniFile.php b/app/Core/IniFile.php index fa3bb27..0ac4cba 100644 --- a/app/Core/IniFile.php +++ b/app/Core/IniFile.php @@ -41,7 +41,11 @@ class IniFile // сохраняем порядок foreach (array_keys($ini) as $code) { - $data = redis()->get($code); + try { + $data = @redis()->get($code); + } catch (Throwable) { + $data = false; + } if ($data === false) { $raw = $ini[$code]; $data = [ diff --git a/config/routes.php b/config/routes.php index 59c3eea..f47be9b 100644 --- a/config/routes.php +++ b/config/routes.php @@ -6,6 +6,7 @@ */ use App\Controllers\ApiController; +use App\Controllers\BasicController; use App\Controllers\BotController; use App\Controllers\WebController; @@ -56,13 +57,13 @@ return [ [ 'method' => 'GET', - 'path' => '/{code:[0-9a-zA-Z]+}/json', - 'handler' => [ApiController::class, 'json'], - 'name' => 'json', + 'path' => '/api/playlists/{code:[0-9a-zA-Z]+}', + 'handler' => [ApiController::class, 'getOne'], + 'name' => 'api::getOne', ], [ 'method' => 'GET', - 'path' => '/{code:[0-9a-zA-Z]+}/qrcode', + 'path' => '/api/playlists/{code:[0-9a-zA-Z]+}/qrcode', 'handler' => [ApiController::class, 'makeQrCode'], 'name' => 'api::makeQrCode', ], diff --git a/views/details.twig b/views/details.twig index 2d79ead..db2f530 100644 --- a/views/details.twig +++ b/views/details.twig @@ -175,7 +175,7 @@