diff --git a/personal/index.md b/personal/index.md index c25071f5..8a78d881 100644 --- a/personal/index.md +++ b/personal/index.md @@ -142,6 +142,7 @@ Hub: [[personal/projects/media-pipeline-tracker-parsers|Media Pipeline Roadmap]] - [[personal/tech/karabiner-keyboard-config|⌨️ Karabiner — конфиг, раскладки, символы]] - [[personal/music-download-practices|Music Download Practices]] - [[personal/spotify-library|Spotify Library]] +- [[personal/tech/yandex-music-api|🎵 Yandex Music API — выгрузка библиотеки]] --- diff --git a/personal/spotify-library.md b/personal/spotify-library.md index 00b6741d..5b4895d0 100644 --- a/personal/spotify-library.md +++ b/personal/spotify-library.md @@ -2,6 +2,9 @@ > Выгружено: 2026-05-12 | [Профиль](https://open.spotify.com/user/mixsxmcds20znczu4na52ghox) +> ⚠️ **Токен для повторной выгрузки не найден** — desktop-приложение не пишет cookies на диск. +> Способы обновления: [[personal/tech/yandex-music-api|Yandex Music API → раздел Spotify]] + --- ## 🎵 Лайкнутые треки (162 всего, показаны 50) diff --git a/personal/tech/yandex-music-api.md b/personal/tech/yandex-music-api.md new file mode 100644 index 00000000..bcfa8374 --- /dev/null +++ b/personal/tech/yandex-music-api.md @@ -0,0 +1,182 @@ +--- +title: Yandex Music API — выгрузка библиотеки +updated: '2026-09-26' +type: tech +tags: + - music + - yandex + - api + - personal +related: personal/spotify-library +--- + +# Yandex Music API — выгрузка библиотеки + +> Рабочий метод выгрузки лайков, плейлистов и альбомов из Яндекс Музыки +> **БЕЗ OAuth-флоу** — токен лежит в Local Storage desktop-приложения. +> Проверено живыми запросами: 2026-09-26. +> Skill: `yandex-music-library-export` (`~/.hermes/hermes-whale/skills/media/`) + +--- + +## 1. Извлечение токена (главное) + +Desktop-приложение Яндекс Музыки хранит OAuth-токен в **Local Storage LevelDB** в открытом виде (без шифрования, не в Keychain). + +**Путь:** +``` +~/Library/Application Support/YandexMusic/Local Storage/leveldb/ +``` +Файлы: `000394.log`, `000396.ldb` — **номер файла меняется**, искать по маске `*.ldb` / `*.log`. + +**Формат токена:** `y0_` + ~56 символов base64url (итого ~59-60 символов). + +```bash +LS="$HOME/Library/Application Support/YandexMusic/Local Storage/leveldb" +find "$LS" -type f \( -name "*.ldb" -o -name "*.log" \) \ + | while read f; do strings "$f" | grep -oE "y0_[A-Za-z0-9_.-]{20,}"; done \ + | head -1 > /tmp/ym_token +chmod 600 /tmp/ym_token +``` + +### Что НЕ работает — не тратить время + +| Источник | Результат | +|---|---| +| `YandexMusic/Cookies` (Session_id, sessionid2) | ❌ HTTP 401 | +| Keychain (`security find-generic-password -s "Yandex Music Safe Storage"`) | ❌ Записи не существует | +| `IndexedDB/*.leveldb/*.log` | ❌ Токена нет, там кэш | +| `Preferences`, `.updaterId` | ❌ Только UUID и настройки | + +**Важно:** `sessionid2` содержит суффикс `fakesign000...` — это заглушка, реальная авторизация идёт через OAuth-токен. + +--- + +## 2. uid пользователя + +```bash +H="Authorization: OAuth $(cat /tmp/ym_token)" +curl -s -H "$H" "https://api.music.yandex.net/account/status" | jq -r '.result.account.uid' +# → 16635693 +``` + +Заголовок — именно **`OAuth`**, не `Bearer`. + +--- + +## 3. Проверенные эндпоинты + +База: `https://api.music.yandex.net` + +| Что | Endpoint | Проверено | +|---|---|---| +| Статус аккаунта + uid | `GET /account/status` | ✅ | +| Настройки | `GET /account/settings` | ✅ | +| **Лайкнутые треки** | `GET /users/{uid}/likes/tracks` | ✅ 956 треков | +| **Плейлисты** | `GET /users/{uid}/playlists/list` | ✅ 8 штук | +| Лайкнутые альбомы | `GET /users/{uid}/likes/albums` | ✅ 100 | +| Метаданные треков | `GET /tracks?track-ids=ID1,ID2,...` | ✅ title/artists/albums | + +### Ответ `likes/tracks` — только id и timestamp! + +```json +{ + "result": { + "library": { + "tracks": [ + {"id": "149422838", "albumId": "41220806", "timestamp": "2026-08-27T02:05:47+00:00"} + ] + } + } +} +``` +`timestamp` — дата лайка. Названий и артистов НЕТ — нужен второй запрос на `/tracks` батчами по ~100 id. + +### Ответ `playlists/list` + +```json +[{"kind": 1009, "title": "Классика", "trackCount": 3}] +``` +Параметр `?with-tracks=true` добавляет треки в тот же ответ. + +--- + +## 4. Прослушанное (история) — НЕ ДОСТУПНО ⛔ + +Ни один из вариантов не существует в публичном API: + +| Endpoint | Ответ | +|---|---| +| `/users/{uid}/history` | `not-found` | +| `/users/{uid}/music-history` | `not-found` | +| `/users/{uid}/recent-tracks` | `not-found` | +| `/users/{uid}/play-history` | `not-found` | +| `/users/{uid}/plays` | `not-found` | +| `/users/{uid}/listening` | `not-found` | + +`GET /landing3?blocks=personal-playlists` возвращает блоки, но `data.title: null` — контент скрыт за авторизацией веб-клиента. + +**Вывод:** историю прослушивания Яндекс через этот API не отдаёт. + +--- + +## 5. Spotify — токен НЕ найден ⛔ + +Проверено (2026-09-26), ни одного `sp_dc` / `sp_t` / `access_token`: + +| Место | Результат | +|---|---| +| Desktop app `PersistentCache/public.ldb/*.log` | ❌ Только телеметрия | +| `Users/-user/prefs` | ❌ Только настройки UI и DIAL-устройства | +| Keychain `Spotify Safe Storage` | ❌ Записи не существует | +| Chrome (Default, Profile 4, Guest) | ❌ 0 spotify-cookies | +| Firefox (3 профиля) | ❌ 0 | +| Safari (`Cookies.binarycookies`) | ❌ 0 | +| Arc / Brave | ❌ Профилей нет | + +**Приложение Spotify на Mac не пишет cookies на диск.** Токен либо в памяти, либо в Keychain под другим именем. + +**Рабочие варианты (не проверялись):** +1. `spotify.com/account/privacy` → **Request data** (Extended streaming history) — ZIP на email +2. Official Web API `GET /v1/me/tracks` — требует OAuth-приложения в Developer Dashboard +3. `sp_dc` из залогиненной веб-сессии `open.spotify.com` + +--- + +## 6. Итоговое состояние (2026-09-26) + +| | Яндекс Музыка | Spotify | +|---|---|---| +| Токен | ✅ `y0_...` в `/tmp/ym_token` | ❌ нет | +| uid | `16635693` (login mAlleXXX) | `mixsxmcds20znczu4na52ghox` | +| Лайки | ✅ 956 треков | ⚠️ 162 (данные в [[personal/spotify-library]] от 2026-05-12) | +| Плейлисты | ✅ 8 штук | ⚠️ 6 (2026-05-12) | +| Альбомы | ✅ 100 | ⚠️ 40 (2026-05-12) | +| История | ❌ API не отдаёт | ❌ токена нет | + +**8 плейлистов Яндекс:** Классика (3), ДР (3), ok (4), олдскуд (3), Слушать позже (34), Best (1), Мои аудиозаписи ВКонтакте (237), Мегаpolice - АК-47 (20) + +### Открытая задача +Выгрузить 956 лайков + 8 плейлистов + 100 альбомов в `personal/yandex-music-library.md` по образцу [[personal/spotify-library]]. **Не сделано — ждёт подтверждения.** + +--- + +## 7. Подводные камни + +- **`$(...)` внутри write_file может быть вырезан** санитайзером → `syntax error near unexpected token )`. Решение: писать скрипт без inline-подстановок, читать токен из файла; либо `source /dev/stdin <<'EOF'`. +- **Не эхоить токен в stdout** — попадает в лог сессии. Писать в `/tmp/ym_token` с `chmod 600`. +- **Токен привязан к устройству и обновляется** — при 401 перечитать из LevelDB (приложение должно быть запущено и залогинено). +- **Токен в `/tmp` сбрасывается при перезагрузке** — извлекать заново. +- **Не пихать 956 id в один URL** `/tracks?track-ids=` — бить на батчи по ~100. +- **uid `0` не работает**: `/users/0/likes/tracks` → `invalid uid: 0`. Только реальный uid. + +--- + +## 8. Связанные документы + +- [[personal/spotify-library]] — выгрузка Spotify (2026-05-12) +- [[personal/music-download-practices]] — источники mp3, загрузка на TrueNAS +- [[personal/documents/music-recommendations]] — музыкальные рекомендации + +--- +*Создано: 2026-09-26 | Сессия: разведка способов выгрузки Яндекс Музыки и Spotify*