wip7
@@ -0,0 +1,190 @@
|
||||
:root {
|
||||
/* Image admonition */
|
||||
--md-admonition-icon--image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M16 13.25A1.75 1.75 0 0 1 14.25 15H1.75A1.75 1.75 0 0 1 0 13.25V2.75C0 1.784.784 1 1.75 1h12.5c.966 0 1.75.784 1.75 1.75ZM1.75 2.5a.25.25 0 0 0-.25.25v10.5c0 .138.112.25.25.25h.94l.03-.03 6.077-6.078a1.75 1.75 0 0 1 2.412-.06L14.5 10.31V2.75a.25.25 0 0 0-.25-.25Zm12.5 11a.25.25 0 0 0 .25-.25v-.917l-4.298-3.889a.25.25 0 0 0-.344.009L4.81 13.5ZM7 6a2 2 0 1 1-3.999.001A2 2 0 0 1 7 6M5.5 6a.5.5 0 1 0-1 0 .5.5 0 0 0 1 0"/></svg>');
|
||||
/* Yoomoney logo */
|
||||
--md-admonition-icon--yoomoney: url('data:image/svg+xml;charset=utf-8,<svg width="169" height="120" viewBox="0 0 169 120" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M108.99 0C75.5725 0 48.9902 26.962 48.9902 60C48.9902 93.4177 75.9523 120 108.99 120C142.028 120 168.99 93.038 168.99 60C168.99 26.962 142.028 0 108.99 0ZM108.99 82.4051C96.8383 82.4051 86.5852 72.1519 86.5852 60C86.5852 47.8481 96.8383 37.5949 108.99 37.5949C121.142 37.5949 131.395 47.8481 131.395 60C131.016 72.1519 121.142 82.4051 108.99 82.4051Z" fill="white"/><path d="M48.6076 17.4684V104.81H27.3418L0 17.4684H48.6076V17.4684Z" fill="white"/></svg>');
|
||||
/* Boosty logo */
|
||||
--md-admonition-icon--boosty: url('data:image/svg+xml;charset=utf-8,<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M2.661 14.337 6.801 0h6.362L11.88 4.444l-0.038 0.077 -3.378 11.733h3.15c-1.321 3.289 -2.35 5.867 -3.086 7.733 -5.816 -0.063 -7.442 -4.228 -6.02 -9.155M8.554 24l7.67 -11.035h-3.25l2.83 -7.073c4.852 0.508 7.137 4.33 5.791 8.952C20.16 19.81 14.344 24 8.68 24h-0.127z" fill="white" stroke-width="1"></path></svg>');
|
||||
}
|
||||
|
||||
/* Image admonition styling */
|
||||
|
||||
.md-typeset .admonition.image,
|
||||
.md-typeset details.image {
|
||||
border-color: var(--md-admonition-fg-color);
|
||||
}
|
||||
.md-typeset .image > .admonition-title::before,
|
||||
.md-typeset .image > summary::before {
|
||||
background-color: var(--md-admonition-fg-color);
|
||||
-webkit-mask-image: var(--md-admonition-icon--image);
|
||||
mask-image: var(--md-admonition-icon--image);
|
||||
}
|
||||
|
||||
/* Yoomoney admonition styling */
|
||||
|
||||
.md-typeset .admonition.yoomoney,
|
||||
.md-typeset details.yoomoney {
|
||||
border-color: rgba(113, 47, 244, 1);
|
||||
}
|
||||
.md-typeset .yoomoney > .admonition-title::before,
|
||||
.md-typeset .yoomoney > summary::before {
|
||||
background-color: rgb(113, 47, 244);
|
||||
-webkit-mask-image: var(--md-admonition-icon--yoomoney);
|
||||
mask-image: var(--md-admonition-icon--yoomoney);
|
||||
}
|
||||
|
||||
/* Boosty admonition styling */
|
||||
|
||||
.md-typeset .admonition.boosty,
|
||||
.md-typeset details.boosty {
|
||||
border-color: rgb(241, 95, 44);
|
||||
}
|
||||
.md-typeset .boosty > .admonition-title::before,
|
||||
.md-typeset .boosty > summary::before {
|
||||
background-color: rgb(241, 95, 44);
|
||||
-webkit-mask-image: var(--md-admonition-icon--boosty);
|
||||
mask-image: var(--md-admonition-icon--boosty);
|
||||
}
|
||||
|
||||
|
||||
.badge {
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
color: rgb(33, 37, 41);
|
||||
display: inline-block;
|
||||
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', 'Noto Sans', 'Liberation Sans', Arial,
|
||||
sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
font-size: 10.5px;
|
||||
font-weight: 700;
|
||||
height: 17.8438px;
|
||||
line-height: 10.5px;
|
||||
margin-right: 4px;
|
||||
padding-bottom: 3.675px;
|
||||
padding-left: 6.825px;
|
||||
padding-right: 6.825px;
|
||||
padding-top: 3.675px;
|
||||
text-align: center;
|
||||
text-size-adjust: 100%;
|
||||
text-wrap-mode: nowrap;
|
||||
vertical-align: baseline;
|
||||
white-space-collapse: collapse;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.badge.online {
|
||||
background-color: rgb(25, 135, 84);
|
||||
}
|
||||
|
||||
.badge.online-percent {
|
||||
border: 1px solid rgb(25, 135, 84);
|
||||
color: var(--md-typeset-color);
|
||||
}
|
||||
|
||||
.badge.offline {
|
||||
background-color: rgb(220, 53, 69);
|
||||
}
|
||||
|
||||
.badge.unknown {
|
||||
background-color: rgb(108, 117, 125);
|
||||
}
|
||||
|
||||
.badge.adult {
|
||||
background-color: rgb(255, 193, 7);
|
||||
}
|
||||
|
||||
.badge.lapka {
|
||||
background-color: rgb(13, 202, 240);
|
||||
}
|
||||
|
||||
.icon.online {
|
||||
color: rgb(25, 135, 84);
|
||||
}
|
||||
|
||||
.icon.offline {
|
||||
color: rgb(220, 53, 69);
|
||||
}
|
||||
|
||||
.md-typeset .md-button--primary {
|
||||
background: var(--md-accent-fg-color--transparent);
|
||||
color: var(--md-accent-fg-color);
|
||||
}
|
||||
|
||||
.md-typeset .wordwrap * {
|
||||
text-wrap: auto;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
/* Landing page template (overrides/landing.html) */
|
||||
|
||||
.tx-hero {
|
||||
margin: -2.4rem -1.6rem 2.4rem;
|
||||
padding: 3.5rem 1.6rem;
|
||||
}
|
||||
.tx-hero h1 {
|
||||
margin: 0 0 0.5rem;
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.1;
|
||||
}
|
||||
.tx-hero p {
|
||||
max-width: 40rem;
|
||||
font-size: 1.15rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.tx-hero__buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.md-typeset kbd {
|
||||
border-radius: .2rem;
|
||||
font-size: .85em;
|
||||
padding: 0 .5em;
|
||||
margin: 0 .1em;
|
||||
box-shadow:
|
||||
0 0.1rem 0 0.05rem var(--md-typeset-kbd-border-color),
|
||||
0 0.1rem 0 var(--md-typeset-kbd-border-color),
|
||||
0 -0.05rem 0.1rem var(--md-typeset-kbd-accent-color) inset;
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
/* Inline badges (inline_badges.py) */
|
||||
|
||||
|
||||
.md-typeset .mdx-badge {
|
||||
font-size: 0.8rem;
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
overflow: hidden;
|
||||
border: .1rem solid var(--md-accent-fg-color--transparent);
|
||||
border-radius: .25rem;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.md-typeset .mdx-badge__icon,
|
||||
.md-typeset .mdx-badge__text {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.md-typeset .mdx-badge__icon {
|
||||
justify-content: center;
|
||||
background-color: var(--md-accent-fg-color--transparent);
|
||||
padding: .15rem;
|
||||
color: var(--md-primary-fg-color);
|
||||
}
|
||||
|
||||
.md-typeset .mdx-badge__text {
|
||||
font-size: .85em;
|
||||
padding: 0 .5rem;
|
||||
}
|
||||
|
||||
.md-typeset .mdx-badge__text code {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,103 @@
|
||||
---
|
||||
icon: material/file-refresh-outline
|
||||
tags: ["статусы", "плейлисты", "каналы", "iptvc"]
|
||||
---
|
||||
|
||||
# :material-file-refresh-outline: Проверки и статусы
|
||||
|
||||
!!! danger "Я не гарантирую корректность и актуальность плейлистов, которые ты увидишь на сайте, как и корректность результатов их проверки."
|
||||
После прочтения этой страницы ты поймёшь почему.
|
||||
|
||||
Плейлисты [проверяются автоматически](../iptvc/overview.md) с некоей периодичностью.
|
||||
|
||||
Хотя я и стараюсь улучшать качество проверок, но всё же рекомендую проверять желаемые плейлисты самостоятельно вручную, ибо нет никаких гарантий:
|
||||
|
||||
* что плейлист составлен корректно и обработается правильно;
|
||||
* что плейлист (не) работоспособен:
|
||||
* он может работать, но проверка заврешена из-за какой-то технической ошибки;
|
||||
* он уже может не работать, но результаты последней проверки показывают обратное;
|
||||
* что транслируемый контент соответствует заявленным названиям;
|
||||
* что сейчас или через X времени там не окажется [заглушка](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"><ion-icon name="paw"></ion-icon></span> — плейлист может быть нестабилен
|
||||
Это значит, что в нём есть каналы со специальными параметрами: токенами, логинами и паролями, которые рано или поздно истекут или будут заблокированы (если ещё не).
|
||||
Также это признак бесплатного пробного периода.
|
||||
* <ion-icon name="folder-open-outline"></ion-icon> — каналы плейлиста разбиты на группы (например, музыкальные каналы и региональные);
|
||||
* <ion-icon name="newspaper-outline"></ion-icon> — плейлист предоставляет программу передач для каналов;
|
||||
* <ion-icon name="play-back"></ion-icon> — плейлист предоставляет возможность перемотки передач.
|
||||
|
||||
Если плейлист <span class="badge unknown">unknown</span> или <span class="badge offline">offline</span>, этих иконок не будет.
|
||||
|
||||
!!! info "Обрати внимание"
|
||||
1. Пропорции рабочих и нерабочих каналов в плейлистах могут меняться от проверки к проверке.
|
||||
Это нормально, таковы технические особенности проверки.
|
||||
2. Работа архива и программы передач зависит от выбранного [плеера](../common/players.md).
|
||||
Некоторые это просто не поддерживают.
|
||||
|
||||
## Статусы каналов { id="channels" }
|
||||
|
||||
Каждый канал в любом плейлисте может быть в одном из трёх статусов:
|
||||
|
||||
* <span class="icon online"><ion-icon name="radio-button-on-outline"></ion-icon></span> — ***Возможно*, канал работает**
|
||||
Но там может транслироваться какая-нибудь [заглушка](faq.md#заглушка) (например, от [Wink](faq.md#wink)) или другой канал.
|
||||
|
||||
* <span class="icon offline"><ion-icon name="radio-button-on-outline"></ion-icon></span> — ***Возможно*, канал не работает**
|
||||
Чем больше таких каналов в плейлисте, тем сложнее будет листать плейлист в плеере или на ТВ.
|
||||
Но *возможно когда-нибудь* плейлист обновят и канал будет работать исправно.
|
||||
Также здесь может быть просто разовый сбой (например, таймаут проверки).
|
||||
|
||||
* <span class="badge lapka"><ion-icon name="paw"></ion-icon></span> — **Канал может быть нестабилен**
|
||||
Это значит, что для него указаны специальные параметры: токен, логин или пароль, которые рано или поздно истекут или будут заблокированы.
|
||||
Тогда канал перестанет работать.
|
||||
Также это признак бесплатного пробного периода.
|
||||
|
||||
* <span class="badge adult">18+</span> — **Канал для взрослых**
|
||||
Читай ниже.
|
||||
|
||||
## Контент для взрослых { id="adult" }
|
||||
|
||||
Это откровенно порнографический, эротический или другой контент, неприемлемый для детской психики (например, жанровые каналы с фильмами ужасов).
|
||||
|
||||
Если при проверке плейлиста обнаружен хотя бы один канал для взрослых, то этот канал и весь плейлист помечается значком <span class="badge adult">18+</span>.
|
||||
|
||||
Такие каналы определяются благодаря правилам, описанным в файле [channels.json](../common/formats/channels.md).
|
||||
Они применяются к названиям каналов и их атрибутам (`tvg-id`, `tvg-name`), которые описывают канал в плейлисте.
|
||||
|
||||
Для каналов со взрослым контентом применяется тег `adult`.
|
||||
|
||||
!!! warning "Обрати внимание"
|
||||
Далеко не все каналы могут быть помечены таким тегом.
|
||||
Хотя набор правил для тегов очень богат, но невозможно угадать все каналы с приемлемой точностью.
|
||||
Почему — читай [здесь](../common/formats/channels.md#warnings).
|
||||
|
||||
---
|
||||
|
||||
!!! info "Примечание"
|
||||
Теперь должно стать понятно, почему я не даю и не могу дать никаких гарантий относительно результатов проверок и тегов.
|
||||
Каждый раз это просто непредсказуемый процесс.
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
---
|
||||
icon: material/frequently-asked-questions
|
||||
tags: ["сайт", "каналы", "плейлисты", "epg", "плееры", "user-agent", "wink", "подписка"]
|
||||
---
|
||||
|
||||
# :material-frequently-asked-questions: FAQ (ЧАстые ВОпросы)
|
||||
|
||||
## Не работает канал!
|
||||
|
||||
Ну штош ¯\\\_(ツ)\_/¯
|
||||
|
||||
## Добавь каналы!
|
||||
|
||||
Пожалуйста, обратитесь к [этому разделу документации](https://go-friend-go.narod.ru).
|
||||
|
||||
## Удали каналы!
|
||||
|
||||
Пожалуйста, обратитесь к [этому разделу документации](https://go-friend-go.narod.ru).
|
||||
|
||||
## Но мне нужны конкретные каналы!
|
||||
|
||||
Пожалуйста, обратитесь к [этому разделу документации](https://go-friend-go.narod.ru).
|
||||
|
||||
## Сделай мне плейлист!
|
||||
|
||||
Пожалуйста, обратитесь к [этому разделу документации](https://go-friend-go.narod.ru).
|
||||
|
||||
## Исправь плейлист!
|
||||
|
||||
Пожалуйста, обратитесь к [этому разделу документации](https://go-friend-go.narod.ru).
|
||||
|
||||
## А за деньги?
|
||||
|
||||
Пожалуйста, обратитесь к [этому разделу документации](https://go-friend-go.narod.ru).
|
||||
|
||||
## Эти плейлисты бесплатны?
|
||||
|
||||
Возможно.
|
||||
По крайней мере, так утверждают источники, которые их распространяют.
|
||||
Но гарантий никаких никто не даёт и не может.
|
||||
|
||||
Любой плейлист и любой канал в любом плейлисте может сдохнуть навсегда в любой момент.
|
||||
Или показать [заглушку](#заглушка).
|
||||
|
||||
И претензии на этот счёт я не принимаю.
|
||||
|
||||
## Откуда берутся логотипы каналов и программы передач?
|
||||
|
||||
Всё это (не) [указывается](../common/formats/m3u.md#tvg-logo) внутри плейлиста его авторами.
|
||||
Но в некоторых [плеерах](../common/players.md) можно вручную указывать программу передач (см. ниже).
|
||||
|
||||
## У канала нет логотипа!
|
||||
|
||||
Вспоминай.
|
||||
|
||||
## У **канала** нет программы передач (EPG), что делать?
|
||||
|
||||
Фига в том, что EPG может быть и [указан](../common/formats/m3u.md#url-tvg) в плейлисте, но у конкретного канала могут быть указаны некорректные [`tvg-id`](../common/formats/m3u.md#tvg-id) или [`tvg-name`](../common/formats/m3u.md#tvg-name).
|
||||
Может, его дёрнули из другого листа и не подогнали под другую EPG.
|
||||
|
||||
Так что вариантов масса:
|
||||
|
||||
* смотреть как есть;
|
||||
* найти другой плейлист, где этот канал есть с телепрограммой;
|
||||
* скачать плейлист себе файлом, исправить атрибуты канала и добавить в плеер уже этот лист, но забыть о его автообновлении;
|
||||
* настроить другую программу передач (см. ниже).
|
||||
|
||||
Также, помни, что не все плееры вообще поддерживают работу с телепрограммой.
|
||||
|
||||
## У **плейлиста** нет программы передач (EPG), что делать?
|
||||
|
||||
Помни:
|
||||
|
||||
* не все плееры вообще поддерживают работу с телепрограммой;
|
||||
* в плейлисте она просто может не быть указана.
|
||||
|
||||
Но если [плеер](../common/players.md) позволяет, можно указать ссылку на сторонную телепрограмму.
|
||||
|
||||
И это целое дело.
|
||||
Надо чтобы совпадали [`tvg-id`](../common/formats/m3u.md#tvg-id) или [`tvg-name`](../common/formats/m3u.md#tvg-name) каналов с теми, которые указываются в EPG.
|
||||
Так что не всякая телепрограмма подойдёт, не ко всякому плейлисту и не ко всем каналам.
|
||||
Надо подбирать и то, и то.
|
||||
|
||||
## А где взять программу передач (EPG)? { id="epg" }
|
||||
|
||||
1. Из самого плейлиста.
|
||||
Часто в атрибут [`url-tvg`](../common/formats/m3u.md#url-tvg) тега `#EXTM3U` указывают одну или две ссылки на EPG, разделяя их `;`.
|
||||
Их можно использовать отдельно, например, если плеер не может корректно обработать такое значение.
|
||||
|
||||
2. Взять одну из этих ссылок:
|
||||
|
||||
??? quote "Список"
|
||||
* `http://epg.fox-tv.fun/1.xmltv`
|
||||
* `http://epg.it999.ru/edem.xml.gz`
|
||||
* `http://epg.lightiptv.cc/epg.xml.gz`
|
||||
* `http://epg.one/epg.xml.gz`
|
||||
* `http://epg.team/tvteam.xml.7.2`
|
||||
* `http://epg.team/tvteam.xml.gz`
|
||||
* `http://programtv.ru/xmltv.xml.gz`
|
||||
* `http://spacetv.in/api/epg.xml.gz`
|
||||
* `http://www.teleguide.info/download/new3/xmltv.xml.gz`
|
||||
* `https://bcumedia.pro/epg.xml.gz`
|
||||
* `https://epg.fox-tv.fun/1.xmltv`
|
||||
* `https://filmax-tv.ru/epg.xml.gz`
|
||||
* `https://iptvx.one/epg/epg_lite.xml.gz`
|
||||
* `https://iptvx.one/epg/epg.xml.gz`
|
||||
* `https://klimedia.space/epg.xml.gz`
|
||||
* `https://list.satfor.pro/f/epg.xml.gz`
|
||||
|
||||
3. Найти другие здесь:
|
||||
* `https://iptvx.one/viewtopic.php?f=12&t=4`
|
||||
* `https://iptvmaster.ru/epg-for-iptv`
|
||||
* [https://google.com](https://google.com)
|
||||
|
||||
## Почему на сайте плейлист онлайн, но в нём 0 каналов?
|
||||
|
||||
[Тебе сюда](checks.md#playlists).
|
||||
|
||||
## Почему на сайте плейлист онлайн, но у меня он не работает?
|
||||
|
||||
Что значит "не работает"?
|
||||
|
||||
* Ты уверен, что ссылка в [правильном формате](../iptvc/site/details.md#shortlink)?
|
||||
* Ты уверен, что у тебя нормальное интернет-соединение?
|
||||
* Плеер показывает какую-то ошибку при добавлении плейлиста?
|
||||
* Плейлист добавляется по ссылке, но каналы не загружаются или плеер зависает?
|
||||
* Плейлист добавляется в плеер, каналы загружаются полностью, но не каналы показывают?
|
||||
* А есть скриншоты? Логи? Тексты ошибок?
|
||||
|
||||
Попробуй погуглить проблему с конкретным плеером, может ты не один с такой проблемой.
|
||||
Или [узнать в чате](../tg/chat.md).
|
||||
|
||||
Но вообще, это зависит от:
|
||||
|
||||
* автора плейлиста (дохлые каналы почти всегда есть даже в свежайших листах, но если лист не обновлялся год, что ты вряд-ли узнаешь, то рабочих каналов там не ищи);
|
||||
* твоего [плеера](../common/players.md) (видеотрансляции могут использовать кодек, который просто не поддерживается плеером);
|
||||
* ширины твоего интернет-канала (не надо пытаться врубать FHD/4K трансляции с мобильного интернета на самом дешёвом тарифе в лесу);
|
||||
* ретроградности Меркурия и магнитных бурь (а вдруг);
|
||||
* настроек твоей сети, твоего интернет-провайдера, VPN (подумай хорошенько, хочешь ли ты смотреть российские каналы из РФ через Уганду или США);
|
||||
* степени цензурирования интернета в твоём государстве (некоторые хосты официально блочатся на уровне провайдеров);
|
||||
* чёрта лысого.
|
||||
|
||||
Я не знаю.
|
||||
Вряд-ли знает хоть кто-то.
|
||||
|
||||
## А если я добавлю себе плейлист отсюда, он будет работать? Долго?
|
||||
|
||||
Наверное, будет.
|
||||
|
||||
Наверное, даже долго.
|
||||
|
||||
Мёртвые плейлисты я периодически вычищаю, реже — добавляю новые.
|
||||
|
||||
Короткие коды плейлистов могут меняться, поэтому вполне может произойти внезапная подмена одного другим, однако это происходит крайне редко.
|
||||
|
||||
Плюс читай про доверие [результатам проверки](checks.md).
|
||||
|
||||
## В плейлистах порнуха!
|
||||
|
||||
Да, в плейлистах порнуха.
|
||||
|
||||
Это [явно помечается](checks.md#adult) везде, где это технически возможно.
|
||||
Смотри с удовольствием сколько хочешь, всё для тебя.
|
||||
|
||||
Или без удовольствия.
|
||||
|
||||
Или не смотри.
|
||||
|
||||
Или не хоти.
|
||||
|
||||
### Но у меня же дети! Яжмать! Яжотец!
|
||||
|
||||
Я вот детям порнуху не показываю.
|
||||
|
||||
Ты тоже не показывай.
|
||||
|
||||
Это твоя проблема.
|
||||
|
||||
## Как часто изменяется список плейлистов?
|
||||
|
||||
Время от времени.
|
||||
Периодически я наблюдаю за ними и удаляю нерабочие.
|
||||
|
||||
Иногда я гуляю по интернету и ищу другие плейлисты, которых в проекте ещё нет.
|
||||
|
||||
Если есть кандидаты на добавление, то читай ниже.
|
||||
|
||||
## Что значит автообновляемый плейлист? { id="автообновляемый" }
|
||||
|
||||
Например, ты на своём компе:
|
||||
|
||||
* открываешь любой текстовый редактор;
|
||||
* оформляешь текст в формате [m3u](../common/formats/m3u.md);
|
||||
* сохраняешь в файл `pls.m3u`.
|
||||
|
||||
Получился плейлист `pls.m3u`.
|
||||
Открываешь его в проигрывателе (плеере) **вручную** и наслаждаешься.
|
||||
|
||||
Спустя время, ты хочешь его изменить:
|
||||
|
||||
* открываешь файл `pls.m3u` в любом текстовом редакторе;
|
||||
* изменяешь текст (добавляешь или удаляешь записи);
|
||||
* сохраняешь в файл `pls.m3u`.
|
||||
|
||||
Плейлист `pls.m3u` обновлён на диске **вручную**.
|
||||
Открываешь его в плеере **вручную** и наслаждаешься.
|
||||
|
||||
Но править его ручками неудобно, нужно что-то попроще:
|
||||
|
||||
* запускаешь свой плеер;
|
||||
* открываешь в нём окно плейлиста (он же "список воспроизведения");
|
||||
* накидываешь туда файлов из какой-нибудь папки;
|
||||
* сохраняешь в файл `pls.m3u`.
|
||||
|
||||
Надо изменить?
|
||||
Тоже легко:
|
||||
|
||||
* открываешь файл `pls.m3u` в плеере;
|
||||
* накидываешь туда ещё файлов из какой-нибудь папки;
|
||||
* сохраняешь в файл `pls.m3u`.
|
||||
|
||||
Плейлист `pls.m3u` обновлён на диске.
|
||||
Но всё ещё **вручную**, просто немного поудобнее.
|
||||
|
||||
Открываешь его в плеере, тоже **вручную** (потому что, скорее всего, он просто у тебя под курсором и проще дважды кликнуть по нему, а без этого плеер не сам может и не перечитать плейлист с диска), и наслаждаешься.
|
||||
|
||||
Теперь представь, что кто-то сделал всё то же самое, но открыл доступ к своему файлу плейлиста по ссылке.
|
||||
Ты добавляешь плейлист в плеер по этой ссылке и сразу наслаждаешься.
|
||||
|
||||
В чём плюсы:
|
||||
|
||||
* ты сам не изменяешь этот *чей-то* файл и не паришься;
|
||||
* возможно, кто-то за ним следит и периодически обновляет самостоятельно (вручную или как-то автоматически — это не твоя проблема);
|
||||
* возможно, твой плеер сам подтянет плейлист после запуска (чаще всего так и происходит) или по твоей команде (если такая кнопка в нём есть) — **это и есть автообновление**.
|
||||
|
||||
В чём минус: этот *кто-то* по своим причинам может удалить твой любимый канал или вообще плейлист, и больше он не подгрузится.
|
||||
|
||||
Чаще всего, это происходит по двум причинам:
|
||||
|
||||
* *указанный в этом плейлисте* канал перестал вещать;
|
||||
* к автору обратились правообладатели *указанного в этом плейлисте* канала и велели убрать нелегальщину.
|
||||
|
||||
Таким образом, при следующем открытии плеера, у тебя будет **автоматически обновлённый** твоим плеером на твоём устройстве плейлист.
|
||||
|
||||
## Как часто обновляется содержимое плейлистов?
|
||||
|
||||
Зависит от источника.
|
||||
Я этим не занимаюсь.
|
||||
|
||||
## Есть приложение?
|
||||
|
||||
Нет, и не планируется.
|
||||
|
||||
Ищи [плеер](../common/players.md) и добавляй плейлист туда по ссылке.
|
||||
|
||||
## На канале отображается заглушка { id="заглушка" }
|
||||
|
||||
### Просят денег и/или подписку { id="заглушка1" }
|
||||
|
||||
??? image "Уважаемый клиент! Для возобновления просмотра Вам необходимо использовать не более 2 устройств"
|
||||

|
||||
> Уважаемый клиент! Для возобновления просмотра Вам необходимо использовать не более 2 устройств.
|
||||
> Обратитесь к поставщику контента для уточнения.
|
||||
|
||||
??? image "Ваша подписка не активна"
|
||||

|
||||
> Ваша подписка не активна
|
||||
> Your subscription is not active
|
||||
|
||||
??? image "Мы обнаружили систематическое нарушение правил использования нашего сервиса"
|
||||

|
||||
> Мы обнаружили систематическое нарушение правил использования нашего сервиса и заблокировали возможность просмотра контента.
|
||||
> Для возобновления просмотра необходимо сменить OTTID в личном кабинете, и обновить плейлисты на ваших устройствах.
|
||||
> Если вы считаете, что произошла какая-то ошибка - пожалуйста, обратитесь в техподдержку.
|
||||
|
||||
??? image "Вы превысили разрешённое количество одновременных поджключений"
|
||||

|
||||
> Вы превысили разрешённое количество одновременных подключений
|
||||
> Для возобновления просмотра ограничьте количество подключённых устройств
|
||||
|
||||
Это либо тестовый/платный плейлист платного провайдера, либо канал от платного провайдера в чьём-то сборном бесплатном плейлисте.
|
||||
|
||||
Такие бесплатно работать не будут, а если и работают, то недолго и не у всех.
|
||||
|
||||
**Забудь про этот плейлист.**
|
||||
|
||||
**Ищи другой.**
|
||||
|
||||
**Без вариантов.**
|
||||
|
||||
**Такова цена халявы.**
|
||||
|
||||
Этот плейлист — главный кандидат на удаление с сайта.
|
||||
|
||||
### Wink { id="wink" }
|
||||
|
||||
??? image "Просмотр ТВ-каналов, фильмов и сериалов доступен только в официальных приложениях Wink и на территории России"
|
||||

|
||||
> Просмотр ТВ-каналов, фильмов и сериалов доступен только в официальных приложениях Wink и на территории России
|
||||
|
||||
??? image "Wink ещё не показывает видео на этой территории"
|
||||

|
||||
> Wink ещё не показывает видео на этой территории
|
||||
|
||||
**Решение 1:** купить подписку Wink и использовать официальные приложения.
|
||||
|
||||
**Решение 2:** найти другой плейлист.
|
||||
|
||||
**Решение 3:** если IP не российский, то сделать его российским (любыми способами).
|
||||
|
||||
**Решение 4:** использовать [плеер](../common/players.md), который позволяет указать **User-Agent**, и вставить туда какой-нибудь из этих:
|
||||
|
||||
```
|
||||
Mozilla/5.0 WINK/1.28.2 (AndroidTV/9) HlsWinkPlayer
|
||||
Mozilla/5.0 WINK/1.30.1 (AndroidTV/9) HlsWinkPlayer
|
||||
Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer
|
||||
Mozilla/5.0 WINK/1.42.1 (AndroidTV/12) HlsWinkPlayer
|
||||
Mozilla/5.0 WINK/1.31.1 (AndroidTV/7.1.1) HlsWinkPlayer
|
||||
Mozilla/5.0 (Linux; arm; Android 9; WinkBox 2)
|
||||
Mozilla/5.0 (Linux; Android 9; SWITRON-i12A Build/PSV1.210329.021; wv)
|
||||
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
|
||||
```
|
||||
|
||||
Можно попробовать прописать без `Mozilla/5.0` в начале, но это не должно быть критично.
|
||||
|
||||
Гарантий никаких, но кому-то помогает.
|
||||
|
||||
## Где спортивные каналы? Почему они не работают?
|
||||
|
||||
Спортивные телеканалы очень пристально следят за тем, куда текут их трансляции.
|
||||
|
||||
Они зарабатывают на спорте и активно защищают свои права на трансляцию каких-то уникальных спортивных состязаний и событий.
|
||||
|
||||
Они активно рубят все левые источники, приходят к авторам плейлистов и любезно просят удалить любые упоминания, ссылки и трансляции их каналов из паблика.
|
||||
|
||||
Винить в этом кого-то и бороться с этим бессмысленно.
|
||||
Это большой бизнес, и он будет вне зависимости от нашего желания.
|
||||
|
||||
Поэтому некоторые авторы сразу предупреждают, что в плейлистах таких каналов нет.
|
||||
Судиться потом, вот это всё... нафиг надо.
|
||||
|
||||
Нет, я не буду добавлять каналы в плейлисты.
|
||||
|
||||
Если будет спортивный рабочий плейлист — добавлю на сайт.
|
||||
|
||||
## Как добавить плейлист в общий список?
|
||||
|
||||
Сделать pull-request в [репозиторий](https://git.axenov.dev/IPTV/playlists).
|
||||
|
||||
Я проверю плейлист и добавлю его, если всё ок.
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
icon: material/home
|
||||
hide: [toc]
|
||||
---
|
||||
|
||||
# :material-home: Об агрегаторе m3u.su
|
||||
|
||||
Этот сервис предназначен для централизованного сбора ссылок на публичные IPTV-плейлисты, которые находятся в открытом доступе.
|
||||
Они отбираются вручную и периодически проверяются автоматически.
|
||||
|
||||
!!! info "Все необходимые адреса"
|
||||
**Веб-сайт:** [m3u.su](https://m3u.su)
|
||||
Документация: [m3u.su/docs](https://m3u.su/docs)
|
||||
Исходный код: [git.axenov.dev/IPTV](https://git.axenov.dev/IPTV)
|
||||
Telegram-канал: [@iptv_aggregator](https://t.me/iptv_aggregator)
|
||||
|
||||
Далеко не все пользователи, желающие использовать цифровое ТВ, могут позволить себе подключение IPTV у своего провайдера или поставщиков контента.
|
||||
|
||||
И проблема не только в деньгах и подписках: граждане, живущие зарубежом, испытывают недостаток информации на родных языках, поскольку местные власти цензурируют и блокируют местные и зарубежные СМИ.
|
||||
Так, например, давно происходит в европейских странах.
|
||||
|
||||
В интернете очень много энтузиастов, которые составляют, поддерживают в рабочем состоянии и публикуют бесплатные плейлисты IPTV.
|
||||
В таких плейлистах есть самый разный набор теле- и радиоканалов.
|
||||
|
||||
Сервис предоставляет возможность:
|
||||
|
||||
* обращаться к этим плейлистам по коротким ссылкам вместо длинных,
|
||||
* увидеть какие из них действительно работают, какие в них каналы и работают ли они;
|
||||
* найти плейлист на любой вкус.
|
||||
|
||||
## Основные принципы проекта
|
||||
|
||||
1. Проект должен быть публичен и бесплатен для всех.
|
||||
2. Проект не должен нарушать права третьих лиц.
|
||||
3. Весь исходный код проекта должен быть открыт и распространяться под MIT-лицензией.
|
||||
|
||||
## Для чего предназначен сервис
|
||||
|
||||
1. Для хранения ссылок на сторонние плейлисты.
|
||||
2. Для периодической проверки доступности плейлистов и их каналов.
|
||||
3. Для кратковременного хранения результатов проверок и их публикации (в человекочитаемом и машиночитаемом виде).
|
||||
4. Для категоризации плейлистов и их каналов с помощью тегов.
|
||||
5. Для предоставления коротких ссылок на плейлисты (для удобства ввода с пульта).
|
||||
6. Для переадресации с короткого адреса плейлиста на исходный.
|
||||
7. Для публикации общей информации о каналах (название, логотип).
|
||||
|
||||
## Для чего НЕ предназначен сервис
|
||||
|
||||
1. Для создания плейлистов, их хранения или модификации
|
||||
2. Для записи, хранения или ретрансляции каналов
|
||||
3. Для бесплатного доступа к платным каналам
|
||||
4. Для сбора платежей за доступ к каким-либо каналам
|
||||
|
||||
Автор проекта не занимается созданием, изменением, размещением и хранением плейлистов.
|
||||
Ни бесплатно, ни за деньги, ни бартером, ни за спасибо.
|
||||
Все плейлисты, которые отображаются на сайте, созданы, размещены и поддерживаются третьими лицами на чужих серверах.
|
||||
|
||||
Автор проекта не взимает плату за размещение ссылок на сторонние плейлисты и ресурсы.
|
||||
За содержимое плейлистов и их качество отвечают авторы плейлистов.
|
||||
|
||||
Автор не зарабатывает на проекте и не собирается.
|
||||
Всё, что отображается на сайте, сделано бесплатно и на энтузиазме.
|
||||
|
||||
Но ты можешь сделать [добровольное пожертвование](../common/support.md), которое поможет мне компенсировать затраты на поддержку и техническое развитие проекта.
|
||||
|
||||
## Условия, гарантии, обязательства и последствия
|
||||
|
||||
См. текст [лицензии MIT](https://opensource.org/license/mit).
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
icon: material/file-eye-outline
|
||||
tags: ["статусы", "плейлисты"]
|
||||
---
|
||||
|
||||
# :material-file-eye-outline: Как отбираются плейлисты
|
||||
|
||||
Есть некоторые важные критерии, по которым плейлисты отбираются в проект:
|
||||
|
||||
- открытый источник и прямая ссылка;
|
||||
- автообновление;
|
||||
- бесплатный доступ, без необходимости регистрации, без пробного периода;
|
||||
- без ограничений, в т. ч. по количеству устройств, плеерам, длительности просмотра;
|
||||
- безусловная доступность с территории РФ.
|
||||
|
||||
В основном, в плейлистах именно трансляции телеканалов, но может быть и медиатека: просто список каких-то (мульт)фильмов и записи телепередач, находящихся на чужих дисках (как если бы вы сами составили плейлист, например, с музыкой).
|
||||
|
||||
!!! danger "Плейлисты, нарушающие законодательство, удаляются с сайта окончательно по факту обращения от правообладателя."
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
icon: material/pulse
|
||||
tags: ["сайт"]
|
||||
---
|
||||
|
||||
# :material-pulse: Статус сервиса
|
||||
|
||||
Так выглядит статусная страница сервиса.
|
||||
Попасть на неё можно по ссылке "[Аптайм](https://status.m3u.su)" в шапке сайта.
|
||||
|
||||

|
||||
|
||||
Здесь отображается состояние компонентов сервиса:
|
||||
|
||||
* веб-интерфейс (то, что открывается в браузере);
|
||||
* чекер (фоновая проверка плейлистов с помощью [iptvc](../iptvc/overview.md));
|
||||
* кэш (база данных с временными данными о результатах проверки плейлистов).
|
||||
|
||||
Шкалы движутся во времени справа налево.
|
||||
Они должны быть зелёными, а статус компонента должен быть «Healthy».
|
||||
Каждое деление на шкале приблизительно равно 10 минутам между проверками.
|
||||
|
||||
Можно нажать на название сервиса и посмотреть детальную информацию:
|
||||
|
||||

|
||||
|
||||
Если на шкале появляется красное деление, значит был кратковременный сбой.
|
||||
|
||||
Но если вместо зелёного преобладают красные цвета, значит на сервере что-то основательно сломалось.
|
||||
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 70 KiB |
@@ -0,0 +1,577 @@
|
||||
---
|
||||
title: config.yml
|
||||
icon: material/file-cog
|
||||
tags: ["iptvc", "конфигурация"]
|
||||
---
|
||||
|
||||
# :material-file-cog: Конфигурация config.yml
|
||||
|
||||
Программа читает настройки из YAML-файла `config.yml` в корне проекта.
|
||||
Путь к файлу можно задать через глобальный флаг `--config`.
|
||||
|
||||
## Приоритет настроек
|
||||
|
||||
От низшего к высшему:
|
||||
|
||||
1. **Значения по умолчанию** — встроены в код;
|
||||
2. **`config.yml`** — YAML-файл;
|
||||
3. **Переменные окружения** — переопределяют `config.yml` (если заданы);
|
||||
4. **CLI-флаги** — переопределяют переменные окружения и `config.yml` (если заданы явно).
|
||||
|
||||
Файл `.env` загружается автоматически, переменные из него применяются как переменные окружения.
|
||||
|
||||
## Структура файла
|
||||
|
||||
```yaml
|
||||
app:
|
||||
timezone: GMT
|
||||
debug: false
|
||||
log_level: info
|
||||
playlists: ./playlists.ini
|
||||
tags: ./channels.json
|
||||
|
||||
server:
|
||||
host: localhost
|
||||
port: 8080
|
||||
|
||||
site:
|
||||
base-url: http://localhost:8080
|
||||
repo-url: https://git.axenov.dev/IPTV
|
||||
page-size: 0
|
||||
favicon:
|
||||
header:
|
||||
title: IPTV Checker
|
||||
navigation:
|
||||
- title: Документация
|
||||
url: /docs
|
||||
icon: document-text-outline
|
||||
footer-links:
|
||||
- title: Исходники
|
||||
url: https://git.axenov.dev/IPTV
|
||||
icon: code-slash-outline
|
||||
|
||||
check:
|
||||
start-on-serve: false
|
||||
playlists:
|
||||
user-agent:
|
||||
- Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer
|
||||
timeout: 10000
|
||||
all-cooldown: 0
|
||||
one-cooldown: 0
|
||||
max-routines: 5
|
||||
per-routine: 1
|
||||
channels:
|
||||
user-agent: Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer
|
||||
timeout: 10000
|
||||
byte-range: 512
|
||||
cooldown: 0
|
||||
max-routines: 50
|
||||
per-routine: 10
|
||||
|
||||
cache:
|
||||
enabled: false
|
||||
host: localhost
|
||||
port: 6379
|
||||
username:
|
||||
password:
|
||||
db: 0
|
||||
ttl: 1800
|
||||
```
|
||||
|
||||
Каждый параметр ниже описан отдельной секцией с указанием значения по умолчанию, переменной окружения и соответствующего CLI-флага.
|
||||
|
||||
---
|
||||
|
||||
## Секция `app` { id=app }
|
||||
|
||||
### `app.timezone` { id=app-timezone }
|
||||
|
||||
<!-- md:default GMT -->
|
||||
<!-- md:env APP_TIMEZONE -->
|
||||
|
||||
Часовой пояс, используемый в логах и при отображении времени проверок.
|
||||
|
||||
---
|
||||
|
||||
### `app.debug` { id=app-debug }
|
||||
|
||||
<!-- md:default false -->
|
||||
<!-- md:env APP_DEBUG -->
|
||||
<!-- md:arg --debug -->
|
||||
|
||||
Режим отладки.
|
||||
Включает расширенное логирование и дополнительные проверки в логике приложения.
|
||||
|
||||
---
|
||||
|
||||
### `app.log_level` { id=app-log-level }
|
||||
|
||||
<!-- md:default info -->
|
||||
<!-- md:env APP_LOG_LEVEL -->
|
||||
<!-- md:arg --log-level -->
|
||||
|
||||
Уровень логирования.
|
||||
Допустимые значения: `debug`, `info`, `warn`, `error`.
|
||||
|
||||
---
|
||||
|
||||
### `app.playlists` { id=app-playlists }
|
||||
|
||||
<!-- md:default ./playlists.ini -->
|
||||
<!-- md:env APP_PLAYLISTS -->
|
||||
<!-- md:arg --ini -->
|
||||
|
||||
Путь к локальному [ini-файлу](../../common/formats/playlists.md) с описанием плейлистов.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
### `app.tags` { id=app-tags }
|
||||
|
||||
<!-- md:default ./channels.json -->
|
||||
<!-- md:env APP_TAGS -->
|
||||
<!-- md:arg --tags -->
|
||||
|
||||
Путь к локальному [json-файлу](../../common/formats/channels.md) с описанием тегов каналов.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
## Секция `server` { id=server }
|
||||
|
||||
### `server.host` { id=server-host }
|
||||
|
||||
<!-- md:default -->
|
||||
<!-- md:env WEB_HOST -->
|
||||
<!-- md:arg --host -->
|
||||
|
||||
Хост для привязки веб-сервера.
|
||||
Пустая строка — слушать на всех интерфейсах.
|
||||
|
||||
!!! info "Аргумент работает только для команды `serve`."
|
||||
|
||||
---
|
||||
|
||||
### `server.port` { id=server-port }
|
||||
|
||||
<!-- md:default 8080 -->
|
||||
<!-- md:env WEB_PORT -->
|
||||
<!-- md:arg -p, --port -->
|
||||
|
||||
Порт веб-сервера.
|
||||
|
||||
!!! info "Аргумент работает только для команды `serve`."
|
||||
|
||||
---
|
||||
|
||||
## Секция `site` { id=site }
|
||||
|
||||
Настройки внешнего вида и ссылок сайта: заголовок, навигация, пагинация, иконка.
|
||||
|
||||
### `site.base-url` { id=site-base-url }
|
||||
|
||||
<!-- md:default http://localhost:8080 -->
|
||||
<!-- md:env APP_URL -->
|
||||
|
||||
Базовый URL сайта.
|
||||
Используется при формировании абсолютных ссылок в шаблонах.
|
||||
|
||||
---
|
||||
|
||||
### `site.repo-url` { id=site-repo-url }
|
||||
|
||||
<!-- md:default https://git.axenov.dev/IPTV -->
|
||||
<!-- md:env REPO_URL -->
|
||||
|
||||
Ссылка на исходный репозиторий (отображается в подвале).
|
||||
|
||||
---
|
||||
|
||||
### `site.page-size` { id=site-page-size }
|
||||
|
||||
<!-- md:default 0 -->
|
||||
<!-- md:env PAGE_SIZE -->
|
||||
|
||||
Размер страницы пагинации.
|
||||
При значении `0` пагинация отключена, на главной странице выводятся все плейлисты.
|
||||
|
||||
---
|
||||
|
||||
### `site.favicon` { id=site-favicon }
|
||||
|
||||
<!-- md:default -->
|
||||
<!-- md:env SITE_FAVICON -->
|
||||
|
||||
Путь к файлу иконки сайта. Пустая строка — используется встроенная.
|
||||
|
||||
---
|
||||
|
||||
### `site.header.title` { id=site-header-title }
|
||||
|
||||
<!-- md:default IPTV Checker -->
|
||||
<!-- md:env APP_TITLE -->
|
||||
|
||||
Заголовок сайта, отображается в `<title>` и в navbar.
|
||||
|
||||
---
|
||||
|
||||
### `site.header.navigation` { id=site-header-navigation }
|
||||
|
||||
Массив элементов [`Link`](#link) в шапке сайта.
|
||||
|
||||
---
|
||||
|
||||
### `site.footer-links` { id=site-footer-links }
|
||||
|
||||
Массив элементов [`Link`](#link) в подвале сайта.
|
||||
|
||||
---
|
||||
|
||||
### Тип `Link` { id=link }
|
||||
|
||||
Элемент навигации или подвала.
|
||||
Если задано `children`, рендерится как выпадающее меню.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
| ---------- | ------ | ----------------------------------------------------------- |
|
||||
| `title` | string | Текст ссылки |
|
||||
| `url` | string | URL ссылки (можно опустить, если есть `children`) |
|
||||
| `icon` | string | Имя иконки |
|
||||
| `children` | Link[] | Дочерние ссылки (выпадающее меню, один уровень вложенности) |
|
||||
|
||||
--8<-- "ionicons-name.md"
|
||||
|
||||
```yaml title="Пример"
|
||||
site:
|
||||
header:
|
||||
navigation:
|
||||
- title: Документация
|
||||
url: /docs
|
||||
icon: document-text-outline
|
||||
- title: Telegram
|
||||
icon: paper-plane-outline
|
||||
children:
|
||||
- title: Канал
|
||||
url: https://t.me/iptv_aggregator
|
||||
icon: megaphone-outline
|
||||
- title: Чат
|
||||
url: https://t.me/iptv_aggregator_chat
|
||||
icon: chatbubbles-outline
|
||||
footer-links:
|
||||
- title: Исходники
|
||||
url: https://git.axenov.dev/IPTV
|
||||
icon: code-slash-outline
|
||||
- title: axenov.dev
|
||||
url: https://axenov.dev
|
||||
icon: person-outline
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Секция `check` { id=check }
|
||||
|
||||
Параметры проверки плейлистов и каналов. Поддерживаются скаляры и массивы.
|
||||
|
||||
---
|
||||
|
||||
### `check.start-on-serve` { id=check-start-on-serve }
|
||||
|
||||
<!-- md:default false -->
|
||||
<!-- md:env CHECK_START_ON_SERVE -->
|
||||
|
||||
Запустить фоновую проверку при `serve` без явного флага `--check`.
|
||||
|
||||
Независимый переключатель от CLI-флага `--check` — фоновая проверка стартует, если **хотя бы один** из них активен.
|
||||
|
||||
---
|
||||
|
||||
### `check.playlists` { id=check-playlists }
|
||||
|
||||
Параметры проверки плейлистов (загрузка m3u-файлов по URL или из ФС).
|
||||
|
||||
---
|
||||
|
||||
#### `check.playlists.user-agent` { id=check-playlists-user-agent }
|
||||
|
||||
<!-- md:default Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer -->
|
||||
|
||||
<!-- md:env CHECK_PLAYLISTS_USER_AGENT_* -->
|
||||
<!-- md:arg --playlists-user-agent -->
|
||||
|
||||
User-Agent для HTTP-запросов плейлистов.
|
||||
|
||||
!!! info "Необычный параметр"
|
||||
Если значение параметра задано строкой, то в запросах к плейлистам будет использоваться только оно.
|
||||
|
||||
Если значение параметра задано массивом строк, то в запросах к плейлистам будет использоваться случайный из указанных.
|
||||
|
||||
!!! info "Необычная переменная"
|
||||
В окружении может задаваться индексированными переменными:
|
||||
|
||||
- `CHECK_PLAYLISTS_USER_AGENT_1="value1"`
|
||||
- `CHECK_PLAYLISTS_USER_AGENT_2="value2"`
|
||||
- и т.д.; чтение останавливается на первой отсутствующей.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.playlists.timeout` { id=check-playlists-timeout }
|
||||
|
||||
<!-- md:default 10000 -->
|
||||
<!-- md:env CHECK_PLAYLISTS_TIMEOUT -->
|
||||
<!-- md:arg --playlists-timeout -->
|
||||
|
||||
Таймаут HTTP-запроса плейлиста в миллисекундах.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.playlists.all-cooldown` { id=check-playlists-all-cooldown }
|
||||
|
||||
<!-- md:default 0 -->
|
||||
<!-- md:env CHECK_PLAYLISTS_ALL_COOLDOWN -->
|
||||
<!-- md:arg --playlists-all-cooldown -->
|
||||
|
||||
Задержка после проверки всех плейлистов в миллисекундах.
|
||||
|
||||
!!! info "Необычная переменная"
|
||||
Если значение переменной указано одним числом, то для задержки будет использоваться только оно.
|
||||
|
||||
Если значение переменной указано двумя числами через запятую, то будет использоваться случайная задержка в указанном диапазоне.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.playlists.one-cooldown` { id=check-playlists-one-cooldown }
|
||||
|
||||
<!-- md:default 0 -->
|
||||
<!-- md:env CHECK_PLAYLISTS_ONE_COOLDOWN -->
|
||||
<!-- md:arg --playlists-one-cooldown -->
|
||||
|
||||
Задержка после проверки каждого плейлиста в миллисекундах.
|
||||
|
||||
!!! info "Необычная переменная"
|
||||
Если значение переменной указано одним числом, то для задержки будет использоваться только оно.
|
||||
|
||||
Если значение переменной указано двумя числами через запятую, то будет использоваться случайная задержка в указанном диапазоне.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.playlists.max-routines` { id=check-playlists-max-routines }
|
||||
|
||||
<!-- md:default 5 -->
|
||||
<!-- md:env CHECK_PLAYLISTS_MAX_ROUTINES -->
|
||||
<!-- md:arg --playlists-max-routines -->
|
||||
|
||||
Максимальное количество параллельных потоков (рутин) проверки плейлистов.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.playlists.per-routine` { id=check-playlists-per-routine }
|
||||
|
||||
<!-- md:default 1 -->
|
||||
<!-- md:env CHECK_PLAYLISTS_PER_ROUTINE -->
|
||||
<!-- md:arg --playlists-per-routine -->
|
||||
|
||||
Максимальное количество плейлистов в каждом потоке (рутине) проверки.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
### `check.channels` { id=check-channels }
|
||||
|
||||
Параметры проверки каналов внутри плейлиста.
|
||||
|
||||
---
|
||||
|
||||
#### `check.channels.user-agent` { id=check-channels-user-agent }
|
||||
|
||||
<!-- md:default Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer -->
|
||||
|
||||
<!-- md:env CHECK_CHANNELS_USER_AGENT_* -->
|
||||
<!-- md:arg --channels-user-agent -->
|
||||
|
||||
User-Agent для HTTP-запроса каждого канала каждого плейлиста.
|
||||
|
||||
!!! info "Необычный параметр"
|
||||
Если значение параметра задано строкой, то в запросах к каналам будет использоваться только оно.
|
||||
|
||||
Если значение параметра задано массивом строк, то в запросах к каналам будет использоваться случайный из указанных.
|
||||
|
||||
!!! info "Необычная переменная"
|
||||
В окружении может задаваться индексированными переменными:
|
||||
|
||||
- `CHECK_CHANNELS_USER_AGENT_1="value1"`
|
||||
- `CHECK_CHANNELS_USER_AGENT_2="value2"`
|
||||
- и т.д.; чтение останавливается на первой отсутствующей.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.channels.timeout` { id=check-channels-timeout }
|
||||
|
||||
<!-- md:default 10000 -->
|
||||
<!-- md:env CHECK_PLAYLISTS_TIMEOUT -->
|
||||
<!-- md:arg --channels-timeout -->
|
||||
|
||||
Таймаут HTTP-запроса каждого канала каждого плейлиста в миллисекундах.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.channels.byte-range` { id=check-channels-byte-range }
|
||||
|
||||
<!-- md:default 512 -->
|
||||
<!-- md:env CHECK_CHANNELS_BYTE_RANGE -->
|
||||
<!-- md:arg --channels-byte-range -->
|
||||
|
||||
Объём данных в байтах, запрашиваемых у сервера при проверке каждого канала каждого плейлиста.
|
||||
|
||||
Меньшее значение повышает риск ошибок в определении типа контента (mime-type).
|
||||
|
||||
Большее значение может приводить к повышенной нагрузке и увеличению времени проверки.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.channels.cooldown` { id=check-channels-cooldown }
|
||||
|
||||
<!-- md:default 0 -->
|
||||
<!-- md:env CHECK_CHANNELS_COOLDOWN -->
|
||||
<!-- md:arg --channels-cooldown -->
|
||||
|
||||
Задержка после проверки каждого канала каждого плейлиста в миллисекундах.
|
||||
|
||||
!!! info "Необычная переменная"
|
||||
Если значение переменной указано одним числом, то для задержки будет использоваться только оно.
|
||||
|
||||
Если значение переменной указано двумя числами через запятую, то будет использоваться случайная задержка в указанном диапазоне.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.channels.max-routines` { id=check-channels-max-routines }
|
||||
|
||||
<!-- md:default 50 -->
|
||||
<!-- md:env CHECK_CHANNELS_MAX_ROUTINES -->
|
||||
<!-- md:arg --channels-max-routines -->
|
||||
|
||||
Максимальное количество параллельных потоков (рутин) проверки каналов каждого плейлиста.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
#### `check.channels.per-routine` { id=check-channels-per-routine }
|
||||
|
||||
<!-- md:default 10 -->
|
||||
<!-- md:env CHECK_CHANNELS_PER_ROUTINE -->
|
||||
<!-- md:arg --channels-per-routine -->
|
||||
|
||||
Максимальное количество каналов в каждом потоке (рутине) проверки каждого плейлиста.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
## Секция `cache` { id=cache }
|
||||
|
||||
Параметры подключения к KeyDB/Redis для хранения результатов проверок.
|
||||
|
||||
---
|
||||
|
||||
### `cache.enabled` { id=cache-enabled }
|
||||
|
||||
<!-- md:default false -->
|
||||
<!-- md:env CACHE_ENABLED -->
|
||||
<!-- md:arg --cache-enabled -->
|
||||
|
||||
Включить использование внешнего кеша.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
### `cache.host` { id=cache-host }
|
||||
|
||||
<!-- md:default localhost -->
|
||||
<!-- md:env CACHE_HOST -->
|
||||
<!-- md:arg --cache-host -->
|
||||
|
||||
Хост KeyDB/Redis.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
### `cache.port` { id=cache-port }
|
||||
|
||||
<!-- md:default 6379 -->
|
||||
<!-- md:env CACHE_PORT -->
|
||||
<!-- md:arg --cache-port -->
|
||||
|
||||
Порт KeyDB/Redis.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
### `cache.username` { id=cache-username }
|
||||
|
||||
<!-- md:default -->
|
||||
<!-- md:env CACHE_USERNAME -->
|
||||
<!-- md:arg --cache-username -->
|
||||
|
||||
Логин для подключения. Пустая строка — без аутентификации.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
### `cache.password` { id=cache-password }
|
||||
|
||||
<!-- md:default -->
|
||||
<!-- md:env CACHE_PASSWORD -->
|
||||
<!-- md:arg --cache-password -->
|
||||
|
||||
Пароль для подключения.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
### `cache.db` { id=cache-db }
|
||||
|
||||
<!-- md:default 0 -->
|
||||
<!-- md:env CACHE_DB -->
|
||||
<!-- md:arg --cache-db -->
|
||||
|
||||
Номер логической базы данных в KeyDB/Redis.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
|
||||
---
|
||||
|
||||
### `cache.ttl` { id=cache-ttl }
|
||||
|
||||
<!-- md:default 1800 -->
|
||||
<!-- md:env CACHE_TTL -->
|
||||
<!-- md:arg --cache-ttl -->
|
||||
|
||||
TTL записей кеша, секунды.
|
||||
|
||||
!!! info "Аргумент работает только для команд `check` и `serve --check`."
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
icon: material/book-open-page-variant-outline
|
||||
---
|
||||
|
||||
# :material-book-open-page-variant-outline: Об этой документации
|
||||
|
||||
!!! warning "Актуальность документации может отставать от текущей версии сервиса, его исходных кодов и инфраструктуры"
|
||||
Поддерживать содержимое в актуальном состоянии большой труд.
|
||||
Прошу отнестись с пониманием, а лучше — [помочь делом](support.md#participate).
|
||||
|
||||
<!--
|
||||
!!! danger "Тем не менее, прошу прочесть её!"
|
||||
Потому что очень часто и мне, и в общий чат поступают одинаковые вопросы, на которые уже просто нет сил отвечать персонально.
|
||||
-->
|
||||
|
||||
Если у тебя возникает вопрос, на который уже есть ответ на одной из этих страниц, то ты рискуешь
|
||||
|
||||
* либо быть посланным сюда;
|
||||
* либо быть посланным далеко не сюда;
|
||||
* либо остаться в игноре.
|
||||
|
||||
## Навигация
|
||||
|
||||
К твоим услугам:
|
||||
|
||||
1. в заголовке сайта — глобальный поиск;
|
||||
2. над заголовком страницы — метки страницы (полный список ниже);
|
||||
3. слева — общее содержание;
|
||||
4. справа — содержание конкретной страницы.
|
||||
|
||||
??? info end "На мобильниках содержание страницы спрятано за этой кнопкой в боковом меню:"
|
||||

|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: channels.json
|
||||
icon: material/code-json
|
||||
tags: ["iptvc", "теги", "каналы"]
|
||||
---
|
||||
|
||||
# :material-code-json: Формат файла `channels.json`
|
||||
|
||||
Категории каналов указываются в файле `channels.json` в следующем формате:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"tvg-id": "регулярное выражение для значения атрибута tvg-id",
|
||||
"tvg-name": "регулярное выражение для значения атрибута tvg-name",
|
||||
"title": "регулярное выражение для названия канала",
|
||||
"tags": [
|
||||
"список",
|
||||
"тегов",
|
||||
"(см. ниже)"
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Приоритет параметров:
|
||||
|
||||
* `tvg-id`
|
||||
* `tvg-name`
|
||||
* `title`
|
||||
|
||||
Если указаны все или несколько, то применится только тот один, который по приоритету выше.
|
||||
|
||||
Параметр `tags` обязателен, список может быть (не)пустым.
|
||||
Категории в списке указываются в двойных кавычках.
|
||||
После каждой категории, кроме последней, ставится запятая.
|
||||
|
||||
Регулярные выражения должны быть PCRE-совместимыми.
|
||||
|
||||
Каналы сопоставляются в нижнем регистре.
|
||||
|
||||
## Рекомендации и предостережения { id="warnings" }
|
||||
|
||||
1. Если хочешь написать новое правило, будь осторожен с регулярками.
|
||||
Старайся не охватывать несколько каналов сразу.
|
||||
Если канал попадёт в несколько регулярок, то его **теги могут оказаться неожиданными** и найти проблему может быть сложно.
|
||||
2. Указывай внутри `{}` только `tags` и один из параметров `tvg-id`, `tvg-name` или `title`.
|
||||
Множество параметров на точность не влияет, зато будет проще уместить всё правило в одну строку и grep-ать файл.
|
||||
3. Не забывай, что название на кириллице не всегда означает, что это российский канал или вещание на русском языке.
|
||||
4. Разные каналы могут быть названы одинаково или похоже.
|
||||
Например, `Первый канал`, `Первый Тульский`, `Первый городской`.
|
||||
5. Один канал может быть назван по-разному.
|
||||
Например, `Ю` или `Ю!`, `Россия 1 +5` или `Россия-1`.
|
||||
6. Важно учитывать холдинги.
|
||||
Например, российские Матч, ТНТ и НТВ имеют множество разных каналов, и тупо искать `^нтв$` — тупо.
|
||||
7. У всех каналов есть `title`.
|
||||
Не все каналы имеют `tvg-id`.
|
||||
Некоторые каналы имеют `tvg-name`.
|
||||
Все три параметра могут оказаться на кириллице.
|
||||
|
||||
## Доступные теги { id="доступные-теги" }
|
||||
|
||||
| Ключевое слово | Описание |
|
||||
| -------------- | ----------------------------------------------------------- |
|
||||
| `untagged` | Неизвестно (ставится по умолчанию, если нет иных) |
|
||||
| `unstable` | Нестабильные каналы |
|
||||
| `hd` | Каналы в высоком качестве |
|
||||
| `4k` | Каналы в супервысоком качестве |
|
||||
| `8k` | Каналы в гигавысоком качестве (а вдруг?) |
|
||||
| `adult` | Контент для взрослых 18+ |
|
||||
| `army` | Каналы военные, об оружии, технике, армии, боевых действиях |
|
||||
| `central` | Центральное ТВ (гос. каналы, федеральные) |
|
||||
| `child` | Детские и подростковые каналы |
|
||||
| `culture` | Каналы о культуре, театре |
|
||||
| `crime` | Каналы с детективами и о преступлениях (true-crime) |
|
||||
| `cyber` | Киберспортивные |
|
||||
| `docs` | Каналы с документальными фильмами |
|
||||
| `fashion` | Мода и стиль |
|
||||
| `film` | Каналы с фильмами |
|
||||
| `finance` | Бизнес, финансы, капитал |
|
||||
| `food` | Кулинарные каналы |
|
||||
| `fun` | Развлекательные каналы и шоу |
|
||||
| `garden` | Сад, огород, фермерство, домашнее хозяйство |
|
||||
| `health` | Каналы о здоровье |
|
||||
| `history` | Исторические каналы |
|
||||
| `house` | О строительстве, ремонте, интерьере и жилье |
|
||||
| `humor` | Юмористические каналы, комедии |
|
||||
| `hunt-fish` | Охота и рыбалка |
|
||||
| `local` | Местные региональные каналы |
|
||||
| `music` | Музыкальные |
|
||||
| `mystic` | Каналы о мистике, потустороннем, НЛО и прочей пиздаболии |
|
||||
| `nature` | Каналы о природе, животных |
|
||||
| `news` | Новостные каналы |
|
||||
| `politic` | Каналы политические, партийные, правительстенные |
|
||||
| `radio` | Радиоканалы (радиостанции, подкасты, аудиоспектакли...) |
|
||||
| `religion` | Религиозные каналы |
|
||||
| `retro` | Ностальгия и ретро, музыка, старые передачи |
|
||||
| `sci` | Научные и познавательные |
|
||||
| `series` | Каналы с сериалами |
|
||||
| `shopping` | Телемагазины |
|
||||
| `sport` | Спортивные |
|
||||
| `tech` | Каналы о технологиях |
|
||||
| `transport` | Каналы о транспорте (авто, мото, ЖД...) |
|
||||
| `travel` | Каналы о путешествиях |
|
||||
| `webcam` | Уличные веб-камеры |
|
||||
|
||||
Также в категориях можно указывать страну вещания.
|
||||
Это должен быть буквенный код АЛЬФА-2 из общероссийского классификатора стран мира (ОКСМ):
|
||||
|
||||
* [normativ.kontur.ru](https://normativ.kontur.ru/document?moduleId=1&documentId=22668#h1296)
|
||||
* [classifikators.ru](https://classifikators.ru/oksm)
|
||||
@@ -0,0 +1,135 @@
|
||||
---
|
||||
title: "*.m3u (*.m3u8)"
|
||||
icon: material/playlist-play
|
||||
tags: ["плейлисты", "каналы"]
|
||||
---
|
||||
|
||||
# :material-playlist-play: Формат файлов `*.m3u` (`*.m3u8`)
|
||||
|
||||
Формат применяется для составления мультимедиа плейлистов, как оффлайн, так и онлайн.
|
||||
|
||||
Разница между m3u и m3u8 уже давно отсутствует, но исторически так сложилось, то m3u8 должен был быть только в формате UTF-8.
|
||||
|
||||
Директивы начинаются с новой строки и символа `#`.
|
||||
У каждой директивы могут (не) быть атрибуты, которые следуют в одну строку.
|
||||
|
||||
После директив с новой строки указывается ссылка на канал (или путь к файлу).
|
||||
|
||||
В свою чередь, по этой ссылке может быть:
|
||||
|
||||
* либо текстовое представление контента в формате m3u/m3u8/XMLTV/MPD с описанием непосредственно участки трансляции;
|
||||
* либо непосредственно сама потоковая трансляция mp4 или т. п.
|
||||
|
||||
Рассмотрим на выдуманном примере плейлиста IPTV:
|
||||
|
||||
```m3u
|
||||
#EXTM3U url-tvg="https://iptvx.one/EPG" catchup="append" catchup-days="3" catchup-source="?offset=-${offset}&utcstart=${timestamp}"
|
||||
|
||||
#EXTINF:-1 tvg-id="ntv" tvg-logo="http://epg.it999.ru/img2/2001.png",НТВ HD
|
||||
#EXTGRP:🇷🇺 Эфирные
|
||||
http://example.com/play-ntv.m3u
|
||||
|
||||
#EXTINF:-1 tvg-logo="http://tvoetv.space/tvoetv.png" tvg-id="tvoetv",Твоё ТВ HD v8 с VPN
|
||||
http://example.com/play-tvoetv.m3u
|
||||
|
||||
#EXTINF:0 tvg-name="BBC" audio-track="eng" tvg-logo="http://mylogos.domain/BBC.png", BBC World
|
||||
http://example.com/play-bbc.m3u
|
||||
|
||||
#EXTINF:-1 tvg-id="5TV.am" tvg-country="AM" tvg-language="Armenian" tvg-logo="https://i.imgur.com/yigw9dr.png" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" group-title="General",5-րդ ալիք (480p)
|
||||
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
|
||||
#EXTVLCOPT:http-caching=1200
|
||||
http://example.com/play-am.m3u8
|
||||
```
|
||||
|
||||
### Директива `#EXTM3U` { id="EXTM3U" }
|
||||
|
||||
Заголовок файла (обязателен).
|
||||
|
||||
#### Атрибут `url-tvg` (он же `x-tvg-url`) { id="url-tvg" }
|
||||
|
||||
Ссылка программу передач в формате `*.xml` или `*.xml.gz`.
|
||||
|
||||
#### Атрибуты `catchup*` { id="catchup" }
|
||||
|
||||
Читай здесь: [Архив телепрограмм (SS IPTV)](https://ss-iptv.com/ru/operators/catchup)
|
||||
|
||||
### Директива `#EXTGRP` { id="EXTGRP" }
|
||||
|
||||
Название группы, к которой относится контент (звуковая дорожка или канал).
|
||||
|
||||
Указывается в формате `#EXTGRP:XXX`, где: `XXX` — название группы.
|
||||
|
||||
### Директива `#EXTINF` { id="EXTINF" }
|
||||
|
||||
Описывает контент (звуковую дорожку или канал).
|
||||
|
||||
Указывается в формате `#EXTINF:XXX YYY,ZZZ`, где:
|
||||
* `XXX` — длительность в секундах (обязательно, но может быть `-1` или `0`);
|
||||
* `YYY` — атрибуты (см. ниже);
|
||||
* `ZZZ` — название контента;
|
||||
|
||||
#### Атрибут `tvg-shift` { id="tvg-shift" }
|
||||
|
||||
Cмещение телепрограммы в часах относительно указанного в программе.
|
||||
|
||||
#### Атрибуты `tvg-id` и `tvg-name` { id="tvg-id" }
|
||||
<a id="tvg-name"></a>
|
||||
|
||||
Идентификатор телепрограммы канала.
|
||||
По нему телепрограмма привязывается к трансляции с учётом смещения времени.
|
||||
|
||||
#### Атрибут `tvg-logo` { id="tvg-logo" }
|
||||
|
||||
Ссылка на логотип канала.
|
||||
|
||||
#### Атрибут `tvg-country` { id="tvg-country" }
|
||||
|
||||
Код Alpha-2 страны вещания согласно ISO 3166-1 или ОКСМ.
|
||||
|
||||
#### Атрибут `tvg-language` { id="tvg-language" }
|
||||
|
||||
Название языка телепередачи согласно ISO 639-2.
|
||||
|
||||
#### Атрибут `group-title` { id="group-title" }
|
||||
|
||||
Название группы.
|
||||
По функционалу идентичен директиве `#EXTGRP`.
|
||||
|
||||
#### Атрибут `user-agent` { id="user-agent" }
|
||||
|
||||
Значение заголовка `User-Agent` для обращения к контенту по http.
|
||||
|
||||
#### Атрибут `audio-track` { id="audio-track" }
|
||||
|
||||
Языковой код (ISO 639-2) аудио дорожки канала, например: "eng,rus".
|
||||
|
||||
Допускается указание нескольких аудио дорожек через запятую: "rus,ukr,eng".
|
||||
|
||||
Дорожкой по умолчанию устанавливается первая указанная в списке.
|
||||
|
||||
#### Атрибут `aspect-ratio` { id="aspect-ratio" }
|
||||
|
||||
Определяет пропорции экрана (может быть недоступно для некоторых моделей телевизоров).
|
||||
|
||||
Допустимые значения: 16:9, 3:2, 4:3, 1,85:1, 2,39:1 (наиболее распространенное значение для фильмов)
|
||||
|
||||
### Директива `#EXTVLCOPT` { id="EXTVLCOPT" }
|
||||
|
||||
Специфична для VLC Player.
|
||||
Директив может быть множество для одной дорожки (канала).
|
||||
|
||||
Указывается в формате `#EXTVLCOPT:XXX` или `#EXTVLCOPT--XXX=YYY`, где:
|
||||
* `XXX` — параметр командной строки VLC Player ([полный список](https://wiki.videolan.org/VLC_command-line_help/));
|
||||
* `YYY` — значения параметра.
|
||||
|
||||
## Дополнительные материалы
|
||||
|
||||
* [Инструкция по формату M3U (SS IPTV)](https://ss-iptv.com/ru/users/documents/m3u)
|
||||
* [Архив телепрограмм (SS IPTV)](https://ss-iptv.com/ru/operators/catchup)
|
||||
* [VLC command-line help](https://wiki.videolan.org/VLC_command-line_help/)
|
||||
* [ISO 639-2 Codes for the Representation of Names of Languages](https://www.loc.gov/standards/iso639-2/php/code_list.php)
|
||||
* [ISO 3166-1 Wikipedia](https://en.wikipedia.org/wiki/ISO_3166-1)
|
||||
* ОКСМ:
|
||||
* [normativ.kontur.ru](https://normativ.kontur.ru/document?moduleId=1&documentId=22668#h1296)
|
||||
* [classifikators.ru](https://classifikators.ru/oksm)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
icon: material/file-code-outline
|
||||
hide: [toc]
|
||||
---
|
||||
|
||||
# :material-file-code-outline: Форматы файлов
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
- [:material-code-brackets: Формат файла `playlists.ini`](playlists.md)
|
||||
|
||||
---
|
||||
Список плейлистов, которые отображаются на сайте и периодически проверяются
|
||||
|
||||
- [:material-code-json: Формат файла `channels.json`](channels.md)
|
||||
|
||||
---
|
||||
Список правил для применения тегов к разным каналам
|
||||
|
||||
- [:material-playlist-play: Формат файлов `*.m3u` (`*.m3u8`)](m3u.md)
|
||||
|
||||
---
|
||||
Плейлист — это вообще что?
|
||||
</div>
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: playlists.ini
|
||||
icon: material/code-brackets
|
||||
tags: ["плейлисты"]
|
||||
---
|
||||
|
||||
# :material-code-brackets: Формат файла `playlists.ini`
|
||||
|
||||
Рассмотрим на примере:
|
||||
|
||||
```ini
|
||||
[code]
|
||||
name = Рабочий автообновляемый IPTV плейлист M3U
|
||||
desc = "В этом IPTV плейлисте есть каналы в высоком качестве"
|
||||
pls = 'https://example.com/pls.m3u'
|
||||
src = 'https://example.com/super-duper-playlist'
|
||||
# комментарий 1
|
||||
; ещё один комментарий
|
||||
```
|
||||
|
||||
Перенос строк невозможен.
|
||||
Комментарии игнорируются.
|
||||
|
||||
Для значений можно (не) использовать 'одинарные' или "двойные" кавычки.
|
||||
Ради единообразия рекомендуется использовать 'одинарные'.
|
||||
|
||||
## `code` { id="code" }
|
||||
|
||||
Код плейлиста в рамках этого конфига (**обязательно**).
|
||||
|
||||
Должен быть коротким и уникальным.
|
||||
|
||||
Подставляется в короткую ссылку, по которой произойдёт переадресация на прямой адрес `pls`.
|
||||
|
||||
!!! note
|
||||
Для удобства ввода с пульта, код рекомендуется задавать числом или короткой строкой без пробелов и др. спецсимволов.
|
||||
Чем короче, тем лучше.
|
||||
|
||||
## `name` { id="name" }
|
||||
|
||||
Название плейлиста (необязательно).
|
||||
|
||||
По умолчанию: `Playlist #<code>`.
|
||||
|
||||
## `desc` { id="desc" }
|
||||
|
||||
Краткое описание из источника или от себя (необязательно).
|
||||
|
||||
По умолчанию: пусто.
|
||||
|
||||
## `pls` { id="pls" }
|
||||
|
||||
Прямая ссылка на m3u/m3u8 плейлист (**обязательно**).
|
||||
|
||||
## `src` { id="src" }
|
||||
|
||||
Ссылка на источник (страницу сайта), откуда был взят плейлист (необязательно).
|
||||
|
||||
По умолчанию: пусто.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
icon: material/file-document
|
||||
hide: [toc]
|
||||
---
|
||||
|
||||
# Общая информация
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
- [:material-cogs: Как работает сервис](../aggregator/overview.md)
|
||||
- [:material-file-eye-outline: Как отбираются плейлисты](../aggregator/selection.md)
|
||||
- [:material-file-refresh-outline: Проверки и статусы](../aggregator/checks.md)
|
||||
- [:fontawesome-solid-list-check: Список плейлистов](../iptvc/site/list.md)
|
||||
- [:material-table-eye: Страница плейлиста](../iptvc/site/details.md)
|
||||
- [:material-television-play: Как подключить плейлист](../iptvc/site/connect.md)
|
||||
- [:material-multimedia: IPTV плееры](players.md)
|
||||
</div>
|
||||
@@ -0,0 +1,294 @@
|
||||
---
|
||||
icon: material/multimedia
|
||||
tags: ["плееры"]
|
||||
---
|
||||
|
||||
# :material-multimedia: IPTV плееры
|
||||
|
||||
Здесь указаны **не все** плееры, существующие на этой планете, и такой цели нет.
|
||||
|
||||
В списке ниже только те плееры, которые широко известны и популярны у зрителей IPTV, а также рекомендуются специализированными сайтами.
|
||||
|
||||
Некоторые из них помечены значком :thumbsup: — значит, он уже зарекомендовал себя как стабильный и удобный, с ним меньше всего хлопот.
|
||||
|
||||
Список для удобства разбит по платформам и ОС.
|
||||
Обращайся к содержанию справа для быстрой навигации.
|
||||
|
||||
!!! info "Здесь не хватает очень много подробностей"
|
||||
Если ты имел дело с каким-то плеером, знаешь как его настроить или какие-то другие детали, я прошу тебя помочь [актуализировать эту страницу](support.md#participate), чтобы через это помочь другим пользователям с выбором и настройкой плеера под свои цели.
|
||||
|
||||
## Кроссплатформенные
|
||||
|
||||
!!! info
|
||||
Эти плееры разрабатываются для множества платформ одновременно и/или существуют в виде веб-приложения.
|
||||
Их можно устанавливать и открывать почти на любом подходящем устройстве.
|
||||
|
||||
!!! warning "Веб-приложения могут не работать со сторонними плейлистами из-за ошибок CORS"
|
||||
Исправить эту ошибку может выдача разрешения на загрузку небезопасного контента в настройках сайта в браузере, но гарантий нет.
|
||||
|
||||
### :thumbsup: VLC Media Player
|
||||
|
||||
* Скачать: <https://www.videolan.org/vlc/>
|
||||
|
||||
Универсальный плеер практически для любого мультимедиа-контента.
|
||||
|
||||
??? image "Главное окно"
|
||||

|
||||
|
||||
??? image "Добавление плейлиста на десктопе"
|
||||
!!! warning "Указание протокола `https://` обязательно!"
|
||||

|
||||

|
||||
|
||||
??? image "Добавление плейлиста на андроиде"
|
||||
!!! warning "Указание протокола `https://` обязательно!"
|
||||

|
||||

|
||||
|
||||
### :thumbsup: IPTVnator
|
||||
|
||||
* Веб-версия: <https://iptvnator.vercel.app>
|
||||
* Скачать: <https://github.com/4gray/iptvnator/releases/latest>
|
||||
|
||||
Простой рабочий плеер, который можно открыть в браузере.
|
||||
|
||||
Поддерживает подгрузку множества плейлистов по ссылкам, субтитры, группировку каналов, избранное.
|
||||
Имеет тёмную и светлую темы.
|
||||
|
||||
Если использовать веб-версию, то настройки сохраняются в браузере.
|
||||
|
||||
??? image "Главное окно"
|
||||

|
||||
|
||||
??? image "Добавление плейлиста"
|
||||
!!! warning "Указание протокола `https://` обязательно!"
|
||||

|
||||

|
||||
|
||||
### IPTV Web Player
|
||||
|
||||
* Веб-версия: <http://iptv.apiweb.uz>
|
||||
|
||||
Простой и удобный веб-плеер.
|
||||
Загрузка плейлиста по ссылкам или из файла, но только одного.
|
||||
|
||||
Подгрузка и отображение телепрограммы (используется https://cdn.epg.one/epg2.xml).
|
||||
|
||||
??? image "Главное окно"
|
||||

|
||||
|
||||
??? image "Добавление плейлиста"
|
||||
!!! success "Указание протокола `https://` необязательно!"
|
||||

|
||||
|
||||
### Kodi
|
||||
|
||||
* Скачать: <https://kodi.tv>
|
||||
* [Простая настройка IPTV на Kodi за 5 минут](https://prodigtv.ru/iptv/software/nastrojka-na-kodi)
|
||||
|
||||
Полноценный медиацентр.
|
||||
Ориентирован на большие экраны и ТВ с пультами.
|
||||
Имеет богатый функционал, который наращивается дополнениями, не выходя из приложения.
|
||||
|
||||
### KMPlayer
|
||||
|
||||
* Скачать: <https://www.kmplayer.com/home>
|
||||
|
||||
### OttPlayer
|
||||
|
||||
* Веб-версия: <http://widget.ottplayer.tv>
|
||||
* Скачать: <https://ottplayer.tv/soft>
|
||||
|
||||
!!! warning "Требует учётную запись сервиса ottplayer.tv"
|
||||
|
||||
### Ott-Play
|
||||
|
||||
* Веб-версия: <https://ottp.eu.org/f/pc/>
|
||||
* Скачать: <https://ottp.eu.org/www/install/>
|
||||
|
||||
!!! warning "Ошибка CORS"
|
||||
Она может не уйти даже если менять [плеер в настройках](https://ottp.eu.org/www/faq/#q4003).
|
||||
|
||||
---
|
||||
|
||||
!!! info "Ниже перечислено ПО, специфичное только для конкретных платформ"
|
||||
|
||||
## Десктопные
|
||||
|
||||
### Windows
|
||||
|
||||
#### :thumbsup: IP-TV Player
|
||||
|
||||
* Скачать: <https://borpas.info/iptvplayer>
|
||||
|
||||
---
|
||||
|
||||
### Linux
|
||||
|
||||
#### :thumbsup: yuki-iptv
|
||||
|
||||
* Скачать: <https://codeberg.org/liya/yuki-iptv/releases/latest>
|
||||
|
||||
Продолжение развития Astroncia IPTV.
|
||||
|
||||
Визуально очень похож на IP-TV Player для Windows.
|
||||
|
||||
Поддерживает плейлисты по ссылкам, сторонние телепрограммы, группировку каналов, изменение плейлистов и многое другое.
|
||||
|
||||
??? image "Главное окно"
|
||||

|
||||
|
||||
??? image "Добавление плейлиста"
|
||||
!!! warning "Указание протокола `https://` обязательно!"
|
||||

|
||||
|
||||
---
|
||||
|
||||
## SmartTV
|
||||
|
||||
### :thumbsup: SS IPTV
|
||||
|
||||
* Сайт: <https://ss-iptv.com/ru/>
|
||||
* Веб-версия: <https://app.ss-iptv.com> (скорее всего, не заработает)
|
||||
* Редактор плейлистов: <https://ss-iptv.com/ru/users/playlist>
|
||||
* Установить: <https://ss-iptv.com/ru/users/documents/installing>
|
||||
|
||||
Плеер, который предустанавливается в ПО некоторых телевизоров и некоторых приставок.
|
||||
|
||||
### Forkplayer
|
||||
|
||||
---
|
||||
|
||||
## Мобильные
|
||||
|
||||
### Кроссплатформенные
|
||||
|
||||
#### GSE SMART IPTV
|
||||
|
||||
---
|
||||
|
||||
### Android
|
||||
|
||||
#### :thumbsup: Televizo
|
||||
|
||||
* Скачать: [play.google.com](https://play.google.com/store/apps/details?id=com.ottplay.ottplay)
|
||||
|
||||
??? image "Главный экран"
|
||||

|
||||

|
||||
|
||||
??? image "Добавление плейлиста"
|
||||
!!! warning "Указание протокола `https://` обязательно!"
|
||||

|
||||

|
||||
|
||||
Из настроек:
|
||||
|
||||

|
||||

|
||||
|
||||
И дальше те же шаги 3-5 на скриншотах выше.
|
||||
|
||||
??? quote "Установка User-Agent"
|
||||
На экране добавления/редактирования плейлиста снять галочку "User-Agent по умолчанию" и ввести необходимый.
|
||||
Например, для [Wink](../aggregator/faq.md#wink).
|
||||
|
||||
#### :thumbsup: M3U
|
||||
|
||||
* Скачать: <https://f-droid.org/ru/packages/com.m3u.androidApp>
|
||||
|
||||
Умеет показывать картинку-в-картинке, отображать группы и сортировать каналы.
|
||||
|
||||
Программу передач нужно [подключать отдельной ссылкой](../aggregator/faq.md#epg), из плейлиста не тянет.
|
||||
|
||||
??? image "Главный экран"
|
||||

|
||||
|
||||
??? image "Добавление плейлиста"
|
||||
!!! warning "Указание протокола `https://` обязательно!"
|
||||

|
||||

|
||||
|
||||
??? image "Установка User-Agent"
|
||||

|
||||

|
||||
|
||||
#### IPTV (Александр Софронов)
|
||||
|
||||
* Скачать: [play.google.com](https://play.google.com/store/apps/details?id=ru.iptvremote.android.iptv)
|
||||
|
||||
#### IPTV# (IPTV Sharp)
|
||||
|
||||
* Скачать: [play.google.com](https://play.google.com/store/apps/details?id=com.iptvsharp.app)
|
||||
|
||||
#### Lazy IPTV
|
||||
|
||||
#### Lazy IPTV Deluxe
|
||||
|
||||
#### Perfect Player
|
||||
|
||||
#### TiviMate
|
||||
|
||||
#### OTT Navigator
|
||||
|
||||
#### IPTV Player Live
|
||||
|
||||
---
|
||||
|
||||
### macOS, iOS, AppleTV
|
||||
|
||||
#### GoodPlayer
|
||||
|
||||
#### ProgTV
|
||||
|
||||
#### microiptv
|
||||
|
||||
#### Xtream IPTV
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/xtream-iptv-tv-player-ip-pro/id1583776992)
|
||||
|
||||
#### Nplayer
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/nplayer/id1116905928)
|
||||
|
||||
#### Nplayer Lite
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/nplayer-lite/id1078835991)
|
||||
|
||||
#### IPTV плеер
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/iptv/id1598794264)
|
||||
|
||||
#### Peers.TV
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/peers-tv/id540754699)
|
||||
|
||||
#### SPB TV Россия
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/spb-tv/id1056140537)
|
||||
|
||||
#### Русское TV
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%BE%D0%B5-%D1%82%D0%B2-hd-%D0%BE%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD-%D1%82%D0%B2/id594760614)
|
||||
|
||||
#### Tviz
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/%D1%82%D0%B5%D0%BB%D0%B5%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0-tviz-%D1%82%D0%B2-%D0%BE%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD/id816291886)
|
||||
|
||||
#### Лайм HD TV
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/%D0%BB%D0%B0%D0%B9%D0%BC-hd-tv-%D1%82%D0%B2-%D0%BA%D0%B8%D0%BD%D0%BE-%D0%B8-%D1%81%D0%B5%D1%80%D0%B8%D0%B0%D0%BB%D1%8B/id998832333)
|
||||
|
||||
#### TV+
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/tv-%D0%BF%D0%BB%D1%8E%D1%81-hd-%D1%82%D0%B5%D0%BB%D0%B5%D0%B2%D0%B8%D0%B7%D0%BE%D1%80-%D0%BE%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD/id1141924092?l=en)
|
||||
|
||||
#### UniPlayer
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/uniplayer-iptv-ott-solution/id1208562731)
|
||||
|
||||
#### ProgTV
|
||||
|
||||
* Скачать: [apps.apple.com](https://apps.apple.com/ru/app/progtv/id1447796133)
|
||||
|
||||
---
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
icon: material/hand-heart-outline
|
||||
---
|
||||
|
||||
# :material-hand-heart-outline: Поддержка проекта
|
||||
|
||||
Проект держится только на сугубо техническом интересе одного разработчика в свободное от работы время.
|
||||
|
||||
Проект сознательно не монетизируется: это неправильно по отношению к пользователям и правообладателям.
|
||||
|
||||
Ниже перечислены минимально доступные вам способы — от самых простых к более сложным.
|
||||
|
||||
## :simple-telegram: Подписаться в Telegram
|
||||
|
||||
У проекта есть два публичных ресурса для прямой связи с пользователями.
|
||||
Там можно ставить **платные реакции** к постам и/или **дарить голоса** (бусты):
|
||||
|
||||
* канал: [@iptv_aggregator](https://t.me/iptv_aggregator) ([boost](https://t.me/iptv_aggregator?boost)) — в нём новости о проекте (общие объявления и проведённые доработки);
|
||||
* чат: [@iptv_aggregator_chat](../tg/chat.md) ([boost](https://t.me/iptv_aggregator_chat?boost)) — комментарии к каналу, общение по теме проекта и IPTV.
|
||||
|
||||
## :material-wallet: Внести пожертвование
|
||||
|
||||
Вы можете внести прямое денежное **пожертвование** с банковской карты на виртуальный кошелёк ЮMoney:
|
||||
|
||||
!!! yoomoney "[yoomoney.ru/to/41001685237530](https://yoomoney.ru/to/41001685237530)"
|
||||
Разовый платёж, без подписок, на любую сумму.
|
||||
|
||||
Также вы можете оформить подписку на Boosty:
|
||||
|
||||
!!! boosty "[boosty.to/anthonyaxenov](https://boosty.to/anthonyaxenov)"
|
||||
Разовый платёж или платная подписка.
|
||||
|
||||
Пожертвования добровольны.
|
||||
Они не дают права на эксклюзивный доступ к чему-либо и не рассматриваются как способ обогащения.
|
||||
Это лишь попытка компенсировать затраты на содержание проекта.
|
||||
|
||||
На пожертвования [был приобретён](https://t.me/iptv_aggregator/30) домен `m3u.su`, который сейчас используется в качестве основного адреса.
|
||||
|
||||
## :simple-git: Принять участие в разработке { id="participate" }
|
||||
|
||||
Весь исходный код проекта хранится в репозиториях организации: [git.axenov.dev/IPTV](https://git.axenov.dev/IPTV)
|
||||
|
||||
Чтобы принять участие в разработке, необходимо [зарегистрироваться на сайте git.axenov.dev](https://git.axenov.dev/user/sign_up) и **активировать** учётную запись по e-mail.
|
||||
|
||||
!!! info "Это бесплатно, но неактивированные учётки периодически удаляются."
|
||||
|
||||
### :octicons-issue-opened-16: Создать задачу
|
||||
|
||||
Любое ПО неидеально, как и документация к нему.
|
||||
|
||||
Если вы нашли ошибку, опечатку, неожиданное поведение ПО или есть предложение по улучшению — можете создать задачу в соответствующем репозитории организации.
|
||||
|
||||
### :octicons-git-pull-request-16: Прислать изменения
|
||||
|
||||
Вы можете внести исправления в код самостоятельно и прислать pull-request для принятия в основную ветку.
|
||||
|
||||
Это может быть новый функционал, исправления ошибок или опечаток.
|
||||
|
||||
Если есть идеи и желание для расширения функционала проекта, можем обсудить создание нового репозитория с выдачей необходимых прав.
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Добро пожаловать!
|
||||
template: landing.html
|
||||
hide: [navigation, toc]
|
||||
hero:
|
||||
title: Агрегатор плейлистов
|
||||
subtitle: Бесплатный сервис для сбора публичных IPTV-плейлистов с автоматической проверкой доступности каналов
|
||||
buttons:
|
||||
- text: О сервисе
|
||||
url: aggregator/overview.html
|
||||
primary: true
|
||||
- text: Открыть сайт
|
||||
url: https://m3u.su
|
||||
primary: false
|
||||
---
|
||||
|
||||
Ниже представлена информация о проекте по разделам.
|
||||
Для навигации используйте
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-home:{ .lg .middle } **Агрегатор m3u.su**
|
||||
|
||||
---
|
||||
|
||||
Что это за сервис и как он работает?
|
||||
Основные принципы и цель проекта.
|
||||
|
||||
[Подробнее :octicons-arrow-right-24:](aggregator/overview.md){ .md-button .md-button--primary }
|
||||
|
||||
- :material-console:{ .lg .middle } **iptvc**
|
||||
|
||||
---
|
||||
|
||||
CLI-утилита для запуска веб-интерфейса и проверки IPTV-плейлистов: установка, команды, конфигурация
|
||||
|
||||
[Подробнее :octicons-arrow-right-24:](iptvc/overview.md){ .md-button .md-button--primary }
|
||||
|
||||
- :material-web:{ .lg .middle } **Запуск сайта**
|
||||
|
||||
---
|
||||
|
||||
Создай собственный агрегатор плейлистов на базе iptvc, используй его в собственной домашней сети
|
||||
|
||||
[Подробнее :octicons-arrow-right-24:](iptvc/site/first-steps.md){ .md-button .md-button--primary }
|
||||
|
||||
- :material-file-cog:{ .lg .middle } **Конфигурация**
|
||||
|
||||
---
|
||||
|
||||
Полное описание `config.yml`, переменных окружения и CLI-флагов
|
||||
|
||||
[Подробнее :octicons-arrow-right-24:](common/config/config.md){ .md-button .md-button--primary }
|
||||
|
||||
- :material-book-open-page-variant-outline:{ .lg .middle } **Об этой документации**
|
||||
|
||||
---
|
||||
|
||||
Подборка плееров для всех платформ — найдите и настройте плеер для себя
|
||||
|
||||
[Подробнее :octicons-arrow-right-24:](common/players.md){ .md-button .md-button--primary }
|
||||
|
||||
- :material-hand-heart:{ .lg .middle } **Поддержка проекта**
|
||||
|
||||
---
|
||||
|
||||
Проекту важна поддержка, и вот как вы можете принять участие
|
||||
|
||||
[Подробнее :octicons-arrow-right-24:](common/support.md){ .md-button .md-button--primary }
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,384 @@
|
||||
---
|
||||
title: check
|
||||
tags: [iptvc]
|
||||
---
|
||||
|
||||
# Команда `check`
|
||||
|
||||
Команда поддерживает множество аргументов для разных целей.
|
||||
|
||||
Они могут дополнять друг друга.
|
||||
|
||||
Порядок аргументов не имеет значения.
|
||||
|
||||
## `-i`, `--ini` { id=ini }
|
||||
|
||||
Указывает путь к локальному [ini-файлу](../../common/formats/playlists.md) с описанием плейлистов.
|
||||
|
||||
Можно указать только однажды.
|
||||
|
||||
Значение по умолчанию: `./playlists.ini`
|
||||
|
||||
Если файл не найден, проверка плейлистов будет доступна только по ссылкам ([`--url`](#url)) или из локальных файлов ([`--file`](#file)).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini
|
||||
```
|
||||
|
||||
## `-t`, `--tags` { id=tags }
|
||||
|
||||
Указывает путь к локальному [json-файлу](../../common/formats/channels.md) с описанием тегов каналов.
|
||||
|
||||
Можно указать только однажды.
|
||||
|
||||
Значение по умолчанию: `./channels.json`
|
||||
|
||||
Если файл не найден, то будет выведено предупреждение о том, что каналы не будут помечены тегами.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -t ~/tags.json
|
||||
```
|
||||
|
||||
## `-f`, `--file` { id=file }
|
||||
|
||||
Указывает путь к локальному файлу плейлиста `*.m3u`/`*.m3u8`.
|
||||
|
||||
Можно указать несколько разных.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -f playlist.m3u
|
||||
./iptvc check -f playlist1.m3u --file playlist2.m3u8
|
||||
./iptvc check --file /path/to/playlist.m3u
|
||||
```
|
||||
|
||||
## `-u`, `--url` { id=url }
|
||||
|
||||
Указывает URL удалённого плейлиста (поддерживаются протоколы http/https).
|
||||
|
||||
Можно указать несколько разных.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -u http://example.com/playlist.m3u
|
||||
./iptvc check -u https://site.com/playlist.m3u8 --url http://other.com/list.m3u
|
||||
```
|
||||
|
||||
## `-c`, `--code` { id=code }
|
||||
|
||||
Указывает код плейлиста из файла [playlists.ini](../../common/formats/playlists.md).
|
||||
|
||||
Можно указать несколько разных.
|
||||
|
||||
!!! warning "Работает только вместе с [`--ini`](#ini)."
|
||||
|
||||
Если не указан ни разу, то будут проверены все плейлисты, которые указаны в ini-файле.
|
||||
|
||||
Если используется кеширование, то проверенные плейлисты (результаты проверки которых ещё находятся в кеше) проверяться не будут.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini -c RU_BASIC --code MOVIE_PREMIUM
|
||||
```
|
||||
|
||||
## `--repeat` { id=repeat }
|
||||
|
||||
Указывает количество повторений (итераций) команды.
|
||||
|
||||
Значение по умолчанию: `1`
|
||||
|
||||
Если указано `0`, тогда:
|
||||
|
||||
* повторение будет бесконечным;
|
||||
|
||||
* если переданы [`--url`](#url), [`--file`](#file) или [`--code`](#code), то на каждой итерации будут проверяться только указанные плейлисты;
|
||||
|
||||
* если не переданы [`--url`](#url), [`--file`](#file) или [`--code`](#code), то на каждой итерации список плейлистов будет подготавливаться заново.
|
||||
Если при этом используется кеширование, то проверенные плейлисты (результаты проверки которых ещё находятся в кеше) проверяться не будут.
|
||||
|
||||
```shell title="Пример"
|
||||
# проверить 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
|
||||
# бесконечно проверять плейлист из файла
|
||||
./iptvc check -f test.m3u --repeat 0
|
||||
```
|
||||
|
||||
## `--playlists-all-cooldown` { id=playlists-all-cooldown }
|
||||
|
||||
Указывает паузу между полными циклами проверки в миллисекундах. Параметр переопределяет `check.playlists.all-cooldown` из конфигурации.
|
||||
|
||||
Пауза применяется после завершения полного цикла и перед началом следующего. Внутри цикла этот параметр не используется: для задержки между плейлистами применяется `check.playlists.one-cooldown`.
|
||||
|
||||
Значение по умолчанию: значение `check.playlists.all-cooldown` из конфигурации, обычно `0`.
|
||||
|
||||
```shell title="Пример"
|
||||
# проверить 5 раз с паузой 5 секунд между циклами
|
||||
./iptvc check -i ~/my.ini -c xx --code yy --repeat 5 --playlists-all-cooldown 5000
|
||||
# бесконечно проверять все плейлисты из my.ini каждый час
|
||||
./iptvc check -i ~/my.ini --repeat 0 --playlists-all-cooldown 3600000
|
||||
# бесконечно проверять плейлист из файла с паузой 10 секунд
|
||||
./iptvc check -f test.m3u --repeat 0 --playlists-all-cooldown 10000
|
||||
```
|
||||
|
||||
## `-r`, `--random` { id=random }
|
||||
|
||||
Указывает максимальное количество случайных плейлистов из ini-файла для проверки.
|
||||
|
||||
!!! warning "Работает только вместе с [`--ini`](#ini)."
|
||||
|
||||
Если не указан ни разу, то будут проверены все плейлисты, которые указаны в ini-файле.
|
||||
|
||||
Если используется кеширование, то проверенные плейлисты (результаты проверки которых ещё находятся в кеше) проверяться не будут.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini -r 10
|
||||
```
|
||||
|
||||
## `-j`, `--json` { id=json }
|
||||
|
||||
Если указано, то подробные результаты проверки будут выводиться в формате JSON.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -f playlist.m3u --json
|
||||
```
|
||||
|
||||
## `-q`, `--quiet` { id=quiet }
|
||||
|
||||
Подавляет вывод всех логов.
|
||||
|
||||
!!! info "Не влияет на [`--json`](#json) (JSON-данные будут выведены в stdout), но перекрывает [`--verbose`](#verbose) (логов не будет вовсе, независимо от повышенной подробности)."
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --random 10 --quiet --json
|
||||
```
|
||||
|
||||
## `-v`, `--verbose` { id=verbose }
|
||||
|
||||
Включает подробное логирование.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check --random 10 --verbose
|
||||
```
|
||||
|
||||
## Глобальные флаги { id=global }
|
||||
|
||||
Эти флаги доступны для всех команд и переопределяют значения из `config.yml`.
|
||||
|
||||
### `--debug` { id=debug }
|
||||
|
||||
Включает режим отладки. Переопределяет `app.debug` из `config.yml` и переменную `APP_DEBUG`.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --debug
|
||||
```
|
||||
|
||||
### `--log-level` { id=log-level }
|
||||
|
||||
Устанавливает уровень логирования. Переопределяет `app.log_level` из `config.yml`.
|
||||
|
||||
Доступные значения: `debug`, `info`, `warn`, `error`.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --log-level debug
|
||||
```
|
||||
|
||||
## Флаги проверки плейлистов { id=check-playlists }
|
||||
|
||||
Эти флаги переопределяют параметры секции `check.playlists` из `config.yml`. Доступны для команд `check` и `serve`.
|
||||
|
||||
### `--playlists-timeout` { id=playlists-timeout }
|
||||
|
||||
Таймаут HTTP-запроса плейлиста в миллисекундах.
|
||||
|
||||
Переопределяет `check.playlists.timeout` (по умолчанию `10000`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --playlists-timeout 5000
|
||||
```
|
||||
|
||||
### `--playlists-all-cooldown` { id=playlists-all-cooldown }
|
||||
|
||||
Задержка в миллисекундах после проверки всех плейлистов.
|
||||
|
||||
Переопределяет `check.playlists.all-cooldown` (по умолчанию `0`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --playlists-all-cooldown 10000
|
||||
```
|
||||
|
||||
### `--playlists-one-cooldown` { id=playlists-one-cooldown }
|
||||
|
||||
Задержка в миллисекундах после проверки каждого плейлиста.
|
||||
|
||||
Переопределяет `check.playlists.one-cooldown` (по умолчанию `0`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --playlists-one-cooldown 2000
|
||||
```
|
||||
|
||||
### `--playlists-max-routines` { id=playlists-max-routines }
|
||||
|
||||
Максимум одновременно проверяемых плейлистов.
|
||||
|
||||
Переопределяет `check.playlists.max-routines` (по умолчанию `5`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --playlists-max-routines 10
|
||||
```
|
||||
|
||||
### `--playlists-per-routine` { id=playlists-per-routine }
|
||||
|
||||
Количество плейлистов на одну процедуру проверки.
|
||||
|
||||
Переопределяет `check.playlists.per-routine` (по умолчанию `1`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --playlists-per-routine 3
|
||||
```
|
||||
|
||||
### `--playlists-user-agent` { id=playlists-user-agent }
|
||||
|
||||
User-Agent для HTTP-запросов плейлистов. Можно указать несколько — будет выбран случайный при каждом запросе.
|
||||
|
||||
Переопределяет `check.playlists.user-agent`.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --playlists-user-agent "Mozilla/5.0" "curl/8.0"
|
||||
```
|
||||
|
||||
## Флаги проверки каналов { id=check-channels }
|
||||
|
||||
Эти флаги переопределяют параметры секции `check.channels` из `config.yml`. Доступны для команд `check` и `serve`.
|
||||
|
||||
### `--channels-timeout` { id=channels-timeout }
|
||||
|
||||
Таймаут HTTP-запроса канала в миллисекундах.
|
||||
|
||||
Переопределяет `check.channels.timeout` (по умолчанию `10000`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --channels-timeout 8000
|
||||
```
|
||||
|
||||
### `--channels-byte-range` { id=channels-byte-range }
|
||||
|
||||
Объём данных в байтах для загрузки от сервера при проверке канала.
|
||||
|
||||
Переопределяет `check.channels.byte-range` (по умолчанию `512`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --channels-byte-range 1024
|
||||
```
|
||||
|
||||
### `--channels-cooldown` { id=channels-cooldown }
|
||||
|
||||
Задержка в миллисекундах после проверки каждого канала.
|
||||
|
||||
Переопределяет `check.channels.cooldown` (по умолчанию `0`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --channels-cooldown 100
|
||||
```
|
||||
|
||||
### `--channels-max-routines` { id=channels-max-routines }
|
||||
|
||||
Максимум одновременно проверяемых каналов.
|
||||
|
||||
Переопределяет `check.channels.max-routines` (по умолчанию `50`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --channels-max-routines 100
|
||||
```
|
||||
|
||||
### `--channels-per-routine` { id=channels-per-routine }
|
||||
|
||||
Количество каналов на одну процедуру проверки.
|
||||
|
||||
Переопределяет `check.channels.per-routine` (по умолчанию `10`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --channels-per-routine 20
|
||||
```
|
||||
|
||||
### `--channels-user-agent` { id=channels-user-agent }
|
||||
|
||||
User-Agent для HTTP-запросов каналов. Можно указать несколько — будет выбран случайный при каждом запросе.
|
||||
|
||||
Переопределяет `check.channels.user-agent`.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --channels-user-agent "Mozilla/5.0" "VLC/3.0"
|
||||
```
|
||||
|
||||
## Флаги кеша { id=cache-flags }
|
||||
|
||||
Эти флаги переопределяют параметры секции `cache` из `config.yml`. Доступны для команд `check` и `serve`.
|
||||
|
||||
### `--cache-enabled` { id=cache-enabled }
|
||||
|
||||
Включает кеширование результатов в KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.enabled` (по умолчанию `false`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --cache-enabled
|
||||
```
|
||||
|
||||
### `--cache-host` { id=cache-host }
|
||||
|
||||
Хост KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.host` (по умолчанию `localhost`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --cache-enabled --cache-host 192.168.1.10
|
||||
```
|
||||
|
||||
### `--cache-port` { id=cache-port }
|
||||
|
||||
Порт KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.port` (по умолчанию `6379`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --cache-enabled --cache-port 6380
|
||||
```
|
||||
|
||||
### `--cache-username` { id=cache-username }
|
||||
|
||||
Логин для подключения к KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.username`.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --cache-enabled --cache-username myuser
|
||||
```
|
||||
|
||||
### `--cache-password` { id=cache-password }
|
||||
|
||||
Пароль для подключения к KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.password`.
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --cache-enabled --cache-password secret
|
||||
```
|
||||
|
||||
### `--cache-db` { id=cache-db }
|
||||
|
||||
Номер базы данных KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.db` (по умолчанию `0`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --cache-enabled --cache-db 2
|
||||
```
|
||||
|
||||
### `--cache-ttl` { id=cache-ttl }
|
||||
|
||||
TTL записей кеша в секундах.
|
||||
|
||||
Переопределяет `cache.ttl` (по умолчанию `1800`).
|
||||
|
||||
```shell title="Пример"
|
||||
./iptvc check -i ~/my.ini --cache-enabled --cache-ttl 3600
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: help
|
||||
tags: [iptvc]
|
||||
---
|
||||
|
||||
# Команда `help`
|
||||
|
||||
Для получения помощи о программе, нужно вызвать команду `help` или передать аргумент `-h` или `--help`.
|
||||
|
||||
Равнозначные команды:
|
||||
|
||||
```
|
||||
./iptvc help
|
||||
./iptvc --help
|
||||
./iptvc -h
|
||||
```
|
||||
|
||||
Вывод (может незначительно отличаться в разных версиях):
|
||||
|
||||
```
|
||||
Simple utility to check iptv playlists. Part of m3u.su project.
|
||||
Copyright (c) 2025, Антон Аксенов, MIT license.
|
||||
|
||||
Usage:
|
||||
iptvc [command]
|
||||
|
||||
Available Commands:
|
||||
check Check playlists
|
||||
completion Generate the autocompletion script for the specified shell
|
||||
help Help about any command
|
||||
serve Start web interface
|
||||
version Show version
|
||||
|
||||
Flags:
|
||||
--config string path to config file (default "config.yml")
|
||||
--debug enable debug mode (overrides config.yml)
|
||||
-h, --help help for iptvc
|
||||
--log-level string log level: debug, info, warn, error (overrides config.yml)
|
||||
-v, --verbose enable additional output
|
||||
|
||||
Use "iptvc [command] --help" for more information about a command.
|
||||
```
|
||||
|
||||
Чтобы получить справку о конкретной команде, можно вызвать программу одним из способов:
|
||||
|
||||
```
|
||||
./iptvc help <КОМАНДА>
|
||||
./iptvc <КОМАНДА> --help
|
||||
./iptvc <КОМАНДА> -h
|
||||
```
|
||||
|
||||
Список команд указан в этом разделе.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
icon: octicons/terminal-24
|
||||
hide: [toc]
|
||||
---
|
||||
|
||||
# :octicons-terminal-24: Справочник команд
|
||||
|
||||
* [`check`](check.md) — проверка плейлистов
|
||||
* [`serve`](serve.md) — запуск веб-интерфейса
|
||||
* [`version`](version.md) — получение версии и выход
|
||||
* [`help`](help.md) — получение справки о программе и выход
|
||||
|
||||
Каждая команда отвечает за конкретную операцию и имеет свои настройки (аргументы), которыми можно влиять на логику выполнения операции.
|
||||
|
||||
Также есть глобальные аргументы, которые доступны для всех команд:
|
||||
|
||||
| Флаг | Тип | Соответствует в `config.yml` | Описание |
|
||||
| ----------------- | ------ | ---------------------------- | ----------------------------------------------------- |
|
||||
| `--config` | string | — | Путь к файлу конфигурации (по умолчанию `config.yml`) |
|
||||
| `--debug` | bool | `app.debug` | Включить режим отладки |
|
||||
| `--log-level` | string | `app.log_level` | Уровень логирования: `debug`, `info`, `warn`, `error` |
|
||||
| `-v`, `--verbose` | bool | — | Подробное логирование |
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
---
|
||||
title: serve
|
||||
tags: [iptvc]
|
||||
---
|
||||
|
||||
# Команда `serve`
|
||||
|
||||
Запускает встроенный веб-сервер для просмотра плейлистов и результатов их проверки в браузере.
|
||||
|
||||
```bash
|
||||
iptvc serve [flags]
|
||||
```
|
||||
|
||||
## Веб-сервер
|
||||
|
||||
### `-p`, `--port` { id="port" }
|
||||
|
||||
Порт для веб-сервера.
|
||||
|
||||
Переопределяет `server.port` из `config.yml` и переменную `WEB_PORT`.
|
||||
|
||||
Если не указан, используется значение из `config.yml` (по умолчанию `8080`).
|
||||
|
||||
```bash
|
||||
iptvc serve -p 3000
|
||||
```
|
||||
|
||||
### `--host` { id="host" }
|
||||
|
||||
Хост для привязки веб-сервера.
|
||||
|
||||
Переопределяет `server.host` из `config.yml` и переменную `WEB_HOST`.
|
||||
|
||||
Если не указан, используется значение из `config.yml` (по умолчанию — все интерфейсы).
|
||||
|
||||
```bash
|
||||
iptvc serve --host 127.0.0.1
|
||||
```
|
||||
|
||||
## Фоновая проверка
|
||||
|
||||
### `--check` { id="check" }
|
||||
|
||||
Включает фоновую проверку плейлистов. По умолчанию выключена.
|
||||
|
||||
Без этого флага веб-сервер работает standalone — отображает данные из кеша (если включён) или статус `unknown` для всех плейлистов.
|
||||
|
||||
```bash
|
||||
iptvc serve --check
|
||||
```
|
||||
|
||||
При `--check` доступны следующие флаги:
|
||||
|
||||
### `-i`, `--ini` { id="ini" }
|
||||
|
||||
Путь к локальному [ini-файлу](../../common/formats/playlists.md) с описанием плейлистов.
|
||||
|
||||
Значение по умолчанию: `./playlists.ini`
|
||||
|
||||
```bash
|
||||
iptvc serve --check -i ~/my.ini
|
||||
```
|
||||
|
||||
### `-t`, `--tags` { id="tags" }
|
||||
|
||||
Путь к [json-файлу](../../common/formats/channels.md) с описанием тегов каналов.
|
||||
|
||||
Значение по умолчанию: `./channels.json`
|
||||
|
||||
```bash
|
||||
iptvc serve --check -t ~/tags.json
|
||||
```
|
||||
|
||||
### `--playlists-all-cooldown` { id=playlists-all-cooldown }
|
||||
|
||||
Пауза между полными циклами фоновой проверки в миллисекундах. Параметр переопределяет `check.playlists.all-cooldown` из конфигурации.
|
||||
|
||||
Значение по умолчанию: значение `check.playlists.all-cooldown` из конфигурации, обычно `0`.
|
||||
|
||||
```bash
|
||||
# пауза 2 минуты между циклами
|
||||
iptvc serve --check --playlists-all-cooldown 120000
|
||||
```
|
||||
|
||||
### `--repeat` { id="repeat" }
|
||||
|
||||
Количество циклов фоновой проверки.
|
||||
|
||||
Значение по умолчанию: `0` (бесконечно)
|
||||
|
||||
```bash
|
||||
# проверить один раз и остановить фоновую проверку
|
||||
iptvc serve --check --repeat 1
|
||||
```
|
||||
|
||||
### `-r`, `--random` { id="random" }
|
||||
|
||||
Максимальное количество случайных плейлистов из ini-файла для проверки.
|
||||
|
||||
```bash
|
||||
iptvc serve --check -r 10
|
||||
```
|
||||
|
||||
## Глобальные флаги
|
||||
|
||||
### `--config` { id="config" }
|
||||
|
||||
Путь к файлу конфигурации `config.yml`.
|
||||
|
||||
Значение по умолчанию: `config.yml`
|
||||
|
||||
```bash
|
||||
iptvc serve --config /etc/iptvc/config.yml
|
||||
```
|
||||
|
||||
### `--debug` { id="debug" }
|
||||
|
||||
Включает режим отладки. Переопределяет `app.debug` из `config.yml` и переменную `APP_DEBUG`.
|
||||
|
||||
```bash
|
||||
iptvc serve --debug
|
||||
```
|
||||
|
||||
### `--log-level` { id="log-level" }
|
||||
|
||||
Устанавливает уровень логирования. Переопределяет `app.log_level` из `config.yml`.
|
||||
|
||||
Доступные значения: `debug`, `info`, `warn`, `error`.
|
||||
|
||||
```bash
|
||||
iptvc serve --log-level debug
|
||||
```
|
||||
|
||||
### `-v`, `--verbose` { id="verbose" }
|
||||
|
||||
Включает подробное логирование.
|
||||
|
||||
## Флаги проверки плейлистов
|
||||
|
||||
Эти флаги переопределяют параметры секции `check.playlists` из `config.yml`. Доступны для команд `check` и `serve`. Имеют смысл только при включённой фоновой проверке (`--check` или `check.start-on-serve: true`).
|
||||
|
||||
### `--playlists-timeout` { id="playlists-timeout" }
|
||||
|
||||
Таймаут HTTP-запроса плейлиста в миллисекундах.
|
||||
|
||||
Переопределяет `check.playlists.timeout` (по умолчанию `10000`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --playlists-timeout 5000
|
||||
```
|
||||
|
||||
### `--playlists-all-cooldown` { id="playlists-all-cooldown" }
|
||||
|
||||
Задержка в миллисекундах после проверки всех плейлистов.
|
||||
|
||||
Переопределяет `check.playlists.all-cooldown` (по умолчанию `0`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --playlists-all-cooldown 10000
|
||||
```
|
||||
|
||||
### `--playlists-one-cooldown` { id="playlists-one-cooldown" }
|
||||
|
||||
Задержка в миллисекундах после проверки каждого плейлиста.
|
||||
|
||||
Переопределяет `check.playlists.one-cooldown` (по умолчанию `0`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --playlists-one-cooldown 2000
|
||||
```
|
||||
|
||||
### `--playlists-max-routines` { id="playlists-max-routines" }
|
||||
|
||||
Максимум одновременно проверяемых плейлистов.
|
||||
|
||||
Переопределяет `check.playlists.max-routines` (по умолчанию `5`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --playlists-max-routines 10
|
||||
```
|
||||
|
||||
### `--playlists-per-routine` { id="playlists-per-routine" }
|
||||
|
||||
Количество плейлистов на одну процедуру проверки.
|
||||
|
||||
Переопределяет `check.playlists.per-routine` (по умолчанию `1`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --playlists-per-routine 3
|
||||
```
|
||||
|
||||
### `--playlists-user-agent` { id="playlists-user-agent" }
|
||||
|
||||
User-Agent для HTTP-запросов плейлистов. Можно указать несколько — будет выбран случайный при каждом запросе.
|
||||
|
||||
Переопределяет `check.playlists.user-agent`.
|
||||
|
||||
```bash
|
||||
iptvc serve --check --playlists-user-agent "Mozilla/5.0" "curl/8.0"
|
||||
```
|
||||
|
||||
## Флаги проверки каналов
|
||||
|
||||
Эти флаги переопределяют параметры секции `check.channels` из `config.yml`. Доступны для команд `check` и `serve`. Имеют смысл только при включённой фоновой проверке.
|
||||
|
||||
### `--channels-timeout` { id="channels-timeout" }
|
||||
|
||||
Таймаут HTTP-запроса канала в миллисекундах.
|
||||
|
||||
Переопределяет `check.channels.timeout` (по умолчанию `10000`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --channels-timeout 8000
|
||||
```
|
||||
|
||||
### `--channels-byte-range` { id="channels-byte-range" }
|
||||
|
||||
Объём данных в байтах для загрузки от сервера при проверке канала.
|
||||
|
||||
Переопределяет `check.channels.byte-range` (по умолчанию `512`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --channels-byte-range 1024
|
||||
```
|
||||
|
||||
### `--channels-cooldown` { id="channels-cooldown" }
|
||||
|
||||
Задержка в миллисекундах после проверки каждого канала.
|
||||
|
||||
Переопределяет `check.channels.cooldown` (по умолчанию `0`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --channels-cooldown 100
|
||||
```
|
||||
|
||||
### `--channels-max-routines` { id="channels-max-routines" }
|
||||
|
||||
Максимум одновременно проверяемых каналов.
|
||||
|
||||
Переопределяет `check.channels.max-routines` (по умолчанию `50`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --channels-max-routines 100
|
||||
```
|
||||
|
||||
### `--channels-per-routine` { id="channels-per-routine" }
|
||||
|
||||
Количество каналов на одну процедуру проверки.
|
||||
|
||||
Переопределяет `check.channels.per-routine` (по умолчанию `10`).
|
||||
|
||||
```bash
|
||||
iptvc serve --check --channels-per-routine 20
|
||||
```
|
||||
|
||||
### `--channels-user-agent` { id="channels-user-agent" }
|
||||
|
||||
User-Agent для HTTP-запросов каналов. Можно указать несколько — будет выбран случайный при каждом запросе.
|
||||
|
||||
Переопределяет `check.channels.user-agent`.
|
||||
|
||||
```bash
|
||||
iptvc serve --check --channels-user-agent "Mozilla/5.0" "VLC/3.0"
|
||||
```
|
||||
|
||||
## Флаги кеша
|
||||
|
||||
Эти флаги переопределяют параметры секции `cache` из `config.yml`. Доступны для команд `check` и `serve`.
|
||||
|
||||
### `--cache-enabled` { id="cache-enabled" }
|
||||
|
||||
Включает кеширование результатов в KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.enabled` (по умолчанию `false`).
|
||||
|
||||
```bash
|
||||
iptvc serve --cache-enabled
|
||||
```
|
||||
|
||||
### `--cache-host` { id="cache-host" }
|
||||
|
||||
Хост KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.host` (по умолчанию `localhost`).
|
||||
|
||||
```bash
|
||||
iptvc serve --cache-enabled --cache-host 192.168.1.10
|
||||
```
|
||||
|
||||
### `--cache-port` { id="cache-port" }
|
||||
|
||||
Порт KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.port` (по умолчанию `6379`).
|
||||
|
||||
```bash
|
||||
iptvc serve --cache-enabled --cache-port 6380
|
||||
```
|
||||
|
||||
### `--cache-username` { id="cache-username" }
|
||||
|
||||
Логин для подключения к KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.username`.
|
||||
|
||||
```bash
|
||||
iptvc serve --cache-enabled --cache-username myuser
|
||||
```
|
||||
|
||||
### `--cache-password` { id="cache-password" }
|
||||
|
||||
Пароль для подключения к KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.password`.
|
||||
|
||||
```bash
|
||||
iptvc serve --cache-enabled --cache-password secret
|
||||
```
|
||||
|
||||
### `--cache-db` { id="cache-db" }
|
||||
|
||||
Номер базы данных KeyDB/Redis.
|
||||
|
||||
Переопределяет `cache.db` (по умолчанию `0`).
|
||||
|
||||
```bash
|
||||
iptvc serve --cache-enabled --cache-db 2
|
||||
```
|
||||
|
||||
### `--cache-ttl` { id="cache-ttl" }
|
||||
|
||||
TTL записей кеша в секундах.
|
||||
|
||||
Переопределяет `cache.ttl` (по умолчанию `1800`).
|
||||
|
||||
```bash
|
||||
iptvc serve --cache-enabled --cache-ttl 3600
|
||||
```
|
||||
|
||||
## Примеры
|
||||
|
||||
```bash
|
||||
# просто веб-сервер без проверки
|
||||
iptvc serve
|
||||
|
||||
# веб-сервер с фоновой проверкой каждые 2 минуты
|
||||
iptvc serve --check --playlists-all-cooldown 120000
|
||||
|
||||
# веб-сервер на порту 3000 с проверкой 10 случайных плейлистов
|
||||
iptvc serve -p 3000 --check -r 10
|
||||
|
||||
# один цикл проверки, затем только веб-сервер
|
||||
iptvc serve --check --repeat 1 --playlists-all-cooldown 0
|
||||
|
||||
# веб-сервер с кешем и фоновой проверкой, увеличенные лимиты параллелизма
|
||||
iptvc serve --check --cache-enabled \
|
||||
--playlists-max-routines 10 \
|
||||
--channels-max-routines 100
|
||||
|
||||
# веб-сервер с отладкой и кастомным user-agent
|
||||
iptvc serve --check --debug \
|
||||
--playlists-user-agent "Mozilla/5.0" \
|
||||
--channels-user-agent "VLC/3.0"
|
||||
```
|
||||
|
||||
## Веб-маршруты
|
||||
|
||||
| Метод | Путь | Описание |
|
||||
| --- | --- | --- |
|
||||
| GET | `/` | Главная страница со списком плейлистов |
|
||||
| GET | `/page/{N}` | Страница N списка плейлистов |
|
||||
| GET | `/{code}` | Редирект на прямую ссылку плейлиста |
|
||||
| GET | `/{code}.m3u[8]` | Редирект на прямую ссылку плейлиста |
|
||||
| GET | `/{code}/details` | Страница с описанием плейлиста |
|
||||
| GET | `/api/playlists/{code}` | JSON: информация о плейлисте |
|
||||
| GET | `/api/version` | JSON: версии компонентов |
|
||||
| GET | `/api/health` | JSON: состояние сервиса |
|
||||
| GET | `/api/stats` | JSON: статистика по плейлистам и каналам |
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: version
|
||||
tags: [iptvc]
|
||||
---
|
||||
|
||||
# Команда `version`
|
||||
|
||||
Выводит версию программы:
|
||||
|
||||
```bash
|
||||
./iptvc version
|
||||
```
|
||||
|
||||
Пример результата:
|
||||
|
||||
```
|
||||
iptvc v1.1.3
|
||||
```
|
||||
|
||||
Версия также доступна через [API](serve.md) — endpoint `GET /api/version`.
|
||||
@@ -0,0 +1,223 @@
|
||||
---
|
||||
# icon: material/architecture
|
||||
tags: ["iptvc", "разработка", "архитектура"]
|
||||
---
|
||||
|
||||
# Архитектура iptvc
|
||||
|
||||
Внутреннее устройство программы для разработчиков.
|
||||
|
||||
## Стек технологий
|
||||
|
||||
- **Go 1.22+** — язык программирования;
|
||||
- `net/http` — HTTP-сервер (Go 1.22 routing patterns);
|
||||
- `html/template` — шаблоны HTML;
|
||||
- `//go:embed` — встраивание шаблонов в бинарник;
|
||||
- `github.com/spf13/cobra` — CLI-фреймворк;
|
||||
- `gopkg.in/yaml.v3` — парсинг `config.yml`;
|
||||
- `github.com/joho/godotenv` — загрузка `.env`;
|
||||
- `github.com/redis/go-redis/v9` — клиент KeyDB/Redis.
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```
|
||||
iptvc/
|
||||
├── main.go # точка входа
|
||||
├── config.yml # конфигурация
|
||||
├── .env # переменные окружения (опционально)
|
||||
├── cmd/ # CLI-команды (Cobra)
|
||||
│ ├── root.go # корневая команда, глобальные флаги
|
||||
│ ├── check.go # команда check
|
||||
│ ├── serve.go # команда serve
|
||||
│ ├── flags.go # общие флаги check/serve
|
||||
│ └── version.go # команда version
|
||||
├── app/
|
||||
│ ├── app.go # глобальные переменные: Args, Config, Cache
|
||||
│ ├── config/
|
||||
│ │ └── config.go # Config, Init(), validate(), IntRange, UserAgents
|
||||
│ ├── checker/
|
||||
│ │ └── checker.go # CheckPlaylists(), CheckChannels(), OnPlaylistChecked
|
||||
│ ├── playlist/
|
||||
│ │ └── playlist.go # Playlist, Channel, Parse(), Download()
|
||||
│ ├── inifile/
|
||||
│ │ └── inifile.go # чтение playlists.ini
|
||||
│ ├── tagfile/
|
||||
│ │ └── tagfile.go # чтение channels.json, назначение тегов
|
||||
│ ├── cache/
|
||||
│ │ └── cache.go # подключение к KeyDB/Redis
|
||||
│ ├── logger/
|
||||
│ │ └── logger.go # настройка логирования
|
||||
│ ├── utils/
|
||||
│ │ └── utils.go # Fetch(), ExpandPath(), ArrayUnique(), Md5str()
|
||||
│ └── web/
|
||||
│ ├── server.go # Server, Start(), StartBackgroundChecker()
|
||||
│ ├── handlers.go # HTTP-обработчики
|
||||
│ ├── templates.go # TemplateManager, //go:embed
|
||||
│ └── views/ # HTML-шаблоны
|
||||
│ ├── base.html
|
||||
│ ├── list.html
|
||||
│ ├── details.html
|
||||
│ └── notfound.html
|
||||
└── go.mod
|
||||
```
|
||||
|
||||
## Пакеты
|
||||
|
||||
### `app`
|
||||
|
||||
Глобальный контейнер: `Args` (CLI-флаги), `Config` (конфигурация), `Cache` (Redis-клиент).
|
||||
`Init()` загружает конфигурацию, инициализирует логгер и подключение к кешу.
|
||||
|
||||
### `app.config`
|
||||
|
||||
Структуры: `Config` → `AppConfig`, `ServerConfig`, `CheckConfig`, `CacheConfig`.
|
||||
|
||||
Кастомные YAML-типы:
|
||||
|
||||
- **`IntRange`** — скаляр или `[min, max]`. Метод `Value()` возвращает константу или случайное значение.
|
||||
- **`UserAgents`** — строка или массив строк. Метод `Pick()` возвращает случайный элемент.
|
||||
|
||||
`Init(configPath)` — загружает `config.yml`, применяет env, валидирует.
|
||||
|
||||
`validate()` — проверяет все значения, исправляет некорректные с логированием.
|
||||
|
||||
### `app.checker`
|
||||
|
||||
Содержит логику проверки:
|
||||
|
||||
- **`PrepareListsToCheck(files, urls, codes)`** — формирует список плейлистов из файлов, URL и кодов ini-файла.
|
||||
- **`CheckPlaylists(lists)`** — параллельная проверка плейлистов (семфор `per-routine`), загрузка, парсинг, вызов `CheckChannels` для каждого.
|
||||
- **`CheckChannels(pls)`** — параллельная проверка каналов (семфор `per-routine`), HTTP-запрос с `Range` header.
|
||||
- **`OnPlaylistChecked`** — глобальный callback, вызывается после проверки каждого плейлиста. Используется веб-сервером для обновления in-memory кеша.
|
||||
- **`cachePlaylist(pls)`** — сохранение результата в Redis (если включён).
|
||||
|
||||
Параметры проверки берутся из `app.Config.Check.Playlists` и `app.Config.Check.Channels`.
|
||||
|
||||
### `app.playlist`
|
||||
|
||||
- **`Playlist`** — плейлист: код, URL, контент, каналы, статус.
|
||||
- **`Channel`** — канал: ID, название, URL, статус, теги.
|
||||
- **`Download(userAgent, timeout)`** — загрузка по URL.
|
||||
- **`ReadFromFs()`** — чтение из файла.
|
||||
- **`Parse()`** — парсинг m3u/m3u8 контента.
|
||||
|
||||
### `app.web`
|
||||
|
||||
Веб-сервер на `net/http` (Go 1.22 routing).
|
||||
|
||||
- **`Server`** — структура: конфиг, кеш, шаблоны, in-memory кеш (`memCache` с `sync.RWMutex`).
|
||||
- **`Start()`** — запуск HTTP-сервера.
|
||||
- **`StartBackgroundChecker(opts)`** — фоновая проверка в отдельной горутине.
|
||||
- **`CheckOptions`** — параметры: Every, Repeat, Random, Files, Urls, Codes.
|
||||
|
||||
Маршруты (Go 1.22 patterns):
|
||||
|
||||
```
|
||||
GET /api/playlists/{code} — JSON плейлиста
|
||||
GET /api/version — версия
|
||||
GET /api/health — здоровье сервиса
|
||||
GET /api/stats — статистика
|
||||
GET /{$} — главная (catch-all root)
|
||||
GET /{path...} — все остальные маршруты (catch-all)
|
||||
```
|
||||
|
||||
Catch-all `/{path...}` используется для избежания конфликтов паттернов в Go 1.22 mux.
|
||||
|
||||
In-memory кеш (`memCache`) обновляется через `OnPlaylistChecked` callback.
|
||||
Это позволяет отображать результаты проверки в реальном времени без ожидания завершения цикла и без Redis.
|
||||
|
||||
ini-файл кешируется на 30 секунд, кеш сбрасывается при каждом обновлении `memCache`.
|
||||
|
||||
## Жизненный цикл `serve --check`
|
||||
|
||||
```
|
||||
main → app.Init() → web.NewServer() → go StartBackgroundChecker() → server.Start()
|
||||
|
||||
StartBackgroundChecker:
|
||||
loop:
|
||||
runCheckerOnce()
|
||||
→ checker.PrepareListsToCheck()
|
||||
→ checker.CheckPlaylists()
|
||||
→ for each playlist (parallel, per-routine):
|
||||
→ Download() / ReadFromFs()
|
||||
→ Parse()
|
||||
→ CheckChannels()
|
||||
→ for each channel (parallel, per-routine):
|
||||
→ HTTP GET with Range header
|
||||
→ check status + content type
|
||||
→ OnPlaylistChecked(pls) → memCache update
|
||||
→ one-cooldown sleep
|
||||
→ all-cooldown sleep
|
||||
sleep(every)
|
||||
if repeat > 0 && iteration >= repeat: stop
|
||||
```
|
||||
|
||||
## CLI-флаги
|
||||
|
||||
### Общие (`cmd/flags.go`)
|
||||
|
||||
Используются командами `check` и `serve --check`:
|
||||
|
||||
| Флаг | Поле | Описание |
|
||||
| -------------------------- | -------------------- | ---------------------------------- |
|
||||
| `-i, --ini` | `Args.IniPath` | Путь к playlists.ini |
|
||||
| `-t, --tags` | `Args.TagsPath` | Путь к channels.json |
|
||||
| `-r, --random` | `Args.RandomCount` | Случайные N плейлистов |
|
||||
| `--repeat` | `Args.RepeatCount` | Количество циклов (0 = бесконечно) |
|
||||
| `--playlists-all-cooldown` | `Args.PlAllCooldown` | Миллисекунд между циклами |
|
||||
|
||||
### Только `check` (`addCheckOnlyFlags`)
|
||||
|
||||
| Флаг | Поле | Описание |
|
||||
| ------------- | ---------------- | ------------------- |
|
||||
| `-j, --json` | `Args.NeedJson` | Вывод в JSON |
|
||||
| `-q, --quiet` | `Args.NeedQuiet` | Подавить логи |
|
||||
| `-f, --file` | `Args.Files` | Локальные m3u файлы |
|
||||
| `-u, --url` | `Args.Urls` | URL плейлистов |
|
||||
| `-c, --code` | `Args.Codes` | Коды из ini-файла |
|
||||
|
||||
### Только `serve`
|
||||
|
||||
| Флаг | Поле | Описание |
|
||||
| ------------ | ----------------- | ------------------------- |
|
||||
| `-p, --port` | `Args.ServerPort` | Порт веб-сервера |
|
||||
| `--host` | `Args.ServerHost` | Хост привязки |
|
||||
| `--check` | `Args.NeedCheck` | Включить фоновую проверку |
|
||||
|
||||
### Глобальные (`cmd/root.go`)
|
||||
|
||||
| Флаг | Поле | Описание |
|
||||
| --------------- | ----------------- | ----------------- |
|
||||
| `--config` | `Args.ConfigPath` | Путь к config.yml |
|
||||
| `-v, --verbose` | `Args.Verbose` | Подробный лог |
|
||||
|
||||
## Конфигурация
|
||||
|
||||
Подробное описание параметров — в разделе [config.yml](../../common/config/config.md).
|
||||
|
||||
Приоритет: Defaults < `config.yml` < Env < CLI-флаги.
|
||||
|
||||
CLI-флаги переопределяют конфигурацию только если переданы явно (`cmd.Flags().Changed()`).
|
||||
Для этого в Cobra используются zero-value defaults (0, "", false), чтобы отличить «не передан» от «передан со значением по умолчанию».
|
||||
|
||||
## Шаблоны
|
||||
|
||||
HTML-шаблоны встроены через `//go:embed`:
|
||||
|
||||
- `base.html` — общий каркас (header, footer);
|
||||
- `list.html` — список плейлистов с пагинацией;
|
||||
- `details.html` — детали плейлиста и список каналов;
|
||||
- `notfound.html` — страница 404.
|
||||
|
||||
SVG-логотипы каналов передаются через `encodeURIComponent` в data-URI для корректной работы с кавычками в HTML.
|
||||
|
||||
При отсутствии `playlists.ini` рендерится пустое состояние с alert-блоком.
|
||||
|
||||
## Кеширование
|
||||
|
||||
Два уровня кеша:
|
||||
|
||||
1. **Redis/KeyDB** (опционально) — постоянный кеш результатов проверки. TTL из `cache.ttl`.
|
||||
2. **In-memory** (`memCache`) — только при `serve --check`. Обновляется в реальном времени через callback. Не требует Redis.
|
||||
|
||||
In-memory кеш приоритетнее Redis при отображении в веб-интерфейсе.
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
title: Компиляция
|
||||
icon: material/cog
|
||||
tags: ["iptvc", "сборка"]
|
||||
---
|
||||
|
||||
# Компиляция из исходного кода
|
||||
|
||||
Для компиляции потребуется [Go](https://go.dev/dl/) 1.23.6 и выше.
|
||||
|
||||
```bash
|
||||
git clone https://git.axenov.dev/IPTV/iptvc.git
|
||||
cd iptvc
|
||||
make linux
|
||||
# или make help для получения справки по рецептам
|
||||
```
|
||||
|
||||
## Доступные рецепты Makefile
|
||||
|
||||
| Команда | Назначение |
|
||||
| --- | --- |
|
||||
| `make linux` | Сборка под Linux (amd64 по умолчанию) |
|
||||
| `make win` | Сборка под Windows |
|
||||
| `make darwin` | Сборка под macOS |
|
||||
| `make release` | Сборка под все платформы (linux/windows/darwin × amd64/arm64) |
|
||||
| `make clean` | Удаление скомпилированных бинарников |
|
||||
| `make help` | Вывод списка доступных рецептов |
|
||||
|
||||
## Управление архитектурой
|
||||
|
||||
Архитектура целевой платформы задаётся переменной `GOARCH`:
|
||||
|
||||
```bash
|
||||
make darwin GOARCH=arm64 # macOS на Apple Silicon
|
||||
make linux GOARCH=arm64 # Linux ARM (Raspberry Pi и т.п.)
|
||||
```
|
||||
|
||||
## Результат
|
||||
|
||||
Скомпилированные бинарники и ZIP-архивы помещаются в директорию `bin/`:
|
||||
|
||||
```
|
||||
bin/
|
||||
├── linux_amd64/iptvc # или linux_arm64/
|
||||
├── linux_amd64.zip
|
||||
├── windows_amd64/iptvc.exe # или windows_arm64/
|
||||
├── windows_amd64.zip
|
||||
├── darwin_amd64/iptvc # или darwin_arm64/
|
||||
└── darwin_amd64.zip
|
||||
```
|
||||
|
||||
## Сборка без Make
|
||||
|
||||
Можно скомпилировать напрямую через `go build`:
|
||||
|
||||
```bash
|
||||
go build -o iptvc .
|
||||
go build -trimpath -ldflags="-s -w" -o iptvc .
|
||||
```
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Docker-образ
|
||||
icon: simple/docker
|
||||
tags: ["iptvc", "docker"]
|
||||
---
|
||||
|
||||
# Построение Docker-образа
|
||||
|
||||
## Сборка
|
||||
|
||||
Образ собирается из [Dockerfile](https://git.axenov.dev/IPTV/iptvc/src/branch/master/Dockerfile) — multi-stage сборка на базе `golang:1.25-alpine` с финальным образом `alpine:3.22`.
|
||||
|
||||
```bash
|
||||
docker build -t iptvc ./iptvc
|
||||
```
|
||||
|
||||
Можно передать версию через build-arg:
|
||||
|
||||
```bash
|
||||
docker build --build-arg IPTVC_VERSION=1.1.3 -t iptvc:v1.1.3 ./iptvc
|
||||
```
|
||||
|
||||
Целевая платформа и архитектура задаются через `GOOS` и `GOARCH`:
|
||||
|
||||
```bash
|
||||
docker build --build-arg GOOS=linux --build-arg GOARCH=arm64 -t iptvc:linux-arm64 ./iptvc
|
||||
```
|
||||
|
||||
## Запуск
|
||||
|
||||
```bash
|
||||
# Проверка плейлистов
|
||||
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 60000
|
||||
|
||||
# Веб-сервер с фоновой проверкой
|
||||
docker run --rm -p 8080:8080 \
|
||||
-v ./playlists.ini:/app/playlists.ini \
|
||||
-v ./channels.json:/app/channels.json \
|
||||
iptvc serve -i playlists.ini -p 8080 --check
|
||||
```
|
||||
|
||||
## Использование в compose
|
||||
|
||||
В `compose.yml` сервиса `checker` образ собирается автоматически:
|
||||
|
||||
```yaml
|
||||
checker:
|
||||
image: git.axenov.dev/iptv/iptvc:latest
|
||||
build:
|
||||
context: ./iptvc
|
||||
dockerfile: Dockerfile
|
||||
command: ["check", "--repeat", "0", "--playlists-all-cooldown", "${CHECK_PLAYLISTS_ALL_COOLDOWN:-60000}"]
|
||||
```
|
||||
|
||||
Подробнее о полном окружении — в разделе [Развёртывание](../site/deploy.md).
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
icon: material/book-cog-outline
|
||||
---
|
||||
|
||||
# :material-book-cog-outline: Сборка документации
|
||||
|
||||
## Стилистика и правила оформления
|
||||
|
||||
Все исходники хранятся в директории `content/` в формате **Markdown** (формат файлов `.md`).
|
||||
|
||||
Структура проекта и его конфигурация описываются в файле `mkdocs.yml` в корне репозитория.
|
||||
|
||||
Структура исходных файлов документации и содержание должны быть согласованными.
|
||||
|
||||
Все ссылки на соседние страницы и изображения должны быть относительными.
|
||||
|
||||
**Каждое предложение должно быть на одной строке.**
|
||||
Это даёт более наглядную разницу (diff) в тексте при работе с git.
|
||||
|
||||
Абзацы и списки должны отделяться 1 пустой строкой до и после.
|
||||
|
||||
Допустимо использовать любые стилистические возможности темы **Material for MkDocs** и самого **mkdocs**, но не следует визуально перегружать текст.
|
||||
Документацию по ним см. по ссылкам ниже.
|
||||
|
||||
## Добавление изображений
|
||||
|
||||
**Все изображения хранятся в директории `_assets/` рядом с документом.**
|
||||
|
||||
Общая суть такова:
|
||||
|
||||
* чем больше размеры, тем хуже должно быть качество;
|
||||
* чем меньше размеры, тем чётче должен быть текст.
|
||||
|
||||
Каждое изображение должно:
|
||||
|
||||
* быть сохранено в формате jpg;
|
||||
* иметь размер неболее 150 Кб;
|
||||
* быть сжатым с качеством 65-80% от исходного;
|
||||
* быть размером до 1500 px по наибольшей стороне.
|
||||
|
||||
Если на изображении есть текст, он должен оставаться различимым и читаемым.
|
||||
|
||||
Но если на изображении есть любые конфиденциальные данные и его невозможно кадрировать без потери смысла, то их необходимо скрыть.
|
||||
|
||||
Хорошей практикой будет использовать спойлеры для скрытия больших и/или идущих подряд нескольких изображений, например:
|
||||
|
||||
```
|
||||
Совершенно любой текст, lorem ipsum dolor sit amet.
|
||||
Совершенно любой текст, lorem ipsum dolor sit amet.
|
||||
|
||||
??? quote "В этом спойлере несколько больших картинок"
|
||||

|
||||

|
||||
|
||||
Продолжение текста, lorem ipsum dolor sit amet.
|
||||
Продолжение текста, lorem ipsum dolor sit amet.
|
||||
```
|
||||
|
||||
Эти простые правила позволят поддерживать репозиторий достаточно компактным, а страницы делать комфортными для чтения, экономя трафик для мобильных устройств.
|
||||
|
||||
## Стек
|
||||
|
||||
* make
|
||||
* [docker](https://docker.com)
|
||||
* [mkdocs](https://www.mkdocs.org/)
|
||||
* [squidfunk/mkdocs-material](https://hub.docker.com/r/squidfunk/mkdocs-material)
|
||||
* <https://squidfunk.github.io/mkdocs-material>
|
||||
* <https://squidfunk.github.io/mkdocs-material/reference/admonitions/>
|
||||
* <https://squidfunk.github.io/mkdocs-material/reference/icons-emojis/>
|
||||
|
||||
## Запуск mkdocs в контейнере
|
||||
|
||||
```
|
||||
make live
|
||||
```
|
||||
|
||||
Перегенерирует документацию на лету сразу после сохранения файлов.
|
||||
|
||||
Документацию в реальном времени можно просматривать по адресу [localhost:3000](http://localhost:3000).
|
||||
|
||||
## Генерация статического сайта
|
||||
|
||||
```
|
||||
make site
|
||||
```
|
||||
|
||||
Генерирует статические файлы, которую можно версионировать, хранить,деплоить отдельно или просматривать на ПК через браузер.
|
||||
|
||||
Готовый скомпилированный статический сайт с документацией находится в директории `site/`.
|
||||
|
||||
## Генерация docker-образа
|
||||
|
||||
```
|
||||
make image
|
||||
```
|
||||
|
||||
Собирает docker-образ на основе nginx, генерируя перед этим статический сайт.
|
||||
|
||||
Запустить контейнер из этого образа по адресу [localhost:3001](http://localhost:3001) можно командой:
|
||||
|
||||
```
|
||||
make run
|
||||
```
|
||||
@@ -0,0 +1,550 @@
|
||||
Информацию о лицензии см. на странице [Свободное ПО](../../../legal/license.md)
|
||||
|
||||
| Иконка | Код для вставки в текст | Код для вставки в frontmatter |
|
||||
| ------------------------------------------------ | -------------------------------------------------- | ------------------------------------------------ |
|
||||
| :vscode-account: | `:vscode-account:` | `vscode/account` |
|
||||
| :vscode-activate-breakpoints: | `:vscode-activate-breakpoints:` | `vscode/activate-breakpoints` |
|
||||
| :vscode-add: | `:vscode-add:` | `vscode/add` |
|
||||
| :vscode-add-small: | `:vscode-add-small:` | `vscode/add-small` |
|
||||
| :vscode-agent: | `:vscode-agent:` | `vscode/agent` |
|
||||
| :vscode-archive: | `:vscode-archive:` | `vscode/archive` |
|
||||
| :vscode-arrow-both: | `:vscode-arrow-both:` | `vscode/arrow-both` |
|
||||
| :vscode-arrow-circle-down: | `:vscode-arrow-circle-down:` | `vscode/arrow-circle-down` |
|
||||
| :vscode-arrow-circle-left: | `:vscode-arrow-circle-left:` | `vscode/arrow-circle-left` |
|
||||
| :vscode-arrow-circle-right: | `:vscode-arrow-circle-right:` | `vscode/arrow-circle-right` |
|
||||
| :vscode-arrow-circle-up: | `:vscode-arrow-circle-up:` | `vscode/arrow-circle-up` |
|
||||
| :vscode-arrow-down: | `:vscode-arrow-down:` | `vscode/arrow-down` |
|
||||
| :vscode-arrow-left: | `:vscode-arrow-left:` | `vscode/arrow-left` |
|
||||
| :vscode-arrow-right: | `:vscode-arrow-right:` | `vscode/arrow-right` |
|
||||
| :vscode-arrow-small-down: | `:vscode-arrow-small-down:` | `vscode/arrow-small-down` |
|
||||
| :vscode-arrow-small-left: | `:vscode-arrow-small-left:` | `vscode/arrow-small-left` |
|
||||
| :vscode-arrow-small-right: | `:vscode-arrow-small-right:` | `vscode/arrow-small-right` |
|
||||
| :vscode-arrow-small-up: | `:vscode-arrow-small-up:` | `vscode/arrow-small-up` |
|
||||
| :vscode-arrow-swap: | `:vscode-arrow-swap:` | `vscode/arrow-swap` |
|
||||
| :vscode-arrow-up: | `:vscode-arrow-up:` | `vscode/arrow-up` |
|
||||
| :vscode-ask: | `:vscode-ask:` | `vscode/ask` |
|
||||
| :vscode-attach: | `:vscode-attach:` | `vscode/attach` |
|
||||
| :vscode-azure: | `:vscode-azure:` | `vscode/azure` |
|
||||
| :vscode-azure-devops: | `:vscode-azure-devops:` | `vscode/azure-devops` |
|
||||
| :vscode-beaker: | `:vscode-beaker:` | `vscode/beaker` |
|
||||
| :vscode-beaker-stop: | `:vscode-beaker-stop:` | `vscode/beaker-stop` |
|
||||
| :vscode-bell: | `:vscode-bell:` | `vscode/bell` |
|
||||
| :vscode-bell-dot: | `:vscode-bell-dot:` | `vscode/bell-dot` |
|
||||
| :vscode-bell-slash: | `:vscode-bell-slash:` | `vscode/bell-slash` |
|
||||
| :vscode-bell-slash-dot: | `:vscode-bell-slash-dot:` | `vscode/bell-slash-dot` |
|
||||
| :vscode-blank: | `:vscode-blank:` | `vscode/blank` |
|
||||
| :vscode-bold: | `:vscode-bold:` | `vscode/bold` |
|
||||
| :vscode-book: | `:vscode-book:` | `vscode/book` |
|
||||
| :vscode-bookmark: | `:vscode-bookmark:` | `vscode/bookmark` |
|
||||
| :vscode-bracket-dot: | `:vscode-bracket-dot:` | `vscode/bracket-dot` |
|
||||
| :vscode-bracket-error: | `:vscode-bracket-error:` | `vscode/bracket-error` |
|
||||
| :vscode-briefcase: | `:vscode-briefcase:` | `vscode/briefcase` |
|
||||
| :vscode-broadcast: | `:vscode-broadcast:` | `vscode/broadcast` |
|
||||
| :vscode-browser: | `:vscode-browser:` | `vscode/browser` |
|
||||
| :vscode-bug: | `:vscode-bug:` | `vscode/bug` |
|
||||
| :vscode-build: | `:vscode-build:` | `vscode/build` |
|
||||
| :vscode-calendar: | `:vscode-calendar:` | `vscode/calendar` |
|
||||
| :vscode-call-incoming: | `:vscode-call-incoming:` | `vscode/call-incoming` |
|
||||
| :vscode-call-outgoing: | `:vscode-call-outgoing:` | `vscode/call-outgoing` |
|
||||
| :vscode-case-sensitive: | `:vscode-case-sensitive:` | `vscode/case-sensitive` |
|
||||
| :vscode-chat-export: | `:vscode-chat-export:` | `vscode/chat-export` |
|
||||
| :vscode-chat-import: | `:vscode-chat-import:` | `vscode/chat-import` |
|
||||
| :vscode-chat-sparkle: | `:vscode-chat-sparkle:` | `vscode/chat-sparkle` |
|
||||
| :vscode-chat-sparkle-error: | `:vscode-chat-sparkle-error:` | `vscode/chat-sparkle-error` |
|
||||
| :vscode-chat-sparkle-warning: | `:vscode-chat-sparkle-warning:` | `vscode/chat-sparkle-warning` |
|
||||
| :vscode-check: | `:vscode-check:` | `vscode/check` |
|
||||
| :vscode-check-all: | `:vscode-check-all:` | `vscode/check-all` |
|
||||
| :vscode-checklist: | `:vscode-checklist:` | `vscode/checklist` |
|
||||
| :vscode-chevron-down: | `:vscode-chevron-down:` | `vscode/chevron-down` |
|
||||
| :vscode-chevron-left: | `:vscode-chevron-left:` | `vscode/chevron-left` |
|
||||
| :vscode-chevron-right: | `:vscode-chevron-right:` | `vscode/chevron-right` |
|
||||
| :vscode-chevron-up: | `:vscode-chevron-up:` | `vscode/chevron-up` |
|
||||
| :vscode-chip: | `:vscode-chip:` | `vscode/chip` |
|
||||
| :vscode-chrome-close: | `:vscode-chrome-close:` | `vscode/chrome-close` |
|
||||
| :vscode-chrome-maximize: | `:vscode-chrome-maximize:` | `vscode/chrome-maximize` |
|
||||
| :vscode-chrome-minimize: | `:vscode-chrome-minimize:` | `vscode/chrome-minimize` |
|
||||
| :vscode-chrome-restore: | `:vscode-chrome-restore:` | `vscode/chrome-restore` |
|
||||
| :vscode-circle: | `:vscode-circle:` | `vscode/circle` |
|
||||
| :vscode-circle-filled: | `:vscode-circle-filled:` | `vscode/circle-filled` |
|
||||
| :vscode-circle-large: | `:vscode-circle-large:` | `vscode/circle-large` |
|
||||
| :vscode-circle-large-filled: | `:vscode-circle-large-filled:` | `vscode/circle-large-filled` |
|
||||
| :vscode-circle-slash: | `:vscode-circle-slash:` | `vscode/circle-slash` |
|
||||
| :vscode-circle-small: | `:vscode-circle-small:` | `vscode/circle-small` |
|
||||
| :vscode-circle-small-filled: | `:vscode-circle-small-filled:` | `vscode/circle-small-filled` |
|
||||
| :vscode-circuit-board: | `:vscode-circuit-board:` | `vscode/circuit-board` |
|
||||
| :vscode-claude: | `:vscode-claude:` | `vscode/claude` |
|
||||
| :vscode-clear-all: | `:vscode-clear-all:` | `vscode/clear-all` |
|
||||
| :vscode-clippy: | `:vscode-clippy:` | `vscode/clippy` |
|
||||
| :vscode-clockface: | `:vscode-clockface:` | `vscode/clockface` |
|
||||
| :vscode-close: | `:vscode-close:` | `vscode/close` |
|
||||
| :vscode-close-all: | `:vscode-close-all:` | `vscode/close-all` |
|
||||
| :vscode-cloud: | `:vscode-cloud:` | `vscode/cloud` |
|
||||
| :vscode-cloud-download: | `:vscode-cloud-download:` | `vscode/cloud-download` |
|
||||
| :vscode-cloud-small: | `:vscode-cloud-small:` | `vscode/cloud-small` |
|
||||
| :vscode-cloud-upload: | `:vscode-cloud-upload:` | `vscode/cloud-upload` |
|
||||
| :vscode-code: | `:vscode-code:` | `vscode/code` |
|
||||
| :vscode-code-oss: | `:vscode-code-oss:` | `vscode/code-oss` |
|
||||
| :vscode-code-review: | `:vscode-code-review:` | `vscode/code-review` |
|
||||
| :vscode-coffee: | `:vscode-coffee:` | `vscode/coffee` |
|
||||
| :vscode-collapse-all: | `:vscode-collapse-all:` | `vscode/collapse-all` |
|
||||
| :vscode-collection: | `:vscode-collection:` | `vscode/collection` |
|
||||
| :vscode-collection-small: | `:vscode-collection-small:` | `vscode/collection-small` |
|
||||
| :vscode-color-mode: | `:vscode-color-mode:` | `vscode/color-mode` |
|
||||
| :vscode-combine: | `:vscode-combine:` | `vscode/combine` |
|
||||
| :vscode-comment: | `:vscode-comment:` | `vscode/comment` |
|
||||
| :vscode-comment-discussion: | `:vscode-comment-discussion:` | `vscode/comment-discussion` |
|
||||
| :vscode-comment-discussion-quote: | `:vscode-comment-discussion-quote:` | `vscode/comment-discussion-quote` |
|
||||
| :vscode-comment-discussion-sparkle: | `:vscode-comment-discussion-sparkle:` | `vscode/comment-discussion-sparkle` |
|
||||
| :vscode-comment-draft: | `:vscode-comment-draft:` | `vscode/comment-draft` |
|
||||
| :vscode-comment-unresolved: | `:vscode-comment-unresolved:` | `vscode/comment-unresolved` |
|
||||
| :vscode-compass: | `:vscode-compass:` | `vscode/compass` |
|
||||
| :vscode-compass-active: | `:vscode-compass-active:` | `vscode/compass-active` |
|
||||
| :vscode-compass-dot: | `:vscode-compass-dot:` | `vscode/compass-dot` |
|
||||
| :vscode-copilot: | `:vscode-copilot:` | `vscode/copilot` |
|
||||
| :vscode-copilot-blocked: | `:vscode-copilot-blocked:` | `vscode/copilot-blocked` |
|
||||
| :vscode-copilot-error: | `:vscode-copilot-error:` | `vscode/copilot-error` |
|
||||
| :vscode-copilot-in-progress: | `:vscode-copilot-in-progress:` | `vscode/copilot-in-progress` |
|
||||
| :vscode-copilot-large: | `:vscode-copilot-large:` | `vscode/copilot-large` |
|
||||
| :vscode-copilot-not-connected: | `:vscode-copilot-not-connected:` | `vscode/copilot-not-connected` |
|
||||
| :vscode-copilot-snooze: | `:vscode-copilot-snooze:` | `vscode/copilot-snooze` |
|
||||
| :vscode-copilot-success: | `:vscode-copilot-success:` | `vscode/copilot-success` |
|
||||
| :vscode-copilot-unavailable: | `:vscode-copilot-unavailable:` | `vscode/copilot-unavailable` |
|
||||
| :vscode-copilot-warning: | `:vscode-copilot-warning:` | `vscode/copilot-warning` |
|
||||
| :vscode-copilot-warning-large: | `:vscode-copilot-warning-large:` | `vscode/copilot-warning-large` |
|
||||
| :vscode-copy: | `:vscode-copy:` | `vscode/copy` |
|
||||
| :vscode-coverage: | `:vscode-coverage:` | `vscode/coverage` |
|
||||
| :vscode-credit-card: | `:vscode-credit-card:` | `vscode/credit-card` |
|
||||
| :vscode-cursor: | `:vscode-cursor:` | `vscode/cursor` |
|
||||
| :vscode-dash: | `:vscode-dash:` | `vscode/dash` |
|
||||
| :vscode-dashboard: | `:vscode-dashboard:` | `vscode/dashboard` |
|
||||
| :vscode-database: | `:vscode-database:` | `vscode/database` |
|
||||
| :vscode-debug: | `:vscode-debug:` | `vscode/debug` |
|
||||
| :vscode-debug-all: | `:vscode-debug-all:` | `vscode/debug-all` |
|
||||
| :vscode-debug-alt: | `:vscode-debug-alt:` | `vscode/debug-alt` |
|
||||
| :vscode-debug-alt-small: | `:vscode-debug-alt-small:` | `vscode/debug-alt-small` |
|
||||
| :vscode-debug-breakpoint-conditional: | `:vscode-debug-breakpoint-conditional:` | `vscode/debug-breakpoint-conditional` |
|
||||
| :vscode-debug-breakpoint-conditional-unverified: | `:vscode-debug-breakpoint-conditional-unverified:` | `vscode/debug-breakpoint-conditional-unverified` |
|
||||
| :vscode-debug-breakpoint-data: | `:vscode-debug-breakpoint-data:` | `vscode/debug-breakpoint-data` |
|
||||
| :vscode-debug-breakpoint-data-unverified: | `:vscode-debug-breakpoint-data-unverified:` | `vscode/debug-breakpoint-data-unverified` |
|
||||
| :vscode-debug-breakpoint-function: | `:vscode-debug-breakpoint-function:` | `vscode/debug-breakpoint-function` |
|
||||
| :vscode-debug-breakpoint-function-unverified: | `:vscode-debug-breakpoint-function-unverified:` | `vscode/debug-breakpoint-function-unverified` |
|
||||
| :vscode-debug-breakpoint-log: | `:vscode-debug-breakpoint-log:` | `vscode/debug-breakpoint-log` |
|
||||
| :vscode-debug-breakpoint-log-unverified: | `:vscode-debug-breakpoint-log-unverified:` | `vscode/debug-breakpoint-log-unverified` |
|
||||
| :vscode-debug-breakpoint-unsupported: | `:vscode-debug-breakpoint-unsupported:` | `vscode/debug-breakpoint-unsupported` |
|
||||
| :vscode-debug-connected: | `:vscode-debug-connected:` | `vscode/debug-connected` |
|
||||
| :vscode-debug-console: | `:vscode-debug-console:` | `vscode/debug-console` |
|
||||
| :vscode-debug-continue: | `:vscode-debug-continue:` | `vscode/debug-continue` |
|
||||
| :vscode-debug-continue-small: | `:vscode-debug-continue-small:` | `vscode/debug-continue-small` |
|
||||
| :vscode-debug-coverage: | `:vscode-debug-coverage:` | `vscode/debug-coverage` |
|
||||
| :vscode-debug-disconnect: | `:vscode-debug-disconnect:` | `vscode/debug-disconnect` |
|
||||
| :vscode-debug-line-by-line: | `:vscode-debug-line-by-line:` | `vscode/debug-line-by-line` |
|
||||
| :vscode-debug-pause: | `:vscode-debug-pause:` | `vscode/debug-pause` |
|
||||
| :vscode-debug-rerun: | `:vscode-debug-rerun:` | `vscode/debug-rerun` |
|
||||
| :vscode-debug-restart: | `:vscode-debug-restart:` | `vscode/debug-restart` |
|
||||
| :vscode-debug-restart-frame: | `:vscode-debug-restart-frame:` | `vscode/debug-restart-frame` |
|
||||
| :vscode-debug-reverse-continue: | `:vscode-debug-reverse-continue:` | `vscode/debug-reverse-continue` |
|
||||
| :vscode-debug-stackframe: | `:vscode-debug-stackframe:` | `vscode/debug-stackframe` |
|
||||
| :vscode-debug-stackframe-active: | `:vscode-debug-stackframe-active:` | `vscode/debug-stackframe-active` |
|
||||
| :vscode-debug-start: | `:vscode-debug-start:` | `vscode/debug-start` |
|
||||
| :vscode-debug-step-back: | `:vscode-debug-step-back:` | `vscode/debug-step-back` |
|
||||
| :vscode-debug-step-into: | `:vscode-debug-step-into:` | `vscode/debug-step-into` |
|
||||
| :vscode-debug-step-out: | `:vscode-debug-step-out:` | `vscode/debug-step-out` |
|
||||
| :vscode-debug-step-over: | `:vscode-debug-step-over:` | `vscode/debug-step-over` |
|
||||
| :vscode-debug-stop: | `:vscode-debug-stop:` | `vscode/debug-stop` |
|
||||
| :vscode-desktop-download: | `:vscode-desktop-download:` | `vscode/desktop-download` |
|
||||
| :vscode-device-camera: | `:vscode-device-camera:` | `vscode/device-camera` |
|
||||
| :vscode-device-camera-video: | `:vscode-device-camera-video:` | `vscode/device-camera-video` |
|
||||
| :vscode-device-mobile: | `:vscode-device-mobile:` | `vscode/device-mobile` |
|
||||
| :vscode-diff: | `:vscode-diff:` | `vscode/diff` |
|
||||
| :vscode-diff-added: | `:vscode-diff-added:` | `vscode/diff-added` |
|
||||
| :vscode-diff-ignored: | `:vscode-diff-ignored:` | `vscode/diff-ignored` |
|
||||
| :vscode-diff-modified: | `:vscode-diff-modified:` | `vscode/diff-modified` |
|
||||
| :vscode-diff-multiple: | `:vscode-diff-multiple:` | `vscode/diff-multiple` |
|
||||
| :vscode-diff-removed: | `:vscode-diff-removed:` | `vscode/diff-removed` |
|
||||
| :vscode-diff-renamed: | `:vscode-diff-renamed:` | `vscode/diff-renamed` |
|
||||
| :vscode-diff-single: | `:vscode-diff-single:` | `vscode/diff-single` |
|
||||
| :vscode-discard: | `:vscode-discard:` | `vscode/discard` |
|
||||
| :vscode-download: | `:vscode-download:` | `vscode/download` |
|
||||
| :vscode-edit: | `:vscode-edit:` | `vscode/edit` |
|
||||
| :vscode-edit-code: | `:vscode-edit-code:` | `vscode/edit-code` |
|
||||
| :vscode-edit-session: | `:vscode-edit-session:` | `vscode/edit-session` |
|
||||
| :vscode-edit-sparkle: | `:vscode-edit-sparkle:` | `vscode/edit-sparkle` |
|
||||
| :vscode-editor-layout: | `:vscode-editor-layout:` | `vscode/editor-layout` |
|
||||
| :vscode-ellipsis: | `:vscode-ellipsis:` | `vscode/ellipsis` |
|
||||
| :vscode-empty-window: | `:vscode-empty-window:` | `vscode/empty-window` |
|
||||
| :vscode-eraser: | `:vscode-eraser:` | `vscode/eraser` |
|
||||
| :vscode-error: | `:vscode-error:` | `vscode/error` |
|
||||
| :vscode-error-small: | `:vscode-error-small:` | `vscode/error-small` |
|
||||
| :vscode-exclude: | `:vscode-exclude:` | `vscode/exclude` |
|
||||
| :vscode-expand-all: | `:vscode-expand-all:` | `vscode/expand-all` |
|
||||
| :vscode-export: | `:vscode-export:` | `vscode/export` |
|
||||
| :vscode-extensions: | `:vscode-extensions:` | `vscode/extensions` |
|
||||
| :vscode-extensions-large: | `:vscode-extensions-large:` | `vscode/extensions-large` |
|
||||
| :vscode-eye: | `:vscode-eye:` | `vscode/eye` |
|
||||
| :vscode-eye-closed: | `:vscode-eye-closed:` | `vscode/eye-closed` |
|
||||
| :vscode-feedback: | `:vscode-feedback:` | `vscode/feedback` |
|
||||
| :vscode-file: | `:vscode-file:` | `vscode/file` |
|
||||
| :vscode-file-binary: | `:vscode-file-binary:` | `vscode/file-binary` |
|
||||
| :vscode-file-code: | `:vscode-file-code:` | `vscode/file-code` |
|
||||
| :vscode-file-media: | `:vscode-file-media:` | `vscode/file-media` |
|
||||
| :vscode-file-pdf: | `:vscode-file-pdf:` | `vscode/file-pdf` |
|
||||
| :vscode-file-submodule: | `:vscode-file-submodule:` | `vscode/file-submodule` |
|
||||
| :vscode-file-symlink-directory: | `:vscode-file-symlink-directory:` | `vscode/file-symlink-directory` |
|
||||
| :vscode-file-symlink-file: | `:vscode-file-symlink-file:` | `vscode/file-symlink-file` |
|
||||
| :vscode-file-text: | `:vscode-file-text:` | `vscode/file-text` |
|
||||
| :vscode-file-zip: | `:vscode-file-zip:` | `vscode/file-zip` |
|
||||
| :vscode-files: | `:vscode-files:` | `vscode/files` |
|
||||
| :vscode-filter: | `:vscode-filter:` | `vscode/filter` |
|
||||
| :vscode-filter-filled: | `:vscode-filter-filled:` | `vscode/filter-filled` |
|
||||
| :vscode-flag: | `:vscode-flag:` | `vscode/flag` |
|
||||
| :vscode-flame: | `:vscode-flame:` | `vscode/flame` |
|
||||
| :vscode-fold: | `:vscode-fold:` | `vscode/fold` |
|
||||
| :vscode-fold-down: | `:vscode-fold-down:` | `vscode/fold-down` |
|
||||
| :vscode-fold-up: | `:vscode-fold-up:` | `vscode/fold-up` |
|
||||
| :vscode-folder: | `:vscode-folder:` | `vscode/folder` |
|
||||
| :vscode-folder-active: | `:vscode-folder-active:` | `vscode/folder-active` |
|
||||
| :vscode-folder-library: | `:vscode-folder-library:` | `vscode/folder-library` |
|
||||
| :vscode-folder-opened: | `:vscode-folder-opened:` | `vscode/folder-opened` |
|
||||
| :vscode-forward: | `:vscode-forward:` | `vscode/forward` |
|
||||
| :vscode-game: | `:vscode-game:` | `vscode/game` |
|
||||
| :vscode-gear: | `:vscode-gear:` | `vscode/gear` |
|
||||
| :vscode-gift: | `:vscode-gift:` | `vscode/gift` |
|
||||
| :vscode-gist: | `:vscode-gist:` | `vscode/gist` |
|
||||
| :vscode-gist-secret: | `:vscode-gist-secret:` | `vscode/gist-secret` |
|
||||
| :vscode-git-branch: | `:vscode-git-branch:` | `vscode/git-branch` |
|
||||
| :vscode-git-branch-changes: | `:vscode-git-branch-changes:` | `vscode/git-branch-changes` |
|
||||
| :vscode-git-branch-conflicts: | `:vscode-git-branch-conflicts:` | `vscode/git-branch-conflicts` |
|
||||
| :vscode-git-branch-staged-changes: | `:vscode-git-branch-staged-changes:` | `vscode/git-branch-staged-changes` |
|
||||
| :vscode-git-commit: | `:vscode-git-commit:` | `vscode/git-commit` |
|
||||
| :vscode-git-compare: | `:vscode-git-compare:` | `vscode/git-compare` |
|
||||
| :vscode-git-fetch: | `:vscode-git-fetch:` | `vscode/git-fetch` |
|
||||
| :vscode-git-merge: | `:vscode-git-merge:` | `vscode/git-merge` |
|
||||
| :vscode-git-pull-request: | `:vscode-git-pull-request:` | `vscode/git-pull-request` |
|
||||
| :vscode-git-pull-request-closed: | `:vscode-git-pull-request-closed:` | `vscode/git-pull-request-closed` |
|
||||
| :vscode-git-pull-request-create: | `:vscode-git-pull-request-create:` | `vscode/git-pull-request-create` |
|
||||
| :vscode-git-pull-request-done: | `:vscode-git-pull-request-done:` | `vscode/git-pull-request-done` |
|
||||
| :vscode-git-pull-request-draft: | `:vscode-git-pull-request-draft:` | `vscode/git-pull-request-draft` |
|
||||
| :vscode-git-pull-request-go-to-changes: | `:vscode-git-pull-request-go-to-changes:` | `vscode/git-pull-request-go-to-changes` |
|
||||
| :vscode-git-pull-request-new-changes: | `:vscode-git-pull-request-new-changes:` | `vscode/git-pull-request-new-changes` |
|
||||
| :vscode-git-stash: | `:vscode-git-stash:` | `vscode/git-stash` |
|
||||
| :vscode-git-stash-apply: | `:vscode-git-stash-apply:` | `vscode/git-stash-apply` |
|
||||
| :vscode-git-stash-pop: | `:vscode-git-stash-pop:` | `vscode/git-stash-pop` |
|
||||
| :vscode-github: | `:vscode-github:` | `vscode/github` |
|
||||
| :vscode-github-action: | `:vscode-github-action:` | `vscode/github-action` |
|
||||
| :vscode-github-alt: | `:vscode-github-alt:` | `vscode/github-alt` |
|
||||
| :vscode-github-inverted: | `:vscode-github-inverted:` | `vscode/github-inverted` |
|
||||
| :vscode-github-project: | `:vscode-github-project:` | `vscode/github-project` |
|
||||
| :vscode-globe: | `:vscode-globe:` | `vscode/globe` |
|
||||
| :vscode-go-to-editing-session: | `:vscode-go-to-editing-session:` | `vscode/go-to-editing-session` |
|
||||
| :vscode-go-to-file: | `:vscode-go-to-file:` | `vscode/go-to-file` |
|
||||
| :vscode-go-to-search: | `:vscode-go-to-search:` | `vscode/go-to-search` |
|
||||
| :vscode-grabber: | `:vscode-grabber:` | `vscode/grabber` |
|
||||
| :vscode-graph: | `:vscode-graph:` | `vscode/graph` |
|
||||
| :vscode-graph-left: | `:vscode-graph-left:` | `vscode/graph-left` |
|
||||
| :vscode-graph-line: | `:vscode-graph-line:` | `vscode/graph-line` |
|
||||
| :vscode-graph-scatter: | `:vscode-graph-scatter:` | `vscode/graph-scatter` |
|
||||
| :vscode-gripper: | `:vscode-gripper:` | `vscode/gripper` |
|
||||
| :vscode-group-by-ref-type: | `:vscode-group-by-ref-type:` | `vscode/group-by-ref-type` |
|
||||
| :vscode-heart: | `:vscode-heart:` | `vscode/heart` |
|
||||
| :vscode-heart-filled: | `:vscode-heart-filled:` | `vscode/heart-filled` |
|
||||
| :vscode-history: | `:vscode-history:` | `vscode/history` |
|
||||
| :vscode-home: | `:vscode-home:` | `vscode/home` |
|
||||
| :vscode-horizontal-rule: | `:vscode-horizontal-rule:` | `vscode/horizontal-rule` |
|
||||
| :vscode-hubot: | `:vscode-hubot:` | `vscode/hubot` |
|
||||
| :vscode-inbox: | `:vscode-inbox:` | `vscode/inbox` |
|
||||
| :vscode-indent: | `:vscode-indent:` | `vscode/indent` |
|
||||
| :vscode-index-zero: | `:vscode-index-zero:` | `vscode/index-zero` |
|
||||
| :vscode-info: | `:vscode-info:` | `vscode/info` |
|
||||
| :vscode-insert: | `:vscode-insert:` | `vscode/insert` |
|
||||
| :vscode-inspect: | `:vscode-inspect:` | `vscode/inspect` |
|
||||
| :vscode-issue-draft: | `:vscode-issue-draft:` | `vscode/issue-draft` |
|
||||
| :vscode-issue-reopened: | `:vscode-issue-reopened:` | `vscode/issue-reopened` |
|
||||
| :vscode-issues: | `:vscode-issues:` | `vscode/issues` |
|
||||
| :vscode-italic: | `:vscode-italic:` | `vscode/italic` |
|
||||
| :vscode-jersey: | `:vscode-jersey:` | `vscode/jersey` |
|
||||
| :vscode-json: | `:vscode-json:` | `vscode/json` |
|
||||
| :vscode-kebab-vertical: | `:vscode-kebab-vertical:` | `vscode/kebab-vertical` |
|
||||
| :vscode-key: | `:vscode-key:` | `vscode/key` |
|
||||
| :vscode-keyboard-tab: | `:vscode-keyboard-tab:` | `vscode/keyboard-tab` |
|
||||
| :vscode-keyboard-tab-above: | `:vscode-keyboard-tab-above:` | `vscode/keyboard-tab-above` |
|
||||
| :vscode-keyboard-tab-below: | `:vscode-keyboard-tab-below:` | `vscode/keyboard-tab-below` |
|
||||
| :vscode-law: | `:vscode-law:` | `vscode/law` |
|
||||
| :vscode-layers: | `:vscode-layers:` | `vscode/layers` |
|
||||
| :vscode-layers-active: | `:vscode-layers-active:` | `vscode/layers-active` |
|
||||
| :vscode-layers-dot: | `:vscode-layers-dot:` | `vscode/layers-dot` |
|
||||
| :vscode-layout: | `:vscode-layout:` | `vscode/layout` |
|
||||
| :vscode-layout-activitybar-left: | `:vscode-layout-activitybar-left:` | `vscode/layout-activitybar-left` |
|
||||
| :vscode-layout-activitybar-right: | `:vscode-layout-activitybar-right:` | `vscode/layout-activitybar-right` |
|
||||
| :vscode-layout-centered: | `:vscode-layout-centered:` | `vscode/layout-centered` |
|
||||
| :vscode-layout-menubar: | `:vscode-layout-menubar:` | `vscode/layout-menubar` |
|
||||
| :vscode-layout-panel: | `:vscode-layout-panel:` | `vscode/layout-panel` |
|
||||
| :vscode-layout-panel-center: | `:vscode-layout-panel-center:` | `vscode/layout-panel-center` |
|
||||
| :vscode-layout-panel-dock: | `:vscode-layout-panel-dock:` | `vscode/layout-panel-dock` |
|
||||
| :vscode-layout-panel-justify: | `:vscode-layout-panel-justify:` | `vscode/layout-panel-justify` |
|
||||
| :vscode-layout-panel-left: | `:vscode-layout-panel-left:` | `vscode/layout-panel-left` |
|
||||
| :vscode-layout-panel-off: | `:vscode-layout-panel-off:` | `vscode/layout-panel-off` |
|
||||
| :vscode-layout-panel-right: | `:vscode-layout-panel-right:` | `vscode/layout-panel-right` |
|
||||
| :vscode-layout-sidebar-left: | `:vscode-layout-sidebar-left:` | `vscode/layout-sidebar-left` |
|
||||
| :vscode-layout-sidebar-left-dock: | `:vscode-layout-sidebar-left-dock:` | `vscode/layout-sidebar-left-dock` |
|
||||
| :vscode-layout-sidebar-left-off: | `:vscode-layout-sidebar-left-off:` | `vscode/layout-sidebar-left-off` |
|
||||
| :vscode-layout-sidebar-right: | `:vscode-layout-sidebar-right:` | `vscode/layout-sidebar-right` |
|
||||
| :vscode-layout-sidebar-right-dock: | `:vscode-layout-sidebar-right-dock:` | `vscode/layout-sidebar-right-dock` |
|
||||
| :vscode-layout-sidebar-right-off: | `:vscode-layout-sidebar-right-off:` | `vscode/layout-sidebar-right-off` |
|
||||
| :vscode-layout-statusbar: | `:vscode-layout-statusbar:` | `vscode/layout-statusbar` |
|
||||
| :vscode-library: | `:vscode-library:` | `vscode/library` |
|
||||
| :vscode-lightbulb: | `:vscode-lightbulb:` | `vscode/lightbulb` |
|
||||
| :vscode-lightbulb-autofix: | `:vscode-lightbulb-autofix:` | `vscode/lightbulb-autofix` |
|
||||
| :vscode-lightbulb-empty: | `:vscode-lightbulb-empty:` | `vscode/lightbulb-empty` |
|
||||
| :vscode-lightbulb-sparkle: | `:vscode-lightbulb-sparkle:` | `vscode/lightbulb-sparkle` |
|
||||
| :vscode-link: | `:vscode-link:` | `vscode/link` |
|
||||
| :vscode-link-external: | `:vscode-link-external:` | `vscode/link-external` |
|
||||
| :vscode-list-filter: | `:vscode-list-filter:` | `vscode/list-filter` |
|
||||
| :vscode-list-flat: | `:vscode-list-flat:` | `vscode/list-flat` |
|
||||
| :vscode-list-ordered: | `:vscode-list-ordered:` | `vscode/list-ordered` |
|
||||
| :vscode-list-selection: | `:vscode-list-selection:` | `vscode/list-selection` |
|
||||
| :vscode-list-tree: | `:vscode-list-tree:` | `vscode/list-tree` |
|
||||
| :vscode-list-unordered: | `:vscode-list-unordered:` | `vscode/list-unordered` |
|
||||
| :vscode-live-share: | `:vscode-live-share:` | `vscode/live-share` |
|
||||
| :vscode-loading: | `:vscode-loading:` | `vscode/loading` |
|
||||
| :vscode-location: | `:vscode-location:` | `vscode/location` |
|
||||
| :vscode-lock: | `:vscode-lock:` | `vscode/lock` |
|
||||
| :vscode-lock-small: | `:vscode-lock-small:` | `vscode/lock-small` |
|
||||
| :vscode-magnet: | `:vscode-magnet:` | `vscode/magnet` |
|
||||
| :vscode-mail: | `:vscode-mail:` | `vscode/mail` |
|
||||
| :vscode-mail-read: | `:vscode-mail-read:` | `vscode/mail-read` |
|
||||
| :vscode-map: | `:vscode-map:` | `vscode/map` |
|
||||
| :vscode-map-filled: | `:vscode-map-filled:` | `vscode/map-filled` |
|
||||
| :vscode-map-vertical: | `:vscode-map-vertical:` | `vscode/map-vertical` |
|
||||
| :vscode-map-vertical-filled: | `:vscode-map-vertical-filled:` | `vscode/map-vertical-filled` |
|
||||
| :vscode-markdown: | `:vscode-markdown:` | `vscode/markdown` |
|
||||
| :vscode-mcp: | `:vscode-mcp:` | `vscode/mcp` |
|
||||
| :vscode-megaphone: | `:vscode-megaphone:` | `vscode/megaphone` |
|
||||
| :vscode-mention: | `:vscode-mention:` | `vscode/mention` |
|
||||
| :vscode-menu: | `:vscode-menu:` | `vscode/menu` |
|
||||
| :vscode-merge: | `:vscode-merge:` | `vscode/merge` |
|
||||
| :vscode-merge-into: | `:vscode-merge-into:` | `vscode/merge-into` |
|
||||
| :vscode-mic: | `:vscode-mic:` | `vscode/mic` |
|
||||
| :vscode-mic-filled: | `:vscode-mic-filled:` | `vscode/mic-filled` |
|
||||
| :vscode-milestone: | `:vscode-milestone:` | `vscode/milestone` |
|
||||
| :vscode-mirror: | `:vscode-mirror:` | `vscode/mirror` |
|
||||
| :vscode-mortar-board: | `:vscode-mortar-board:` | `vscode/mortar-board` |
|
||||
| :vscode-move: | `:vscode-move:` | `vscode/move` |
|
||||
| :vscode-multiple-windows: | `:vscode-multiple-windows:` | `vscode/multiple-windows` |
|
||||
| :vscode-music: | `:vscode-music:` | `vscode/music` |
|
||||
| :vscode-mute: | `:vscode-mute:` | `vscode/mute` |
|
||||
| :vscode-new-collection: | `:vscode-new-collection:` | `vscode/new-collection` |
|
||||
| :vscode-new-file: | `:vscode-new-file:` | `vscode/new-file` |
|
||||
| :vscode-new-folder: | `:vscode-new-folder:` | `vscode/new-folder` |
|
||||
| :vscode-new-session: | `:vscode-new-session:` | `vscode/new-session` |
|
||||
| :vscode-newline: | `:vscode-newline:` | `vscode/newline` |
|
||||
| :vscode-no-newline: | `:vscode-no-newline:` | `vscode/no-newline` |
|
||||
| :vscode-note: | `:vscode-note:` | `vscode/note` |
|
||||
| :vscode-notebook: | `:vscode-notebook:` | `vscode/notebook` |
|
||||
| :vscode-notebook-template: | `:vscode-notebook-template:` | `vscode/notebook-template` |
|
||||
| :vscode-octoface: | `:vscode-octoface:` | `vscode/octoface` |
|
||||
| :vscode-open-in-product: | `:vscode-open-in-product:` | `vscode/open-in-product` |
|
||||
| :vscode-open-in-window: | `:vscode-open-in-window:` | `vscode/open-in-window` |
|
||||
| :vscode-open-preview: | `:vscode-open-preview:` | `vscode/open-preview` |
|
||||
| :vscode-openai: | `:vscode-openai:` | `vscode/openai` |
|
||||
| :vscode-organization: | `:vscode-organization:` | `vscode/organization` |
|
||||
| :vscode-output: | `:vscode-output:` | `vscode/output` |
|
||||
| :vscode-package: | `:vscode-package:` | `vscode/package` |
|
||||
| :vscode-paintcan: | `:vscode-paintcan:` | `vscode/paintcan` |
|
||||
| :vscode-pass: | `:vscode-pass:` | `vscode/pass` |
|
||||
| :vscode-pass-filled: | `:vscode-pass-filled:` | `vscode/pass-filled` |
|
||||
| :vscode-percentage: | `:vscode-percentage:` | `vscode/percentage` |
|
||||
| :vscode-person: | `:vscode-person:` | `vscode/person` |
|
||||
| :vscode-person-add: | `:vscode-person-add:` | `vscode/person-add` |
|
||||
| :vscode-piano: | `:vscode-piano:` | `vscode/piano` |
|
||||
| :vscode-pie-chart: | `:vscode-pie-chart:` | `vscode/pie-chart` |
|
||||
| :vscode-pin: | `:vscode-pin:` | `vscode/pin` |
|
||||
| :vscode-pinned: | `:vscode-pinned:` | `vscode/pinned` |
|
||||
| :vscode-pinned-dirty: | `:vscode-pinned-dirty:` | `vscode/pinned-dirty` |
|
||||
| :vscode-play: | `:vscode-play:` | `vscode/play` |
|
||||
| :vscode-play-circle: | `:vscode-play-circle:` | `vscode/play-circle` |
|
||||
| :vscode-plug: | `:vscode-plug:` | `vscode/plug` |
|
||||
| :vscode-preserve-case: | `:vscode-preserve-case:` | `vscode/preserve-case` |
|
||||
| :vscode-preview: | `:vscode-preview:` | `vscode/preview` |
|
||||
| :vscode-primitive-square: | `:vscode-primitive-square:` | `vscode/primitive-square` |
|
||||
| :vscode-project: | `:vscode-project:` | `vscode/project` |
|
||||
| :vscode-pulse: | `:vscode-pulse:` | `vscode/pulse` |
|
||||
| :vscode-python: | `:vscode-python:` | `vscode/python` |
|
||||
| :vscode-question: | `:vscode-question:` | `vscode/question` |
|
||||
| :vscode-quote: | `:vscode-quote:` | `vscode/quote` |
|
||||
| :vscode-quotes: | `:vscode-quotes:` | `vscode/quotes` |
|
||||
| :vscode-radio-tower: | `:vscode-radio-tower:` | `vscode/radio-tower` |
|
||||
| :vscode-reactions: | `:vscode-reactions:` | `vscode/reactions` |
|
||||
| :vscode-record: | `:vscode-record:` | `vscode/record` |
|
||||
| :vscode-record-keys: | `:vscode-record-keys:` | `vscode/record-keys` |
|
||||
| :vscode-record-small: | `:vscode-record-small:` | `vscode/record-small` |
|
||||
| :vscode-redo: | `:vscode-redo:` | `vscode/redo` |
|
||||
| :vscode-references: | `:vscode-references:` | `vscode/references` |
|
||||
| :vscode-refresh: | `:vscode-refresh:` | `vscode/refresh` |
|
||||
| :vscode-regex: | `:vscode-regex:` | `vscode/regex` |
|
||||
| :vscode-remote: | `:vscode-remote:` | `vscode/remote` |
|
||||
| :vscode-remote-explorer: | `:vscode-remote-explorer:` | `vscode/remote-explorer` |
|
||||
| :vscode-remove: | `:vscode-remove:` | `vscode/remove` |
|
||||
| :vscode-remove-small: | `:vscode-remove-small:` | `vscode/remove-small` |
|
||||
| :vscode-rename: | `:vscode-rename:` | `vscode/rename` |
|
||||
| :vscode-replace: | `:vscode-replace:` | `vscode/replace` |
|
||||
| :vscode-replace-all: | `:vscode-replace-all:` | `vscode/replace-all` |
|
||||
| :vscode-reply: | `:vscode-reply:` | `vscode/reply` |
|
||||
| :vscode-repo: | `:vscode-repo:` | `vscode/repo` |
|
||||
| :vscode-repo-clone: | `:vscode-repo-clone:` | `vscode/repo-clone` |
|
||||
| :vscode-repo-fetch: | `:vscode-repo-fetch:` | `vscode/repo-fetch` |
|
||||
| :vscode-repo-force-push: | `:vscode-repo-force-push:` | `vscode/repo-force-push` |
|
||||
| :vscode-repo-forked: | `:vscode-repo-forked:` | `vscode/repo-forked` |
|
||||
| :vscode-repo-pinned: | `:vscode-repo-pinned:` | `vscode/repo-pinned` |
|
||||
| :vscode-repo-pull: | `:vscode-repo-pull:` | `vscode/repo-pull` |
|
||||
| :vscode-repo-push: | `:vscode-repo-push:` | `vscode/repo-push` |
|
||||
| :vscode-repo-selected: | `:vscode-repo-selected:` | `vscode/repo-selected` |
|
||||
| :vscode-report: | `:vscode-report:` | `vscode/report` |
|
||||
| :vscode-request-changes: | `:vscode-request-changes:` | `vscode/request-changes` |
|
||||
| :vscode-robot: | `:vscode-robot:` | `vscode/robot` |
|
||||
| :vscode-rocket: | `:vscode-rocket:` | `vscode/rocket` |
|
||||
| :vscode-root-folder: | `:vscode-root-folder:` | `vscode/root-folder` |
|
||||
| :vscode-root-folder-opened: | `:vscode-root-folder-opened:` | `vscode/root-folder-opened` |
|
||||
| :vscode-rss: | `:vscode-rss:` | `vscode/rss` |
|
||||
| :vscode-ruby: | `:vscode-ruby:` | `vscode/ruby` |
|
||||
| :vscode-run-above: | `:vscode-run-above:` | `vscode/run-above` |
|
||||
| :vscode-run-all: | `:vscode-run-all:` | `vscode/run-all` |
|
||||
| :vscode-run-all-coverage: | `:vscode-run-all-coverage:` | `vscode/run-all-coverage` |
|
||||
| :vscode-run-below: | `:vscode-run-below:` | `vscode/run-below` |
|
||||
| :vscode-run-coverage: | `:vscode-run-coverage:` | `vscode/run-coverage` |
|
||||
| :vscode-run-errors: | `:vscode-run-errors:` | `vscode/run-errors` |
|
||||
| :vscode-run-with-deps: | `:vscode-run-with-deps:` | `vscode/run-with-deps` |
|
||||
| :vscode-save: | `:vscode-save:` | `vscode/save` |
|
||||
| :vscode-save-all: | `:vscode-save-all:` | `vscode/save-all` |
|
||||
| :vscode-save-as: | `:vscode-save-as:` | `vscode/save-as` |
|
||||
| :vscode-screen-cut: | `:vscode-screen-cut:` | `vscode/screen-cut` |
|
||||
| :vscode-screen-full: | `:vscode-screen-full:` | `vscode/screen-full` |
|
||||
| :vscode-screen-normal: | `:vscode-screen-normal:` | `vscode/screen-normal` |
|
||||
| :vscode-search: | `:vscode-search:` | `vscode/search` |
|
||||
| :vscode-search-fuzzy: | `:vscode-search-fuzzy:` | `vscode/search-fuzzy` |
|
||||
| :vscode-search-large: | `:vscode-search-large:` | `vscode/search-large` |
|
||||
| :vscode-search-sparkle: | `:vscode-search-sparkle:` | `vscode/search-sparkle` |
|
||||
| :vscode-search-stop: | `:vscode-search-stop:` | `vscode/search-stop` |
|
||||
| :vscode-send: | `:vscode-send:` | `vscode/send` |
|
||||
| :vscode-send-to-remote-agent: | `:vscode-send-to-remote-agent:` | `vscode/send-to-remote-agent` |
|
||||
| :vscode-server: | `:vscode-server:` | `vscode/server` |
|
||||
| :vscode-server-environment: | `:vscode-server-environment:` | `vscode/server-environment` |
|
||||
| :vscode-server-process: | `:vscode-server-process:` | `vscode/server-process` |
|
||||
| :vscode-session-in-progress: | `:vscode-session-in-progress:` | `vscode/session-in-progress` |
|
||||
| :vscode-settings: | `:vscode-settings:` | `vscode/settings` |
|
||||
| :vscode-settings-gear: | `:vscode-settings-gear:` | `vscode/settings-gear` |
|
||||
| :vscode-share: | `:vscode-share:` | `vscode/share` |
|
||||
| :vscode-share-window: | `:vscode-share-window:` | `vscode/share-window` |
|
||||
| :vscode-shield: | `:vscode-shield:` | `vscode/shield` |
|
||||
| :vscode-sign-in: | `:vscode-sign-in:` | `vscode/sign-in` |
|
||||
| :vscode-sign-out: | `:vscode-sign-out:` | `vscode/sign-out` |
|
||||
| :vscode-skip: | `:vscode-skip:` | `vscode/skip` |
|
||||
| :vscode-smiley: | `:vscode-smiley:` | `vscode/smiley` |
|
||||
| :vscode-snake: | `:vscode-snake:` | `vscode/snake` |
|
||||
| :vscode-sort-precedence: | `:vscode-sort-precedence:` | `vscode/sort-precedence` |
|
||||
| :vscode-source-control: | `:vscode-source-control:` | `vscode/source-control` |
|
||||
| :vscode-sparkle: | `:vscode-sparkle:` | `vscode/sparkle` |
|
||||
| :vscode-sparkle-filled: | `:vscode-sparkle-filled:` | `vscode/sparkle-filled` |
|
||||
| :vscode-split-horizontal: | `:vscode-split-horizontal:` | `vscode/split-horizontal` |
|
||||
| :vscode-split-vertical: | `:vscode-split-vertical:` | `vscode/split-vertical` |
|
||||
| :vscode-squirrel: | `:vscode-squirrel:` | `vscode/squirrel` |
|
||||
| :vscode-star-empty: | `:vscode-star-empty:` | `vscode/star-empty` |
|
||||
| :vscode-star-full: | `:vscode-star-full:` | `vscode/star-full` |
|
||||
| :vscode-star-half: | `:vscode-star-half:` | `vscode/star-half` |
|
||||
| :vscode-stop-circle: | `:vscode-stop-circle:` | `vscode/stop-circle` |
|
||||
| :vscode-strikethrough: | `:vscode-strikethrough:` | `vscode/strikethrough` |
|
||||
| :vscode-surround-with: | `:vscode-surround-with:` | `vscode/surround-with` |
|
||||
| :vscode-symbol-array: | `:vscode-symbol-array:` | `vscode/symbol-array` |
|
||||
| :vscode-symbol-boolean: | `:vscode-symbol-boolean:` | `vscode/symbol-boolean` |
|
||||
| :vscode-symbol-class: | `:vscode-symbol-class:` | `vscode/symbol-class` |
|
||||
| :vscode-symbol-color: | `:vscode-symbol-color:` | `vscode/symbol-color` |
|
||||
| :vscode-symbol-constant: | `:vscode-symbol-constant:` | `vscode/symbol-constant` |
|
||||
| :vscode-symbol-enum: | `:vscode-symbol-enum:` | `vscode/symbol-enum` |
|
||||
| :vscode-symbol-enum-member: | `:vscode-symbol-enum-member:` | `vscode/symbol-enum-member` |
|
||||
| :vscode-symbol-event: | `:vscode-symbol-event:` | `vscode/symbol-event` |
|
||||
| :vscode-symbol-field: | `:vscode-symbol-field:` | `vscode/symbol-field` |
|
||||
| :vscode-symbol-file: | `:vscode-symbol-file:` | `vscode/symbol-file` |
|
||||
| :vscode-symbol-interface: | `:vscode-symbol-interface:` | `vscode/symbol-interface` |
|
||||
| :vscode-symbol-key: | `:vscode-symbol-key:` | `vscode/symbol-key` |
|
||||
| :vscode-symbol-keyword: | `:vscode-symbol-keyword:` | `vscode/symbol-keyword` |
|
||||
| :vscode-symbol-method: | `:vscode-symbol-method:` | `vscode/symbol-method` |
|
||||
| :vscode-symbol-method-arrow: | `:vscode-symbol-method-arrow:` | `vscode/symbol-method-arrow` |
|
||||
| :vscode-symbol-misc: | `:vscode-symbol-misc:` | `vscode/symbol-misc` |
|
||||
| :vscode-symbol-namespace: | `:vscode-symbol-namespace:` | `vscode/symbol-namespace` |
|
||||
| :vscode-symbol-numeric: | `:vscode-symbol-numeric:` | `vscode/symbol-numeric` |
|
||||
| :vscode-symbol-operator: | `:vscode-symbol-operator:` | `vscode/symbol-operator` |
|
||||
| :vscode-symbol-parameter: | `:vscode-symbol-parameter:` | `vscode/symbol-parameter` |
|
||||
| :vscode-symbol-property: | `:vscode-symbol-property:` | `vscode/symbol-property` |
|
||||
| :vscode-symbol-ruler: | `:vscode-symbol-ruler:` | `vscode/symbol-ruler` |
|
||||
| :vscode-symbol-snippet: | `:vscode-symbol-snippet:` | `vscode/symbol-snippet` |
|
||||
| :vscode-symbol-string: | `:vscode-symbol-string:` | `vscode/symbol-string` |
|
||||
| :vscode-symbol-structure: | `:vscode-symbol-structure:` | `vscode/symbol-structure` |
|
||||
| :vscode-symbol-variable: | `:vscode-symbol-variable:` | `vscode/symbol-variable` |
|
||||
| :vscode-sync: | `:vscode-sync:` | `vscode/sync` |
|
||||
| :vscode-sync-ignored: | `:vscode-sync-ignored:` | `vscode/sync-ignored` |
|
||||
| :vscode-table: | `:vscode-table:` | `vscode/table` |
|
||||
| :vscode-tag: | `:vscode-tag:` | `vscode/tag` |
|
||||
| :vscode-target: | `:vscode-target:` | `vscode/target` |
|
||||
| :vscode-tasklist: | `:vscode-tasklist:` | `vscode/tasklist` |
|
||||
| :vscode-telescope: | `:vscode-telescope:` | `vscode/telescope` |
|
||||
| :vscode-terminal: | `:vscode-terminal:` | `vscode/terminal` |
|
||||
| :vscode-terminal-bash: | `:vscode-terminal-bash:` | `vscode/terminal-bash` |
|
||||
| :vscode-terminal-cmd: | `:vscode-terminal-cmd:` | `vscode/terminal-cmd` |
|
||||
| :vscode-terminal-debian: | `:vscode-terminal-debian:` | `vscode/terminal-debian` |
|
||||
| :vscode-terminal-git-bash: | `:vscode-terminal-git-bash:` | `vscode/terminal-git-bash` |
|
||||
| :vscode-terminal-linux: | `:vscode-terminal-linux:` | `vscode/terminal-linux` |
|
||||
| :vscode-terminal-powershell: | `:vscode-terminal-powershell:` | `vscode/terminal-powershell` |
|
||||
| :vscode-terminal-secure: | `:vscode-terminal-secure:` | `vscode/terminal-secure` |
|
||||
| :vscode-terminal-tmux: | `:vscode-terminal-tmux:` | `vscode/terminal-tmux` |
|
||||
| :vscode-terminal-ubuntu: | `:vscode-terminal-ubuntu:` | `vscode/terminal-ubuntu` |
|
||||
| :vscode-text-size: | `:vscode-text-size:` | `vscode/text-size` |
|
||||
| :vscode-thinking: | `:vscode-thinking:` | `vscode/thinking` |
|
||||
| :vscode-three-bars: | `:vscode-three-bars:` | `vscode/three-bars` |
|
||||
| :vscode-thumbsdown: | `:vscode-thumbsdown:` | `vscode/thumbsdown` |
|
||||
| :vscode-thumbsdown-filled: | `:vscode-thumbsdown-filled:` | `vscode/thumbsdown-filled` |
|
||||
| :vscode-thumbsup: | `:vscode-thumbsup:` | `vscode/thumbsup` |
|
||||
| :vscode-thumbsup-filled: | `:vscode-thumbsup-filled:` | `vscode/thumbsup-filled` |
|
||||
| :vscode-tools: | `:vscode-tools:` | `vscode/tools` |
|
||||
| :vscode-trash: | `:vscode-trash:` | `vscode/trash` |
|
||||
| :vscode-triangle-down: | `:vscode-triangle-down:` | `vscode/triangle-down` |
|
||||
| :vscode-triangle-left: | `:vscode-triangle-left:` | `vscode/triangle-left` |
|
||||
| :vscode-triangle-right: | `:vscode-triangle-right:` | `vscode/triangle-right` |
|
||||
| :vscode-triangle-up: | `:vscode-triangle-up:` | `vscode/triangle-up` |
|
||||
| :vscode-twitter: | `:vscode-twitter:` | `vscode/twitter` |
|
||||
| :vscode-type-hierarchy: | `:vscode-type-hierarchy:` | `vscode/type-hierarchy` |
|
||||
| :vscode-type-hierarchy-sub: | `:vscode-type-hierarchy-sub:` | `vscode/type-hierarchy-sub` |
|
||||
| :vscode-type-hierarchy-super: | `:vscode-type-hierarchy-super:` | `vscode/type-hierarchy-super` |
|
||||
| :vscode-unarchive: | `:vscode-unarchive:` | `vscode/unarchive` |
|
||||
| :vscode-unfold: | `:vscode-unfold:` | `vscode/unfold` |
|
||||
| :vscode-ungroup-by-ref-type: | `:vscode-ungroup-by-ref-type:` | `vscode/ungroup-by-ref-type` |
|
||||
| :vscode-unlock: | `:vscode-unlock:` | `vscode/unlock` |
|
||||
| :vscode-unmute: | `:vscode-unmute:` | `vscode/unmute` |
|
||||
| :vscode-unverified: | `:vscode-unverified:` | `vscode/unverified` |
|
||||
| :vscode-variable-group: | `:vscode-variable-group:` | `vscode/variable-group` |
|
||||
| :vscode-verified: | `:vscode-verified:` | `vscode/verified` |
|
||||
| :vscode-verified-filled: | `:vscode-verified-filled:` | `vscode/verified-filled` |
|
||||
| :vscode-versions: | `:vscode-versions:` | `vscode/versions` |
|
||||
| :vscode-vm: | `:vscode-vm:` | `vscode/vm` |
|
||||
| :vscode-vm-active: | `:vscode-vm-active:` | `vscode/vm-active` |
|
||||
| :vscode-vm-connect: | `:vscode-vm-connect:` | `vscode/vm-connect` |
|
||||
| :vscode-vm-outline: | `:vscode-vm-outline:` | `vscode/vm-outline` |
|
||||
| :vscode-vm-pending: | `:vscode-vm-pending:` | `vscode/vm-pending` |
|
||||
| :vscode-vm-running: | `:vscode-vm-running:` | `vscode/vm-running` |
|
||||
| :vscode-vm-small: | `:vscode-vm-small:` | `vscode/vm-small` |
|
||||
| :vscode-vr: | `:vscode-vr:` | `vscode/vr` |
|
||||
| :vscode-vscode: | `:vscode-vscode:` | `vscode/vscode` |
|
||||
| :vscode-vscode-insiders: | `:vscode-vscode-insiders:` | `vscode/vscode-insiders` |
|
||||
| :vscode-wand: | `:vscode-wand:` | `vscode/wand` |
|
||||
| :vscode-warning: | `:vscode-warning:` | `vscode/warning` |
|
||||
| :vscode-watch: | `:vscode-watch:` | `vscode/watch` |
|
||||
| :vscode-whitespace: | `:vscode-whitespace:` | `vscode/whitespace` |
|
||||
| :vscode-whole-word: | `:vscode-whole-word:` | `vscode/whole-word` |
|
||||
| :vscode-window: | `:vscode-window:` | `vscode/window` |
|
||||
| :vscode-window-active: | `:vscode-window-active:` | `vscode/window-active` |
|
||||
| :vscode-word-wrap: | `:vscode-word-wrap:` | `vscode/word-wrap` |
|
||||
| :vscode-workspace-trusted: | `:vscode-workspace-trusted:` | `vscode/workspace-trusted` |
|
||||
| :vscode-workspace-unknown: | `:vscode-workspace-unknown:` | `vscode/workspace-unknown` |
|
||||
| :vscode-workspace-untrusted: | `:vscode-workspace-untrusted:` | `vscode/workspace-untrusted` |
|
||||
| :vscode-worktree: | `:vscode-worktree:` | `vscode/worktree` |
|
||||
| :vscode-worktree-small: | `:vscode-worktree-small:` | `vscode/worktree-small` |
|
||||
| :vscode-zoom-in: | `:vscode-zoom-in:` | `vscode/zoom-in` |
|
||||
| :vscode-zoom-out: | `:vscode-zoom-out:` | `vscode/zoom-out` |
|
||||
@@ -0,0 +1,306 @@
|
||||
# Компоненты
|
||||
|
||||
Здесь показаны примеры компонентов, которые можно внедрять в документацию.
|
||||
|
||||
Для синтаксиса обращайся в [документацию Zensical][1] и репозиторий [этой документации][2].
|
||||
|
||||
[1]: https://zensical.org/docs
|
||||
[2]: https://git.axenov.dev/IPTV/docs
|
||||
|
||||
## Мелочёвка
|
||||
|
||||
=== "Бейджи"
|
||||
|
||||
Это кастомный функционал, в основе которого лежит `inline_badges.py` в корне репозитория.
|
||||
|
||||
<!-- md:env SOME_VAR -->
|
||||
<!-- md:arg --arg -->
|
||||
<!-- md:config server.host -->
|
||||
<!-- md:version 1.2.3 -->
|
||||
<!-- md:default default_value -->
|
||||
<!-- md:beta -->
|
||||
|
||||
=== "Frontmatter"
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: My Page
|
||||
description: Some page description
|
||||
icon: material/star
|
||||
tags: [tag1, tag2]
|
||||
hide: [navigation, toc, path]
|
||||
status: new
|
||||
#status: deprecated
|
||||
#status: beta
|
||||
---
|
||||
|
||||
# My Super-Duper Page
|
||||
|
||||
# Markdown content goes here
|
||||
```
|
||||
|
||||
=== "Тултипы"
|
||||
|
||||
:material-information-outline:{ title="текст подсказки" }
|
||||
|
||||
[Hover me 1](https://example.com "I'm first tooltip!")
|
||||
|
||||
[Hover me 2][example]
|
||||
|
||||
[example]: https://example.com "I'm second tooltip!"
|
||||
|
||||
=== "Кнопки"
|
||||
|
||||
[Серая кнопка](https://example.com/){ .md-button }
|
||||
|
||||
[Синяя кнопка](https://example.com/){ .md-button .md-button--primary }
|
||||
|
||||
[:fontawesome-solid-paper-plane: Кнопка серая с иконкой и подсказкой](https://example.com/){ .md-button title="текст подсказки 2" }
|
||||
|
||||
[:fontawesome-solid-paper-plane: Кнопка синяя с иконкой](https://example.com/){ .md-button .md-button--primary }
|
||||
|
||||
---
|
||||
|
||||
=== "Простой блок"
|
||||
|
||||
```python
|
||||
def _render_icon(shortcode: str, md) -> str:
|
||||
emoji_pattern = md.inlinePatterns.get("emoji")
|
||||
if emoji_pattern is None:
|
||||
return escape(shortcode)
|
||||
```
|
||||
|
||||
=== "С аннотациями"
|
||||
|
||||
```python
|
||||
def _render_icon(shortcode: str, md) -> str: #(1)!
|
||||
emoji_pattern = md.inlinePatterns.get("emoji") #(2)!
|
||||
if emoji_pattern is None:
|
||||
return escape(shortcode) #(3)!
|
||||
```
|
||||
|
||||
1. сигнатура функции
|
||||
2. инициализация переменной
|
||||
3. возврат результата
|
||||
|
||||
=== "С заголовком"
|
||||
|
||||
```python title="example.py"
|
||||
def _render_icon(shortcode: str, md) -> str:
|
||||
emoji_pattern = md.inlinePatterns.get("emoji")
|
||||
if emoji_pattern is None:
|
||||
return escape(shortcode)
|
||||
```
|
||||
|
||||
=== "Нумерация с 5"
|
||||
|
||||
```python linenums="5"
|
||||
def _render_icon(shortcode: str, md) -> str:
|
||||
emoji_pattern = md.inlinePatterns.get("emoji")
|
||||
if emoji_pattern is None:
|
||||
return escape(shortcode)
|
||||
```
|
||||
|
||||
=== "Выделение"
|
||||
|
||||
```python linenums="1" hl_lines="2-5 8 9 22"
|
||||
def _render_icon(shortcode: str, md) -> str:
|
||||
try:
|
||||
emoji_pattern = md.inlinePatterns["emoji"]
|
||||
except KeyError:
|
||||
return escape(shortcode)
|
||||
|
||||
icon = emoji_pattern.emoji_index["emoji"].get(shortcode)
|
||||
if icon is None:
|
||||
return escape(shortcode)
|
||||
|
||||
element = emoji_pattern.generator(
|
||||
emoji_pattern.emoji_index["name"],
|
||||
shortcode,
|
||||
None,
|
||||
None,
|
||||
shortcode,
|
||||
"",
|
||||
icon.get("category", ""),
|
||||
emoji_pattern.options,
|
||||
md,
|
||||
)
|
||||
return tostring(element, encoding="unicode", method="html")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Врезки
|
||||
|
||||
=== "Полные"
|
||||
|
||||
!!! note "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! abstract "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! info "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! tip "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! success "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! question "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! warning "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! failure "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! danger "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! bug "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! example "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
!!! quote "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
=== "Свёрнутые"
|
||||
|
||||
??? note "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? abstract "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? info "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? tip "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? success "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? question "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? warning "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? failure "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? danger "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? bug "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? example "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? quote "Заголовок свёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
=== "Сворачиваемые"
|
||||
|
||||
???+ note "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ abstract "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ info "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ tip "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ success "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ question "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ warning "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ failure "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ danger "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ bug "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ example "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
???+ quote "Заголовок развёрнутой врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
=== "Короткие"
|
||||
|
||||
!!! note
|
||||
Дефолтный заголовок
|
||||
|
||||
!!! abstract ""
|
||||
Пустой заголовок
|
||||
|
||||
!!! info "Пустое содержимое"
|
||||
|
||||
=== "Кастомные"
|
||||
|
||||
??? image "Врезка для скриншота"
|
||||
Тут должна быть картинка
|
||||
|
||||
!!! boosty "Врезка Boosty"
|
||||
Тут должна быть релевантная информация
|
||||
|
||||
!!! yoomoney "Врезка Yoomoney"
|
||||
Тут должна быть релевантная информация
|
||||
|
||||
---
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
icon: material/application-brackets-outline
|
||||
tags: ["iptvc", "разработка"]
|
||||
---
|
||||
|
||||
# :material-application-brackets-outline: Среда разработки
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
Для локальной разработки `iptvc` достаточно установить [Go 1.23.6+][1] и клонировать репозиторий:
|
||||
|
||||
```bash
|
||||
git clone https://git.axenov.dev/IPTV/iptvc.git
|
||||
cd iptvc
|
||||
go run . serve -i playlists.ini -p 8080 --check
|
||||
```
|
||||
|
||||
Веб-интерфейс будет доступен по адресу <http://localhost:8080>.
|
||||
|
||||
## Требования
|
||||
|
||||
| ПО | Версия | Назначение |
|
||||
| ----------- | --------------------- | ------------------------------------- |
|
||||
| [Go][1] | 1.23.6+ | Компиляция и запуск |
|
||||
| [Make][2] | любая | Сборка через `Makefile` (опционально) |
|
||||
| [Docker][3] | с `docker compose` v2 | Полное окружение (опционально) |
|
||||
|
||||
[1]: https://go.dev/dl/
|
||||
[2]: https://www.gnu.org/software/make
|
||||
[3]: https://docs.docker.com/engine/install
|
||||
|
||||
|
||||
## Команды для разработки
|
||||
|
||||
```bash
|
||||
# Запуск веб-сервера с фоновой проверкой
|
||||
go run . serve -i playlists.ini -p 8080 --check
|
||||
|
||||
# Запуск проверки без веб-сервера
|
||||
go run . check -i playlists.ini --repeat 1
|
||||
|
||||
# Сборка бинарника
|
||||
go build -o iptvc .
|
||||
|
||||
# Проверка кода
|
||||
go vet ./...
|
||||
|
||||
# Сборка под все платформы
|
||||
make release
|
||||
```
|
||||
|
||||
## Файлы конфигурации
|
||||
|
||||
Для работы `iptvc` нужны два файла рядом с бинарником:
|
||||
|
||||
- `playlists.ini` — список плейлистов. Формат описан в [справочнике форматов](../../common/formats/playlists.md).
|
||||
- `channels.json` — правила тегов каналов. Формат описан в [справочнике форматов](../../common/formats/channels.md).
|
||||
- `config.yml` — конфигурация программы. Описание — в [разделе config.yml](../../common/config/config.md).
|
||||
|
||||
## Полное Docker-окружение
|
||||
|
||||
Полная инфраструктура проекта (nginx, KeyDB, checker, docs) развёртывается через Docker.
|
||||
|
||||
Подробнее — в разделе [Развёртывание](../site/deploy.md).
|
||||
|
||||
## Дополнительные материалы
|
||||
|
||||
- [Компиляция из исходного кода](compile.md)
|
||||
- [Построение Docker-образа](docker.md)
|
||||
- [Архитектура iptvc](arch.md)
|
||||
- [Развёртывание и доставка обновлений](../site/deploy.md)
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
icon: material/robot-outline
|
||||
---
|
||||
|
||||
# :material-robot-outline: Telegram-бот
|
||||
|
||||
!!! info "Обрати внимание"
|
||||
Локальная среда разработки должна быть [настроена и запущена](local-dev.md).
|
||||
|
||||
## Подготовка бота на стороне Telegram
|
||||
|
||||
1. Написать [@botfather](https://t.me/botfather), создать бота
|
||||
2. Полученный токен установить значением переменной `TG_BOT_TOKEN` в файле `.env` репозитория `web`
|
||||
3. Командой `/mybots` в [@botfather](https://t.me/botfather) выбрать свежесозданного бота, далее `Edit Bot` > `Edit Commands` и отправить текст:
|
||||
```
|
||||
list - Список плейлистов
|
||||
info - Подробности о плейлисте по его коду
|
||||
help - Помощь по командам бота
|
||||
links - Ссылки на все страницы проекта
|
||||
stats - Статистика по плейлистам и каналам
|
||||
```
|
||||
|
||||
## Проброс внешних запросов на локальную машину
|
||||
|
||||
1. Установить [telebit](https://telebit.cloud) и пройти примитивную регистрацию.
|
||||
В результате будет выдан уникальный адрес в формате `https://foo-bar-99.telebit.io`.
|
||||
На email, указанный при регистрации, будет оформлен бесплатный SSL-серификат Let's Encrypt для этого домена.
|
||||
Если адрес не используется месяц+, то сертификат протухнет, но он автоматически восстановится, если адрес начнёт использоваться вновь.
|
||||
|
||||
2. В терминале выполнить:
|
||||
```
|
||||
telebit http 8080
|
||||
```
|
||||
где `8080` — порт локальной машины, на который проброшен порт 80 из контейнера `iptv-nginx`.
|
||||
Для выключения выполнить:
|
||||
```
|
||||
telebit http
|
||||
```
|
||||
|
||||
3. Проверить работу адреса, перейдя по нему браузером.
|
||||
Должен открыться твой локальный проект.
|
||||
|
||||
4. Полученный адрес установить значением переменной `APP_URL` в файле `.env` репозитория `web`
|
||||
|
||||
5. Установить веб-хук, отправив запрос браузером или любым HTTP-клиентом на адрес:
|
||||
```
|
||||
https://api.telegram.org/bot$BOT_TOKEN/setWebhook?url=$TELEBIT_URL/bot/webhook&secret_token=$SECRET_TOKEN
|
||||
```
|
||||
где:
|
||||
* `$BOT_TOKEN` - авторизационный токен, который @botfather выдал твоему боту;
|
||||
* `$TELEBIT_URL` - адрес, который telebit выдал тебе;
|
||||
* `$SECRET_TOKEN` - секретный токен, опционален, см. ниже.
|
||||
|
||||
6. Проверить веб-хук, отправив запрос браузером или любым HTTP-клиентом на адрес:
|
||||
```
|
||||
https://api.telegram.org/bot$BOT_TOKEN/getWebhookInfo
|
||||
```
|
||||
где:
|
||||
* `$BOT_TOKEN` - авторизационный токен, который @botfather выдал твоему боту.
|
||||
|
||||
7. После разработки нужно установить "боевой" адрес веб-хука аналогично п4.
|
||||
|
||||
## Что за секретный токен?
|
||||
|
||||
Telegram авторизует твоего бота по токену, который выдал ему сам.
|
||||
|
||||
Ты тоже можешь (не) авторизовать Telegram по токену, который ты выдашь ему.
|
||||
|
||||
Для этого нужно в значением переменной `TG_BOT_SECRET` в файле `.env` репозитория `web` установить любую строку.
|
||||
Если ты это сделаешь, тогда ту же строку ты должен передать в параметре `secret_token` метода `setWebhook`.
|
||||
|
||||
В этом случае, все HTTP-запросы, которые приходят от Telegram, будут содержать заголовок `X-Telegram-Bot-Api-Secret-Token` со этой строкой в качестве значения.
|
||||
Эта строка сверяется с той, что указана в `.env` проекта.
|
||||
Если такого заголовка нет или его значение некорректно, входящий запрос отклоняется.
|
||||
|
||||
Если переменная `TG_BOT_SECRET` не задана, то заголовок проверяться не будет.
|
||||
|
||||
См. подробности в документации: [setWebhook](https://core.telegram.org/bots/api#setwebhook)
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
icon: material/download
|
||||
tags: ["iptvc"]
|
||||
---
|
||||
|
||||
# Установка и запуск
|
||||
|
||||
## Запуск готовой программы
|
||||
|
||||
Достаточно скачать и распаковать архив с подходящим исполняемым файлом [со страницы последнего релиза][rel_page] в любую удобную директорию:
|
||||
|
||||
| ОС | Скачать для `amd64` | Скачать для `arm64` |
|
||||
| ------- | ---------------------------------- | ---------------------------------- |
|
||||
| Linux | [linux_amd64.zip][linux_amd64] | [linux_arm64.zip][linux_arm64] |
|
||||
| MacOS | [darwin_amd64.zip][darwin_amd64] | [darwin_arm64.zip][darwin_arm64] |
|
||||
| Windows | [windows_amd64.zip][windows_amd64] | [windows_arm64.zip][windows_arm64] |
|
||||
|
||||
[rel_page]: https://git.axenov.dev/IPTV/iptvc/releases/latest
|
||||
[linux_amd64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/linux_amd64.zip
|
||||
[linux_arm64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/linux_arm64.zip
|
||||
[darwin_amd64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/darwin_amd64.zip
|
||||
[darwin_arm64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/darwin_arm64.zip
|
||||
[windows_amd64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/windows_amd64.zip
|
||||
[windows_arm64]: https://git.axenov.dev/IPTV/iptvc/releases/download/latest/windows_arm64.zip
|
||||
|
||||
## Запуск релизного образа
|
||||
|
||||
Релизные docker-образы строятся для платформы `linux` и архитектуры `amd64`.
|
||||
|
||||
Найти их можно здесь: <https://git.axenov.dev/IPTV/-/packages/container/iptvc>
|
||||
|
||||
Тег `latest` всегда соответствует последней версии, он подразумевается по умолчанию:
|
||||
|
||||
=== "Запуск последней версии"
|
||||
|
||||
```shell
|
||||
docker run \
|
||||
--pull always \
|
||||
--name iptvc \
|
||||
git.axenov.dev/iptv/iptvc \ #(1)!
|
||||
КОМАНДА [АРГУМЕНТЫ]
|
||||
```
|
||||
|
||||
1. Подразумевается `:latest`, можно указать явно
|
||||
|
||||
=== "Запуск другой версии"
|
||||
|
||||
```shell
|
||||
docker run \
|
||||
--pull always \
|
||||
--name iptvc \
|
||||
git.axenov.dev/iptv/iptvc:v1.1.3 \ #(1)!
|
||||
КОМАНДА [АРГУМЕНТЫ]
|
||||
```
|
||||
|
||||
1. Список версий доступен на [релизной странице][rel_page]
|
||||
|
||||
## Использование образа в Docker compose
|
||||
|
||||
```yaml title="compose.yml"
|
||||
services:
|
||||
#...
|
||||
iptvc:
|
||||
container_name: iptvc
|
||||
image: git.axenov.dev/iptv/iptvc:latest
|
||||
command: [serve] #(1)!
|
||||
#...
|
||||
```
|
||||
|
||||
1. Доступные команды и аргументы см. в [**Справочнике команд**](commands/index.md)
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
title: Введение
|
||||
icon: octicons/sparkles-fill-16
|
||||
hide: [toc]
|
||||
---
|
||||
|
||||
# IPTV Checker (iptvc)
|
||||
|
||||
Это простая программа для проверки IPTV плейлистов, входящая в состав проекта m3u.su.
|
||||
|
||||
Поддерживает проверку как локальных файлов `*.m3u`/`*.m3u8`, так и удалённых плейлистов по прямым ссылкам, с возможностью кеширования результатов и его вывода в различных форматах.
|
||||
|
||||
> Программа не предназначена для хранения, воспроизведения или распространения пиратского контента.
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
- :material-flag-checkered: **Быстрый старт**
|
||||
|
||||
---
|
||||
|
||||
Коротко о главном, если не терпится
|
||||
|
||||
[Подробности :material-arrow-right:][start]{ .md-button .md-button--primary }
|
||||
|
||||
- :material-application-brackets-outline: **Запуск сайта**
|
||||
|
||||
---
|
||||
|
||||
Создайте свой агрегатор плейлистов
|
||||
|
||||
[Подробности :material-arrow-right:][site]{ .md-button .md-button--primary }
|
||||
|
||||
- :octicons-terminal-24: **Работа в терминале**
|
||||
|
||||
---
|
||||
|
||||
Как обрабатывать плейлисты без GUI
|
||||
|
||||
[Подробности :material-arrow-right:][cli]{ .md-button .md-button--primary }
|
||||
|
||||
- :material-file-cog: **Конфигурация**
|
||||
|
||||
---
|
||||
|
||||
Настройте `iptvc` для своих целей
|
||||
|
||||
[Подробности :material-arrow-right:][cfg]{ .md-button .md-button--primary }
|
||||
</div>
|
||||
|
||||
[start]: quickstart.md "Перейти к разделу"
|
||||
[site]: site/first-steps.md "Перейти к разделу"
|
||||
[cli]: commands/index.md "Перейти к разделу"
|
||||
[cfg]: ../common/config/config.md "Перейти к разделу"
|
||||
|
||||
<!--
|
||||
## :material-cog-sync-outline: Как работает `iptvc`
|
||||
|
||||
Принцип её работы очень простой:
|
||||
|
||||
1. Получить плейлист по ссылке.
|
||||
2. Полученный плейлист распарсить:
|
||||
обрабатывается полученный текст в формате [m3u](../common/formats/m3u.md), из него вычленется информация о каналах и их группировке.
|
||||
3. Каждый найденный канал проверить:
|
||||
получить информацию по ссылке и принять решение — работает ли канал (технически) или нет.
|
||||
4. Если необходимо, каждому каналу [присвоить теги](../common/formats/channels.md#доступные-теги) согласно [правилам](../common/formats/channels.md).
|
||||
5. Если необходимо, закешировать результаты проверок.
|
||||
|
||||
Во время работы программа пишет лог проверки плейлиста и каналов в достаточно компактном человекочитаемом виде, а в конце пишет результаты проверок.
|
||||
|
||||
При желании, можно включить более подробный вывод, чтобы тщательно следить за ходом проверки в реальном времени, а также вывод результатов в машиночитаемом виде (в формате json).
|
||||
|
||||
Подробности см. в разделе [Команда `check`](../iptvc/commands/check.md).
|
||||
|
||||
-->
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
icon: material/flag-checkered
|
||||
tags: ["iptvc"]
|
||||
---
|
||||
|
||||
# :material-flag-checkered: Быстрый старт
|
||||
|
||||
Для простоты представим, что программа скачана и распакована в любую директорию и вы находитесь в ней.
|
||||
|
||||
Используйте тот способ запуска, который выбрали на шаге [установки](install.md).
|
||||
|
||||
Ниже представлены лишь частые примеры запуска программы с разными аргументами под разные случаи.
|
||||
|
||||
## Проверить плейлист по прямой ссылке
|
||||
|
||||
```
|
||||
./iptvc check -u https://example.com/pls.m3u
|
||||
./iptvc check --url https://example.com/pls.m3u
|
||||
```
|
||||
|
||||
## Проверить файл плейлиста с диска
|
||||
|
||||
```
|
||||
./iptvc check -f /home/user/pls.m3u
|
||||
./iptvc check --file /home/user/pls.m3u
|
||||
```
|
||||
|
||||
## Проверить плейлист по короткому коду из [`playlists.ini`](../common/formats/playlists.md)
|
||||
|
||||
```
|
||||
./iptvc check -c X
|
||||
./iptvc check --code X
|
||||
```
|
||||
|
||||
Файл `playlists.ini` должен лежать рядом с `iptvc`.
|
||||
|
||||
Если файл лежит в другой директории, то можно явно указать путь к нему:
|
||||
|
||||
```
|
||||
./iptvc check --ini /home/user/playlists.ini --code X
|
||||
```
|
||||
|
||||
Если ini-файл не будет найден, программа предупредит об этом.
|
||||
|
||||
## Присвоить каналам тематические теги
|
||||
|
||||
Для этого рядом с `iptvc` должен лежать файл [channels.json](../common/formats/channels.md).
|
||||
|
||||
Если файл лежит в другой директории, то можно указать её явно:
|
||||
|
||||
```
|
||||
./iptvc check --tags /home/user/channels.json
|
||||
```
|
||||
|
||||
Если json-файл не будет найден, то программа предупредит о том, что теги не будут присвоены, и продолжит работу.
|
||||
|
||||
## Проверить несколько плейлистов одновременно
|
||||
|
||||
Для этого можно комбинировать все аргументы, перечисленные выше, с учётом особенностей их работы:
|
||||
|
||||
```shell
|
||||
./iptvc check \
|
||||
--ini /home/user/p.ini \ #(1)!
|
||||
--tags /home/user/c.json \ #(2)!
|
||||
--code Y \ #(3)!
|
||||
--file /home/user/tv.m3u \ #(4)!
|
||||
--url https://example.com/pls1.m3u \ #(5)!
|
||||
-u https://example.com/pls2.m3u #(6)!
|
||||
```
|
||||
|
||||
1. Из этого файла будет взят список плейлистов
|
||||
2. Из этого файла будут взяты правила для присвоения тегов каналам
|
||||
3. Из ini-списка будет проверен только плейлист с кодом `Y`
|
||||
4. Это отдельный файл плейлиста на диске, который будет проверен в дополнение к основному списку
|
||||
5. Плейлист на каком-то удалённом сервере, который будет загружен и проверен вместе с прошлыми двумя
|
||||
6. Ещё один по ссылке, просто через короткий вариант аргумента `--url`
|
||||
|
||||
Символ `\` нужен только для наглядного разделения аргументов на несколько строк.
|
||||
Всё это можно писать в одну строку.
|
||||
|
||||
Переданные плейлисты будут обработаны в следующем порядке:
|
||||
|
||||
1. локальные файлы (`-f|--file`);
|
||||
2. по ссылкам (`-u|--url`);
|
||||
3. по кодам из ini-файла (`-i|--ini`, `-c|--code`).
|
||||
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 61 KiB |
@@ -0,0 +1,14 @@
|
||||
---
|
||||
icon: material/television-play
|
||||
tags: ["плееры", "плейлисты"]
|
||||
---
|
||||
|
||||
# :material-television-play: Как подключить плейлист
|
||||
|
||||
1. Найти какой-нибудь [плеер](../../common/players.md)
|
||||
2. Узнать как в него добавить плейлист по ссылке
|
||||
3. Найти желаемый плелист из [списка](./list.md)
|
||||
4. Найти на странице ["Ссылку для ТВ"](details.md#shortlink) и ввести (скопировать) её в поле ввода адреса в плеере
|
||||
|
||||
Для некоторых [плееров](../../common/players.md) уже есть информация как добавить плейлист.
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
---
|
||||
icon: material/upload-network
|
||||
tags: ["iptvc", "docker", "deploy"]
|
||||
---
|
||||
|
||||
# :material-upload-network: Развёртывание и доставка обновлений
|
||||
|
||||
В этом разделе описан фактический порядок настройки окружения `iptv` с приложением `iptvc`, хранилищем KeyDB и сайтом документации.
|
||||
|
||||
## Требования { id="requirements" }
|
||||
|
||||
- [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
|
||||
cd IPTV
|
||||
```
|
||||
|
||||
В корне проекта должны находиться `compose.yml`, `.env`, `config.yml`, `playlists.ini`, `channels.json` и каталог `docker/keydb`.
|
||||
|
||||
Исходный код приложения располагается в `iptvc/`, а документации — в `docs/`.
|
||||
|
||||
## Настройка файлов { id="configuration" }
|
||||
|
||||
Создайте файлы локальной конфигурации на основе примеров:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
cp iptvc/config.yml.example config.yml
|
||||
```
|
||||
|
||||
Отредактируйте `config.yml`.
|
||||
|
||||
В контейнере `iptvc` он подключается как `/app/config.yml`.
|
||||
|
||||
Минимально проверьте следующие параметры:
|
||||
|
||||
- `app.playlists` — путь к файлу плейлистов;
|
||||
- `app.tags` — путь к файлу тегов каналов;
|
||||
- `server.host` и `server.port` — адрес и порт веб-интерфейса;
|
||||
- `cache.enabled` и параметры `cache` — использование KeyDB;
|
||||
- `site.base-url` — внешний адрес приложения.
|
||||
|
||||
Скопируйте входные данные плейлистов в корень окружения:
|
||||
|
||||
```bash
|
||||
cp /path/to/playlists.ini ./playlists.ini
|
||||
cp /path/to/channels.json ./channels.json
|
||||
```
|
||||
|
||||
Эти файлы монтируются в контейнер как `/app/playlists.ini` и `/app/channels.json`.
|
||||
|
||||
В `.env` задаются параметры приложения из `iptvc/.env.example`, включая `APP_URL`, `SERVER_PORT`, `CACHE_ENABLED`, `CACHE_HOST`, `CACHE_PORT`, `CACHE_DB` и `CACHE_TTL`.
|
||||
|
||||
Для подключения к KeyDB из контейнера укажите имя сервиса `keydb` в `CACHE_HOST`, а не `localhost`.
|
||||
|
||||
## Состав окружения { id="services" }
|
||||
|
||||
Файл `compose.yml` запускает три сервиса:
|
||||
|
||||
| Сервис | Образ | Назначение |
|
||||
| --- | --- | --- |
|
||||
| `iptvc` | `git.axenov.dev/iptv/iptvc:latest` | Веб-интерфейс и фоновая проверка плейлистов |
|
||||
| `keydb` | `eqalpha/keydb:latest` | Кеш результатов проверки |
|
||||
| `docs` | `git.axenov.dev/iptv/iptv-docs:latest` | Сайт документации |
|
||||
|
||||
Сервис `iptvc` публикует порт `8800`, а `docs` — порт `8801`.
|
||||
|
||||
KeyDB публикует порт, заданный `KEYDB_PORT`, по умолчанию `6379`.
|
||||
|
||||
Сервис `iptvc` зависит от `keydb` и запускается с командой `serve --check --repeat 0`.
|
||||
|
||||
Это поднимает веб-сервер и запускает бесконечную фоновую проверку.
|
||||
|
||||
## Запуск { id="start" }
|
||||
|
||||
После подготовки файлов соберите и запустите окружение из корня проекта:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Проверьте состояние контейнеров и журналы:
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose logs -f iptvc
|
||||
```
|
||||
|
||||
Веб-интерфейс приложения доступен на `http://localhost:8800`.
|
||||
|
||||
Документация доступна на `http://localhost:8801`.
|
||||
|
||||
Для остановки окружения выполните:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
## Сборка образа iptvc { id="image" }
|
||||
|
||||
Для публикации образа используйте скрипт `iptvc/build-docker-image.sh`.
|
||||
|
||||
Скрипт вычисляет версию из Git, собирает образы с тегами `iptvc:<тег>` и `git.axenov.dev/iptv/iptvc:<тег>`, а затем отправляет registry-тег в registry:
|
||||
|
||||
```bash
|
||||
cd iptvc
|
||||
./build-docker-image.sh latest
|
||||
```
|
||||
|
||||
Для публикации релизного тега:
|
||||
|
||||
```bash
|
||||
./build-docker-image.sh v1.2.3
|
||||
```
|
||||
|
||||
По умолчанию скрипт собирает Linux-образ для `amd64`.
|
||||
|
||||
Платформу можно изменить переменными окружения:
|
||||
|
||||
```bash
|
||||
GOOS=linux GOARCH=arm64 ./build-docker-image.sh v1.2.3
|
||||
```
|
||||
|
||||
Перед публикацией войдите в registry, если это требуется вашей настройкой:
|
||||
|
||||
```bash
|
||||
docker login git.axenov.dev
|
||||
```
|
||||
|
||||
!!! warning "Рабочее дерево Git"
|
||||
Скрипт переключается на Git-тег, переданный первым аргументом, или на тег, возвращённый `git describe`.
|
||||
Перед запуском сохраните локальные изменения и убедитесь, что нужный тег существует.
|
||||
|
||||
## Обновление { id="update" }
|
||||
|
||||
После изменения конфигурации или исходного кода пересоберите и перезапустите сервисы:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Чтобы пересобрать только приложение `iptvc`:
|
||||
|
||||
```bash
|
||||
docker compose build iptvc
|
||||
docker compose up -d iptvc
|
||||
```
|
||||
|
||||
Чтобы использовать опубликованный образ вместо локальной сборки, загрузите его и пересоздайте сервис:
|
||||
|
||||
```bash
|
||||
docker compose pull iptvc
|
||||
docker compose up -d iptvc
|
||||
```
|
||||
|
||||
Обновление документации выполняется пересборкой сервиса `docs`:
|
||||
|
||||
```bash
|
||||
docker compose build docs
|
||||
docker compose up -d docs
|
||||
```
|
||||
|
||||
## Диагностика { id="diagnostics" }
|
||||
|
||||
Для просмотра журналов отдельных сервисов используйте:
|
||||
|
||||
```bash
|
||||
docker compose logs -f iptvc
|
||||
docker compose logs -f keydb
|
||||
docker compose logs -f docs
|
||||
```
|
||||
|
||||
Для проверки конфигурации Compose выполните:
|
||||
|
||||
```bash
|
||||
docker compose config
|
||||
```
|
||||
|
||||
Если `iptvc` не подключается к кешу, проверьте, что в `.env` параметр `CACHE_HOST` имеет значение `keydb`, а сервис `keydb` запущен.
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
icon: material/table-eye
|
||||
tags: ["сайт", "статусы", "каналы"]
|
||||
---
|
||||
|
||||
# :material-table-eye: Страница плейлиста
|
||||
|
||||
Страница содержит подробности об одном конкретном плейлисте.
|
||||
|
||||
В её заголовке указано [название плейлиста](../../common/formats/playlists.md#name).
|
||||
|
||||
Ниже страница разделена на две части: слева две вкладки с информацией и список каналов справа.
|
||||
|
||||
Рассмотрим всё это подробнее.
|
||||
|
||||
## Вкладка "Основная информация"
|
||||
|
||||

|
||||
|
||||
На этой вкладке выводится таблица со следующими строками:
|
||||
|
||||
* **Код** — короткий уникальный [код плейлиста](../../common/formats/playlists.md#code);
|
||||
* **Описание** — [описание плейлиста](../../common/formats/playlists.md#desc) (при наличии);
|
||||
* **Ccылка для ТВ** — короткая ссылка, которую можно использовать для [подключения плейлиста](connect.md), подробнее о ней см. ниже;
|
||||
* **Источник** — [ссылка на ресурс](../../common/formats/playlists.md#src), где была найдена ссылка на плейлист (при наличии);
|
||||
* **Наполнение**:
|
||||
* группы — количество групп, на которые поделены каналы;
|
||||
* каналы — количества каналов общее, онлайн и оффлайн;
|
||||
(всё по нулям, если плейлист <span class="badge offline">offline</span>)
|
||||
* **Возможности** — наличие программы передач и перемотки каналов;
|
||||
* **M3U** — [прямая ссылка](../../common/formats/playlists.md#pls) на плейлист;
|
||||
* **Проверка плейлиста** — дата и время последней [проверки](../../aggregator/checks.md) плейлиста с помощью [iptvc](../overview.md);
|
||||
* **Ошибка проверки** — текст ошибки, которая возникла при проверке
|
||||
(только если плейлист <span class="badge offline">offline</span>)
|
||||
|
||||
Если при проверке плейлиста возникла ошибка, то она будет отображена красным цветом сразу под заголовком:
|
||||
|
||||
??? quote "Скриншот страницы с ошибкой"
|
||||

|
||||
|
||||
!!! info
|
||||
Если в тексте ошибки фигурирует слово `Timeout` и плейлист <span class="badge offline">offline</span> — это ерунда.
|
||||
Скорее всего, при следующей проверке статус позеленеет.
|
||||
Просто в момент проверки сервер не получил файл плейлиста вовремя, а т. к. долго ждать он не может, поэтому плюнул и пошёл проверять другие.
|
||||
|
||||
!!! info "Обрати внимание"
|
||||
Независимо от статуса плейлиста на сайте, его можно добавить в свой плеер по "Ссылке для ТВ" и проверить самостоятельно.
|
||||
Проверка плейлиста не влияет на его работоспособность.
|
||||
|
||||
## Вкладка "Исходный текст"
|
||||
|
||||

|
||||
|
||||
Здесь выводится плейлист как он есть.
|
||||
Над этим текстом — две кнопки:
|
||||
|
||||
* зелёная с кодом плейлиста для скачивания файла;
|
||||
* нажатие на **QR-код** покажет, внезапно, QR-код, в который закодирована "Ссылка для ТВ".
|
||||
|
||||
## Список каналов
|
||||
|
||||
В заголовке пишется их общее количество.
|
||||
|
||||

|
||||
|
||||
В списке всегда отображается не более 100 каналов.
|
||||
|
||||
Воспользуйтесь поиском, чтобы найти интересующий.
|
||||
|
||||
### Поиск каналов
|
||||
|
||||
Количество плейлистов в заголовке над списком учитывает найденные с помощью фильтров каналы.
|
||||
|
||||
Под заголовком есть **выпадающий список групп**.
|
||||
Он отображается только если плейлист поделён на группы.
|
||||
Справа — **кнопка сброса** для отображения всех каналов.
|
||||
|
||||
Под списком групп расположилась **строка поиска**.
|
||||
Она есть вообще всегда.
|
||||
Туда можно начать вводить название канала, и по мере ввода список будет сужаться.
|
||||
|
||||
Справа от строки поиска есть **кнопки фильтрации каналов по их статусу**.
|
||||
Справа — **кнопка сброса** для отображения всех каналов.
|
||||
|
||||
Под строкой поиска есть [**облако тегов**](../../common/formats/channels.md#доступные-теги).
|
||||
|
||||
!!! question inline end "Про теги"
|
||||
Откуда они там появляются, можешь прочесть [здесь](../../common/index.md) и [здесь](../overview.md).
|
||||
|
||||
На любой из них можно нажать, и тогда в списке останутся каналы только с выбранными тегами.
|
||||
Выбранные теги подсвечиваются серым.
|
||||
**Сбросить** выбор можно повторным нажатием на каждый, либо кнопкой сброса у строки поиска.
|
||||
|
||||
??? quote "Пример фильтрации"
|
||||

|
||||
|
||||
## Ссылка для ТВ { id="shortlink" }
|
||||
|
||||
Она может быть задана в нескольких форматах.
|
||||
Поясню базовые принципы формирования адреса:
|
||||
|
||||
1. необязателен префикс протокола `http://` или `https://` перед доменом
|
||||
2. обязателен домен `m3u.su`
|
||||
3. обязателен `/код` плейлиста после домена
|
||||
4. необязателен суффикс расширения после кода `.m3u` или `.m3u8`
|
||||
|
||||
На примере ниже я наглядно покажу все возможные ссылки на один и тот же плейлист с кодом `ru`:
|
||||
|
||||
```
|
||||
https://m3u.su/ru.m3u8
|
||||
https://m3u.su/ru.m3u
|
||||
https://m3u.su/ru
|
||||
http://m3u.su/ru.m3u8
|
||||
http://m3u.su/ru.m3u
|
||||
http://m3u.su/ru
|
||||
m3u.su/ru.m3u8
|
||||
m3u.su/ru.m3u
|
||||
m3u.su/ru
|
||||
```
|
||||
|
||||
!!! info "Адрес может быть любым"
|
||||
Смотря как будет развёрнут сайт, ты можешь заходить на localhost, либо по прямому IP-адресу или доменному имения.
|
||||
См. раздел [**Развёртывание**](deploy.md) для подробностей.
|
||||
|
||||
По идее, можешь использовать любую ссылку из подобных, т. к. технически они отработают одинаково.
|
||||
|
||||
А вот твой [плеер](../../common/players.md) может не принять какую-то из них.
|
||||
Так что, если не подойдёт один формат, используй другой — добавь префикс или суффикс.
|
||||
|
||||
Префикс плееру требуется чаще всего, потому что он при добавлении плейлиста проверяет — а ссылку ли мне вообще предоставил пользователь?
|
||||
|
||||
По наличию суффикса плеер может определить — а прямая ли это ссылка на файл плейлиста?
|
||||
Технически — нет, непрямая, потому что файла плейлиста у меня на сервере нет физически и сервер должен сделать редирект уже на сам плейлист.
|
||||
Но благодаря такой обманке плеер его наверняка подгрузит.
|
||||
|
||||
Или нет.
|
||||
@@ -0,0 +1,415 @@
|
||||
---
|
||||
title: Первые шаги
|
||||
icon: material/rocket-launch
|
||||
tags: ["iptvc", "serve", "сайт"]
|
||||
---
|
||||
|
||||
# :material-rocket-launch: Первые шаги для запуска сайта
|
||||
|
||||
В этой статье мы шаг за шагом запустим собственный сайт-агрегатор IPTV-плейлистов — от простейшего варианта до полной конфигурации с кешем и тонкой настройкой проверки.
|
||||
|
||||
Программа `iptvc` уже должна быть [установлена](../install.md).
|
||||
Все команды ниже выполняются в терминале из директории, где лежит бинарник.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 1. Запускаем пустой сайт
|
||||
|
||||
Минимальный запуск — одна команда:
|
||||
|
||||
```bash
|
||||
./iptvc serve
|
||||
```
|
||||
|
||||
Сайт откроется на `http://localhost:8080`.
|
||||
Это пустая страница: нет ни одного плейлиста, потому что программе пока неоткуда их взять.
|
||||
|
||||
Чтобы изменить порт или хост, не трогая файл конфигурации:
|
||||
|
||||
```bash
|
||||
./iptvc serve -p 3000 --host 0.0.0.0
|
||||
```
|
||||
|
||||
Подробнее об этих флагах — в [документации команды `serve`](../commands/serve.md).
|
||||
|
||||
---
|
||||
|
||||
## Шаг 2. Добавляем плейлисты
|
||||
|
||||
Список плейлистов описывается в файле [`playlists.ini`](../../common/formats/playlists.md).
|
||||
Создадим его рядом с `iptvc`:
|
||||
|
||||
```ini title="playlists.ini"
|
||||
[ru]
|
||||
name = Российские каналы
|
||||
desc = Основные федеральные каналы
|
||||
pls = 'https://example.com/ru.m3u'
|
||||
src = 'https://example.com/ru-playlist'
|
||||
|
||||
[movies]
|
||||
name = Фильмы
|
||||
pls = 'https://example.com/movies.m3u'
|
||||
```
|
||||
|
||||
Каждая секция `[code]` — это плейлист.
|
||||
Код используется в коротких ссылках вида `http://localhost:8080/ru`.
|
||||
Параметр `pls` обязателен, остальные — по желанию.
|
||||
|
||||
Теперь запустим:
|
||||
|
||||
```bash
|
||||
./iptvc serve
|
||||
```
|
||||
|
||||
Сайт покажет оба плейлиста, но их статус — `unknown` (неизвестно).
|
||||
Это нормально: программа знает о них, но ещё не проверяла.
|
||||
Чтобы статусы появились, нужно включить фоновую проверку.
|
||||
|
||||
!!! tip "Путь к ini-файлу"
|
||||
Если файл лежит не рядом с программой, укажите путь через флаг [`-i`](../commands/serve.md#ini) или в [`config.yml`](../../common/config/config.md) → `app.playlists`.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 3. Включаем фоновую проверку
|
||||
|
||||
Без проверки сайт просто показывает список.
|
||||
Чтобы плейлисты и каналы проверялись автоматически, добавим флаг `--check`:
|
||||
|
||||
```bash
|
||||
./iptvc serve --check
|
||||
```
|
||||
|
||||
Теперь программа в фоне загружает каждый плейлист, парсит каналы и проверяет их доступность.
|
||||
Результаты сразу попадают в оперативную память и отображаются на сайте.
|
||||
|
||||
Можно настроить интервал между циклами проверки:
|
||||
|
||||
```bash
|
||||
# пауза 120 секунд между циклами, бесконечно
|
||||
./iptvc serve --check --playlists-all-cooldown 120000
|
||||
|
||||
# проверить один раз и остановить
|
||||
./iptvc serve --check --repeat 1
|
||||
```
|
||||
|
||||
Если не хочется каждый раз писать `--check`, можно включить проверку через [`config.yml`](../../common/config/config.md):
|
||||
|
||||
```yaml title="config.yml"
|
||||
check:
|
||||
start-on-serve: true
|
||||
```
|
||||
|
||||
Тогда обычный `./iptvc serve` автоматически запустит фоновую проверку.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 4. Настраиваем внешний вид сайта
|
||||
|
||||
Сайт можно настроить под себя: заголовок, иконку, навигацию в шапке и ссылки в подвале.
|
||||
Всё это — в секции [`site`](../../common/config/config.md) файла `config.yml`.
|
||||
|
||||
```yaml title="config.yml"
|
||||
site:
|
||||
base-url: http://localhost:8080
|
||||
repo-url: https://git.axenov.dev/IPTV
|
||||
page-size: 20 # пагинация по 20 плейлистов на страницу (0 — без пагинации)
|
||||
favicon: /favicon.ico # путь к иконке
|
||||
header:
|
||||
title: Мой IPTV # заголовок в шапке и вкладке браузера
|
||||
navigation:
|
||||
- title: Документация
|
||||
url: /docs
|
||||
icon: document-text-outline
|
||||
- title: Telegram
|
||||
icon: paper-plane-outline
|
||||
children:
|
||||
- title: Канал
|
||||
url: https://t.me/my_channel
|
||||
icon: megaphone-outline
|
||||
- title: Чат
|
||||
url: https://t.me/my_chat
|
||||
icon: chatbubbles-outline
|
||||
footer-links:
|
||||
- title: Исходники
|
||||
url: https://git.axenov.dev/IPTV
|
||||
icon: code-slash-outline
|
||||
- title: Мой сайт
|
||||
url: https://example.com
|
||||
icon: person-outline
|
||||
```
|
||||
|
||||
--8<-- "ionicons-name.md"
|
||||
|
||||
!!! note "base-url"
|
||||
Параметр `base-url` используется для формирования внутренних ссылок.
|
||||
Если публикуете сайт на домене, укажите его здесь, например `https://my-iptv.ru`.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 5. Добавляем теги каналам
|
||||
|
||||
Теги помогают посетителям находить каналы по темам: спорт, фильмы, музыка и так далее.
|
||||
Правила описываются в файле [`channels.json`](../../common/formats/channels.md).
|
||||
|
||||
```json title="channels.json"
|
||||
[
|
||||
{
|
||||
"tvg-id": "^ru-",
|
||||
"tags": ["russian"]
|
||||
},
|
||||
{
|
||||
"title": "спорт",
|
||||
"tags": ["sport"]
|
||||
},
|
||||
{
|
||||
"title": "кино|фильм",
|
||||
"tags": ["film"]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Путь к файлу указывается в [`config.yml`](../../common/config/config.md) → `app.tags` или через флаг [`-t`](../commands/serve.md#tags):
|
||||
|
||||
```bash
|
||||
./iptvc serve --check -t /path/to/channels.json
|
||||
```
|
||||
|
||||
Полный список доступных тегов — в [справочнике по channels.json](../../common/formats/channels.md#доступные-теги).
|
||||
|
||||
---
|
||||
|
||||
## Шаг 6. Подключаем кеш (KeyDB/Redis)
|
||||
|
||||
По умолчанию результаты проверки хранятся только в оперативной памяти.
|
||||
Если программу перезапустить — все результаты пропадут, и плейлисты снова станут `unknown` до следующей проверки.
|
||||
|
||||
Кеш решает эту проблему: результаты сохраняются в KeyDB (или Redis) и переживают перезапуск.
|
||||
Включается одной строкой в [`config.yml`](../../common/config/config.md):
|
||||
|
||||
```yaml title="config.yml"
|
||||
cache:
|
||||
enabled: true
|
||||
host: localhost
|
||||
port: 6379
|
||||
ttl: 1800 # секунды (30 минут)
|
||||
```
|
||||
|
||||
Или через переменные окружения:
|
||||
|
||||
```bash
|
||||
CACHE_ENABLED=true CACHE_TTL=3600 ./iptvc serve --check
|
||||
```
|
||||
|
||||
Или через флаги:
|
||||
|
||||
```bash
|
||||
./iptvc serve --check --cache-enabled --cache-host 192.168.1.10 --cache-ttl 3600
|
||||
```
|
||||
|
||||
!!! tip "KeyDB или Redis"
|
||||
KeyDB — это форк Redis, полностью совместимый по протоколу.
|
||||
Подойдёт любой из них.
|
||||
Если кеш включён, но сервер недоступен — сайт продолжит работать, просто без кеширования.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 7. Тонкая настройка проверки
|
||||
|
||||
Когда плейлистов много, полезно управлять параллелизмом, таймаутами и задержками.
|
||||
Все параметры — в секции [`check`](../../common/config/config.md) файла `config.yml`.
|
||||
|
||||
### Параллелизм
|
||||
|
||||
```yaml title="config.yml"
|
||||
check:
|
||||
playlists:
|
||||
max-routines: 10 # сколько плейлистов проверять одновременно
|
||||
per-routine: 5 # сколько плейлистов в одной процедуре
|
||||
channels:
|
||||
max-routines: 100 # сколько каналов проверять одновременно
|
||||
per-routine: 20 # сколько каналов в одной процедуре
|
||||
```
|
||||
|
||||
Чем больше значения — тем быстрее проверка, но выше нагрузка на процессор и сеть.
|
||||
Начните со значений по умолчанию и увеличивайте при необходимости.
|
||||
|
||||
### Таймауты
|
||||
|
||||
```yaml title="config.yml"
|
||||
check:
|
||||
playlists:
|
||||
timeout: 10000 # мс на загрузку плейлиста
|
||||
channels:
|
||||
timeout: 10000 # мс на проверку одного канала
|
||||
byte-range: 512 # сколько байт скачать от сервера канала
|
||||
```
|
||||
|
||||
Если плейлисты или каналы медленные, увеличьте `timeout`.
|
||||
Если сервер блокирует большие запросы — уменьшите `byte-range`.
|
||||
|
||||
### Задержки (cooldown)
|
||||
|
||||
Чтобы не перегружать серверы-источники, между проверками можно делать паузы.
|
||||
Параметры поддерживают как фиксированное значение, так и диапазон `[min, max]` — тогда пауза будет случайной при каждом проходе:
|
||||
|
||||
```yaml title="config.yml"
|
||||
check:
|
||||
playlists:
|
||||
all-cooldown: 5000 # 5 секунд после всех плейлистов
|
||||
one-cooldown: [1000, 3000] # 1–3 секунды после каждого плейлиста
|
||||
channels:
|
||||
cooldown: [100, 500] # 100–500 мс после каждого канала
|
||||
```
|
||||
|
||||
### User-Agent
|
||||
|
||||
Некоторые серверы блокируют запросы без правильного User-Agent.
|
||||
Можно указать один или несколько — тогда при каждом запросе будет выбран случайный:
|
||||
|
||||
```yaml title="config.yml"
|
||||
check:
|
||||
playlists:
|
||||
user-agent:
|
||||
- Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer
|
||||
- Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36
|
||||
channels:
|
||||
user-agent: Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36
|
||||
```
|
||||
|
||||
Все эти параметры можно также задавать через [переменные окружения](../../common/config/config.md) или [CLI-флаги](../commands/serve.md) — они имеют наивысший приоритет.
|
||||
|
||||
---
|
||||
|
||||
## Полный пример
|
||||
|
||||
Соберём всё вместе в одном `config.yml`:
|
||||
|
||||
```yaml title="config.yml"
|
||||
app:
|
||||
timezone: GMT+3
|
||||
debug: false
|
||||
log_level: info
|
||||
playlists: ./playlists.ini
|
||||
tags: ./channels.json
|
||||
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8080
|
||||
|
||||
site:
|
||||
base-url: https://my-iptv.ru
|
||||
repo-url: https://git.axenov.dev/IPTV
|
||||
page-size: 20
|
||||
favicon: /favicon.ico
|
||||
header:
|
||||
title: Мой IPTV
|
||||
navigation:
|
||||
- title: Статус
|
||||
url: https://status.my-iptv.ru
|
||||
icon: pulse-outline
|
||||
- title: Документация
|
||||
url: /docs
|
||||
icon: document-text-outline
|
||||
- title: Telegram
|
||||
icon: paper-plane-outline
|
||||
children:
|
||||
- title: Канал
|
||||
url: https://t.me/my_channel
|
||||
icon: megaphone-outline
|
||||
- title: Чат
|
||||
url: https://t.me/my_chat
|
||||
icon: chatbubbles-outline
|
||||
footer-links:
|
||||
- title: Исходники
|
||||
url: https://git.axenov.dev/IPTV
|
||||
icon: code-slash-outline
|
||||
- title: Контакты
|
||||
url: https://example.com
|
||||
icon: person-outline
|
||||
|
||||
check:
|
||||
start-on-serve: true
|
||||
playlists:
|
||||
user-agent:
|
||||
- Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer
|
||||
- Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36
|
||||
timeout: 10000
|
||||
all-cooldown: 5000
|
||||
one-cooldown: [1000, 3000]
|
||||
max-routines: 10
|
||||
per-routine: 5
|
||||
channels:
|
||||
user-agent: Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36
|
||||
timeout: 10000
|
||||
byte-range: 512
|
||||
cooldown: [100, 500]
|
||||
max-routines: 100
|
||||
per-routine: 20
|
||||
|
||||
cache:
|
||||
enabled: true
|
||||
host: localhost
|
||||
port: 6379
|
||||
ttl: 3600
|
||||
```
|
||||
|
||||
Запуск:
|
||||
|
||||
```bash
|
||||
./iptvc serve
|
||||
```
|
||||
|
||||
Поскольку `start-on-serve: true`, фоновая проверка запустится автоматически.
|
||||
Кеш включён, так что результаты переживут перезапуск.
|
||||
Сайт доступен на `http://0.0.0.0:8080`.
|
||||
|
||||
---
|
||||
|
||||
## Docker
|
||||
|
||||
Удобно запускать сайт в контейнере. Образ `iptvc` уже включает бинарник:
|
||||
|
||||
```yaml title="compose.yml"
|
||||
services:
|
||||
iptvc:
|
||||
image: git.axenov.dev/iptv/iptvc:latest
|
||||
command: [serve]
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./config.yml:/app/config.yml:ro
|
||||
- ./playlists.ini:/app/playlists.ini:ro
|
||||
- ./channels.json:/app/channels.json:ro
|
||||
environment:
|
||||
- CHECK_START_ON_SERVE=true
|
||||
- CACHE_ENABLED=true
|
||||
- CACHE_HOST=keydb
|
||||
- CACHE_PORT=6379
|
||||
|
||||
keydb:
|
||||
image: eqalpha/keydb:latest
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Подробнее об установке образа — в [документации по установке](../install.md).
|
||||
|
||||
---
|
||||
|
||||
## Краткая шпаргалка
|
||||
|
||||
| Задача | Как |
|
||||
| ----------------------------- | ------------------------------------------------------- |
|
||||
| Запустить сайт | `./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 120000` |
|
||||
| Подробные логи | `./iptvc serve --check --verbose` |
|
||||
|
||||
Полный список параметров — в [справочнике по `config.yml`](../../common/config/config.md), [переменным окружения](../../common/config/config.md) и [команде `serve`](../commands/serve.md).
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
icon: material/cogs
|
||||
tags: ["плейлисты", "каналы", "теги", "iptvc", "плееры", "сайт"]
|
||||
---
|
||||
|
||||
# :material-cogs: Как работает сервис
|
||||
|
||||
1. В специальном файле [playlists.ini](../../common/formats/playlists.md) описываются плейлисты, которые кем-то опубликованы в интернете.
|
||||
Каждому плейлисту присваивается свой уникальный **короткий код**.
|
||||
2. В специальном файле [channels.json](../../common/formats/channels.md) описываются **ключевые слова** (метки, теги), которые характеризуют каналы.
|
||||
3. В фоновом режиме [работает ПО](../overview.md), которое периодически [проверяет все плейлисты](../../aggregator/checks.md) из п. 1 и **присваивает теги** каналам из п. 2.
|
||||
4. На главной странице сайта выводится [весь список плейлистов](list.md), которые описаны в п. 1: с тегами, описаниями и короткими кодами.
|
||||
5. Каждому плейлисту на сайте посвящена [своя страничка](details.md), где отображаются результаты его проверки, проверки его каналов (с присвоенными тегами) и пр.
|
||||
6. Когда пользователь [обращается к плейлисту](connect.md) по короткому коду (например, `https://m3u.su/xyz`), то происходит **переадресация** на исходный плейлист.
|
||||
|
||||
Более подробную информацию ты можешь прочесть в соответствующих разделах документации.
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
icon: fontawesome/solid/list-check
|
||||
tags: ["сайт", "плейлисты"]
|
||||
---
|
||||
|
||||
# :fontawesome-solid-list-check: Список плейлистов
|
||||
|
||||
Это главная страница сайта.
|
||||
|
||||

|
||||
|
||||
Наверху отображаются:
|
||||
|
||||
* дата последнего изменения файла [playlists.ini](../../common/formats/playlists.md)
|
||||
* общее количество плейлистов и с разделением по статусам.
|
||||
|
||||
Ниже — спиcок плейлистов.
|
||||
|
||||
## Из чего состоит список
|
||||
|
||||
* **Код** — короткий уникальный [код плейлиста](../../common/formats/playlists.md#code)
|
||||
* **Информация о плейлисте**
|
||||
* [статус плейлиста](../../aggregator/checks.md#playlists)
|
||||
* может быть [значок 18+](../../aggregator/checks.md#adult)
|
||||
* [название плейлиста](../../common/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>)
|
||||
* ещё одна ссылка на [страницу плейлиста](details.md)
|
||||
* **Каналов** — фактическое количество каналов в плейлисте (только при статусе <span class="badge online">online</span>) или 0 (при других статусах)
|
||||
* **Ссылка для ТВ** — [короткая ссылка](details.md#shortlink), которую можно использовать для [подключения плейлиста](connect.md).
|
||||
|
||||
В зависимости от ширины экрана, для экономии места может быть скрыто описание с иконками возможностей и короткая ссылка.
|
||||
|
||||

|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
icon: material/wallet-outline
|
||||
---
|
||||
|
||||
# :material-wallet-outline: Правообладателям
|
||||
|
||||
Данные, представленные на сайте https://m3u.su, получены автоматически из открыто доступных в интернете IPTV-плейлистов, опубликованных третьими лицами.
|
||||
При наличии технической возможности, источник плейлиста может быть указан на вкладке [«Основные данные»](../iptvc/site/details.md).
|
||||
|
||||
Сервис https://m3u.su не размещает и не транслирует медиаконтент, не создаёт, не призывает использовать и распространять плейлисты третьих лиц, а также не оказывает услуг по ретрансляции телепрограмм.
|
||||
|
||||
Подробности о проекте и о том, как здесь оказались объекты ваших прав, читайте на страницах этой документации.
|
||||
|
||||
Информация о телеканалах (наименования, логотипы, технический статус и другие сведения) формируется исключительно путём обработки содержимого самого плейлиста.
|
||||
Вся информация носит технический и ознакомительный характер, и её достоверность не гарантируется.
|
||||
|
||||
Все права на торговые марки и графические изображения принадлежат их законным владельцам.
|
||||
Если вы являетесь правообладателем и считаете, что сведения на этой странице затрагивают ваши права, вы можете направить конфиденциальное уведомление на адрес **<abuse@m3u.su>**.
|
||||
|
||||
Плейлисты, нарушающие законодательство, удаляются с сайта окончательно по факту обращения от правообладателя.
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: Свободное ПО
|
||||
icon: material/license
|
||||
---
|
||||
|
||||
# Лицензии свободного ПО
|
||||
|
||||
Весь этот проект, включая документацию, основан на свободном программном обеспечении.
|
||||
|
||||
Ниже перечислен полный список этих проектов с их текстами лицензий.
|
||||
|
||||
??? quote "[microsoft/vscode-codicons](https://github.com/microsoft/vscode-codicons/blob/main/LICENSE) — Creative Commons Attribution 4.0 International"
|
||||
```
|
||||
--8<-- "licenses/vscode-codicons.txt"
|
||||
```
|
||||
|
||||
??? quote "[ionic-team/ionicons](https://github.com/ionic-team/ionicons/blob/master/LICENSE) — MIT"
|
||||
```
|
||||
--8<-- "licenses/ionicons.txt"
|
||||
```
|
||||
|
||||
??? quote "[zensical/zensical](https://github.com/zensical/zensical/blob/master/LICENSE.md) — MIT"
|
||||
```
|
||||
--8<-- "licenses/zensical.txt"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Я благодарю каждого, кто вносит свой посильный вклад в open-source и развивает подобного рода проекты.
|
||||
Ваш труд лежит в основе технологического прогресса.
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Лицензия
|
||||
icon: material/license
|
||||
---
|
||||
|
||||
# MIT License
|
||||
|
||||
=== "Оригинальный текст"
|
||||
|
||||
```plaintext { .wordwrap }
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025-2026 Антон Аксенов (Anthony Axenov)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
|
||||
=== "Русский перевод"
|
||||
|
||||
```plaintext { .wordwrap }
|
||||
Лицензия MIT
|
||||
|
||||
Copyright (c) 2025-2026 Антон Аксенов (Anthony Axenov)
|
||||
|
||||
Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий:
|
||||
|
||||
Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения.
|
||||
|
||||
ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
|
||||
```
|
||||
|
||||
!!! tip "[Построчный разбор лицензии MIT](https://habr.com/ru/articles/310976/)"
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
icon: material/robot-outline
|
||||
tags: ["telegram"]
|
||||
---
|
||||
|
||||
# :material-robot-outline: Telegram-бот
|
||||
|
||||
Позволяет получать информацию с сайта, не выходя из Telegram.
|
||||
Функционал тот же, что у сайта, но информацию выдаёт компактнее, чтобы умещаться в лимиты мессенджера и не перегружать чат.
|
||||
|
||||
> Открыть: [@iptv_aggregator_bot](https://t.me/iptv_aggregator_bot)
|
||||
|
||||
## Команды
|
||||
|
||||
### `/start`
|
||||
|
||||
Стандартное начало работы.
|
||||
|
||||
Позволяет отправлять другие команды.
|
||||
|
||||
### `/help`
|
||||
|
||||
Помощь по использованию бота.
|
||||
|
||||
!!! warning "Запомни эту команду!"
|
||||
В любой непонятной ситуации обращайся к ней.
|
||||
|
||||
### `/links`
|
||||
|
||||
Список ссылок на все ресурсы, связанные с проектом, для быстрого перехода.
|
||||
|
||||
### `/list`
|
||||
|
||||
Список всех кодов плейлистов и их статусов.
|
||||
|
||||
### `/info <XYZ>`
|
||||
|
||||
Информация о плейлисте c кодом `XYZ`:
|
||||
|
||||
* статус и название плейлиста (ссылкой на сайт);
|
||||
* время и результат последней проверки;
|
||||
* количество каналов (всех/онлайн/оффлайн)
|
||||
* возможности плейлиста (перемотка, телепрограмма);
|
||||
* список групп и тегов (при наличии);
|
||||
* ссылки для ТВ.
|
||||
|
||||
### `/stats`
|
||||
|
||||
Небольшая статистика на текущий момент по всем плейлистам, которые доступны в сервисе.
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
icon: material/message-check
|
||||
tags: ["telegram"]
|
||||
---
|
||||
|
||||
# :material-message-check: Telegram-чат
|
||||
|
||||
## Правила
|
||||
|
||||
* 🇷🇺 Говорим по-русски (Russian lang only)
|
||||
* ✅ Уважаем друг друга
|
||||
* ✅ Ведём себя культурно
|
||||
* ✅ Говорим по делу и по теме
|
||||
* ✅ [neprivet.com](https://neprivet.com)
|
||||
* ✅ [nometa.xyz](https://nometa.xyz)
|
||||
* ✅ [novoice.me](https://novoice.me)
|
||||
* ❌ Не спамим, не флудим
|
||||
* ❌ Не нарушаем законов РФ и здравого смысла
|
||||
* ❌ Ботов не тащим (бан)
|
||||
* ❌ Никакой иероглифики или арабицы (бан)
|
||||
* ❌ Никаких войсов, кружочков, игр, контактов, историй или локаций (предупреждение)
|
||||
* ❌ Не удаляй свои сообщения, если на них успели ответить (предупреждение)
|
||||
|
||||
🔶 Настоятельно рекомендуется прочесть хотя бы FAQ, а лучше всю документацию. Там наверняка уже давно есть ответ, который ты ищешь. Санитарка Роза или админ могут реагировать на твои сообщения и применять меры на своё усмотрение.
|
||||
|
||||
!!! failure "Не забывай"
|
||||
К людям надо относиться по-человечески.
|
||||
Твой юмор могут не понять, а пассивную агрессию и дерзость не любит никто.
|
||||
|
||||
## Я только спросить! { id="checklist" }
|
||||
|
||||
Держи чеклист:
|
||||
|
||||
1. **Найди ответ в [FAQ](../aggregator/faq.md)**
|
||||
2. Если не нашёл ответ — прочти остальное
|
||||
3. Если не нашёл ответ и это проблема:
|
||||
* опиши всю ситуацию — сухо и по существу, в чём проблема, чего хочешь и ожидаешь;
|
||||
* если вопрос связан с плейлистом из сервиса — приложи его код и ссылку, которую указываешь в плеере;
|
||||
* если вопрос связан с другим плейлистом — приложи его ссылку;
|
||||
* если вопрос связан с плеером — укажи хотя бы его название;
|
||||
* если есть возможность, приложи скриншот или чёткое фото — чтобы можно было разглядеть проблему и подсказать решение.
|
||||
|
||||
!!! info "Скорее всего, это надо только тебе"
|
||||
Чем больше ты предоставишь полезной информации, тем лучше.
|
||||
Не заставляй выдирать её из тебя клещами.
|
||||
|
||||
И помни, что тебе не обязаны отвечать.
|
||||
Ну, потому что.
|
||||
|
||||
В группе работает бот-модератор и админ.
|
||||
При вступлении в группу нужно явно подтвердить согласие с правилами.
|
||||
|
||||
> Открыть чат: [@iptv_aggregator_chat](https://t.me/iptv_aggregator_chat)
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
icon: simple/telegram
|
||||
hide: [toc]
|
||||
---
|
||||
|
||||
# :simple-telegram: Ресурсы в Telegram
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
- [:material-robot-outline: Бот](bot.md)
|
||||
|
||||
---
|
||||
Получай доступ к плейлистам и делись ими с друзьями, не выходя из мессенджера
|
||||
|
||||
- [:material-message-check: Чат](chat.md)
|
||||
|
||||
---
|
||||
Попроси о помощи у других пользователей или сообщи разработчику о проблеме
|
||||
</div>
|
||||