This commit is contained in:
2026-05-30 09:24:42 +08:00
parent 6c3de4b2ef
commit e054f458bb
17 changed files with 533 additions and 78 deletions

187
AGENTS.md Normal file
View File

@@ -0,0 +1,187 @@
# Контекст проекта: IPTV Checker (iptvc)
> **Важно:** Этот файл создан автоматически на основе анализа кодовой базы. Используй его как справочный контекст при внесении изменений.
---
## Обзор проекта
**IPTV Checker (iptvc)** — консольная утилита для проверки доступности IPTV-плейлистов и каналов в форматах `m3u` / `m3u8`.
- **Назначение:** Быстрая массовая проверка плейлистов из файлов, по URL или из INI-реестра с расчётом статистики (online/offline).
- **Экосистема:** Часть проекта [m3u.su](https://m3u.su).
- **Лицензия:** MIT (см. `LICENSE`).
- **Автор:** Антон Аксенов.
### Основные технологии
- **Язык:** Go 1.23.6+
- **CLI-фреймворк:** [spf13/cobra](https://github.com/spf13/cobra)
- **Кеширование:** [Redis / KeyDB](https://github.com/redis/go-redis) (опционально, через `go-redis/v9`)
- **Конфигурация окружения:** [godotenv](https://github.com/joho/godotenv) + переменные окружения
- **Парсинг INI:** [gopkg.in/ini.v1](https://gopkg.in/ini.v1)
### Архитектура
Приложение построено по классической для Go CLI схеме:
```
cmd/ — команды Cobra (root, check)
app/ — бизнес-логика и инфраструктура
app.go — инициализация конфигурации, логгера, кеша; глобальные аргументы
checker/ — ядро проверки: подготовка списков, HTTP-опрос каналов, семафоры
playlist/ — модели Playlist/Channel/Group, парсинг m3u/m3u8
inifile/ — чтение реестра плейлистов из INI
config/ — чтение конфигурации из env (.env)
cache/ — подключение к Redis/KeyDB
logger/ — настройка вывода логов
tagfile/ — работа с файлом тегов (channels.json)
utils/ — вспомогательные функции (MD5, Fetch, ExpandPath и др.)
main.go — точка входа: контекст с отменой по сигналу, делегация cmd.ExecuteContext
```
---
## Сборка и запуск
### Локальная разработка
```bash
# Быстрый запуск из исходников
go run .
# Сборка бинаря
go build -o iptvc .
# Показать справку
./iptvc help
# Проверить плейлист из файла
./iptvc check -f mypls.m3u
# Проверить плейлист по ссылке
./iptvc check -u http://m3u.su/XYZ
# Проверить плейлисты из INI-файла
./iptvc check -i playlists.ini
# Только JSON-результат, без логов
./iptvc check -f mypls.m3u -j -q
```
### Makefile
| Команда | Описание |
|---------|----------|
| `make help` | Справка по целям |
| `make fmt` | `go fmt ./...` |
| `make vet` | `go vet ./...` |
| `make tidy` | `go mod tidy && go mod verify` |
| `make lint` | `fmt` + `vet` + сборка в `/dev/null` |
| `make clean` | Удаление скомпилированных бинарей и `bin/` |
| `make linux` | Сборка для Linux (`GOARCH=amd64` по умолчанию) |
| `make win` | Сборка для Windows |
| `make darwin` | Сборка для macOS |
| `make release` | Полный релиз: все ОС × amd64 + arm64, упаковка в zip |
> **Примечание:** Переменная `GOARCH` переопределяется через окружение, например: `make linux GOARCH=arm64`.
### Docker
```bash
# Ручная сборка образа
docker build -t iptvc:latest .
# Скрипт сборки и публикации (с версионированием через git-тег)
./build-docker-image.sh [TAG]
```
Dockerfile использует многоступенчатую сборку:
1. `golang:1.25-alpine` — компиляция бинаря (`CGO_ENABLED=0`, `trimpath`, `ldflags`)
2. `alpine:3.22.2` — финальный минимальный образ с непривилегированным пользователем.
---
## Конфигурация
Приложение читает переменные окружения (файл `.env` опционален).
| Переменная | По умолчанию | Описание |
|------------|--------------|----------|
| `CACHE_ENABLED` | `false` | Включить подключение к кешу |
| `CACHE_HOST` | `localhost` | Хост Redis/KeyDB |
| `CACHE_PORT` | `6379` | Порт |
| `CACHE_USERNAME` | — | Пользователь |
| `CACHE_PASSWORD` | — | Пароль |
| `CACHE_DB` | `0` | Номер БД |
| `CACHE_TTL` | `1800` | TTL записей в секундах |
> Файл `.env.example` содержит пример заполнения.
---
## Ключевые файлы и пакеты
| Путь | Назначение |
|------|------------|
| `main.go` | Точка входа: `context.WithCancel`, обработка `SIGINT`/`SIGTERM`, вызов `cmd.ExecuteContext` |
| `cmd/root.go` | Корневая команда Cobra, глобальный флаг `--verbose` |
| `cmd/check.go` | Команда `check`: флаги (`-f`, `-u`, `-i`, `-c`, `-t`, `-r`, `-j`, `-q`, `--repeat`, `--every`), цикл повторений, вызов `checker` |
| `app/app.go` | Глобальные объекты `Args`, `Cache`, `Config`; `Init()` и `Shutdown()` |
| `app/checker/checker.go` | **Ядро:** подготовка списков, скачивание плейлистов, HTTP-опрос каналов с семафором, динамический расчёт `timeout`/`routines`, кеширование результатов |
| `app/playlist/playlist.go` | Структуры `Playlist`, `Channel`, `Group`; парсинг m3u/m3u8 (атрибуты `#EXTINF`, `#EXTGRP`, заголовок `#EXTM3U`) |
| `app/config/config.go` | Чтение конфигурации из env с дефолтами |
| `app/inifile/inifile.go` | Чтение реестра плейлистов в формате INI |
| `app/cache/cache.go` | Инициализация клиента Redis/KeyDB |
| `app/tagfile/tagfile.go` | Загрузка и поиск тегов для каналов |
| `app/utils/utils.go` | Утилиты: `Fetch`, `ExpandPath`, `Md5str`, `ArrayUnique` |
| `app/utils/utils_test.go` | Тесты утилит |
| `app/config/config_test.go` | Тесты конфигурации |
| `app/playlist/playlist_test.go` | Тесты парсера плейлистов |
| `docs/json.md` | Документация по структуре JSON-вывода |
| `build-docker-image.sh` | Скрипт сборки и пуша Docker-образа с версией из git |
| `Dockerfile` | Многоступенчатая сборка контейнера |
---
## Правила разработки
### Стиль кода
- Код оформлен в едином стиле с лидирующими комментариями-заголовками (автор, лицензия, ссылка на репозиторий).
- Используются экспортируемые имена с подробными комментариями на русском языке (доминирующий язык комментариев).
- Глобальные переменные приложения (`Args`, `Cache`, `Config`) расположены в `app/app.go`.
### Тестирование
- Модульные тесты присутствуют для пакетов `utils`, `config`, `playlist`.
- Для запуска: `go test ./...`.
### Линтинг
- В Makefile есть цель `lint`, объединяющая `go fmt`, `go vet` и проверочную сборку.
- Перед коммитом рекомендуется выполнять `make lint`.
### Работа с зависимостями
- Модули Go (`go.mod` / `go.sum`).
- Обновление/очистка: `make tidy`.
### Соглашения по логике
- **Динамические параметры проверки:** количество горутин и HTTP-таймаут рассчитываются в `calcParameters(count)` на основе числа каналов. Чем больше каналов — тем больше параллелизм, но таймаут сокращается.
- **Семафор:** количество одновременных проверок ограничено через буферизированный канал (`chSemaphores`).
- **User-Agent:** при проверке каналов используется фиксированный заголовок `Mozilla/5.0 WINK/1.31.1 (AndroidTV/9) HlsWinkPlayer`.
- **TLS:** проверка выполняется с `InsecureSkipVerify: true`.
- **Кеш:** результаты проверки плейлистов сериализуются в JSON и сохраняются в Redis с TTL.
---
## Коды возврата
| Код | Значение |
|-----|----------|
| `0` | Успех |
| `1` | Общая ошибка |
| `2` | Команда `check` запущена без параметров `-f`, `-u` и `-c` (и нет INI по умолчанию) |
| `130` | Прерывание по сигналу (`SIGINT` / `SIGTERM`) |