DEPENDENCIES.md
Rama main · réplica de lectura del repositorio original.
# Ripster — архитектура «из коробки» и авто-докачка тяжёлых зависимостей
> **Директива владельца (2026-06-20):** весь проект должен работать **из коробки**,
> КРОМЕ тяжёлых зависимостей/движков — их Ripster **докачивает сам**:
> либо в момент установки (GitHub-инсталлятор), либо из вкладки **Setup**
> (если скачана portable-версия, уже собранная в архив). Авто-докачка —
> обязательная способность Ripster.
## Принцип
1. **В git/инсталлятор едет только лёгкое ядро** — Python-исходники (`ripster/`,
`app.py`), статика UI, шаблоны конфигов, `requirements.txt`
(pinned pip-зависимости). Это ставится мгновенно и работает.
2. **Тяжёлое НЕ бандлится** — бинари, Go-сборки, движки-клоны, Node-сборки, CDM.
Их Ripster тянет **по требованию** через `ripster/setup/`.
3. **Два режима поставки** (оба используют одну и ту же авто-докачку):
- **GitHub-инсталлятор** — тянет тяжёлое в момент установки.
- **Portable-архив** (уже собран) — тянет тяжёлое из вкладки **Setup** при
первом запуске / по кнопке.
## Что уже РЕАЛИЗОВАНО (не писать заново!)
`ripster/setup/__init__.py` — рабочая авто-докачка:
- `download_file()`, `download_file_no_ssl()` — generic-загрузчики с прогрессом.
- `install_go_windows()`, `install_gpac_windows()` (MP4Box), `install_mp4decrypt_windows()` (Bento4).
- `clone_downloader()` + `go_mod_download()` — клон+сборка Go Apple-движка.
- `check_tools()` — инвентарь зависимостей (источник истины, см. ниже).
- `find_go()`, `tool_path()`, `check_docker_installed()`, `run_full_setup()`.
`ripster/routes/setup.py` — эндпоинты Setup-вкладки: `run_setup`,
wrapper (start/build/pull/2fa/relogin), `orpheus_login_*`, `soundcloud_install`,
`beatport_install`, `fix_gamdl_deps`, `get_install_log`, `restart_app`.
## Инвентарь зависимостей (из `check_tools()` + бинари)
| Зависимость | Вес | Для чего | Как тянется | В git? |
|---|---|---|---|---|
| pip deps (`requirements.txt`) | лёгкое | весь Python | `pip install` при установке | ✅ (только lock-файл) |
| **Go toolchain** | тяжёлое | zhaarey (Apple lossless) | `install_go_windows()` | ❌ |
| **GPAC / MP4Box** | тяжёлое | zhaarey мукс | `install_gpac_windows()` | ❌ |
| **Bento4 / mp4decrypt** | средн. | декрипт | `install_mp4decrypt_windows()` | ❌ |
| **FFmpeg** | тяжёлое | конвертация/мукс/кавер | авто-поиск + (нужен установщик) | ❌ |
| **N_m3u8DL-RE.exe** | 16.6 МБ | быстрый HLS-загрузчик | download_file (релиз с GitHub) | ❌ |
| **apple-music-downloader.exe** | 19.6 МБ | Go Apple-движок (zhaarey) | **БАНДЛИТСЯ предсобранным (решение владельца 2026-06-21)** — лежит в корне, zhaarey авто-детектит (`use-go-run` деф. False). Apple работает из коробки на Windows БЕЗ Go-сборки. Fallback/кросс-платформа: `clone_downloader`+`go_mod_download` (нужен Go toolchain). ⚠️ exe — Windows-only; не-Windows собирает из Go-исходников через Setup. | ⚠️ staging (origin=upstream, не push) |
| **Docker + zhaarey wrapper** | тяжёлое | локальный Apple lossless | wrapper pull/build (Setup) | ❌ |
| **OrpheusDL + модули** (tidal/spotify/beatport) | средн. | эти движки | git clone в `orpheus/modules/` | ❌ |
| **Node.js + Lucida build** | тяжёлое | SoundCloud | `soundcloud_install()` | ❌ |
| **amz CLI** | средн. | Amazon Music | (нужен установщик в Setup) | ❌ |
| **Widevine `.wvd`** | мал., но ПРИВАТНОЕ | SC DRM (sc_widevine) | юзер кладёт сам (нельзя раздавать — legal) | ❌ |
| **librespot + Spotify blob** | средн. | Spotify OGG | `tools/spotify_pair.py` (один раз) | ❌ |
| Токены/сессии (Tidal/Spotify/Qobuz/Amazon/Yandex…) | — | авторизация | из коробки логины (Setup): TV device-flow, librespot OAuth (#4/#10) | ❌ (приватное) |
## Что НЕ улетает на GitHub (повтор из ROADMAP)
Telegram-бот (`tgbot/`), гостевой режим, вкладки Библиотека/Теггер/Статистика,
боевые токены/сессии/cookies/конфиги, тяжёлые бинари (см. таблицу).
## Приватные/юридически чувствительные артефакты (.wvd, токены) — политика
**Вопрос владельца:** свой `.wvd` в репо положить нельзя — можно ли в установщик
функцию авто-«поднятия» такого?
**Ответ: НЕТ авто-скачивания рабочего CDM, ДА управляемому one-time setup.**
- `.wvd` = сериализованный Widevine L3 CDM (сертификат+ключ устройства). Раздавать
его (в git или авто-докачкой из сети) **нельзя**: (1) юридически — обход DRM /
Widevine ToS / DMCA; (2) технически — расшаренные CDM Google **быстро ревокает**;
(3) безопасность/абьюз. Легитимного API «выдай CDM» не существует — он
извлекается из СВОЕГО устройства (rooted Android / эмулятор), это ручной per-user шаг.
- **Что установщик МОЖЕТ (и уже частично умеет):** управляемый Setup-флоу —
пользователь кладёт СВОЙ `.wvd`, проект его валидирует и подключает.
УЖЕ ЕСТЬ: `routes/soundcloud.py` `sc_upload_wvd` (base64-загрузка + проверка через
`pywidevine.Device.load`, кладёт в `tools/widevine/device.wvd`) и `sc_wvd_status`
(установлен/валиден). Надо: довести до явного шага в Setup-визарде + краткий гайд
«как извлечь свой L3 CDM» (ссылки), кнопка «проверить» (минт тестового ключа).
- **`.wvd` ОПЦИОНАЛЕН** — нужен только для SoundCloud HQ-DRM (движок `sc_widevine`).
Без него SC работает из коробки (mp3/Lucida путь). Значит «из коробки» не ломается;
`.wvd` — opt-in апгрейд, который юзер ставит сам.
- **Токены/cookies/librespot-blob** — тот же принцип: НЕ бандлим, юзер заводит через
управляемые из-коробки логины (Tidal TV device-flow, Spotify librespot OAuth — #4/#10,
`tools/spotify_pair.py`). Это и есть «установка зависимостей», но авторизационных.
**Итог:** «работа из коробки с установкой ВСЕХ зависимостей» = ✅ для всего свободно
распространяемого (Go/ffmpeg/Bento4/N_m3u8DL-RE/OrpheusDL/Node-Lucida/amz — авто-докачка);
для CDM/токенов — управляемый one-time setup (единственная легальная и рабочая модель).
## Лаунчер и автономный запуск (директива 2026-06-20)
**Ключевое: проект должен открываться автономно, как deemix** — скачал → запустил
→ открылось приложение с UI, без ручных шагов.
**Важное отличие:** deemix — это ОДИН файл; Ripster — **многофайловый проект**.
То есть UX автономный (само открывается), но структура остаётся проектом-папкой
(исходники + авто-докачка тяжёлого), а НЕ единый бандл-бинарь. Цель — «папка/архив,
который сам запускается», а не «один .exe».
- **`RipsterLauncher.exe` (35 МБ) переработать и спрятать в сам проект.** Сейчас
это отдельный тяжёлый PyInstaller/PyQt-бинарь-супервизор. Нужно: лёгкий
**launcher из исходников** (часть репозитория), который сам поднимает app
(bootstrap-цепочка `.venv → Py312`, см. [[restart-clean]] в памяти / SESSION_LOG_FULL),
открывает браузер/окно на `127.0.0.1:7799` и супервизит процесс. Без 35 МБ .exe в git.
- Автономный вход = единая точка старта (один скрипт/ярлык) → проверка зависимостей
(`check_tools`) → при нехватке тяжёлого предложить докачку → запуск сервера → UI.
- Для portable-архива: тот же launcher из исходников; тяжёлое тянется в Setup.
- **Своё окно, НЕ браузер (директива 2026-06-20):** UI открывается в собственном
нативном окне, а не во вкладке браузера. Рекомендация — **pywebview** (лёгкая
pure-Python обёртка над системным webview: Edge WebView2 на Windows; без бандла
Chromium, в отличие от Electron/QtWebEngine — отсюда и «не 35 МБ»). Лаунчер:
поднять FastAPI на `127.0.0.1:7799` в фоне → открыть pywebview-окно на этот адрес →
закрытие окна гасит сервер. pywebview добавить в `requirements.txt` (лёгкое,
кросс-платформенное). Фолбэк: если webview недоступен — открыть в браузере.
## Обновление / сопровождение (стратегия, директива-вопрос 2026-06-20)
**Принцип: инкрементальный «Ripster Updater», НЕ полный ре-релиз сетапа каждый раз.**
Публичная версия — интерпретируемый Python-исходник + отдельно докачиваемое тяжёлое,
поэтому апдейт = маленький диф исходников (+ иногда `requirements.txt`). Полный
инсталлятор нужен только для ПЕРВОЙ установки / крупной смены раскладки зависимостей.
**Уже есть:** `APP_VERSION="3.0.0"` (app.py:230); обновление pip-депов
`/api/admin/deps[/update]` (учёт пинов, не трогает тяжёлое); откат `backups/RESTORE_*`;
`restart_app`. ⚠️ Текущий git-`origin` = апстрим `zhaarey/apple-music-downloader`,
Python gitignored → **нужен свой репозиторий Ripster** (предусловие апдейтера).
**Механизм Updater (в Setup-вкладке):**
1. **Версионирование:** semver + GitHub Releases/теги + CHANGELOG (это и есть «принцип»).
2. **Проверка:** сравнить локальный `APP_VERSION` с последним тегом/`VERSION` в репо →
показать changelog → кнопка «Обновить».
3. **Доставка исходников — два пути (поддержать оба):**
- `git pull` если установка — git-клон (git и так required-деп) — чистый диф;
- оверлей **release-zip** для portable-архива (через `setup.download_file`) — без git.
4. **Депы:** если изменился `requirements.txt` — прогнать существующий dep-update
(пин-aware). Тяжёлое НЕ трогаем.
5. **Данные юзера сохраняются:** config.yaml, токены, сессии, `.wvd`, downloads, history —
вне трекаемого дерева/gitignored → апдейт их не затирает.
6. **Безопасность:** снапшот в `backups/` (паттерн есть) → применить → **прогнать
`tests/test_imports.py`** (тест-сеть = идеальный post-update gate на сломанный апдейт)
→ откат при провале → `restart_app`.
7. (опц.) Каналы: stable (теги) + dev (main).
**Почему НЕ полный сетап каждый раз:** лишняя пере-докачка тяжёлого, риск затереть
состояние юзера, медленно и бессмысленно (исходник мал, тяжёлое отдельно).
## ГЭПЫ к финальной сборке (TODO)
1. **`.gitignore` для дистрибутива** — исключить все ❌-строки таблицы (бинари,
`orpheus/modules/*`, `.wvd`, токены, `node_modules`, Go-кэш).
2. **First-run Setup wizard** — на старте дёргать `check_tools()`, показать чего
нет, и «Установить всё» одной кнопкой (оркестратор уже есть — `run_full_setup`).
3. **Недостающие авто-установщики**: FFmpeg (есть авто-поиск, нет авто-install),
`amz` CLI, N_m3u8DL-RE (проверить, тянется ли в `run_full_setup`).
4. **Кросс-платформа**: текущие `install_*_windows()` только под Windows — для
публичного релиза либо явно заявить «Windows-only», либо добавить Linux/macOS.
5. **`config.example.yaml`** без секретов + README с шагами установки.
6. **Манифест версий** тяжёлых артефактов (какой релиз N_m3u8DL-RE / Go и т.п.
тянуть) — чтобы сборки были воспроизводимы.
7. **Дымовой тест чистого клона**: склонировать в пустую папку → `pip install` →
запустить → Setup тянет тяжёлое → загрузка работает.