--- # 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 при отображении в веб-интерфейсе.