Большое обновление

- проект переписан на flight + twig, laravel-like хелперы
- docker-окружение
- новая страница с подробностями о плейлисте
- улучшен json о плейлисте
- нормальный роутинг
- нормальная статусная система
- попытка перекодировки при не utf-8 + предупреждение об этом
- дополнены FAQ + README
This commit is contained in:
2022-09-01 19:54:43 +08:00
parent 649ab85d79
commit c43439b9cc
37 changed files with 2566 additions and 860 deletions

76
src/views/details.twig Normal file
View File

@@ -0,0 +1,76 @@
{% extends "layouts/default.twig" %}
{% block title %}{{ title }}{% endblock %}
{% block header %}
<a href="{{ base_url() }}" class="btn btn-outline-light mb-3"><< Назад</a>
<h2>{{ name }}</h2>
{% if (encoding.alert) %}
<div class="alert alert-warning small" role="alert">
Кодировка исходного плейлиста отличается от UTF-8.
Он был автоматически с конвертирован из {{ encoding.name }}, чтобы отобразить здесь список каналов.
Однако названия каналов могут отображаться некорректно, причём не только здесь, но и в плеере.
</div>
{% endif %}
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-8">
<h4>О плейлисте</h4>
<table class="table table-dark table-hover small">
<tbody>
<tr>
<td class="w-25">ID</td>
<td>
{{ id }}&nbsp;{% if status == 'online' %}
<span class="badge small text-dark bg-success">online</span>
{% elseif status == 'offline' %}
<span class="badge small text-dark bg-danger">offline</span>
{% elseif status == 'timeout' %}
<span class="badge small text-dark bg-warning">timeout</span>
{% elseif status == 'error' %}
<span class="badge small text-dark bg-danger">error</span>
{% endif %}
</td>
</tr>
<tr>
<td>Описание</td>
<td><p>{{ desc }}</p></td>
</tr>
<tr>
<td title="Нажми на ссылку, чтобы скопировать её в буфер обмена"><b>Ccылка для ТВ</b></td>
<td><b onclick="prompt('Скопируй адрес плейлиста', '{{ url }}')"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
class="font-monospace cursor-pointer">{{ url }}</b></td>
</tr>
<tr>
<td>M3U</td>
<td>{{ pls }}</td>
</tr>
<tr>
<td>Источник</td>
<td>{{ src }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-4">
<h4>Список каналов ({{ count }})</h4>
<div class="overflow-auto" style="max-height: 350px;">
<table class="table table-dark table-hover small">
<tbody>
{% for channel in channels %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ channel }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}

149
src/views/faq.twig Normal file
View File

@@ -0,0 +1,149 @@
{% extends "layouts/default.twig" %}
{% block header %}
<a href="{{ base_url() }}" class="btn btn-outline-light mb-3"><< Назад</a>
<h2>FAQ</h2>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-12">
<p>
На этой странице собраны ссылки на IPTV-плейлисты, которые находятся в открытом доступе.
Они отбираются вручную и постоянно проверяются здесь автоматически.
</p>
<p>
Сервис "{{ config('app.title') }}" ({{ base_url() }}) не предназначен для хранения или трансляции
видео/аудио потоков, программ телепередач, плейлистов и их поддержки. Этим занимаются администраторы
ресурсов, указанные как источник, и те, с чьих ресурсов ведётся трансляция.
</p>
<p class="mb-5">
Сервис "{{ config('app.title') }}" ({{ base_url() }}) предоставляет только информацию об активности
плейлистов, найденных в открытом доступе, и короткие ссылки на них для удобства использования в ПО.
Вопросы по содержанию и работоспособности плейлистов, а также вопросы юридического характера, адресуйте
тем, кто несёт за них ответственность (см. источники плейлистов).
</p>
<h3>Как пользоваться сервисом?</h3>
<p class="mb-5">
На главной странице отображается список доступных в плейлистов, их идентификаторы, статусы,
количество каналов и короткие ссылки.
Для просмотра списка каналов следует нажать на ссылку <b>"Подробнее..."</b> под интересующим плейлистом.
Для добавления плейлиста в свой медиаплеер удобно использовать <b>"Ссылку для ТВ"</b>.
Это делается для удобства ввода, например, на телевизоре с пульта.
На странице детальной информации также есть прямая ссылка на сам плейлист от источника.
Можно использовать и её.
</p>
<h3>Эти плейлисты и каналы в них -- бесплатны?</h3>
<p class="mb-5">Возможно. По крайней мере, так утверждают источники. Но гарантий никаких никто не даёт.</p>
<h3>Как подключить плейлист?</h3>
<p class="mb-5">
<a href="https://www.google.com/search?q=%D0%BA%D0%B0%D0%BA%20%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%20iptv%20%D0%BF%D0%BB%D0%B5%D0%B9%D0%BB%D0%B8%D1%81%D1%82%20%D0%BF%D0%BE%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B5">
Добавь в свой медиаплеер</a> "Ссылку для ТВ".
</p>
<h3>Какие плейлисты попадают сюда?</h3>
<p>Есть некоторые критерии, по которым плейлисты отбираются в этот список:</p>
<ul>
<li>Прежде всего -- каналы РФ и бывшего СНГ, но не только</li>
<li>Открытый источник</li>
<li>Прямая ссылка на плейлист</li>
<li>Автообновление плейлиста</li>
</ul>
<p>
В основном, в плейлистах именно трансляции телеканалов, но могут быть просто список каких-то
(мульт)фильмов и передач, находящихся на чужих дисках (как если бы вы сами составили плейлист с музыкой,
например).
</p>
<h3>Что означают статусы плейлистов?</h3>
<ul>
<li>
<span class="badge small text-dark bg-secondary">?</span>
Загрузка данных, нужно немного подождать.
</li>
<li>
<span class="badge small text-dark bg-success">online</span>
Плейлист, возможно, активен.
</li>
<li>
<span class="badge small text-dark bg-warning">timeout</span>
Не удалось вовремя проверить плейлист.
</li>
<li>
<span class="badge small text-dark bg-danger">offline</span>
Плейлист недоступен.
</li>
<li>
<span class="badge small text-dark bg-danger">error</span>
Ошибка при проверке плейлиста.
</li>
</ul>
<p class="mb-5">
На странице детального описания статус может отображаться только online/offline.
Это временно. В некоем скором времени это будет доработано.
</p>
<h3>Почему нельзя доверять результатам проверки?</h3>
<p>
Я не гарантирую корректность и актуальность информации, которую ты увидишь здесь.
Хотя я и стараюсь улучшать качество проверок, но всё же рекомендую проверять желаемые
плейлисты самостоятельно вручную, ибо нет никаких гарантий:
</p>
<ul class="mb-5">
<li>
что это вообще плейлисты, а не чьи-то архивы с мокрыми кисками;
</li>
<li>
что плейлисты по разным ссылкам не дублируют друг друга и отличаются каналами хотя бы на четверть;
</li>
<li>
что плейлист работоспособен (каналы работают, корректно названы, имеют аудио, etc.);
</li>
<li>
что подгрузится корректное количество каналов и их список (хотя на это я ещё могу влиять и
стараюсь как-то улучшить).
</li>
</ul>
<h3>Какова гарантия, что я добавлю себе плейлист отсюда и он работать хоть сколько-нибудь долго?</h3>
<p class="mb-5">
Никакова.
Мёртвые плейлисты я периодически вычищаю, реже -- добавляю новые.
ID плейлистов могут меняться, поэтому вполне может произойти внезапная подмена одного другим, однако
намеренно я так не делаю.
Если один плейлист переезжает на новый адрес, то я ставлю временное перенаправление со старого ID на
новый.
Плюс читай выше про доверие результатам проверки (проблема может быть не стороне сервиса).
</p>
<h3>Где взять программу передач (EPG)?</h3>
<ul class="mb-5">
<li><b>https://iptvx.one/viewtopic.php?f=12&t=4</b></li>
<li>https://iptvmaster.ru/epg-for-iptv</li>
<li>https://google.com</li>
</ul>
<h3>Как часто обновляется этот список?</h3>
<p class="mb-5">
Время от времени.
Иногда я захожу сюда и проверяю всё ли на месте, иногда занимаюсь какими-то доработками.
Если есть кандидаты на добавление, то читай ниже.
</p>
<h3>Как часто обновляется содержимое плейлистов?</h3>
<p class="mb-5">Зависит от источника. Я этим не занимаюсь.</p>
<h3>Есть ли API? Как им пользоваться?</h3>
<p class="mb-5">Есть, подробности <a href="https://github.com/anthonyaxenov/iptv2#api">здесь</a>.</p>
<h3>Как пополнить этот список?</h3>
<p class="mb-5">
Сделать pull-request в <a href="https://github.com/anthonyaxenov/iptv">репозиторий</a>.
Я проверю плейлист и добавлю его в общий список, если всё ок.
</p>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>{{ config('app.title') }}</title>
<meta charset="utf-8">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<link href="{{ base_url('css/bootstrap.min.css') }}" rel="stylesheet">
<style>.cursor-pointer {
cursor: pointer
}</style>
{% block head %}{% endblock %}
</head>
<body class="bg-dark text-light">
<div class="col-lg-8 mx-auto p-3 pt-md-5 pb-0">
<header class="pb-3 mb-3">
<a href="/" class="text-light text-decoration-none">
<h1>{{ config('app.title') }}</h1>
</a>
<p class="small text-muted">
<a class="small" href="{{ base_url('faq') }}">FAQ</a>&nbsp;|&nbsp;<a
class="small" href="https://github.com/anthonyaxenov/iptv">GitHub</a>&nbsp;|&nbsp;<a
class="small" href="https://axenov.dev">axenov.dev</a>
</p>
{% block header %}{% endblock %}
</header>
<div class="container">
{% block content %}{% endblock %}
</div>
</div>
<footer class="py-4 text-center">
<a href="https://github.com/anthonyaxenov/iptv">GitHub</a> | <a href="https://axenov.dev">axenov.dev</a>
<script src="{{ base_url('js/bootstrap.bundle.min.js') }}"></script>
{% block footer %}{% endblock %}
</footer>
</body>
</html>

63
src/views/list.twig Normal file
View File

@@ -0,0 +1,63 @@
{% extends "layouts/default.twig" %}
{% block title %}{{ title }}{% endblock %}
{% block header %}
<p class="text-muted small">
Обновлено:&nbsp;{{ updated_at }}&nbsp;МСК<br/>
Плейлистов в списке:&nbsp;<strong>{{ count }}</strong>
</p>
<hr/>
{% endblock %}
{% block content %}
<table class="table table-dark table-hover small">
<thead>
<tr>
<th>ID</th>
<th>Информация о плейлисте</th>
<th>Каналов</th>
<th title="Нажми на ссылку, чтобы скопировать её в буфер обмена">Ссылка для ТВ</th>
</tr>
</thead>
<tbody>
{% for id, playlist in playlists %}
<tr class="pls" data-playlist-id="{{ id }}">
<td class="text-center id">
<strong>{{ id }}</strong>
</td>
<td class="info">
<strong>{{ playlist.name }}</strong>
<span class="badge small bg-secondary text-dark status">?</span>
<div class="small">
{% if playlist.desc|length > 0 %}
<p class="my-1">{{ playlist.desc }}</p>
{% endif %}
<a href="{{ base_url(id ~ '/details') }}"
target="_blank"
rel="noopener nofollow">Подробнее...</a>
</div>
</td>
<td class="text-center count">
<div class="spinner-border text-success" role="status">
<span class="visually-hidden">загрузка...</span>
</div>
</td>
<td class="col-3">
<span onclick="prompt('Скопируй адрес плейлиста', '{{ playlist.url }}')"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
class="font-monospace cursor-pointer">
{{ playlist.url }}
</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
{% block footer %}
<script src="{{ base_url('js/checker.js') }}"></script>
{% endblock %}