Актуализация страниц о деплое и разработке + мелочи по оформлению

This commit is contained in:
2026-08-02 00:39:36 +08:00
parent 9d817f65d8
commit 89b303fed3
59 changed files with 577 additions and 251 deletions
+25 -15
View File
@@ -13,7 +13,7 @@ tags: [iptvc]
## `-i`, `--ini` { id=ini }
Указывает путь к локальному [ini-файлу](../../common/formats/playlists.md) с описанием плейлистов.
Указывает путь к локальному [ini-файлу](../../ref/formats/playlists.md) с описанием плейлистов.
Можно указать только однажды.
@@ -27,7 +27,7 @@ tags: [iptvc]
## `-t`, `--tags` { id=tags }
Указывает путь к локальному [json-файлу](../../common/formats/channels.md) с описанием тегов каналов.
Указывает путь к локальному [json-файлу](../../ref/formats/channels.md) с описанием тегов каналов.
Можно указать только однажды.
@@ -64,7 +64,7 @@ tags: [iptvc]
## `-c`, `--code` { id=code }
Указывает код плейлиста из файла [playlists.ini](../../common/formats/playlists.md).
Указывает код плейлиста из файла [playlists.ini](../../ref/formats/playlists.md).
Можно указать несколько разных.
@@ -87,14 +87,14 @@ tags: [iptvc]
Если указано `0`, тогда:
* повторение будет бесконечным;
* если переданы [`--url`](#url), [`--file`](#file) или [`--code`](#code), то на каждой итерации будут проверяться только указанные плейлисты;
* если не переданы [`--url`](#url), [`--file`](#file) или [`--code`](#code), то на каждой итерации список плейлистов будет подготавливаться заново.
* если не переданы [`--url`](#url), [`--file`](#file) или [`--code`](#code), то на каждой итерации список плейлистов будет подготавливаться заново.
Если при этом используется кеширование, то проверенные плейлисты (результаты проверки которых ещё находятся в кеше) проверяться не будут.
```shell title="Пример"
# проверить 5 раз плейлисты с кодами xx и yy из my.ini
# проверить 5 раз плейлисты с кодами xx и yy из my.ini
./iptvc check -i ~/my.ini -c xx --code yy --repeat 5
# бесконечно проверять все плейлисты из my.ini, без учёта проверенных
./iptvc check -i ~/my.ini --repeat 0
@@ -151,18 +151,20 @@ tags: [iptvc]
./iptvc check -i ~/my.ini --random 10 --quiet --json
```
## `-v`, `--verbose` { id=verbose }
Включает подробное логирование.
```shell title="Пример"
./iptvc check --random 10 --verbose
```
## Глобальные флаги { id=global }
Эти флаги доступны для всех команд и переопределяют значения из `config.yml`.
### `--config` { id=config }
Путь к файлу конфигурации `config.yml`.
Значение по умолчанию: `config.yml`
```shell title="Пример"
./iptvc check --config /etc/iptvc/config.yml
```
### `--debug` { id=debug }
Включает режим отладки. Переопределяет `app.debug` из `config.yml` и переменную `APP_DEBUG`.
@@ -181,6 +183,14 @@ tags: [iptvc]
./iptvc check -i ~/my.ini --log-level debug
```
### `-v`, `--verbose` { id=verbose }
Включает подробное логирование.
```shell title="Пример"
./iptvc check --random 10 --verbose
```
## Флаги проверки плейлистов { id=check-playlists }
Эти флаги переопределяют параметры секции `check.playlists` из `config.yml`. Доступны для команд `check` и `serve`.
+19 -18
View File
@@ -53,7 +53,7 @@ iptvc serve --check
### `-i`, `--ini` { id="ini" }
Путь к локальному [ini-файлу](../../common/formats/playlists.md) с описанием плейлистов.
Путь к локальному [ini-файлу](../../ref/formats/playlists.md) с описанием плейлистов.
Значение по умолчанию: `./playlists.ini`
@@ -63,7 +63,7 @@ iptvc serve --check -i ~/my.ini
### `-t`, `--tags` { id="tags" }
Путь к [json-файлу](../../common/formats/channels.md) с описанием тегов каналов.
Путь к [json-файлу](../../ref/formats/channels.md) с описанием тегов каналов.
Значение по умолчанию: `./channels.json`
@@ -365,19 +365,20 @@ iptvc serve --check --debug \
## Веб-маршруты
| Метод | Путь | Описание |
| --- | --- | --- |
| GET | `/` | Главная страница со списком плейлистов |
| GET | `/page/{N}` | Страница N списка плейлистов |
| GET | `/{code}` | Редирект на прямую ссылку плейлиста |
| GET | `/{code}.m3u[8]` | Редирект на прямую ссылку плейлиста |
| GET | `/{code}/details` | Страница с описанием плейлиста |
| GET | `/api` | Редирект на `/api/` (Swagger UI) |
| GET | `/api/` | Swagger UI с описанием REST API |
| GET | `/api/openapi.json` | OpenAPI-схема в формате JSON |
| GET | `/api/playlists` | JSON: массив всех плейлистов |
| GET | `/api/playlists/{code}` | JSON: информация о плейлисте |
| GET | `/api/playlists/{code}/channels` | JSON: список каналов плейлиста |
| GET | `/api/version` | JSON: версии компонентов |
| GET | `/api/health` | JSON: состояние сервиса |
| GET | `/api/stats` | JSON: статистика по плейлистам и каналам |
| Метод | Путь | Описание |
| ----- | -------------------------------- | ---------------------------------------- |
| GET | `/` | Главная страница со списком плейлистов |
| GET | `/page/{N}` | Страница N списка плейлистов |
| GET | `/{code}` | Редирект на прямую ссылку плейлиста |
| GET | `/{code}.m3u` | Редирект на прямую ссылку плейлиста |
| GET | `/{code}.m3u8` | Редирект на прямую ссылку плейлиста |
| GET | `/{code}/details` | Страница с описанием плейлиста |
| GET | `/api` | Редирект на `/api/` (Swagger UI) |
| GET | `/api/` | Swagger UI с описанием REST API |
| GET | `/api/openapi.json` | OpenAPI-схема в формате JSON |
| GET | `/api/playlists` | JSON: массив всех плейлистов |
| GET | `/api/playlists/{code}` | JSON: информация о плейлисте |
| GET | `/api/playlists/{code}/channels` | JSON: список каналов плейлиста |
| GET | `/api/version` | JSON: версии компонентов |
| GET | `/api/health` | JSON: состояние сервиса |
| GET | `/api/stats` | JSON: статистика по плейлистам и каналам |
+26 -13
View File
@@ -30,11 +30,13 @@ iptvc/
│ ├── check.go # команда check
│ ├── serve.go # команда serve
│ ├── flags.go # общие флаги check/serve
│ ├── flags_test.go # тесты применения CLI-переопределений
│ └── version.go # команда version
├── app/
│ ├── app.go # глобальные переменные: Args, Config, Cache
│ ├── config/
│ │ ── config.go # Config, Init(), validate(), IntRange, UserAgents
│ │ ── config.go # Config, Init(), validate(), IntRange, UserAgents
│ │ └── config_test.go # тесты конфигурации
│ ├── checker/
│ │ └── checker.go # CheckPlaylists(), CheckChannels(), OnPlaylistChecked
│ ├── playlist/
@@ -52,7 +54,16 @@ iptvc/
│ └── web/
│ ├── server.go # Server, Start(), StartBackgroundChecker()
│ ├── handlers.go # HTTP-обработчики
│ ├── views.go # PlaylistView, ChannelView, PageData
│ ├── views_test.go # тесты представлений
│ ├── templates.go # TemplateManager, //go:embed
│ ├── templates_test.go # тесты шаблонов
│ ├── openapi.go # OpenAPI-спецификация, Swagger UI
│ ├── openapi_test.go # тесты OpenAPI
│ ├── details_test.go # тесты страницы деталей плейлиста
│ ├── testdata/ # тестовые фикстуры
│ ├── swagger/ # встроенные файлы Swagger UI
│ ├── static/ # встроенные статические файлы (CSS, JS)
│ └── views/ # HTML-шаблоны
│ ├── base.html
│ ├── list.html
@@ -66,7 +77,8 @@ iptvc/
### `app`
Глобальный контейнер: `Args` (CLI-флаги), `Config` (конфигурация), `Cache` (Redis-клиент).
`Init()` загружает конфигурацию, инициализирует логгер и подключение к кешу.
`Init()` загружает конфигурацию и инициализирует логгер.
`InitCache()` подключается к KeyDB/Redis, если кеш включён.
### `app.config`
@@ -86,8 +98,8 @@ iptvc/
Содержит логику проверки:
- **`PrepareListsToCheck(files, urls, codes)`** — формирует список плейлистов из файлов, URL и кодов ini-файла.
- **`CheckPlaylists(lists)`** — параллельная проверка плейлистов (семфор `per-routine`), загрузка, парсинг, вызов `CheckChannels` для каждого.
- **`CheckChannels(pls)`** — параллельная проверка каналов (семфор `per-routine`), HTTP-запрос с `Range` header.
- **`CheckPlaylists(lists)`** — параллельная проверка плейлистов (семфор `max-routines`), загрузка, парсинг, вызов `CheckChannels` для каждого.
- **`CheckChannels(pls)`** — параллельная проверка каналов (семфор `max-routines`), HTTP-запрос с `Range` header.
- **`OnPlaylistChecked`** — глобальный callback, вызывается после проверки каждого плейлиста. Используется веб-сервером для обновления in-memory кеша.
- **`cachePlaylist(pls)`** — сохранение результата в Redis (если включён).
@@ -108,7 +120,7 @@ iptvc/
- **`Server`** — структура: конфиг, кеш, шаблоны, in-memory кеш (`memCache` с `sync.RWMutex`).
- **`Start()`** — запуск HTTP-сервера.
- **`StartBackgroundChecker(opts)`** — фоновая проверка в отдельной горутине.
- **`CheckOptions`** — параметры: Every, Repeat, Random, Files, Urls, Codes.
- **`CheckOptions`** — параметры: Repeat, Random, Files, Urls, Codes.
Маршруты (Go 1.22 patterns):
@@ -152,9 +164,8 @@ StartBackgroundChecker:
→ check status + content type
→ OnPlaylistChecked(pls) → memCache update
→ one-cooldown sleep
→ all-cooldown sleep
sleep(every)
if repeat > 0 && iteration >= repeat: stop
→ all-cooldown sleep
if repeat > 0 && iteration >= repeat: stop
```
## CLI-флаги
@@ -191,14 +202,16 @@ StartBackgroundChecker:
### Глобальные (`cmd/root.go`)
| Флаг | Поле | Описание |
| --------------- | ----------------- | ----------------- |
| `--config` | `Args.ConfigPath` | Путь к config.yml |
| `-v, --verbose` | `Args.Verbose` | Подробный лог |
| Флаг | Поле | Описание |
| --------------- | ----------------- | ------------------- |
| `--config` | `Args.ConfigPath` | Путь к config.yml |
| `-v, --verbose` | `Args.Verbose` | Подробный лог |
| `--debug` | `Args.Debug` | Режим отладки |
| `--log-level` | `Args.LogLevel` | Уровень логирования |
## Конфигурация
Подробное описание параметров — в разделе [config.yml](../../common/config/config.md).
Подробное описание параметров — в разделе [config.yml](../../ref/config.md).
Приоритет: Defaults < `config.yml` < Env < CLI-флаги.
+11 -8
View File
@@ -17,14 +17,17 @@ make linux
## Доступные рецепты Makefile
| Команда | Назначение |
| -------------- | ------------------------------------------------------------- |
| `make linux` | Сборка под Linux (amd64 по умолчанию) |
| `make win` | Сборка под Windows |
| `make darwin` | Сборка под macOS |
| `make release` | Сборка под все платформы (linux/windows/darwin × amd64/arm64) |
| `make clean` | Удаление скомпилированных бинарников |
| `make help` | Вывод списка доступных рецептов |
| Команда | Назначение |
| ---------------- | ------------------------------------------------------------- |
| `make linux` | Сборка под Linux (amd64 по умолчанию) |
| `make win` | Сборка под Windows |
| `make darwin` | Сборка под macOS |
| `make release` | Сборка под все платформы (linux/windows/darwin × amd64/arm64) |
| `make test` | Запуск всех тестов |
| `make clear` | Удаление скомпилированных бинарников |
| `make image` | Сборка Docker-образа для текущей платформы |
| `make image-all` | Сборка и отправка multi-arch манифеста в registry |
| `make help` | Вывод списка доступных рецептов |
## Управление архитектурой
+18 -8
View File
@@ -8,22 +8,32 @@ tags: ["iptvc", "docker"]
## Сборка
Образ собирается из [Dockerfile](https://git.axenov.dev/IPTV/iptvc/src/branch/master/Dockerfile) — multi-stage сборка на базе `golang:1.25-alpine` с финальным образом `alpine:3.22`.
Образ собирается из [Dockerfile](https://git.axenov.dev/IPTV/iptvc/src/branch/master/Dockerfile) на базе `alpine:3.22.5`.
Бинарный файл должен быть предварительно собран через `make linux` — Dockerfile берёт уже готовый бинарь из `bin/linux_${TARGETARCH}/iptvc`.
```bash
docker build -t iptvc ./iptvc
# Сборка бинарного файла и образа
make image
# Сборка с указанием архитектуры
make image GOARCH=arm64
# Сборка с указанием тега
make image IMAGE_TAG=v1.1.3
```
Можно передать версию через build-arg:
Целевая архитектура задаётся через `GOARCH`:
```bash
docker build --build-arg IPTVC_VERSION=1.1.3 -t iptvc:v1.1.3 ./iptvc
make linux GOARCH=arm64
make image GOARCH=arm64
```
Целевая платформа и архитектура задаются через `GOOS` и `GOARCH`:
Для публикации multi-arch манифеста в registry:
```bash
docker build --build-arg GOOS=linux --build-arg GOARCH=arm64 -t iptvc:linux-arm64 ./iptvc
make image-all
```
## Запуск
@@ -33,13 +43,13 @@ docker build --build-arg GOOS=linux --build-arg GOARCH=arm64 -t iptvc:linux-arm6
docker run --rm \
-v ./playlists.ini:/app/playlists.ini \
-v ./channels.json:/app/channels.json \
iptvc check -i playlists.ini --repeat 0 --playlists-all-cooldown 60
git.axenov.dev/iptv/iptvc:latest check -i playlists.ini --repeat 0 --playlists-all-cooldown 60
# Веб-сервер с фоновой проверкой
docker run --rm -p 8800:8800 \
-v ./playlists.ini:/app/playlists.ini \
-v ./channels.json:/app/channels.json \
iptvc serve -i playlists.ini -p 8800 --check
git.axenov.dev/iptv/iptvc:latest serve -i playlists.ini -p 8800 --check
```
## Использование в compose
+3 -1
View File
@@ -1,4 +1,6 @@
Информацию о лицензии см. на странице [Свободное ПО](../../../legal/license.md)
# Иконки codicons
Информацию о лицензии см. на странице [Свободное ПО](../../../extra/legal/license.md)
| Иконка | Код для вставки в текст | Код для вставки в frontmatter |
| ------------------------------------------------ | -------------------------------------------------- | ------------------------------------------------ |
+3 -3
View File
@@ -53,9 +53,9 @@ make release
Для работы `iptvc` нужны два файла рядом с бинарником:
- `playlists.ini` — список плейлистов. Формат описан в [справочнике форматов](../../common/formats/playlists.md).
- `channels.json` — правила тегов каналов. Формат описан в [справочнике форматов](../../common/formats/channels.md).
- `config.yml` — конфигурация программы. Описание — в [разделе config.yml](../../common/config/config.md).
- `playlists.ini` — список плейлистов. Формат описан в [справочнике форматов](../../ref/formats/playlists.md).
- `channels.json` — правила тегов каналов. Формат описан в [справочнике форматов](../../ref/formats/channels.md).
- `config.yml` — конфигурация программы. Описание — в [разделе config.yml](../../ref/config.md).
## Полное Docker-окружение
+1 -1
View File
@@ -25,7 +25,7 @@ tags: ["iptvc"]
## Запуск релизного образа
Релизные docker-образы строятся для платформы `linux` и архитектуры `amd64`.
Релизные docker-образы строятся для платформы `linux` и архитектур `amd64` и `arm64`.
Найти их можно здесь: <https://git.axenov.dev/IPTV/-/packages/container/iptvc>
+1 -1
View File
@@ -49,7 +49,7 @@ hide: [toc]
[start]: quickstart.md "Перейти к разделу"
[site]: site/first-steps.md "Перейти к разделу"
[cli]: commands/index.md "Перейти к разделу"
[cfg]: ../common/config/config.md "Перейти к разделу"
[cfg]: ../ref/config.md "Перейти к разделу"
<!--
## :material-cog-sync-outline: Как работает `iptvc`
+2 -2
View File
@@ -25,7 +25,7 @@ tags: ["iptvc"]
./iptvc check --file /home/user/pls.m3u
```
## Проверить плейлист по короткому коду из [`playlists.ini`](../common/formats/playlists.md)
## Проверить плейлист по короткому коду из [`playlists.ini`](../ref/formats/playlists.md)
```
./iptvc check -c X
@@ -44,7 +44,7 @@ tags: ["iptvc"]
## Присвоить каналам тематические теги
Для этого рядом с `iptvc` должен лежать файл [channels.json](../common/formats/channels.md).
Для этого рядом с `iptvc` должен лежать файл [channels.json](../ref/formats/channels.md).
Если файл лежит в другой директории, то можно указать её явно:
+100
View File
@@ -0,0 +1,100 @@
---
icon: material/file-refresh-outline
tags: ["статусы", "плейлисты", "каналы", "iptvc"]
---
# :material-file-refresh-outline: Проверки и статусы
Плейлисты проверяются автоматически с некоей периодичностью, если приложение запущено [соответствующим образом](deploy.md).
Хотя я и стараюсь улучшать качество проверок, но всё же рекомендую проверять желаемые плейлисты самостоятельно вручную, ибо нет никаких гарантий:
* что плейлист составлен корректно и обработается правильно;
* что плейлист (не) работоспособен:
* он может работать, но проверка заврешена из-за какой-то технической ошибки;
* он уже может не работать, но результаты последней проверки показывают обратное;
* что транслируемый контент соответствует заявленным названиям;
* что сейчас или через X времени там не окажется [заглушка](../../aggregator/faq.md#заглушка).
## Статусы плейлистов { id="playlists" }
Каждый плейлист может быть в одном из трёх статусов:
* <span class="badge unknown">unknown</span> — **Плейлист в очереди на проверку**
Он сменит свой статус в ближайшие минуты.
* <span class="badge online">online</span> — **Плейлист проверен**
Это не значит, что он работает.
Это значит, что адрес плейлиста корректен и *вероятно* там *что-то* транслируется.
* <span class="badge offline">offline</span> — **Плейлист недоступен**
Либо плейлист удалён с сервера, где он располагался когда-то, либо это просто разовый сбой (например, таймаут проверки).
*Возможно*, (не) скоро он (не) станет доступен.
!!! info "Обрати внимание"
Независимо от статуса плейлиста на сайте, его можно добавить в свой плеер по "Ссылке для ТВ" и проверить самостоятельно.
Проверка плейлиста не влияет на его работоспособность.
### Дополнительные возможности { id="extra" }
Если плейлист <span class="badge online">online</span> (успешно проверен), то у него могут быть дополнительные значки:
* <span class="badge online-percent">95%</span> — количество рабочих каналов на момент проверки;
* <span class="badge adult">18+</span> — плейлист имеет каналы для взрослых;
* <span class="badge lapka">:material-paw:</span> — плейлист может быть нестабилен:
Это значит, что в нём есть каналы со специальными параметрами: токенами, логинами и паролями, которые рано или поздно истекут или будут заблокированы (если ещё не).
Также это признак бесплатного пробного периода.
* :material-folder-open-outline: — каналы плейлиста разбиты на группы (например, музыкальные каналы и региональные);
* :material-newspaper-variant-outline: — плейлист предоставляет программу передач для каналов;
* :material-skip-backward: — плейлист предоставляет возможность перемотки передач.
Если плейлист <span class="badge unknown">unknown</span> или <span class="badge offline">offline</span>, этих иконок не будет.
!!! info "Обрати внимание"
1. Пропорции рабочих и нерабочих каналов в плейлистах могут меняться от проверки к проверке.
Это нормально, таковы технические особенности проверки.
2. Работа архива и программы передач зависит от выбранного [плеера](../../ref/players.md).
Некоторые это просто не поддерживают.
## Статусы каналов { id="channels" }
Каждый канал в любом плейлисте может быть в одном из трёх статусов:
* <span class="icon online">:material-radiobox-marked:</span> — ***Возможно*, канал работает**
Но там может транслироваться какая-нибудь [заглушка](../../aggregator/faq.md#заглушка) (например, от [Wink](../../aggregator/faq.md#wink)) или другой канал.
* <span class="icon offline">:material-radiobox-marked:</span> — ***Возможно*, канал не работает**
Чем больше таких каналов в плейлисте, тем сложнее будет листать плейлист в плеере или на ТВ.
Но *возможно когда-нибудь* плейлист обновят и канал будет работать исправно.
Также здесь может быть просто разовый сбой (например, таймаут проверки).
* <span class="badge lapka">:material-paw:</span> — **Канал может быть нестабилен**
Это значит, что для него указаны специальные параметры: токен, логин или пароль, которые рано или поздно истекут или будут заблокированы.
Тогда канал перестанет работать.
Также это признак бесплатного пробного периода.
* <span class="badge adult">18+</span> — **Канал для взрослых**
Читай ниже.
## Контент для взрослых { id="adult" }
Это откровенно порнографический, эротический или другой контент, неприемлемый для детской психики (например, жанровые каналы с фильмами ужасов).
Если при проверке плейлиста обнаружен хотя бы один канал для взрослых, то этот канал и весь плейлист помечается значком <span class="badge adult">18+</span>.
Такие каналы определяются благодаря правилам, описанным в файле [channels.json](../../ref/formats/channels.md).
Они применяются к названиям каналов и их атрибутам (`tvg-id`, `tvg-name`), которые описывают канал в плейлисте.
Для каналов со взрослым контентом применяется тег `adult`.
!!! warning "Обрати внимание"
Далеко не все каналы могут быть помечены таким тегом.
Хотя набор правил для тегов очень богат, но невозможно угадать все каналы с приемлемой точностью.
Почему — читай [здесь](../../ref/formats/channels.md#warnings).
---
!!! info "Примечание"
Теперь должно стать понятно, почему я не даю и не могу дать никаких гарантий относительно результатов проверок и тегов.
Каждый раз это просто непредсказуемый процесс.
+2 -2
View File
@@ -5,10 +5,10 @@ tags: ["плееры", "плейлисты"]
# :material-television-play: Как подключить плейлист
1. Найти какой-нибудь [плеер](../../common/players.md)
1. Найти какой-нибудь [плеер](../../ref/players.md)
2. Узнать как в него добавить плейлист по ссылке
3. Найти желаемый плелист из [списка](./list.md)
4. Найти на странице ["Ссылку для ТВ"](details.md#shortlink) и ввести (скопировать) её в поле ввода адреса в плеере
Для некоторых [плееров](../../common/players.md) уже есть информация как добавить плейлист.
Для некоторых [плееров](../../ref/players.md) уже есть информация как добавить плейлист.
+307 -27
View File
@@ -1,29 +1,133 @@
---
icon: material/upload-network
tags: ["iptvc", "docker", "deploy"]
tags: ["iptvc", "docker", "deploy", "nginx", "apache", "ssl"]
---
# :material-upload-network: Развёртывание и доставка обновлений
# :material-upload-network: Развёртывание сайта
В этом разделе описан фактический порядок настройки окружения `iptv` с приложением `iptvc`, хранилищем KeyDB и сайтом документации.
В этом разделе описан фактический порядок настройки `iptvc`, хранилищем KeyDB и документацией.
## Требования { id="requirements" }
## :material-flag-checkered: Базовый вариант развёртывания сервиса { id="local" }
Для запуска приложения не нужен репозиторий с исходниками.
Достаточно [скачать актуальный релиз](../install.md) для своей платформы.
Чтобы запустить его, достаточно расположить его в любой удобной директории на диске и выполнить команду:
```shell
./iptvc serve
```
Откройте в браузере адрес <http://localhost:8800/> и убедитесь в работе сервиса.
Вы должны увидеть ошибку:
```
Не удалось загрузить список плейлистов. Проверьте наличие файла playlists.ini.
```
Всё верно.
Для полноценной работы приложения в качестве веб-сервиса следует провести минимальные настройки.
### Список плейлистов — `playlists.ini` { id="playlists" }
!!! info "Синтаксис описан в [этом разделе документации](../../ref/formats/playlists.md)"
Без этого файла нет смысла запускать веб-сервис.
Файл можно положить рядом с `iptvc`.
Как только вы подготовите файл, перезапустите сервис командой выше.
Вы должны увидеть список плейлистов на главной странице.
Но все они будут серого цвета и будет доступна только базовая информация о них.
Зато будут работать короткие ссылки и их уже можно будет казывать в своём любимом [плеере](../../ref/players.md).
Чтобы плейлисты позеленели, нужно запустить приложение в режиме активной проверки плейлистов:
```shell
./iptvc serve --check
```
!!! tip "У этой команды есть и другие аргументы"
Полный список указан здесь: [**Команда `serve`**](../commands/serve.md).
Они позволят, при необходимости, очень гибко настроить параметры сайта и режима проверки.
### Список правил — `channels.json` { id="channels" }
!!! info "Синтаксис описан в [этом разделе документации](../../ref/formats/channels.md)"
Без этого файла можно жить: веб-сервис будет работать, плейлисты и каналы будут проверяться, короткие ссылки в вашем распоряжении.
Но **все** каналы будут помечены как `#untagged`.
Это значит, что такие каналы можно будет искать только по названиям.
Поиск по жанрам и странам будет недоступен.
Это может быть важно для разных пользователей.
Поэтому варианта здесь три:
1. продолжать пользоваться сервисом как есть;
2. подготовить свой файл `channels.json` согласно его правил синтаксиса;
3. скачать готовый файл из репозитория: [channels.json](https://git.axenov.dev/IPTV/iptvc/raw/branch/master/channels.json)
??? tip "Рекомендуется третий вариант"
Файл в репозитории периодически обновляется по тем плейлистам, которые широко распространяются в сети.
В нём собраны правла для многих телеканалов СНГ и Европы.
Хотя и далеко не все.
Поэтому, если вы умеете работать с регулярными выражениями, вы можете предложить свои правила в репозиторий.
Файл можно положить туда же — рядом с `iptvc`.
Когда файл будет готов, перезапустите приложение предыдущей командой.
Поздравляю, теперь у вас свой собственный рабочий агрегатор плейлистов.
Вы можете его использовать в домашней сети или на своём ПК — для мониторинга состояния плейлистов или для просмотра.
### Конфигурация приложения — `config.yml`
!!! info "Синтаксис описан в [этом разделе документации](../../ref/config.md)"
Теперь можете приступить к конфигурации приложения.
Это позволит вам освободить руки и мозг, чтобы не запоминать и не писать длинные аргументы, а также изменять параметры, недоступные через в командной строке.
Файл можно положить туда же — рядом с `iptvc`.
Но постойте.
Вы уже несколько раз перезапустили приложение, а результаты проверки плейлистов сбрасываются.
А если вы перезагрузите компьютер, то придётся заново вручную запускать приложение.
Давайте это исправим в следующих шагах.
## :simple-docker: Развёртывание через Docker { id="docker" }
Установка docker осуществляется согласно официальной документации.
??? tip "Для MacOS вместо Docker Desktop рекомендую [OrbStack](https://orbstack.dev)"
Он быстрый, лёгкий, бесплатный и не жрёт столько ресурсов, как официальное приложение.
В общем-то, сама по себе гуйня для докера бесполезна и не нужна, но на маке эта тулза поможет с запуском докера на сокете в пространстве текущего пользователя.
К сожалению, иначе на маке докер работать в фоне не может из-за политик безопасности.
Либо может, но это потребует кучу гемора на ровном месте.
Для этого нужно будет скачать ещё один файл из репозитория: [compose.yml](https://git.axenov.dev/IPTV/iptvc/raw/branch/master/compose.yml)
---
---
---
- [Docker](https://docs.docker.com/engine/install/) с плагином `docker compose` версии 2
- Git и доступ к репозиторию `git.axenov.dev/IPTV`
- Права на запись в каталог данных KeyDB
- Доступ к registry `git.axenov.dev`, если вы публикуете образ `iptvc`
!!! warning "Только docker compose v2"
Используйте команду `docker compose`.
Устаревшая команда `docker-compose` в этом сценарии не поддерживается.
## Подготовка репозитория { id="repository" }
Клонируйте основной репозиторий и перейдите в его каталог:
```bash
git clone https://git.axenov.dev/IPTV.git
git clone https://git.axenov.dev/IPTV/.git
cd IPTV
```
@@ -108,30 +212,206 @@ docker compose logs -f iptvc
docker compose down
```
## Реверс-прокси и SSL { id="reverse-proxy" }
Для публикации приложения на домене с HTTPS настроим реверс-прокси, который будет терминировать SSL и проксировать запросы на контейнеры `iptvc` (порт `8800`) и `docs` (порт `8801`).
Ниже рассмотрены два варианта: nginx и Apache2.
!!! tip "site.base-url"
После настройки домена укажите внешний адрес в `config.yml` или `.env`:
```yaml
site:
base-url: https://example.com
```
Или через переменную окружения:
```bash
SITE_BASE_URL=https://example.com
```
### Подготовка { id="reverse-proxy-prep" }
Убедитесь, что:
- домен `example.com` (и при необходимости `docs.example.com`) направляет A-запись на IP сервера;
- порты `80` и `443` открыты в файрволе;
- Docker-окружение запущено (`docker compose up -d`);
- порты `8800` и `8801` доступны локально (проверьте `curl -I http://localhost:8800`).
### nginx { id="reverse-proxy-nginx" }
Установите nginx и Certbot:
```bash
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
```
Создайте конфигурацию для приложения:
```nginx title="/etc/nginx/sites-available/iptvc" linenums="1"
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8800;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
При необходимости добавьте отдельный `server`-блок для документации:
```nginx title="/etc/nginx/sites-available/iptv-docs" linenums="1"
server {
listen 80;
server_name docs.example.com;
location / {
proxy_pass http://127.0.0.1:8801;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Включите конфигурации и проверьте синтаксис:
```bash
sudo ln -s /etc/nginx/sites-available/iptvc /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/iptv-docs /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
Получите SSL-сертификат через Certbot:
```bash
sudo certbot --nginx -d example.com -d docs.example.com
```
Certbot автоматически изменит конфигурацию nginx, добавит HTTPS и настройке редирект с HTTP на HTTPS.
Проверьте автоматическое продление:
```bash
sudo certbot renew --dry-run
```
### Apache2 { id="reverse-proxy-apache" }
Установите Apache2 и Certbot:
```bash
sudo apt update
sudo apt install -y apache2 certbot python3-certbot-apache
```
Включите необходимые модули:
```bash
sudo a2enmod proxy proxy_http ssl rewrite headers
sudo systemctl restart apache2
```
Создайте конфигурацию виртуального хоста для приложения:
```apache title="/etc/apache2/sites-available/iptvc.conf" linenums="1"
<VirtualHost *:80>
ServerName example.com
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8800/
ProxyPassReverse / http://127.0.0.1:8800/
RequestHeader set X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-Port "80"
</VirtualHost>
```
При необходимости добавьте виртуальный хост для документации:
```apache title="/etc/apache2/sites-available/iptv-docs.conf" linenums="1"
<VirtualHost *:80>
ServerName docs.example.com
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8801/
ProxyPassReverse / http://127.0.0.1:8801/
RequestHeader set X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-Port "80"
</VirtualHost>
```
Включите конфигурации и проверьте синтаксис:
```bash
sudo a2ensite iptvc iptv-docs
sudo apache2ctl configtest
sudo systemctl reload apache2
```
Получите SSL-сертификат через Certbot:
```bash
sudo certbot --apache -d example.com -d docs.example.com
```
Certbot автоматически создаст HTTPS-виртуальные хосты и настроит редирект с HTTP на HTTPS.
Проверьте автоматическое продление:
```bash
sudo certbot renew --dry-run
```
### Проверка { id="reverse-proxy-check" }
После настройки откройте в браузере:
- `https://example.com` — веб-интерфейс `iptvc`;
- `https://docs.example.com` — сайт документации.
Убедитесь, что сертификат валиден, а редирект с HTTP на HTTPS работает.
!!! note "Ограничение портов"
После настройки реверс-прокси можно убрать публикацию портов `8800` и `8801` наружу в `compose.yml`, оставив их доступными только локально.
Это предотвратит прямой доступ к сервисам в обход прокси.
## Сборка образа iptvc { id="image" }
Для публикации образа используйте скрипт `iptvc/build-docker-image.sh`.
Скрипт вычисляет версию из Git, собирает образы с тегами `iptvc:<тег>` и `git.axenov.dev/iptv/iptvc:<тег>`, а затем отправляет registry-тег в registry:
Для сборки и публикации образа используйте цели Makefile в каталоге `iptvc/`:
```bash
cd iptvc
./build-docker-image.sh latest
# Сборка одноархитектурного образа (linux/amd64 по умолчанию)
make image
# Сборка под arm64
make image GOARCH=arm64
# Сборка с указанием тега
make image IMAGE_TAG=v1.2.3
```
Для публикации релизного тега:
Для публикации multi-arch манифеста (linux/amd64 + linux/arm64):
```bash
./build-docker-image.sh v1.2.3
make image-all
```
По умолчанию скрипт собирает Linux-образ для `amd64`.
Платформу можно изменить переменными окружения:
```bash
GOOS=linux GOARCH=arm64 ./build-docker-image.sh v1.2.3
```
Цель `image-all` всегда отправляет образ в registry — это ограничение `docker buildx`: multi-arch манифест нельзя загрузить в локальный Docker daemon.
Перед публикацией войдите в registry, если это требуется вашей настройкой:
@@ -140,8 +420,8 @@ docker login git.axenov.dev
```
!!! warning "Рабочее дерево Git"
Скрипт переключается на Git-тег, переданный первым аргументом, или на тег, возвращённый `git describe`.
Перед запуском сохраните локальные изменения и убедитесь, что нужный тег существует.
Версия и коммит вшиваются в бинарь из `git describe` и `git rev-parse` на хосте в момент запуска `make`.
Перед сборкой убедитесь, что рабочая копия чистая и находится на нужном теге или коммите.
## Обновление { id="update" }
+15 -11
View File
@@ -7,7 +7,7 @@ tags: ["сайт", "статусы", "каналы"]
Страница содержит подробности об одном конкретном плейлисте.
В её заголовке указано [название плейлиста](../../common/formats/playlists.md#name).
В её заголовке указано [название плейлиста](../../ref/formats/playlists.md#name).
Ниже страница разделена на две части: слева две вкладки с информацией и список каналов справа.
@@ -19,17 +19,17 @@ tags: ["сайт", "статусы", "каналы"]
На этой вкладке выводится таблица со следующими строками:
* **Код** — короткий уникальный [код плейлиста](../../common/formats/playlists.md#code);
* **Описание** — [описание плейлиста](../../common/formats/playlists.md#desc) (при наличии);
* **Код** — короткий уникальный [код плейлиста](../../ref/formats/playlists.md#code);
* **Описание** — [описание плейлиста](../../ref/formats/playlists.md#desc) (при наличии);
* **Ccылка для ТВ** — короткая ссылка, которую можно использовать для [подключения плейлиста](connect.md), подробнее о ней см. ниже;
* **Источник** — [ссылка на ресурс](../../common/formats/playlists.md#src), где была найдена ссылка на плейлист (при наличии);
* **Источник** — [ссылка на ресурс](../../ref/formats/playlists.md#src), где была найдена ссылка на плейлист (при наличии);
* **Наполнение**:
* группы — количество групп, на которые поделены каналы;
* каналы — количества каналов общее, онлайн и оффлайн;
(всё по нулям, если плейлист <span class="badge offline">offline</span>)
* **Возможности** — наличие программы передач и перемотки каналов;
* **M3U** — [прямая ссылка](../../common/formats/playlists.md#pls) на плейлист;
* **Проверка плейлиста** — дата и время последней [проверки](../../aggregator/checks.md) плейлиста с помощью [iptvc](../overview.md);
* **M3U** — [прямая ссылка](../../ref/formats/playlists.md#pls) на плейлист;
* **Проверка плейлиста** — дата и время последней [проверки](checks.md) плейлиста с помощью [iptvc](../overview.md);
* **Ошибка проверки** — текст ошибки, которая возникла при проверке
(только если плейлист <span class="badge offline">offline</span>)
@@ -82,7 +82,7 @@ tags: ["сайт", "статусы", "каналы"]
Справа от строки поиска есть **кнопки фильтрации каналов по их статусу**.
Справа — **кнопка сброса** для отображения всех каналов.
Под строкой поиска есть [**облако тегов**](../../common/formats/channels.md#доступные-теги).
Под строкой поиска есть [**облако тегов**](../../ref/formats/channels.md#доступные-теги).
!!! question inline end "Про теги"
Откуда они там появляются, можешь прочесть [здесь](../../common/index.md) и [здесь](../overview.md).
@@ -99,11 +99,15 @@ tags: ["сайт", "статусы", "каналы"]
Она может быть задана в нескольких форматах.
Поясню базовые принципы формирования адреса:
1. необязателен префикс протокола `http://` или `https://` перед доменом
2. обязателен домен `m3u.su`
1. префикс протокола `http://` или `https://` перед доменом
2. ваш домен или IP-адрес, порт после `:`
3. обязателен `/код` плейлиста после домена
4. необязателен суффикс расширения после кода `.m3u` или `.m3u8`
Пункты 1 и 2 напрямую зависят от того, как развёрнут сайт.
Базово, если запускать на своём ПК без дополнительных настроек, то адрес будет `http://localhost:8000`.
Доступ по домену требует, помимо самого домена, грамотную настройку реверс-прокси и SSL (в наше время иначе уже не модно).
На примере ниже я наглядно покажу все возможные ссылки на один и тот же плейлист с кодом `ru`:
```
@@ -119,12 +123,12 @@ m3u.su/ru
```
!!! info "Адрес может быть любым"
Смотря как будет развёрнут сайт, ты можешь заходить на localhost, либо по прямому IP-адресу или доменному имения.
Смотря как будет развёрнут сайт, ты можешь заходить на `localhost`, либо по прямому IP-адресу или доменному имени.
См. раздел [**Развёртывание**](deploy.md) для подробностей.
По идее, можешь использовать любую ссылку из подобных, т. к. технически они отработают одинаково.
А вот твой [плеер](../../common/players.md) может не принять какую-то из них.
А вот твой [плеер](../../ref/players.md) может не принять какую-то из них.
Так что, если не подойдёт один формат, используй другой — добавь префикс или суффикс.
Префикс плееру требуется чаще всего, потому что он при добавлении плейлиста проверяет — а ссылку ли мне вообще предоставил пользователь?
+21 -21
View File
@@ -36,7 +36,7 @@ tags: ["iptvc", "serve", "сайт"]
## Шаг 2. Добавляем плейлисты
Список плейлистов описывается в файле [`playlists.ini`](../../common/formats/playlists.md).
Список плейлистов описывается в файле [`playlists.ini`](../../ref/formats/playlists.md).
Создадим его рядом с `iptvc`:
```ini title="playlists.ini"
@@ -66,7 +66,7 @@ pls = 'https://example.com/movies.m3u'
Чтобы статусы появились, нужно включить фоновую проверку.
!!! tip "Путь к ini-файлу"
Если файл лежит не рядом с программой, укажите путь через флаг [`-i`](../commands/serve.md#ini) или в [`config.yml`](../../common/config/config.md) → `app.playlists`.
Если файл лежит не рядом с программой, укажите путь через флаг [`-i`](../commands/serve.md#ini) или в [`config.yml`](../../ref/config.md) → `app.playlists`.
---
@@ -92,7 +92,7 @@ pls = 'https://example.com/movies.m3u'
./iptvc serve --check --repeat 1
```
Если не хочется каждый раз писать `--check`, можно включить проверку через [`config.yml`](../../common/config/config.md):
Если не хочется каждый раз писать `--check`, можно включить проверку через [`config.yml`](../../ref/config.md):
```yaml title="config.yml"
check:
@@ -106,7 +106,7 @@ check:
## Шаг 4. Настраиваем внешний вид сайта
Сайт можно настроить под себя: заголовок, иконку, навигацию в шапке и ссылки в подвале.
Всё это — в секции [`site`](../../common/config/config.md) файла `config.yml`.
Всё это — в секции [`site`](../../ref/config.md) файла `config.yml`.
```yaml title="config.yml"
site:
@@ -150,7 +150,7 @@ site:
## Шаг 5. Добавляем теги каналам
Теги помогают посетителям находить каналы по темам: спорт, фильмы, музыка и так далее.
Правила описываются в файле [`channels.json`](../../common/formats/channels.md).
Правила описываются в файле [`channels.json`](../../ref/formats/channels.md).
```json title="channels.json"
[
@@ -169,13 +169,13 @@ site:
]
```
Путь к файлу указывается в [`config.yml`](../../common/config/config.md) → `app.tags` или через флаг [`-t`](../commands/serve.md#tags):
Путь к файлу указывается в [`config.yml`](../../ref/config.md) → `app.tags` или через флаг [`-t`](../commands/serve.md#tags):
```bash
./iptvc serve --check -t /path/to/channels.json
```
Полный список доступных тегов — в [справочнике по channels.json](../../common/formats/channels.md#доступные-теги).
Полный список доступных тегов — в [справочнике по channels.json](../../ref/formats/channels.md#доступные-теги).
---
@@ -185,7 +185,7 @@ site:
Если программу перезапустить — все результаты пропадут, и плейлисты снова станут `unknown` до следующей проверки.
Кеш решает эту проблему: результаты сохраняются в KeyDB (или Redis) и переживают перезапуск.
Включается одной строкой в [`config.yml`](../../common/config/config.md):
Включается одной строкой в [`config.yml`](../../ref/config.md):
```yaml title="config.yml"
cache:
@@ -217,7 +217,7 @@ CACHE_ENABLED=true CACHE_TTL=3600 ./iptvc serve --check
## Шаг 7. Тонкая настройка проверки
Когда плейлистов много, полезно управлять параллелизмом, таймаутами и задержками.
Все параметры — в секции [`check`](../../common/config/config.md) файла `config.yml`.
Все параметры — в секции [`check`](../../ref/config.md) файла `config.yml`.
### Параллелизм
@@ -277,7 +277,7 @@ check:
user-agent: Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36
```
Все эти параметры можно также задавать через [переменные окружения](../../common/config/config.md) или [CLI-флаги](../commands/serve.md) — они имеют наивысший приоритет.
Все эти параметры можно также задавать через [переменные окружения](../../ref/config.md) или [CLI-флаги](../commands/serve.md) — они имеют наивысший приоритет.
---
@@ -403,15 +403,15 @@ docker compose up -d
## Краткая шпаргалка
| Задача | Как |
| ----------------------------- | ------------------------------------------------------- |
| Запустить сайт | `./iptvc serve` |
| С проверкой плейлистов | `./iptvc serve --check` |
| На другом порту | `./iptvc serve -p 3000` |
| С ini-файлом из другого места | `./iptvc serve -i /path/to/playlists.ini` |
| С кешем | `./iptvc serve --check --cache-enabled` |
| Один цикл проверки | `./iptvc serve --check --repeat 1` |
| Пауза 2 минуты между циклами | `./iptvc serve --check --playlists-all-cooldown 120` |
| Подробные логи | `./iptvc serve --check --verbose` |
| Задача | Как |
| ----------------------------- | ---------------------------------------------------- |
| Запустить сайт | `./iptvc serve` |
| С проверкой плейлистов | `./iptvc serve --check` |
| На другом порту | `./iptvc serve -p 3000` |
| С ini-файлом из другого места | `./iptvc serve -i /path/to/playlists.ini` |
| С кешем | `./iptvc serve --check --cache-enabled` |
| Один цикл проверки | `./iptvc serve --check --repeat 1` |
| Пауза 2 минуты между циклами | `./iptvc serve --check --playlists-all-cooldown 120` |
| Подробные логи | `./iptvc serve --check --verbose` |
Полный список параметров — в [справочнике по `config.yml`](../../common/config/config.md), [переменным окружения](../../common/config/config.md) и [команде `serve`](../commands/serve.md).
Полный список параметров — в [справочнике по `config.yml`](../../ref/config.md), [переменным окружения](../../ref/config.md) и [команде `serve`](../commands/serve.md).
+3 -3
View File
@@ -5,10 +5,10 @@ tags: ["плейлисты", "каналы", "теги", "iptvc", "плееры"
# :material-cogs: Как работает сервис
1. В специальном файле [playlists.ini](../../common/formats/playlists.md) описываются плейлисты, которые кем-то опубликованы в интернете.
1. В специальном файле [playlists.ini](../../ref/formats/playlists.md) описываются плейлисты, которые кем-то опубликованы в интернете.
Каждому плейлисту присваивается свой уникальный **короткий код**.
2. В специальном файле [channels.json](../../common/formats/channels.md) описываются **ключевые слова** (метки, теги), которые характеризуют каналы.
3. В фоновом режиме [работает ПО](../overview.md), которое периодически [проверяет все плейлисты](../../aggregator/checks.md) из п. 1 и **присваивает теги** каналам из п. 2.
2. В специальном файле [channels.json](../../ref/formats/channels.md) описываются **ключевые слова** (метки, теги), которые характеризуют каналы.
3. В фоновом режиме [работает ПО](../overview.md), которое периодически [проверяет все плейлисты](checks.md) из п. 1 и **присваивает теги** каналам из п. 2.
4. На главной странице сайта выводится [весь список плейлистов](list.md), которые описаны в п. 1: с тегами, описаниями и короткими кодами.
5. Каждому плейлисту на сайте посвящена [своя страничка](details.md), где отображаются результаты его проверки, проверки его каналов (с присвоенными тегами) и пр.
6. Когда пользователь [обращается к плейлисту](connect.md) по короткому коду (например, `https://m3u.su/xyz`), то происходит **переадресация** на исходный плейлист.
+10 -10
View File
@@ -7,30 +7,30 @@ tags: ["сайт", "плейлисты"]
Это главная страница сайта.
![Скриншот с примером главной страницы на десктопе](../_assets/img/pls-list/pc.jpg)
![Скриншот с примером главной страницы на десктопе](_assets/pls-list/pc.jpg)
Наверху отображаются:
* дата последнего изменения файла [playlists.ini](../../common/formats/playlists.md)
* дата последнего изменения файла [playlists.ini](../../ref/formats/playlists.md)
* общее количество плейлистов и с разделением по статусам.
Ниже — спиcок плейлистов.
## Из чего состоит список
* **Код** — короткий уникальный [код плейлиста](../../common/formats/playlists.md#code)
* **Код** — короткий уникальный [код плейлиста](../../ref/formats/playlists.md#code)
* **Информация о плейлисте**
* [статус плейлиста](../../aggregator/checks.md#playlists)
* может быть [значок 18+](../../aggregator/checks.md#adult)
* [название плейлиста](../../common/formats/playlists.md#name) — ссылка на [страницу плейлиста](details.md)
* [статус плейлиста](checks.md#playlists)
* может быть [значок 18+](checks.md#adult)
* [название плейлиста](../../ref/formats/playlists.md#name) — ссылка на [страницу плейлиста](details.md)
под ним:
* [иконки возможностей плейлиста](../../aggregator/checks.md#extra) (только при статусе <span class="badge online">online</span>)
* [описание плейлиста](../../common/formats/playlists.md#desc) (при наличии)
* [список тегов](../../common/formats/channels.md#доступные-теги), собранный со всех каналов после их проверки (только при статусе <span class="badge online">online</span>)
* [иконки возможностей плейлиста](checks.md#extra) (только при статусе <span class="badge online">online</span>)
* [описание плейлиста](../../ref/formats/playlists.md#desc) (при наличии)
* [список тегов](../../ref/formats/channels.md#доступные-теги), собранный со всех каналов после их проверки (только при статусе <span class="badge online">online</span>)
* ещё одна ссылка на [страницу плейлиста](details.md)
* **Каналов** — фактическое количество каналов в плейлисте (только при статусе <span class="badge online">online</span>) или 0 (при других статусах)
* **Ссылка для ТВ** — [короткая ссылка](details.md#shortlink), которую можно использовать для [подключения плейлиста](connect.md).
В зависимости от ширины экрана, для экономии места может быть скрыто описание с иконками возможностей и короткая ссылка.
![Скриншот с примером главной страницы на смартфоне](../_assets/img/pls-list/mobile.jpg)
![Скриншот с примером главной страницы на смартфоне](_assets/pls-list/mobile.jpg)