Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
f25e128299
|
@@ -0,0 +1,387 @@
|
||||
---
|
||||
name: koda-zensical
|
||||
description: Навык, который необходим для работы в этом репозитории и должен закружаться безусловно. Этот навык содержит инструкции, которые позволят правильно писать и форматировать исходные файлы документации.
|
||||
---
|
||||
|
||||
# Документирование
|
||||
|
||||
## Принципы написания документации
|
||||
|
||||
### Язык и стиль
|
||||
|
||||
- Пиши простым и понятным языком
|
||||
- Избегай просторечий и сложных технических терминов без объяснения
|
||||
- Используй активный залог
|
||||
- Обращайся к пользователю на "вы"
|
||||
- Поддерживай единый стиль во всех документах
|
||||
- Не злоупотребляй emoji
|
||||
|
||||
### Примеры
|
||||
|
||||
- Приводи примеры конфигурации
|
||||
- Показывай скриншоты для важных шагов
|
||||
- Добавляй таблицы для сравнения опций
|
||||
|
||||
### Исправление и избегание ошибок
|
||||
|
||||
- Синтаксические и грамматические ошибки должны исправляться в соответствии с правиламии и нормами естественного языка
|
||||
- При изменении структуры документации:
|
||||
- в новый документ следует добавить ссылки на другие релевантные документы или якоря
|
||||
- ссылки на перемещённый или удалённый документ/якорь следует обновить в каждом существующем документе
|
||||
- следует проверять вывод команды `make site` на наличие ошибок и предупреждений компилятора
|
||||
|
||||
## Синтаксис файлов
|
||||
|
||||
В основе документации лежит расширенный markdown.
|
||||
|
||||
Ниже описаны правила оформления и синтаксиса, которые отличаются от стандартного markdown и github-flavoured markdown.
|
||||
|
||||
Расширения синтаксиса предоставляются связкой:
|
||||
|
||||
- `zensical` (документация: <https://zensical.org/docs/>)
|
||||
- `pymdown-extensions` (документация: <https://facelessuser.github.io/pymdown-extensions>)
|
||||
|
||||
Ниже только необходимые и достаточные правила:
|
||||
|
||||
- для качественной документации;
|
||||
- хорошего человеческого восприятия;
|
||||
- корректного формирования документации без ошибок.
|
||||
|
||||
Применение этих подходов необязательно, но требования к каждому требуется соблюдать строго.
|
||||
|
||||
Если приведены ссылки на документацию, можешь использовать их для получения актуальной информации.
|
||||
Там так же могут быть описаные дополнительные приёмы для работы с документами.
|
||||
|
||||
### Frontmatter
|
||||
|
||||
Каждый документ должен начинаться с этого блока метаданных.
|
||||
|
||||
После frontmatter должна быть пустая строка.
|
||||
|
||||
Внутри должен быть валидный yaml.
|
||||
Часто используются следующие опциональные параметры (* — желательны):
|
||||
|
||||
- *`title` — укорочечнное название документа для отображения в навигации (умолчание — заголовок 1 уровня)
|
||||
- *`description` — небольшое осмысленное описание документа (умолчание — пусто)
|
||||
- *`icon` — код иконки для отображения в навигации рядом с названием (умолчание — пусто)
|
||||
- *`tags` — массив ключевых слов (тегов), описывающих документ (умолчание — пусто)
|
||||
- `hide` — массив кодов элементов, которые нужно скрыть на странице документа:
|
||||
- `navigation` — главная навигация (слева)
|
||||
- `toc` — содержание страницы (справа)
|
||||
- `path` — хлебные крошки (сверху)
|
||||
- `status` — статус страницы (добавляет к пункту навигации слева иконку с подсказкой)
|
||||
- `new` — новая информация
|
||||
- `deprecated` — устаревшая информация
|
||||
- `beta` — информация о нестабильном функционале
|
||||
|
||||
Параметр `title` не должен быть равен заголовку первого уровня.
|
||||
В таком случае `title` следует убрать или не добавлять.
|
||||
|
||||
### Заголовки
|
||||
|
||||
На странице должен быть только один заголовок 1 уровня — сразу после Frontmatter.
|
||||
|
||||
До и после каждого заголовка должна быть 1 пустая строка.
|
||||
|
||||
В конце строки заголовка должно быть объявление в формате:
|
||||
`{ id="header-slug" }`
|
||||
|
||||
### Абзацы
|
||||
|
||||
До и после каждого абзаца должна быть 1 пустая строка.
|
||||
|
||||
Каждое предложение внутри абзаца должно быть на новой строке.
|
||||
|
||||
### Списки
|
||||
|
||||
Вложенные уровни отступаются на 4 пробела слева.
|
||||
|
||||
До и после каждого списка должна быть 1 пустая строка.
|
||||
|
||||
Ненумерованные списки начинаются с `-`.
|
||||
|
||||
### Многострочные блоки кода
|
||||
|
||||
До и после каждого блока кода должна быть 1 пустая строка.
|
||||
|
||||
Каждый блок кода в заголовке может иметь атрибуты:
|
||||
|
||||
- `title="..."` — заголовок блока (например, название файла)
|
||||
- `hl_lines="..."` — подсветка срок: номера через пробел и/или диапазоны через `-`
|
||||
- `linenums="N"` — включить нумерацию строк, отсчитывая с указанного числа `N`
|
||||
|
||||
В конце строк внутри блока может быть любое число в формате `#(X)!` — это кликальбельные аннотации, содержимое которых будет взято из ближайшего нумерованного списка.
|
||||
|
||||
Полный пример:
|
||||
|
||||
```yaml title="config.yaml" hl_lines="6 8-10 13 17-20" linenums="1"
|
||||
context:
|
||||
- provider: code
|
||||
# - provider: docs # сломан
|
||||
- provider: diff #(2)!
|
||||
- provider: terminal
|
||||
- provider: problems
|
||||
- provider: folder
|
||||
- provider: codebase
|
||||
params:
|
||||
nFinal: 10
|
||||
# - provider: file
|
||||
# - provider: url
|
||||
# - provider: search #(1)!
|
||||
```
|
||||
|
||||
1. Подсказка 1
|
||||
2. **Подсказка** 2
|
||||
|
||||
### Врезки
|
||||
|
||||
Позволяют акцентировать внимание на ключевых моментах, выделяя блок цветом и иконкой.
|
||||
|
||||
Документация: <https://raw.githubusercontent.com/zensical/docs/master/docs/authoring/admonitions.md>
|
||||
|
||||
Синтаксис:
|
||||
|
||||
```
|
||||
!!! <тип> "Заголовок статичной врезки"
|
||||
Содержимое, которое может
|
||||
быть многострочным
|
||||
|
||||
??? <тип> "Заголовок разворачиваемой врезки"
|
||||
Содержимое, которое может быть многострочным
|
||||
и свёрнуто по умолчанию, но разворачивается по клику на заголовке
|
||||
|
||||
???+ <тип> "Заголовок сворачиваемой врезки"
|
||||
Содержимое, которое может быть многострочным
|
||||
и развёрнуто по умолчанию, но сворачивается по клику на заголовке
|
||||
```
|
||||
|
||||
Типы, их цвета и пиктограммы:
|
||||
|
||||
| Тип | Цвет | Пиктограмма |
|
||||
| ---------- | ------- | ------------------ |
|
||||
| `note` | #448aff | карандаш в круге |
|
||||
| `abstract` | #00b0ff | планшет для бумаги |
|
||||
| `info` | #00b8d4 | `i` в круге |
|
||||
| `tip` | #00bfa5 | пламя |
|
||||
| `success` | #00c853 | галочка |
|
||||
| `question` | #64dd17 | `?` в круге |
|
||||
| `warning` | #ff9100 | `!` в треугольнике |
|
||||
| `failure` | #ff5252 | крестик |
|
||||
| `danger` | #ff1744 | молния в круге |
|
||||
| `bug` | #f50057 | жук на щите |
|
||||
| `example` | #7c4dff | пробирка |
|
||||
| `quote` | #9e9e9e | двойная кавычка |
|
||||
|
||||
Заголовок может быть пустым, в этом случае:
|
||||
|
||||
- после типа указываются пустые двойные кавычки (иначе подставится название типа с заглавной буквы на английском языке)
|
||||
- содержимое внутри блока обрамлён цветом своего типа
|
||||
|
||||
Если текста внутри врезки нет, отображается только яркий заголовок с иконкой.
|
||||
|
||||
Содержимое врезки отступается минимум на 4 пробела.
|
||||
Содержимое без отступа (в начале строки) находится вне врезки.
|
||||
|
||||
Для содержимого врезки распространяются все те же markdown-правила, включая указанные в этом документе.
|
||||
|
||||
До и после каждой врезки должна быть 1 пустая строка.
|
||||
|
||||
### Сниппеты
|
||||
|
||||
Это переиспользуемые блоки markdown/html, хранящиеся в файлах.
|
||||
|
||||
- Директория: `snippets` в корне проекта
|
||||
- Документация: <https://raw.githubusercontent.com/facelessuser/pymdown-extensions/refs/heads/main/pymdownx/snippets.py>
|
||||
|
||||
Как использовать:
|
||||
|
||||
1. создать файл с директории
|
||||
2. наполнить содержимым
|
||||
3. во всех местах документации вставить:
|
||||
- пустая строка
|
||||
- `--8<-- "filename.md"`
|
||||
- пустая строка
|
||||
4. если файлов несколько, вставить следующим образом:
|
||||
- пустая строка
|
||||
- `--8<--`
|
||||
- `"filename1.md"`
|
||||
- пустая строка
|
||||
- `"filename2.md"`
|
||||
- `--8<--`
|
||||
- пустая строка
|
||||
|
||||
### Иконки
|
||||
|
||||
Каждая иконка определяется своим идентификатором, который делится на две части: код набора и код иконки.
|
||||
|
||||
Внутри frontmatter (параметр `icon`) используется формат: `набор/иконка`
|
||||
|
||||
В тексте документа используется формат: `:набор-иконка:`
|
||||
|
||||
Если иконка в начале строки, пробел ставится только после неё.
|
||||
Если иконка в середине строки, пробелы ставятся до и после неё.
|
||||
Если иконка в конце строки, пробел ставятся только до неё.
|
||||
|
||||
Доступны 4 встроенных набора иконок:
|
||||
|
||||
| Название | Код набора | Ссылка | Путь в проекте |
|
||||
| --------------- | ------------- | ---------------------------------------------- | --------------------------- |
|
||||
| Lucide | `lucide` | <https://lucide.dev/icons/> | - |
|
||||
| Material Design | `material` | <https://pictogrammers.com/library/mdi/> | - |
|
||||
| FontAwesome | `fontawesome` | <https://fontawesome.com/search> | - |
|
||||
| Octicons | `octicons` | <https://primer.style/octicons/> | - |
|
||||
| Simple Icons | `material` | <https://simpleicons.org/> | - |
|
||||
| VSCode Codicons | `vscode` | <https://github.com/microsoft/vscode-codicons> | `./overrides/.icons/vscode` |
|
||||
|
||||
Полный список названий иконок здесь: <https://squidfunk.github.io/mkdocs-material/assets/javascripts/iconsearch_index.json>
|
||||
|
||||
Получить полный список иконок в этих наборах можно прочитав содержимое указанных директорий в проекте.
|
||||
|
||||
### Гриды (карточки)
|
||||
|
||||
Грид позволяет разместить короткие предложения в формате динамических карточек.
|
||||
|
||||
Он выглядит как markdown-список, обрамлённый в `<div>`.
|
||||
До открывающего и после закрывающего тегов должна быть 1 пустая строка.
|
||||
|
||||
Пример простого грида с компактными карточками:
|
||||
|
||||
```
|
||||
<div class="grid cards" markdown>
|
||||
- :fontawesome-brands-html5: Карточка №1
|
||||
- :fontawesome-brands-js: Карточка №2
|
||||
- :fontawesome-brands-css3: Карточка №3
|
||||
- :fontawesome-brands-internet-explorer: Карточка №4
|
||||
</div>
|
||||
```
|
||||
|
||||
Пример грида с многострочными карточками:
|
||||
|
||||
```
|
||||
<div class="grid cards" markdown>
|
||||
- :fontawesome-brands-html5: **Заголовок карточки №1**
|
||||
|
||||
---
|
||||
|
||||
Многострочное содержимое карточки №1
|
||||
|
||||
- :fontawesome-brands-js: **Заголовок карточки №2**
|
||||
|
||||
---
|
||||
|
||||
Многострочное содержимое карточки №2
|
||||
|
||||
- :fontawesome-brands-css3: **Заголовок карточки №3**
|
||||
|
||||
---
|
||||
|
||||
Многострочное содержимое карточки №3
|
||||
|
||||
- :fontawesome-brands-internet-explorer: **Заголовок карточки №4**
|
||||
|
||||
---
|
||||
|
||||
Многострочное содержимое карточки №4
|
||||
</div>
|
||||
```
|
||||
|
||||
### Вкладки (табы)
|
||||
|
||||
Позволяют уместить информацию на одном уровне, не растягивая страницу по высоте.
|
||||
|
||||
Синтаксис:
|
||||
|
||||
```
|
||||
=== "Заголовок вкладки 1"
|
||||
Содержимое вкладки 1
|
||||
|
||||
=== "Заголовок вкладки 2"
|
||||
Содержимое вкладки 2
|
||||
```
|
||||
|
||||
Содержимое вкладки отступается минимум на 4 пробела.
|
||||
Содержимое без отступа (в начале строки) находится вне вкладки.
|
||||
|
||||
Для содержимого вкладки распространяются все те же markdown-правила, включая указанные в этом документе.
|
||||
|
||||
До и после каждого заголовка вкладки должна быть 1 пустая строка.
|
||||
|
||||
После содержимого последней вкладки должна быть 1 пустая строка.
|
||||
|
||||
### Сноски
|
||||
|
||||
Сноска позволяет добавить надстрочный индекс к слову, чтобы вынести пояснения в конец страницы, быстро переместиться к нему по клику на индекс и вернуться обратно.
|
||||
|
||||
Синтаксис:
|
||||
|
||||
```
|
||||
Lorem[^1] ipsum[^2] dolor sit amet, consectetur adipiscing elit.
|
||||
|
||||
[^1]: однострочная сноска
|
||||
[^2]:
|
||||
многострочная сноска
|
||||
с отступом 4 пробела слева
|
||||
на каждой строке
|
||||
```
|
||||
|
||||
### Подсказки (тултипы) и аббревиатуры
|
||||
|
||||
Они появляются при наведении мыши на какой-либо элемент на странице документа.
|
||||
|
||||
Пример 1: иконка с подсказкой:
|
||||
`:material-information-outline:{ title="текст подсказки" }`
|
||||
|
||||
Пример 2: ссылка с подсказкой:
|
||||
`[Hover me](https://example.com "I'm a tooltip!")`
|
||||
|
||||
Пример 3: альтернативная ссылка с подсказкой:
|
||||
|
||||
```
|
||||
[Hover me][example]
|
||||
|
||||
[example]: https://example.com "I'm a tooltip!"
|
||||
```
|
||||
|
||||
### Горячие клавиши
|
||||
|
||||
В общем случае, для указания корячих клавиш следует использовать тег `<kbd>`.
|
||||
Примеры: `<kbd>B</kbd>`, `<kbd>Esc</kbd>`
|
||||
|
||||
Для описания комбинаций клавиш следует вставлять между каждой клавишей знак `+`, обрамлённый пробелами.
|
||||
Примеры: `<kbd>Shift</kbd> + <kbd>A</kbd>`, `<kbd>Ctrl</kbd> + <kbd>K</kbd> + <kbd>4</kbd>`
|
||||
|
||||
Для MacOS-специфичных тем вставлять `+` не нужно.
|
||||
Примеры: `<kbd>⌘</kbd><kbd>C</kbd>`, `<kbd>⇧</kbd><kbd>⌘</kbd><kbd>P</kbd>`
|
||||
|
||||
Сопоставление пиктограмм с названиями клавиш (служебных и модификаторов) MacOS:
|
||||
|
||||
- Базовые модификаторы:
|
||||
- `⌘` - `Command` (`Cmd`)
|
||||
- `⌥` - `Option` (`Alt`)
|
||||
- `⌃` - `Control` (`Ctrl`)
|
||||
- `⇧` - `Shift`
|
||||
- `⇪` - `Caps Lock`
|
||||
- Навигация и управление:
|
||||
- `⌫` - `Delete` (Backspace, удаление символа слева)
|
||||
- `⌦` - `Forward Delete` (удаление символа справа, `Fn` + D`elete)
|
||||
- `⏎` - `Return` (`Enter`)
|
||||
- `⌕` - `Enter` на цифровой клавиатуре (в некоторых шрифтах)
|
||||
- `⎋` - `Escape` (`Esc`)
|
||||
- `⇥` - `Tab` (Табуляция)
|
||||
- `⇤` - `Backtab` (`Shift` + `Tab`)
|
||||
- `␣` - `Space` (Пробел)
|
||||
- Перемещение по тексту:
|
||||
- `↖` - `Home` (Начало документа, `Fn` + `←`)
|
||||
- `↘` - `End` (Конец документа, `Fn` + `→`)
|
||||
- `⇞` - `Page Up` (Страница вверх, `Fn` + `↑`)
|
||||
- `⇟` - `Page Down` (Страница вниз, `Fn` + `↓`)
|
||||
- Специальные и системные:
|
||||
- `🌐` / `fn` — Функция (`Fn` / Кнопка смены языка/вызова эмодзи)
|
||||
- `⏏` — `Eject` (Извлечение диска)
|
||||
|
||||
### Кнопки
|
||||
|
||||
- `[Серая кнопка](https://example.com/){ .md-button }`
|
||||
- `[Синяя кнопка](https://example.com/){ .md-button .md-button--primary }`
|
||||
- `[:fontawesome-solid-paper-plane: Кнопка серая с иконкой](https://example.com/){ .md-button }`
|
||||
- `[:fontawesome-solid-paper-plane: Кнопка синяя с иконкой](https://example.com/){ .md-button .md-button--primary }`
|
||||
@@ -0,0 +1,6 @@
|
||||
/.git
|
||||
/.gitea
|
||||
/.gitignore
|
||||
/.cache
|
||||
Makefile
|
||||
.DS_Store
|
||||
@@ -0,0 +1,18 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yaml,yml}]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
@@ -1,2 +1,4 @@
|
||||
/.cache
|
||||
/site
|
||||
/.cache/
|
||||
/site/
|
||||
/__pycache__/
|
||||
.DS_Store
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
- Всегда используй навык koda-zensical
|
||||
- Всегда перечитывай файлы перед каждым изменением - пользователь уже мог внести изменения
|
||||
- При изменениях структуры проекта всегда актуализируй AGENTS.md
|
||||
- |
|
||||
В структуре навигации файла `zensical.toml` всегда должен присутствовать закомментированный раздел `Debug`.
|
||||
Это отладочные страницы с примерами, которые не должны попасть в итоговую документацию.
|
||||
Этот раздел раскомментируется вручную по необходимости.
|
||||
- |
|
||||
Для отладки используй команду `make site`.
|
||||
В выводе команды могу быть предупреждения и ошибки в следующем формате:
|
||||
|
||||
```
|
||||
Warning: page does not exist
|
||||
╭─[ test.md:695:10 ]
|
||||
│
|
||||
695 │ - [Edit](../edit/how-to-use-it.md) — редактирование кода
|
||||
│ ────────────┬───────────
|
||||
│ ╰───────────── page does not exist
|
||||
─────╯
|
||||
```
|
||||
что означает буквально следующее: "в файле content/test.md в строке 695 в позиции 10 есть ссылка на несуществующую страницу."
|
||||
Эти предупреждения надо всегда исправлять.
|
||||
|
||||
- При изменениях структуры проекта и только при корректной сборке (без предупреждений и ошибок) всегда актуализируй `./AGENTS.md`
|
||||
- При доработке или расширении функционала этого проекта или синтаксиса всегда актуализируй скилл `./.agents/skills/koda-zensical`
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"editorconfig.editorconfig",
|
||||
"mhutchie.git-graph",
|
||||
"golang.go",
|
||||
"koda.koda",
|
||||
"0x10.mkdocs-material-preview",
|
||||
"redhat.vscode-yaml",
|
||||
"takumii.markdowntable",
|
||||
"tamasfe.even-better-toml"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.md": "python-markdown"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Живой предпросмотр (localhost:8000)",
|
||||
"type": "shell",
|
||||
"command": "make live"
|
||||
},
|
||||
{
|
||||
"label": "Собрать статический сайт (./site)",
|
||||
"type": "shell",
|
||||
"command": "make site"
|
||||
},
|
||||
{
|
||||
"label": "Собрать docker-образ со стат. сайтом",
|
||||
"type": "shell",
|
||||
"command": "make image"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,9 +1,19 @@
|
||||
FROM squidfunk/mkdocs-material AS builder
|
||||
FROM zensical/zensical:latest AS builder
|
||||
ENV PYTHONPATH=/docs
|
||||
COPY . /docs
|
||||
RUN mkdocs build
|
||||
RUN zensical build --clean
|
||||
|
||||
FROM nginx:alpine AS iptv-docs
|
||||
|
||||
LABEL org.opencontainers.image.title="IPTV Checker"
|
||||
LABEL org.opencontainers.image.description="Documentation for our services and products"
|
||||
LABEL org.opencontainers.image.authors="Anthony Axenov <anthonyaxenov@gmail.com>"
|
||||
LABEL org.opencontainers.image.url="https://m3u.su"
|
||||
LABEL org.opencontainers.image.vendor="Anthony Axenov"
|
||||
LABEL org.opencontainers.image.documentation="https://m3u.su/docs"
|
||||
LABEL org.opencontainers.image.licenses="MIT"
|
||||
LABEL org.opencontainers.image.source="https://git.axenov.dev/IPTV/docs"
|
||||
|
||||
COPY --from=builder /docs/site /usr/share/nginx/html
|
||||
WORKDIR /usr/share/nginx/html
|
||||
USER root
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Антон Аксенов (Anthony Axenov)
|
||||
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
|
||||
|
||||
@@ -1,49 +1,58 @@
|
||||
## image: Run mkdocs with live-reloading (localhost:3000)
|
||||
live:
|
||||
@echo "Wait until container starts and open http://localhost:3000 to see live preview"
|
||||
@docker run \
|
||||
--pull always \
|
||||
.DEFAULT_GOAL := help
|
||||
.PHONY: clear live site image push run help
|
||||
|
||||
## clear = Remove cache directories
|
||||
clear:
|
||||
rm -rf __pycache__ .cache site
|
||||
|
||||
## live = Run zensical with live-reloading on http://localhost:8801
|
||||
live: clear
|
||||
@echo "*** Wait until container starts and open http://localhost:8801 to see live preview"
|
||||
@docker stop iptv-docs-dev 2>/dev/null; \
|
||||
docker run \
|
||||
--rm \
|
||||
--interactive \
|
||||
--tty \
|
||||
--publish 3000:8000 \
|
||||
--env PYTHONPATH=/docs \
|
||||
--publish 8801:8801 \
|
||||
--volume ${PWD}:/docs \
|
||||
--name iptv-docs-dev \
|
||||
squidfunk/mkdocs-material:9.6.20
|
||||
zensical/zensical:latest
|
||||
|
||||
## image: Build local static site
|
||||
site:
|
||||
@echo "Wait until mkdocs finish"
|
||||
@docker run \
|
||||
## site = Build a local static site
|
||||
site: clear
|
||||
@echo "*** Wait until zensical finish"
|
||||
@docker stop iptv-docs-dev 2>/dev/null; \
|
||||
docker run \
|
||||
--pull always \
|
||||
--rm \
|
||||
--interactive \
|
||||
--tty \
|
||||
--env PYTHONPATH=/docs \
|
||||
--volume ${PWD}:/docs \
|
||||
--name iptv-docs-dev \
|
||||
squidfunk/mkdocs-material:9.6.20 build
|
||||
zensical/zensical:latest \
|
||||
build \
|
||||
--clean
|
||||
|
||||
## image: Build docker image
|
||||
## image = Build a docker image
|
||||
image:
|
||||
@docker build \
|
||||
--tag iptv-docs:latest \
|
||||
--tag git.axenov.dev/iptv/iptv-docs:latest \
|
||||
.
|
||||
@docker build --tag git.axenov.dev/iptv/iptv-docs:latest:latest .
|
||||
|
||||
## push: Push docker image to registry
|
||||
push:
|
||||
@docker push git.axenov.dev/iptv/iptv-docs:latest
|
||||
|
||||
## run: Run docker image (localhost:3001)
|
||||
## run = Run docker container from image built with `make image` on http://localhost:8802
|
||||
run:
|
||||
@echo "Wait until container starts and open http://localhost:3001 to see ready static website"
|
||||
@docker run \
|
||||
@echo "*** Wait until container starts and open http://localhost:8802 to see ready static website"
|
||||
@docker stop iptv-docs 2>/dev/null; \
|
||||
docker run \
|
||||
--rm \
|
||||
--publish 3001:80 \
|
||||
--publish 8802:80 \
|
||||
--name iptv-docs \
|
||||
git.axenov.dev/iptv/iptv-docs:latest
|
||||
git.axenov.dev/iptv/iptv-docs:latest:latest
|
||||
|
||||
## help: Show this message and exit
|
||||
# push = Push docker image built with `make image` to git.axenov.dev
|
||||
push:
|
||||
@docker login git.axenov.dev; \
|
||||
docker push git.axenov.dev/iptv/iptv-docs:latest:latest
|
||||
|
||||
## help = Show this message and exit (default)
|
||||
help: Makefile
|
||||
@echo "Available recipes:"
|
||||
@sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /'
|
||||
@sed -n 's/^##/ /p' $< | column -t -s '='
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Документация m3u.su
|
||||
# Документация iptvc
|
||||
|
||||
Как работать с документацией: [src/dev/docs.md](src/dev/docs.md)
|
||||
Как работать с документацией: [content/dev/docs.md](content/dev/docs.md)
|
||||
|
||||
## Лицензия
|
||||
|
||||
|
||||
@@ -1,20 +1,31 @@
|
||||
: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>');
|
||||
}
|
||||
|
||||
/* Yoomoney styling */
|
||||
/* 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,
|
||||
.md-typeset .yoomoney > summary {
|
||||
background-color: rgba(113, 47, 244, 0.1);
|
||||
}
|
||||
.md-typeset .yoomoney > .admonition-title::before,
|
||||
.md-typeset .yoomoney > summary::before {
|
||||
background-color: rgb(113, 47, 244);
|
||||
@@ -22,16 +33,12 @@
|
||||
mask-image: var(--md-admonition-icon--yoomoney);
|
||||
}
|
||||
|
||||
/* Boosty styling */
|
||||
/* Boosty admonition styling */
|
||||
|
||||
.md-typeset .admonition.boosty,
|
||||
.md-typeset details.boosty {
|
||||
border-color: rgb(241, 95, 44);
|
||||
}
|
||||
.md-typeset .boosty > .admonition-title,
|
||||
.md-typeset .boosty > summary {
|
||||
background-color: rgba(241, 95, 44, 0.1);
|
||||
}
|
||||
.md-typeset .boosty > .admonition-title::before,
|
||||
.md-typeset .boosty > summary::before {
|
||||
background-color: rgb(241, 95, 44);
|
||||
@@ -40,18 +47,6 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.chapter li.part-title {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
main ol li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
@@ -111,3 +106,85 @@ main ol li {
|
||||
.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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@@ -8,7 +8,7 @@ tags: ["статусы", "плейлисты", "каналы", "iptvc"]
|
||||
!!! danger "Я не гарантирую корректность и актуальность плейлистов, которые ты увидишь на сайте, как и корректность результатов их проверки."
|
||||
После прочтения этой страницы ты поймёшь почему.
|
||||
|
||||
Плейлисты [проверяются автоматически](../iptvc/index.md) с некоей периодичностью.
|
||||
Плейлисты [проверяются автоматически](../iptvc/overview.md) с некоей периодичностью.
|
||||
|
||||
Хотя я и стараюсь улучшать качество проверок, но всё же рекомендую проверять желаемые плейлисты самостоятельно вручную, ибо нет никаких гарантий:
|
||||
|
||||
@@ -17,10 +17,9 @@ tags: ["статусы", "плейлисты", "каналы", "iptvc"]
|
||||
* он может работать, но проверка заврешена из-за какой-то технической ошибки;
|
||||
* он уже может не работать, но результаты последней проверки показывают обратное;
|
||||
* что транслируемый контент соответствует заявленным названиям;
|
||||
* что сейчас или через X времени там не окажется [заглушка](../faq.md#заглушка).
|
||||
* что сейчас или через X времени там не окажется [заглушка](faq.md#заглушка).
|
||||
|
||||
<a id="playlists"></a>
|
||||
## Статусы плейлистов
|
||||
## Статусы плейлистов { id="playlists" }
|
||||
|
||||
Каждый плейлист может быть в одном из трёх статусов:
|
||||
|
||||
@@ -39,8 +38,7 @@ tags: ["статусы", "плейлисты", "каналы", "iptvc"]
|
||||
Независимо от статуса плейлиста на сайте, его можно добавить в свой плеер по "Ссылке для ТВ" и проверить самостоятельно.
|
||||
Проверка плейлиста не влияет на его работоспособность.
|
||||
|
||||
<a id="extra"></a>
|
||||
### Дополнительные возможности
|
||||
### Дополнительные возможности { id="extra" }
|
||||
|
||||
Если плейлист <span class="badge online">online</span> (успешно проверен), то у него могут быть дополнительные значки:
|
||||
|
||||
@@ -58,16 +56,15 @@ tags: ["статусы", "плейлисты", "каналы", "iptvc"]
|
||||
!!! info "Обрати внимание"
|
||||
1. Пропорции рабочих и нерабочих каналов в плейлистах могут меняться от проверки к проверке.
|
||||
Это нормально, таковы технические особенности проверки.
|
||||
2. Работа архива и программы передач зависит от выбранного [плеера](players.md).
|
||||
2. Работа архива и программы передач зависит от выбранного [плеера](../common/players.md).
|
||||
Некоторые это просто не поддерживают.
|
||||
|
||||
<a id="channels"></a>
|
||||
## Статусы каналов
|
||||
## Статусы каналов { id="channels" }
|
||||
|
||||
Каждый канал в любом плейлисте может быть в одном из трёх статусов:
|
||||
|
||||
* <span class="icon online"><ion-icon name="radio-button-on-outline"></ion-icon></span> — ***Возможно*, канал работает**
|
||||
Но там может транслироваться какая-нибудь [заглушка](../faq.md#заглушка) (например, от [Wink](../faq.md#wink)) или другой канал.
|
||||
Но там может транслироваться какая-нибудь [заглушка](faq.md#заглушка) (например, от [Wink](faq.md#wink)) или другой канал.
|
||||
|
||||
* <span class="icon offline"><ion-icon name="radio-button-on-outline"></ion-icon></span> — ***Возможно*, канал не работает**
|
||||
Чем больше таких каналов в плейлисте, тем сложнее будет листать плейлист в плеере или на ТВ.
|
||||
@@ -82,14 +79,13 @@ tags: ["статусы", "плейлисты", "каналы", "iptvc"]
|
||||
* <span class="badge adult">18+</span> — **Канал для взрослых**
|
||||
Читай ниже.
|
||||
|
||||
<a id="adult"></a>
|
||||
## Контент для взрослых
|
||||
## Контент для взрослых { id="adult" }
|
||||
|
||||
Это откровенно порнографический, эротический или другой контент, неприемлемый для детской психики (например, жанровые каналы с фильмами ужасов).
|
||||
|
||||
Если при проверке плейлиста обнаружен хотя бы один канал для взрослых, то этот канал и весь плейлист помечается значком <span class="badge adult">18+</span>.
|
||||
|
||||
Такие каналы определяются благодаря правилам, описанным в файле [channels.json](../formats/channels.md).
|
||||
Такие каналы определяются благодаря правилам, описанным в файле [channels.json](../common/formats/channels.md).
|
||||
Они применяются к названиям каналов и их атрибутам (`tvg-id`, `tvg-name`), которые описывают канал в плейлисте.
|
||||
|
||||
Для каналов со взрослым контентом применяется тег `adult`.
|
||||
@@ -97,7 +93,7 @@ tags: ["статусы", "плейлисты", "каналы", "iptvc"]
|
||||
!!! warning "Обрати внимание"
|
||||
Далеко не все каналы могут быть помечены таким тегом.
|
||||
Хотя набор правил для тегов очень богат, но невозможно угадать все каналы с приемлемой точностью.
|
||||
Почему — читай [здесь](../formats/channels.md#warnings).
|
||||
Почему — читай [здесь](../common/formats/channels.md#warnings).
|
||||
|
||||
---
|
||||
|
||||
@@ -46,8 +46,8 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
|
||||
## Откуда берутся логотипы каналов и программы передач?
|
||||
|
||||
Всё это (не) [указывается](formats/m3u.md#tvg-logo) внутри плейлиста его авторами.
|
||||
Но в некоторых [плеерах](common/players.md) можно вручную указывать программу передач (см. ниже).
|
||||
Всё это (не) [указывается](../common/formats/m3u.md#tvg-logo) внутри плейлиста его авторами.
|
||||
Но в некоторых [плеерах](../common/players.md) можно вручную указывать программу передач (см. ниже).
|
||||
|
||||
## У канала нет логотипа!
|
||||
|
||||
@@ -55,7 +55,7 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
|
||||
## У **канала** нет программы передач (EPG), что делать?
|
||||
|
||||
Фига в том, что EPG может быть и [указан](formats/m3u.md#url-tvg) в плейлисте, но у конкретного канала могут быть указаны некорректные [`tvg-id`](formats/m3u.md#tvg-id) или [`tvg-name`](formats/m3u.md#tvg-name).
|
||||
Фига в том, что EPG может быть и [указан](../common/formats/m3u.md#url-tvg) в плейлисте, но у конкретного канала могут быть указаны некорректные [`tvg-id`](../common/formats/m3u.md#tvg-id) или [`tvg-name`](../common/formats/m3u.md#tvg-name).
|
||||
Может, его дёрнули из другого листа и не подогнали под другую EPG.
|
||||
|
||||
Так что вариантов масса:
|
||||
@@ -74,18 +74,17 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
* не все плееры вообще поддерживают работу с телепрограммой;
|
||||
* в плейлисте она просто может не быть указана.
|
||||
|
||||
Но если [плеер](common/players.md) позволяет, можно указать ссылку на сторонную телепрограмму.
|
||||
Но если [плеер](../common/players.md) позволяет, можно указать ссылку на сторонную телепрограмму.
|
||||
|
||||
И это целое дело.
|
||||
Надо чтобы совпадали [`tvg-id`](formats/m3u.md#tvg-id) или [`tvg-name`](formats/m3u.md#tvg-name) каналов с теми, которые указываются в EPG.
|
||||
Надо чтобы совпадали [`tvg-id`](../common/formats/m3u.md#tvg-id) или [`tvg-name`](../common/formats/m3u.md#tvg-name) каналов с теми, которые указываются в EPG.
|
||||
Так что не всякая телепрограмма подойдёт, не ко всякому плейлисту и не ко всем каналам.
|
||||
Надо подбирать и то, и то.
|
||||
|
||||
<a id="epg"></a>
|
||||
## А где взять программу передач (EPG)?
|
||||
## А где взять программу передач (EPG)? { id="epg" }
|
||||
|
||||
1. Из самого плейлиста.
|
||||
Часто в атрибут [`url-tvg`](formats/m3u.md#url-tvg) тега `#EXTM3U` указывают одну или две ссылки на EPG, разделяя их `;`.
|
||||
Часто в атрибут [`url-tvg`](../common/formats/m3u.md#url-tvg) тега `#EXTM3U` указывают одну или две ссылки на EPG, разделяя их `;`.
|
||||
Их можно использовать отдельно, например, если плеер не может корректно обработать такое значение.
|
||||
|
||||
2. Взять одну из этих ссылок:
|
||||
@@ -115,13 +114,13 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
|
||||
## Почему на сайте плейлист онлайн, но в нём 0 каналов?
|
||||
|
||||
[Тебе сюда](common/checks.md#playlists).
|
||||
[Тебе сюда](checks.md#playlists).
|
||||
|
||||
## Почему на сайте плейлист онлайн, но у меня он не работает?
|
||||
|
||||
Что значит "не работает"?
|
||||
|
||||
* Ты уверен, что ссылка в [правильном формате](common/details.md#shortlink)?
|
||||
* Ты уверен, что ссылка в [правильном формате](../iptvc/site/details.md#shortlink)?
|
||||
* Ты уверен, что у тебя нормальное интернет-соединение?
|
||||
* Плеер показывает какую-то ошибку при добавлении плейлиста?
|
||||
* Плейлист добавляется по ссылке, но каналы не загружаются или плеер зависает?
|
||||
@@ -129,12 +128,12 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
* А есть скриншоты? Логи? Тексты ошибок?
|
||||
|
||||
Попробуй погуглить проблему с конкретным плеером, может ты не один с такой проблемой.
|
||||
Или [узнать в чате](tg/chat.md).
|
||||
Или [узнать в чате](../tg/chat.md).
|
||||
|
||||
Но вообще, это зависит от:
|
||||
|
||||
* автора плейлиста (дохлые каналы почти всегда есть даже в свежайших листах, но если лист не обновлялся год, что ты вряд-ли узнаешь, то рабочих каналов там не ищи);
|
||||
* твоего [плеера](common/players.md) (видеотрансляции могут использовать кодек, который просто не поддерживается плеером);
|
||||
* твоего [плеера](../common/players.md) (видеотрансляции могут использовать кодек, который просто не поддерживается плеером);
|
||||
* ширины твоего интернет-канала (не надо пытаться врубать FHD/4K трансляции с мобильного интернета на самом дешёвом тарифе в лесу);
|
||||
* ретроградности Меркурия и магнитных бурь (а вдруг);
|
||||
* настроек твоей сети, твоего интернет-провайдера, VPN (подумай хорошенько, хочешь ли ты смотреть российские каналы из РФ через Уганду или США);
|
||||
@@ -154,13 +153,13 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
|
||||
Короткие коды плейлистов могут меняться, поэтому вполне может произойти внезапная подмена одного другим, однако это происходит крайне редко.
|
||||
|
||||
Плюс читай про доверие [результатам проверки](common/checks.md).
|
||||
Плюс читай про доверие [результатам проверки](checks.md).
|
||||
|
||||
## В плейлистах порнуха!
|
||||
|
||||
Да, в плейлистах порнуха.
|
||||
|
||||
Это [явно помечается](common/checks.md#adult) везде, где это технически возможно.
|
||||
Это [явно помечается](checks.md#adult) везде, где это технически возможно.
|
||||
Смотри с удовольствием сколько хочешь, всё для тебя.
|
||||
|
||||
Или без удовольствия.
|
||||
@@ -186,13 +185,12 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
|
||||
Если есть кандидаты на добавление, то читай ниже.
|
||||
|
||||
<a id="автообновляемый"></a>
|
||||
## Что значит автообновляемый плейлист?
|
||||
## Что значит автообновляемый плейлист? { id="автообновляемый" }
|
||||
|
||||
Например, ты на своём компе:
|
||||
|
||||
* открываешь любой текстовый редактор;
|
||||
* оформляешь текст в формате [m3u](formats/m3u.md);
|
||||
* оформляешь текст в формате [m3u](../common/formats/m3u.md);
|
||||
* сохраняешь в файл `pls.m3u`.
|
||||
|
||||
Получился плейлист `pls.m3u`.
|
||||
@@ -253,32 +251,30 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
|
||||
Нет, и не планируется.
|
||||
|
||||
Ищи [плеер](common/players.md) и добавляй плейлист туда по ссылке.
|
||||
Ищи [плеер](../common/players.md) и добавляй плейлист туда по ссылке.
|
||||
|
||||
<a id="заглушка"></a>
|
||||
## На канале отображается заглушка
|
||||
## На канале отображается заглушка { id="заглушка" }
|
||||
|
||||
<a id="заглушка1"></a>
|
||||
### Просят денег и/или подписку
|
||||
### Просят денег и/или подписку { id="заглушка1" }
|
||||
|
||||
??? quote "[Скриншот] Уважаемый клиент! Для возобновления просмотра Вам необходимо использовать не более 2 устройств"
|
||||

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

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

|
||||
??? image "Ваша подписка не активна"
|
||||

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

|
||||
??? image "Мы обнаружили систематическое нарушение правил использования нашего сервиса"
|
||||

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

|
||||
??? image "Вы превысили разрешённое количество одновременных поджключений"
|
||||

|
||||
> Вы превысили разрешённое количество одновременных подключений
|
||||
> Для возобновления просмотра ограничьте количество подключённых устройств
|
||||
|
||||
@@ -296,15 +292,14 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
|
||||
Этот плейлист — главный кандидат на удаление с сайта.
|
||||
|
||||
<a id="wink"></a>
|
||||
### Wink
|
||||
### Wink { id="wink" }
|
||||
|
||||
??? quote "[Скриншот] Просмотр ТВ-каналов, фильмов и сериалов доступен только в официальных приложениях Wink и на территории России"
|
||||

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

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

|
||||
??? image "Wink ещё не показывает видео на этой территории"
|
||||

|
||||
> Wink ещё не показывает видео на этой территории
|
||||
|
||||
**Решение 1:** купить подписку Wink и использовать официальные приложения.
|
||||
@@ -313,7 +308,7 @@ tags: ["сайт", "каналы", "плейлисты", "epg", "плееры",
|
||||
|
||||
**Решение 3:** если IP не российский, то сделать его российским (любыми способами).
|
||||
|
||||
**Решение 4:** использовать [плеер](common/players.md), который позволяет указать **User-Agent**, и вставить туда какой-нибудь из этих:
|
||||
**Решение 4:** использовать [плеер](../common/players.md), который позволяет указать **User-Agent**, и вставить туда какой-нибудь из этих:
|
||||
|
||||
```
|
||||
Mozilla/5.0 WINK/1.28.2 (AndroidTV/9) HlsWinkPlayer
|
||||
@@ -1,19 +1,18 @@
|
||||
---
|
||||
icon: material/home
|
||||
hide: [toc]
|
||||
---
|
||||
|
||||
# :material-home: Введение
|
||||
# :material-home: Об агрегаторе m3u.su
|
||||
|
||||
Сервис предназначен для централизованного сбора ссылок на публичные IPTV-плейлисты, которые находятся в открытом доступе.
|
||||
Этот сервис предназначен для централизованного сбора ссылок на публичные IPTV-плейлисты, которые находятся в открытом доступе.
|
||||
Они отбираются вручную и периодически проверяются автоматически.
|
||||
|
||||
!!! info "Все необходимые адреса"
|
||||
**Веб-сайт:** [m3u.su](https://m3u.su)
|
||||
**Документация:** [m3u.su/docs](https://m3u.su/docs)
|
||||
Документация: [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_aggregator_chat](https://t.me/iptv_aggregator_chat)
|
||||
Бот: [@iptv_aggregator_bot](https://t.me/iptv_aggregator_bot)
|
||||
Telegram-канал: [@iptv_aggregator](https://t.me/iptv_aggregator)
|
||||
|
||||
Далеко не все пользователи, желающие использовать цифровое ТВ, могут позволить себе подключение IPTV у своего провайдера или поставщиков контента.
|
||||
|
||||
@@ -62,7 +61,7 @@ icon: material/home
|
||||
Автор не зарабатывает на проекте и не собирается.
|
||||
Всё, что отображается на сайте, сделано бесплатно и на энтузиазме.
|
||||
|
||||
Но ты можешь сделать [добровольное пожертвование](support.md), которое поможет мне компенсировать затраты на поддержку и техническое развитие проекта.
|
||||
Но ты можешь сделать [добровольное пожертвование](../common/support.md), которое поможет мне компенсировать затраты на поддержку и техническое развитие проекта.
|
||||
|
||||
## Условия, гарантии, обязательства и последствия
|
||||
|
||||
@@ -16,4 +16,3 @@ tags: ["статусы", "плейлисты"]
|
||||
В основном, в плейлистах именно трансляции телеканалов, но может быть и медиатека: просто список каких-то (мульт)фильмов и записи телепередач, находящихся на чужих дисках (как если бы вы сами составили плейлист, например, с музыкой).
|
||||
|
||||
!!! danger "Плейлисты, нарушающие законодательство, удаляются с сайта окончательно по факту обращения от правообладателя."
|
||||
И претензии на этот счёт не принимаются.
|
||||
@@ -8,21 +8,21 @@ tags: ["сайт"]
|
||||
Так выглядит статусная страница сервиса.
|
||||
Попасть на неё можно по ссылке "[Аптайм](https://status.m3u.su)" в шапке сайта.
|
||||
|
||||

|
||||

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

|
||||

|
||||
|
||||
Если на шкале появляется красное деление, значит был кратковременный сбой.
|
||||
|
||||
|
After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 70 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`."
|
||||
@@ -8,8 +8,10 @@ icon: material/book-open-page-variant-outline
|
||||
Поддерживать содержимое в актуальном состоянии большой труд.
|
||||
Прошу отнестись с пониманием, а лучше — [помочь делом](support.md#participate).
|
||||
|
||||
<!--
|
||||
!!! danger "Тем не менее, прошу прочесть её!"
|
||||
Потому что очень часто и мне, и в общий чат поступают одинаковые вопросы, на которые уже просто нет сил отвечать персонально.
|
||||
Потому что очень часто и мне, и в общий чат поступают одинаковые вопросы, на которые уже просто нет сил отвечать персонально.
|
||||
-->
|
||||
|
||||
Если у тебя возникает вопрос, на который уже есть ответ на одной из этих страниц, то ты рискуешь
|
||||
|
||||
@@ -27,12 +29,5 @@ icon: material/book-open-page-variant-outline
|
||||
4. справа — содержание конкретной страницы.
|
||||
|
||||
??? info end "На мобильниках содержание страницы спрятано за этой кнопкой в боковом меню:"
|
||||

|
||||

|
||||
|
||||
## Связанные статьи
|
||||
|
||||
Эти статьи пролинкованы между собой и сгруппированы про темам (меткам).
|
||||
|
||||
---
|
||||
|
||||
<!-- material/tags -->
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
title: channels.json
|
||||
icon: material/code-json
|
||||
tags: ["iptvc", "теги", "каналы"]
|
||||
---
|
||||
@@ -38,8 +39,7 @@ tags: ["iptvc", "теги", "каналы"]
|
||||
|
||||
Каналы сопоставляются в нижнем регистре.
|
||||
|
||||
<a id="warnings"></a>
|
||||
## Рекомендации и предостережения
|
||||
## Рекомендации и предостережения { id="warnings" }
|
||||
|
||||
1. Если хочешь написать новое правило, будь осторожен с регулярками.
|
||||
Старайся не охватывать несколько каналов сразу.
|
||||
@@ -58,8 +58,7 @@ tags: ["iptvc", "теги", "каналы"]
|
||||
Некоторые каналы имеют `tvg-name`.
|
||||
Все три параметра могут оказаться на кириллице.
|
||||
|
||||
<a id="доступные-теги">
|
||||
## Доступные теги
|
||||
## Доступные теги { id="доступные-теги" }
|
||||
|
||||
| Ключевое слово | Описание |
|
||||
| -------------- | ----------------------------------------------------------- |
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
title: "*.m3u (*.m3u8)"
|
||||
icon: material/playlist-play
|
||||
tags: ["плейлисты", "каналы"]
|
||||
---
|
||||
@@ -15,6 +16,7 @@ tags: ["плейлисты", "каналы"]
|
||||
После директив с новой строки указывается ссылка на канал (или путь к файлу).
|
||||
|
||||
В свою чередь, по этой ссылке может быть:
|
||||
|
||||
* либо текстовое представление контента в формате m3u/m3u8/XMLTV/MPD с описанием непосредственно участки трансляции;
|
||||
* либо непосредственно сама потоковая трансляция mp4 или т. п.
|
||||
|
||||
@@ -39,30 +41,25 @@ http://example.com/play-bbc.m3u
|
||||
http://example.com/play-am.m3u8
|
||||
```
|
||||
|
||||
<a id="EXTM3U"></a>
|
||||
### Директива `#EXTM3U`
|
||||
### Директива `#EXTM3U` { id="EXTM3U" }
|
||||
|
||||
Заголовок файла (обязателен).
|
||||
|
||||
<a id="url-tvg"></a>
|
||||
#### Атрибут `url-tvg` (он же `x-tvg-url`)
|
||||
#### Атрибут `url-tvg` (он же `x-tvg-url`) { id="url-tvg" }
|
||||
|
||||
Ссылка программу передач в формате `*.xml` или `*.xml.gz`.
|
||||
|
||||
<a id="catchup"></a>
|
||||
#### Атрибуты `catchup*`
|
||||
#### Атрибуты `catchup*` { id="catchup" }
|
||||
|
||||
Читай здесь: [Архив телепрограмм (SS IPTV)](https://ss-iptv.com/ru/operators/catchup)
|
||||
|
||||
<a id="EXTGRP"></a>
|
||||
### Директива `#EXTGRP`
|
||||
### Директива `#EXTGRP` { id="EXTGRP" }
|
||||
|
||||
Название группы, к которой относится контент (звуковая дорожка или канал).
|
||||
|
||||
Указывается в формате `#EXTGRP:XXX`, где: `XXX` — название группы.
|
||||
|
||||
<a id="EXTINF"></a>
|
||||
### Директива `#EXTINF`
|
||||
### Директива `#EXTINF` { id="EXTINF" }
|
||||
|
||||
Описывает контент (звуковую дорожку или канал).
|
||||
|
||||
@@ -71,46 +68,38 @@ http://example.com/play-am.m3u8
|
||||
* `YYY` — атрибуты (см. ниже);
|
||||
* `ZZZ` — название контента;
|
||||
|
||||
<a id="tvg-shift"></a>
|
||||
#### Атрибут `tvg-shift`
|
||||
#### Атрибут `tvg-shift` { id="tvg-shift" }
|
||||
|
||||
Cмещение телепрограммы в часах относительно указанного в программе.
|
||||
|
||||
<a id="tvg-id"></a>
|
||||
#### Атрибуты `tvg-id` и `tvg-name` { id="tvg-id" }
|
||||
<a id="tvg-name"></a>
|
||||
#### Атрибуты `tvg-id` и `tvg-name`
|
||||
|
||||
Идентификатор телепрограммы канала.
|
||||
По нему телепрограмма привязывается к трансляции с учётом смещения времени.
|
||||
|
||||
<a id="tvg-logo"></a>
|
||||
#### Атрибут `tvg-logo`
|
||||
#### Атрибут `tvg-logo` { id="tvg-logo" }
|
||||
|
||||
Ссылка на логотип канала.
|
||||
|
||||
<a id="tvg-country"></a>
|
||||
#### Атрибут `tvg-country`
|
||||
#### Атрибут `tvg-country` { id="tvg-country" }
|
||||
|
||||
Код Alpha-2 страны вещания согласно ISO 3166-1 или ОКСМ.
|
||||
|
||||
<a id="tvg-language"></a>
|
||||
#### Атрибут `tvg-language`
|
||||
#### Атрибут `tvg-language` { id="tvg-language" }
|
||||
|
||||
Название языка телепередачи согласно ISO 639-2.
|
||||
|
||||
<a id="group-title"></a>
|
||||
#### Атрибут `group-title`
|
||||
#### Атрибут `group-title` { id="group-title" }
|
||||
|
||||
Название группы.
|
||||
По функционалу идентичен директиве `#EXTGRP`.
|
||||
|
||||
<a id="user-agent"></a>
|
||||
#### Атрибут `user-agent`
|
||||
#### Атрибут `user-agent` { id="user-agent" }
|
||||
|
||||
Значение заголовка `User-Agent` для обращения к контенту по http.
|
||||
|
||||
<a id="audio-track"></a>
|
||||
#### Атрибут `audio-track`
|
||||
#### Атрибут `audio-track` { id="audio-track" }
|
||||
|
||||
Языковой код (ISO 639-2) аудио дорожки канала, например: "eng,rus".
|
||||
|
||||
@@ -118,15 +107,13 @@ Cмещение телепрограммы в часах относительн
|
||||
|
||||
Дорожкой по умолчанию устанавливается первая указанная в списке.
|
||||
|
||||
<a id="aspect-ratio"></a>
|
||||
#### Атрибут `aspect-ratio`
|
||||
#### Атрибут `aspect-ratio` { id="aspect-ratio" }
|
||||
|
||||
Определяет пропорции экрана (может быть недоступно для некоторых моделей телевизоров).
|
||||
|
||||
Допустимые значения: 16:9, 3:2, 4:3, 1,85:1, 2,39:1 (наиболее распространенное значение для фильмов)
|
||||
|
||||
<a id="EXTVLCOPT"></a>
|
||||
### Директива `#EXTVLCOPT`
|
||||
### Директива `#EXTVLCOPT` { id="EXTVLCOPT" }
|
||||
|
||||
Специфична для VLC Player.
|
||||
Директив может быть множество для одной дорожки (канала).
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
title: playlists.ini
|
||||
icon: material/code-brackets
|
||||
tags: ["плейлисты"]
|
||||
---
|
||||
@@ -23,7 +24,7 @@ src = 'https://example.com/super-duper-playlist'
|
||||
Для значений можно (не) использовать 'одинарные' или "двойные" кавычки.
|
||||
Ради единообразия рекомендуется использовать 'одинарные'.
|
||||
|
||||
## `code`
|
||||
## `code` { id="code" }
|
||||
|
||||
Код плейлиста в рамках этого конфига (**обязательно**).
|
||||
|
||||
@@ -35,23 +36,23 @@ src = 'https://example.com/super-duper-playlist'
|
||||
Для удобства ввода с пульта, код рекомендуется задавать числом или короткой строкой без пробелов и др. спецсимволов.
|
||||
Чем короче, тем лучше.
|
||||
|
||||
## `name`
|
||||
## `name` { id="name" }
|
||||
|
||||
Название плейлиста (необязательно).
|
||||
|
||||
По умолчанию: `Playlist #<code>`.
|
||||
|
||||
## `desc`
|
||||
## `desc` { id="desc" }
|
||||
|
||||
Краткое описание из источника или от себя (необязательно).
|
||||
|
||||
По умолчанию: пусто.
|
||||
|
||||
## `pls`
|
||||
## `pls` { id="pls" }
|
||||
|
||||
Прямая ссылка на m3u/m3u8 плейлист (**обязательно**).
|
||||
|
||||
## `src`
|
||||
## `src` { id="src" }
|
||||
|
||||
Ссылка на источник (страницу сайта), откуда был взят плейлист (необязательно).
|
||||
|
||||
@@ -6,11 +6,11 @@ hide: [toc]
|
||||
# Общая информация
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
- [:material-cogs: Как работает сервис](how-it-works.md)
|
||||
- [:material-file-eye-outline: Как отбираются плейлисты](selection.md)
|
||||
- [:material-file-refresh-outline: Проверки и статусы](checks.md)
|
||||
- [:fontawesome-solid-list-check: Список плейлистов](list.md)
|
||||
- [:material-table-eye: Страница плейлиста](details.md)
|
||||
- [:material-television-play: Как подключить плейлист](connect.md)
|
||||
- [: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>
|
||||
@@ -15,7 +15,7 @@ tags: ["плееры"]
|
||||
Обращайся к содержанию справа для быстрой навигации.
|
||||
|
||||
!!! info "Здесь не хватает очень много подробностей"
|
||||
Если ты имел дело с каким-то плеером, знаешь как его настроить или какие-то другие детали, я прошу тебя помочь [актуализировать эту страницу](../support.md#participate), чтобы через это помочь другим пользователям с выбором и настройкой плеера под свои цели.
|
||||
Если ты имел дело с каким-то плеером, знаешь как его настроить или какие-то другие детали, я прошу тебя помочь [актуализировать эту страницу](support.md#participate), чтобы через это помочь другим пользователям с выбором и настройкой плеера под свои цели.
|
||||
|
||||
## Кроссплатформенные
|
||||
|
||||
@@ -32,18 +32,18 @@ tags: ["плееры"]
|
||||
|
||||
Универсальный плеер практически для любого мультимедиа-контента.
|
||||
|
||||
??? quote "[Скриншот] Главное окно"
|
||||

|
||||
??? image "Главное окно"
|
||||

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

|
||||

|
||||

|
||||

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

|
||||

|
||||

|
||||

|
||||
|
||||
### :thumbsup: IPTVnator
|
||||
|
||||
@@ -57,13 +57,13 @@ tags: ["плееры"]
|
||||
|
||||
Если использовать веб-версию, то настройки сохраняются в браузере.
|
||||
|
||||
??? quote "[Скриншот] Главное окно"
|
||||

|
||||
??? image "Главное окно"
|
||||

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

|
||||

|
||||

|
||||

|
||||
|
||||
### IPTV Web Player
|
||||
|
||||
@@ -74,12 +74,12 @@ tags: ["плееры"]
|
||||
|
||||
Подгрузка и отображение телепрограммы (используется https://cdn.epg.one/epg2.xml).
|
||||
|
||||
??? quote "[Скриншот] Главное окно"
|
||||

|
||||
??? image "Главное окно"
|
||||

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

|
||||

|
||||
|
||||
### Kodi
|
||||
|
||||
@@ -135,12 +135,12 @@ tags: ["плееры"]
|
||||
|
||||
Поддерживает плейлисты по ссылкам, сторонние телепрограммы, группировку каналов, изменение плейлистов и многое другое.
|
||||
|
||||
??? quote "[Скриншот] Главное окно"
|
||||

|
||||
??? image "Главное окно"
|
||||

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

|
||||

|
||||
|
||||
---
|
||||
|
||||
@@ -173,25 +173,25 @@ tags: ["плееры"]
|
||||
|
||||
* Скачать: [play.google.com](https://play.google.com/store/apps/details?id=com.ottplay.ottplay)
|
||||
|
||||
??? quote "[Скриншот] Главный экран"
|
||||

|
||||

|
||||
??? image "Главный экран"
|
||||

|
||||

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

|
||||

|
||||

|
||||

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

|
||||

|
||||

|
||||

|
||||
|
||||
И дальше те же шаги 3-5 на скриншотах выше.
|
||||
|
||||
??? quote "Установка User-Agent"
|
||||
На экране добавления/редактирования плейлиста снять галочку "User-Agent по умолчанию" и ввести необходимый.
|
||||
Например, для [Wink](../faq.md#wink).
|
||||
Например, для [Wink](../aggregator/faq.md#wink).
|
||||
|
||||
#### :thumbsup: M3U
|
||||
|
||||
@@ -199,19 +199,19 @@ tags: ["плееры"]
|
||||
|
||||
Умеет показывать картинку-в-картинке, отображать группы и сортировать каналы.
|
||||
|
||||
Программу передач нужно [подключать отдельной ссылкой](../faq.md#epg), из плейлиста не тянет.
|
||||
Программу передач нужно [подключать отдельной ссылкой](../aggregator/faq.md#epg), из плейлиста не тянет.
|
||||
|
||||
??? quote "[Скриншот] Главный экран"
|
||||

|
||||
??? image "Главный экран"
|
||||

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

|
||||

|
||||

|
||||

|
||||
|
||||
??? quote "[Скриншот] Установка User-Agent"
|
||||

|
||||

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

|
||||

|
||||
|
||||
#### IPTV (Александр Софронов)
|
||||
|
||||
@@ -16,7 +16,7 @@ icon: material/hand-heart-outline
|
||||
Там можно ставить **платные реакции** к постам и/или **дарить голоса** (бусты):
|
||||
|
||||
* канал: [@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.
|
||||
* чат: [@iptv_aggregator_chat](../tg/chat.md) ([boost](https://t.me/iptv_aggregator_chat?boost)) — комментарии к каналу, общение по теме проекта и IPTV.
|
||||
|
||||
## :material-wallet: Внести пожертвование
|
||||
|
||||
@@ -36,8 +36,7 @@ icon: material/hand-heart-outline
|
||||
|
||||
На пожертвования [был приобретён](https://t.me/iptv_aggregator/30) домен `m3u.su`, который сейчас используется в качестве основного адреса.
|
||||
|
||||
<a id="participate"></a>
|
||||
## :simple-git: Принять участие в разработке
|
||||
## :simple-git: Принять участие в разработке { id="participate" }
|
||||
|
||||
Весь исходный код проекта хранится в репозиториях организации: [git.axenov.dev/IPTV](https://git.axenov.dev/IPTV)
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
tags: ["iptvc"]
|
||||
title: help
|
||||
tags: [iptvc]
|
||||
---
|
||||
|
||||
# Команда `help`
|
||||
@@ -27,11 +28,15 @@ 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:
|
||||
-h, --help help for iptvc
|
||||
-v, --verbose enable additional output
|
||||
--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.
|
||||
```
|
||||
@@ -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).
|
||||
@@ -6,7 +6,7 @@ icon: material/book-cog-outline
|
||||
|
||||
## Стилистика и правила оформления
|
||||
|
||||
Все исходники хранятся в директории `src/` в формате **Markdown** (формат файлов `.md`).
|
||||
Все исходники хранятся в директории `content/` в формате **Markdown** (формат файлов `.md`).
|
||||
|
||||
Структура проекта и его конфигурация описываются в файле `mkdocs.yml` в корне репозитория.
|
||||
|
||||
@@ -24,7 +24,7 @@ icon: material/book-cog-outline
|
||||
|
||||
## Добавление изображений
|
||||
|
||||
**Все изображения хранятся только в директории `src/assets/img/` и вложенных в неё.**
|
||||
**Все изображения хранятся в директории `_assets/` рядом с документом.**
|
||||
|
||||
Общая суть такова:
|
||||
|
||||
@@ -49,8 +49,8 @@ icon: material/book-cog-outline
|
||||
Совершенно любой текст, lorem ipsum dolor sit amet.
|
||||
|
||||
??? quote "В этом спойлере несколько больших картинок"
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
Продолжение текста, lorem ipsum dolor sit amet.
|
||||
Продолжение текста, lorem ipsum dolor sit amet.
|
||||
@@ -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,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`).
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
@@ -5,10 +5,10 @@ tags: ["плееры", "плейлисты"]
|
||||
|
||||
# :material-television-play: Как подключить плейлист
|
||||
|
||||
1. Найти какой-нибудь [плеер](./players.md)
|
||||
1. Найти какой-нибудь [плеер](../../common/players.md)
|
||||
2. Узнать как в него добавить плейлист по ссылке
|
||||
3. Найти желаемый плелист из [списка](./list.md)
|
||||
4. Найти на странице ["Ссылку для ТВ"](details.md#shortlink) и ввести (скопировать) её в поле ввода адреса в плеере
|
||||
|
||||
Для некоторых [плееров](./players.md) уже есть информация как добавить плейлист.
|
||||
Для некоторых [плееров](../../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` запущен.
|
||||
@@ -7,7 +7,7 @@ tags: ["сайт", "статусы", "каналы"]
|
||||
|
||||
Страница содержит подробности об одном конкретном плейлисте.
|
||||
|
||||
В её заголовке указано [название плейлиста](../formats/playlists.md#name).
|
||||
В её заголовке указано [название плейлиста](../../common/formats/playlists.md#name).
|
||||
|
||||
Ниже страница разделена на две части: слева две вкладки с информацией и список каналов справа.
|
||||
|
||||
@@ -15,28 +15,28 @@ tags: ["сайт", "статусы", "каналы"]
|
||||
|
||||
## Вкладка "Основная информация"
|
||||
|
||||

|
||||

|
||||
|
||||
На этой вкладке выводится таблица со следующими строками:
|
||||
|
||||
* **Код** — короткий уникальный [код плейлиста](../formats/playlists.md#code);
|
||||
* **Описание** — [описание плейлиста](../formats/playlists.md#desc) (при наличии);
|
||||
* **Ccылка для ТВ** — короткая ссылка, которую можно использовать для [подключения плейлиста](../common/connect.md), подробнее о ней см. ниже;
|
||||
* **Источник** — [ссылка на ресурс](../formats/playlists.md#src), где была найдена ссылка на плейлист (при наличии);
|
||||
* **Код** — короткий уникальный [код плейлиста](../../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** — [прямая ссылка](../formats/playlists.md#pls) на плейлист;
|
||||
* **Проверка плейлиста** — дата и время последней [проверки](../common/checks.md) плейлиста с помощью [iptvc](../iptvc/index.md);
|
||||
* **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> — это ерунда.
|
||||
@@ -49,7 +49,7 @@ tags: ["сайт", "статусы", "каналы"]
|
||||
|
||||
## Вкладка "Исходный текст"
|
||||
|
||||

|
||||

|
||||
|
||||
Здесь выводится плейлист как он есть.
|
||||
Над этим текстом — две кнопки:
|
||||
@@ -61,7 +61,7 @@ tags: ["сайт", "статусы", "каналы"]
|
||||
|
||||
В заголовке пишется их общее количество.
|
||||
|
||||

|
||||

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

|
||||

|
||||
|
||||
<a id="shortlink"></a>
|
||||
## Ссылка для ТВ
|
||||
## Ссылка для ТВ { id="shortlink" }
|
||||
|
||||
Она может быть задана в нескольких форматах.
|
||||
Поясню базовые принципы формирования адреса:
|
||||
@@ -119,13 +118,13 @@ m3u.su/ru.m3u
|
||||
m3u.su/ru
|
||||
```
|
||||
|
||||
!!! info ""
|
||||
Запоминать их не надо.
|
||||
Главное помнить как они формируются.
|
||||
!!! info "Адрес может быть любым"
|
||||
Смотря как будет развёрнут сайт, ты можешь заходить на localhost, либо по прямому IP-адресу или доменному имения.
|
||||
См. раздел [**Развёртывание**](deploy.md) для подробностей.
|
||||
|
||||
По идее, можешь использовать любую сылку из подобных, т. к. технически они отработают одинаково.
|
||||
По идее, можешь использовать любую ссылку из подобных, т. к. технически они отработают одинаково.
|
||||
|
||||
А вот твой [плеер](players.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).
|
||||
@@ -5,10 +5,10 @@ tags: ["плейлисты", "каналы", "теги", "iptvc", "плееры"
|
||||
|
||||
# :material-cogs: Как работает сервис
|
||||
|
||||
1. В специальном файле [playlists.ini](../formats/playlists.md) описываются плейлисты, которые кем-то опубликованы в интернете.
|
||||
1. В специальном файле [playlists.ini](../../common/formats/playlists.md) описываются плейлисты, которые кем-то опубликованы в интернете.
|
||||
Каждому плейлисту присваивается свой уникальный **короткий код**.
|
||||
2. В специальном файле [channels.json](../formats/channels.md) описываются **ключевые слова** (метки, теги), которые характеризуют каналы.
|
||||
3. В фоновом режиме [работает ПО](../iptvc/index.md), которое периодически [проверяет все плейлисты](checks.md) из п. 1 и **присваивает теги** каналам из п. 2.
|
||||
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`), то происходит **переадресация** на исходный плейлист.
|
||||
@@ -7,30 +7,30 @@ tags: ["сайт", "плейлисты"]
|
||||
|
||||
Это главная страница сайта.
|
||||
|
||||

|
||||

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

|
||||

|
||||
@@ -5,7 +5,7 @@ icon: material/wallet-outline
|
||||
# :material-wallet-outline: Правообладателям
|
||||
|
||||
Данные, представленные на сайте https://m3u.su, получены автоматически из открыто доступных в интернете IPTV-плейлистов, опубликованных третьими лицами.
|
||||
При наличии технической возможности, источник плейлиста может быть указан на вкладке [«Основные данные»](common/details.md).
|
||||
При наличии технической возможности, источник плейлиста может быть указан на вкладке [«Основные данные»](../iptvc/site/details.md).
|
||||
|
||||
Сервис https://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/)"
|
||||
@@ -27,12 +27,11 @@ tags: ["telegram"]
|
||||
К людям надо относиться по-человечески.
|
||||
Твой юмор могут не понять, а пассивную агрессию и дерзость не любит никто.
|
||||
|
||||
<a id="checklist"></a>
|
||||
## Я только спросить!
|
||||
## Я только спросить! { id="checklist" }
|
||||
|
||||
Держи чеклист:
|
||||
|
||||
1. **Найди ответ в [FAQ](../faq.md)**
|
||||
1. **Найди ответ в [FAQ](../aggregator/faq.md)**
|
||||
2. Если не нашёл ответ — прочти остальное
|
||||
3. Если не нашёл ответ и это проблема:
|
||||
* опиши всю ситуацию — сухо и по существу, в чём проблема, чего хочешь и ожидаешь;
|
||||
@@ -0,0 +1,85 @@
|
||||
# https://github.com/squidfunk/mkdocs-material/blob/master/src/overrides/hooks/shortcodes.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import unicodedata
|
||||
from html import escape
|
||||
|
||||
from markdown.extensions import Extension
|
||||
from markdown.preprocessors import Preprocessor
|
||||
|
||||
SHORTCODE_RE = re.compile(r"<!--\s*md:(env|arg|config|version|default|beta)\s*(.*?)\s*-->", re.I)
|
||||
|
||||
# Страница с описанием конфигурации. Указана явно, потому что в проекте
|
||||
# нет страницы `/iptvc/config` — соответствующий раздел живёт в
|
||||
# `content/common/config/config.md`. С `use_directory_urls = false` конечные
|
||||
# ссылки должны включать `.html`.
|
||||
CONFIG_PAGE = "/common/config/config.html"
|
||||
|
||||
|
||||
class BadgePreprocessor(Preprocessor):
|
||||
def run(self, lines: list[str]) -> list[str]:
|
||||
return [SHORTCODE_RE.sub(self._replace, line) for line in lines]
|
||||
|
||||
def _replace(self, match: re.Match[str]) -> str:
|
||||
kind, args = match.groups()
|
||||
args = args.strip()
|
||||
|
||||
if kind == "env":
|
||||
value = args or "(нет)"
|
||||
return _badge(":vscode-symbol-variable:", f"`{value}`", 'Переменная окружения')
|
||||
|
||||
if kind == "arg":
|
||||
value = args or "(нет)"
|
||||
return _badge(":vscode-terminal:", f"`{value}`", 'Аргумент командной строки')
|
||||
|
||||
if kind == "config":
|
||||
value = args or "(нет)"
|
||||
anchor = _slugify(args)
|
||||
return _badge(":material-cog-outline:", f"[`{value}`]({CONFIG_PAGE}#{anchor})", 'Параметр файла конфигурации')
|
||||
|
||||
if kind == "version":
|
||||
return _badge(":material-tag-outline:", escape(args), 'Версия, в которой появился этот функционал')
|
||||
|
||||
if kind == "default":
|
||||
value = escape(args or "null")
|
||||
return _badge(":material-water-outline:", f"`{value}`", 'Значение по умолчанию')
|
||||
|
||||
if kind == "beta":
|
||||
return _badge(":material-beta:", '', 'Экспериментальный функционал')
|
||||
|
||||
return match.group(0)
|
||||
|
||||
|
||||
# Slugify, совместимый с дефолтным slugify в pymdownx.slugs:
|
||||
# NFKD-нормализация → отбрасывание не-ASCII → замена не-alphanumeric на дефис →
|
||||
# склейка дефисов → trim → lowercase. Позволяет заранее предсказать якорь,
|
||||
# не дожидаясь обработки Markdown
|
||||
def _slugify(value: str) -> str:
|
||||
if not value:
|
||||
return ""
|
||||
normalized = unicodedata.normalize("NFKD", value)
|
||||
ascii_only = normalized.encode("ascii", "ignore").decode("ascii")
|
||||
slug = re.sub(r"[^a-zA-Z0-9]+", "-", ascii_only)
|
||||
return slug.strip("-").lower()
|
||||
|
||||
|
||||
# Формирует HTML-разметку бейджа. Иконки остаются Zensical-шорткодами
|
||||
# и рендерятся штатным `pymdownx.emoji` на следующем этапе обработки Markdown.
|
||||
def _badge(icon: str, text: str = "", title: str = "") -> str:
|
||||
return "".join([
|
||||
f'<span class="mdx-badge" title="{title}">',
|
||||
f'<span class="mdx-badge__icon">{icon}</span>',
|
||||
*([f'<span class="mdx-badge__text">{text}</span>'] if text else []),
|
||||
'</span>',
|
||||
])
|
||||
|
||||
|
||||
class InlineBadgeExtension(Extension):
|
||||
def extendMarkdown(self, md):
|
||||
md.preprocessors.register(BadgePreprocessor(md), "inline_badges", 175)
|
||||
|
||||
|
||||
def makeExtension(**kwargs):
|
||||
return InlineBadgeExtension(**kwargs)
|
||||
@@ -1,144 +0,0 @@
|
||||
site_name: Документация m3u.su
|
||||
site_description: Описание сервиса m3u.su и его компонентов
|
||||
site_author: Антон Аксенов
|
||||
copyright: Антон Аксенов © 2025 MIT License
|
||||
|
||||
repo_name: Репозиторий
|
||||
repo_url: https://git.axenov.dev/IPTV/docs
|
||||
edit_uri: src/branch/master/src/
|
||||
remote_branch: master
|
||||
|
||||
docs_dir: ./src
|
||||
use_directory_urls: false
|
||||
watch:
|
||||
- src
|
||||
extra_css:
|
||||
- assets/css/custom.css
|
||||
extra_javascript:
|
||||
- https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js
|
||||
|
||||
extra:
|
||||
homepage: /docs
|
||||
logo: assets/img/favicon/logo.png
|
||||
favicon: assets/img/favicon/logo.png
|
||||
social:
|
||||
- name: Канал @iptv_aggregator
|
||||
icon: simple/telegram
|
||||
link: https://t.me/iptv_aggregator
|
||||
- name: Чат @iptv_aggregator_chat
|
||||
icon: simple/telegram
|
||||
link: https://t.me/iptv_aggregator_chat
|
||||
- name: Бот @iptv_aggregator_bot
|
||||
icon: simple/telegram
|
||||
link: https://t.me/iptv_aggregator_bot
|
||||
|
||||
theme:
|
||||
name: 'material'
|
||||
language: ru
|
||||
features:
|
||||
- toc.follow
|
||||
- search.suggest
|
||||
- navigation.top
|
||||
- navigation.footer
|
||||
- navigation.indexes
|
||||
- content.action.edit
|
||||
icon:
|
||||
repo: simple/gitea
|
||||
edit: material/pencil
|
||||
view: material/eye
|
||||
palette:
|
||||
# Автотема
|
||||
- media: "(prefers-color-scheme)"
|
||||
toggle:
|
||||
icon: material/brightness-auto
|
||||
name: Switch to light mode
|
||||
# Тёмная тема
|
||||
- scheme: slate
|
||||
media: "(prefers-color-scheme: light)"
|
||||
accent: teal
|
||||
primary: black
|
||||
toggle:
|
||||
name: Светлая тема
|
||||
icon: material/weather-sunny
|
||||
# Светлая тема
|
||||
- scheme: default
|
||||
media: "(prefers-color-scheme: dark)"
|
||||
accent: teal
|
||||
primary: teal
|
||||
toggle:
|
||||
name: Тёмная тема
|
||||
icon: material/weather-night
|
||||
|
||||
plugins:
|
||||
- minify:
|
||||
minify_html: true
|
||||
- tags:
|
||||
tags: true
|
||||
listings: true
|
||||
- social:
|
||||
cards_layout_options:
|
||||
background_color: teal
|
||||
background_image: null
|
||||
- search:
|
||||
separator: '[\s\-\.]+'
|
||||
# indexing: 'full'
|
||||
|
||||
validation:
|
||||
omitted_files: warn
|
||||
absolute_links: warn
|
||||
unrecognized_links: warn
|
||||
anchors: warn
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- pymdownx.details
|
||||
- pymdownx.superfences
|
||||
- attr_list
|
||||
- md_in_html
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
- toc:
|
||||
permalink: true
|
||||
|
||||
nav:
|
||||
- index.md
|
||||
- docs.md
|
||||
- support.md
|
||||
- legal.md
|
||||
- 'Общая информация':
|
||||
- common/index.md
|
||||
- common/how-it-works.md
|
||||
- common/selection.md
|
||||
- common/checks.md
|
||||
- common/list.md
|
||||
- common/details.md
|
||||
- common/connect.md
|
||||
- common/players.md
|
||||
- 'IPTV Checker (iptvc)':
|
||||
- iptvc/index.md
|
||||
- iptvc/install.md
|
||||
- iptvc/quickstart.md
|
||||
- iptvc/env.md
|
||||
- 'Доступные команды':
|
||||
- iptvc/commands/index.md
|
||||
- iptvc/commands/help.md
|
||||
- iptvc/commands/check.md
|
||||
- iptvc/commands/version.md
|
||||
- statuspage.md
|
||||
- 'Для разработчиков':
|
||||
- dev/index.md
|
||||
- dev/local-dev.md
|
||||
- dev/tgbot.md
|
||||
- dev/docs.md
|
||||
- dev/deploy.md
|
||||
- 'Форматы файлов':
|
||||
- formats/index.md
|
||||
- 'playlists.ini': 'formats/playlists.md'
|
||||
- 'channels.json': 'formats/channels.md'
|
||||
- '*.m3u (*.m3u8)': 'formats/m3u.md'
|
||||
- 'Telegram':
|
||||
- tg/index.md
|
||||
- 'Бот': tg/bot.md
|
||||
- 'Чат': tg/chat.md
|
||||
- 'FAQ (ЧаВо)': 'faq.md'
|
||||