build spotify-to-navidrome migrator with recovery flow
This commit is contained in:
70
README.md
70
README.md
@@ -6,14 +6,18 @@ Spotify -> Navidrome playlist transfer tool in Go.
|
||||
|
||||
- Authenticates with Spotify using Authorization Code + PKCE (no client secret required).
|
||||
- Fetches one or more Spotify playlists by URL/URI/ID.
|
||||
- Optionally transfers Spotify liked songs as a dedicated playlist.
|
||||
- Searches for matching tracks in Navidrome using Subsonic `search3`.
|
||||
- Creates matching playlists in Navidrome and adds matched tracks.
|
||||
- Writes a JSON transfer report with unmatched tracks and errors.
|
||||
- Optional recovery mode: for unmatched tracks, search Qobuz and download whole albums using `qobuz-dl`.
|
||||
- Optional re-add mode: after Navidrome rescan, re-match downloaded tracks and add them to existing playlists.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Go 1.22+
|
||||
- Spotify app client ID with redirect URI configured (default: `http://127.0.0.1:8888/callback`)
|
||||
- If using `--liked`, Spotify scopes must include `user-library-read`
|
||||
- Navidrome URL, username, and password
|
||||
|
||||
## Build
|
||||
@@ -36,10 +40,32 @@ go build ./cmd/navimigrate
|
||||
### Useful flags
|
||||
|
||||
- `--playlist-url "..."` (repeatable): Spotify playlist URL/URI/ID
|
||||
- `--liked`: include Spotify liked songs in transfer
|
||||
- `--liked-playlist-name "Spotify Liked Songs"`: target playlist name for liked songs
|
||||
- `--dry-run`: resolve matches only, do not create playlists or add tracks
|
||||
- `--match-threshold 45`: minimum score needed to accept a match
|
||||
- `--remember-spotify=true|false`: save and reuse Spotify refresh token (default true)
|
||||
- `--session-file ~/.config/navimigrate/session.json`: session storage path
|
||||
- `--report transfer-report.json`: report output path
|
||||
- `--concurrency 4`: concurrent track match workers
|
||||
- `--spotify-manual-code=true|false`: manual callback URL/code entry or local callback server
|
||||
- `--qobuz-download-missing`: search/download albums for unmatched tracks
|
||||
- `--qobuz-manifest missing-downloads.json`: manifest path used by recovery flows
|
||||
- `--qobuz-dl-path qobuz-dl`: binary path, or qobuz-dl project directory
|
||||
- `--qobuz-output /path/to/music`: output directory for qobuz-dl
|
||||
- `--add-downloaded-manifest missing-downloads.json`: re-add tracks from manifest after Navidrome rescan
|
||||
- `--add-downloaded-force`: retry entries already marked added
|
||||
|
||||
Liked-only run (no explicit playlist URLs):
|
||||
|
||||
```bash
|
||||
./navimigrate \
|
||||
--spotify-client-id "<spotify-client-id>" \
|
||||
--navidrome-url "https://music.lofitrek.com" \
|
||||
--navidrome-username "test_user" \
|
||||
--navidrome-password "test_user" \
|
||||
--liked
|
||||
```
|
||||
|
||||
### Navidrome self-test
|
||||
|
||||
@@ -64,18 +90,62 @@ Write-path self-test (creates playlist, adds one track, then deletes playlist):
|
||||
--navidrome-self-test-write
|
||||
```
|
||||
|
||||
### Missing-track recovery flow
|
||||
|
||||
Step 1: transfer and download unmatched albums from Qobuz:
|
||||
|
||||
```bash
|
||||
./navimigrate \
|
||||
--spotify-client-id "<spotify-client-id>" \
|
||||
--navidrome-url "https://music.lofitrek.com" \
|
||||
--navidrome-username "test_user" \
|
||||
--navidrome-password "test_user" \
|
||||
--playlist-url "https://open.spotify.com/playlist/..." \
|
||||
--qobuz-download-missing \
|
||||
--qobuz-username "<qobuz-email>" \
|
||||
--qobuz-password "<qobuz-password>" \
|
||||
--qobuz-dl-path "/home/joren/dev/qobuz-dl" \
|
||||
--qobuz-output "/path/to/downloads"
|
||||
```
|
||||
|
||||
Step 2: after Navidrome rescans your library, re-add from manifest:
|
||||
|
||||
```bash
|
||||
./navimigrate \
|
||||
--navidrome-url "https://music.lofitrek.com" \
|
||||
--navidrome-username "test_user" \
|
||||
--navidrome-password "test_user" \
|
||||
--add-downloaded-manifest "missing-downloads.json"
|
||||
```
|
||||
|
||||
### Environment variables
|
||||
|
||||
- `SPOTIFY_CLIENT_ID`
|
||||
- `SPOTIFY_REDIRECT_URI` (optional)
|
||||
- `SPOTIFY_SCOPES` (optional)
|
||||
- `NAVIMIGRATE_SPOTIFY_MANUAL_CODE` (optional, defaults to true)
|
||||
- `NAVIMIGRATE_REMEMBER_SPOTIFY` (optional, defaults to true)
|
||||
- `NAVIMIGRATE_SESSION_FILE` (optional)
|
||||
- `NAVIMIGRATE_INCLUDE_LIKED` (optional)
|
||||
- `NAVIMIGRATE_LIKED_NAME` (optional)
|
||||
- `NAVIDROME_URL`
|
||||
- `NAVIDROME_USERNAME`
|
||||
- `NAVIDROME_PASSWORD`
|
||||
- `NAVIMIGRATE_DRY_RUN` (optional)
|
||||
- `NAVIMIGRATE_CONCURRENCY` (optional)
|
||||
- `NAVIMIGRATE_MATCH_THRESHOLD` (optional)
|
||||
- `NAVIMIGRATE_REPORT` (optional)
|
||||
- `NAVIMIGRATE_QOBUZ_DOWNLOAD_MISSING` (optional)
|
||||
- `NAVIMIGRATE_QOBUZ_MANIFEST` (optional)
|
||||
- `NAVIMIGRATE_QOBUZ_DL_PATH` (optional)
|
||||
- `NAVIMIGRATE_QOBUZ_OUTPUT` (optional)
|
||||
- `NAVIMIGRATE_QOBUZ_QUALITY` (optional)
|
||||
- `QOBUZ_USERNAME` (optional, required when qobuz download mode enabled)
|
||||
- `QOBUZ_PASSWORD` (optional, required when qobuz download mode enabled)
|
||||
- `QOBUZ_APP_ID` (optional)
|
||||
- `QOBUZ_APP_SECRET` (optional)
|
||||
- `NAVIMIGRATE_ADD_DOWNLOADED_MANIFEST` (optional)
|
||||
- `NAVIMIGRATE_ADD_DOWNLOADED_FORCE` (optional)
|
||||
- `NAVIMIGRATE_NAVIDROME_SELF_TEST` (optional)
|
||||
- `NAVIMIGRATE_NAVIDROME_SELF_TEST_WRITE` (optional)
|
||||
- `NAVIMIGRATE_NAVIDROME_SELF_TEST_QUERY` (optional)
|
||||
|
||||
Reference in New Issue
Block a user