# MusicIndexer Pull your Spotify library and listening stats via the Spotify Web API, index a local music library (audio tags + iTunes XML), and match the two so you can see which tracks you own, what's missing, and your top artists/tracks/playlists — in a Streamlit GUI. ## Features - **Spotify backend** — OAuth (Authorization Code) login, then fetch the user profile, liked tracks, all playlists and their tracks, long-term top tracks and top artists, and playlist/profile cover art. Resilient paginated fetching (follows `next`, retries dropped connections, honours `429` rate limits) with progress bars. - **Local backend** — index a folder of audio files via `mutagen` tags. - **iTunes backend** — parse an iTunes Library XML export. - **Matching** — map local tracks to Spotify tracks (fuzzy matcher; ISRC/MBID matching planned). - **Stats & lyrics** — generate listening stats and fetch lyrics. - **GUI** — browse libraries as artist → album → track tables. ## Setup Requires Python 3.13+. ```bash python -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ### Credentials Create an app at https://developer.spotify.com/dashboard and add `http://127.0.0.1:8888` as a **Redirect URI**. Credentials are read from the environment — never commit them. ```bash cp .env.example .env # edit .env with your client id/secret source .env ``` `Env.py` reads `SPOTIFY_CLIENT_ID` / `SPOTIFY_CLIENT_SECRET` (plus optional `MUSIC_LIBRARY_PATH` and `WORK_DIR`) from the environment. ## Usage Edit `main.py` to uncomment the steps you want, then run: ```bash python main.py ``` The flow steps (see `Flow.py`) include: | Step | What it does | |------|--------------| | `fetch_spotify()` | OAuth login + download all Spotify data into `work_dir/spotify/` | | `fetch_local()` | index local audio files into `work_dir/local/` | | `parse_spotify_library()` / `parse_itunes_library()` / `parse_local_library()` | build normalized libraries | | `load_libraries()` / `save_libraries()` | (de)serialize libraries to `work_dir` | | `map_local_to_spotify()` | match local tracks against the Spotify library | | `fetch_and_save_lyrics()` | fetch lyrics for tracks | | `log_stats()` | generate stats | On first `fetch_spotify()` a browser opens for the Spotify login; a local server on `127.0.0.1:8888` catches the redirect and exchanges the code for a token. ### GUI ```bash ./gui.sh # runs: .venv/bin/streamlit run Gui.py ``` ## Layout ``` main.py entry point (CLI flow) Gui.py / gui.sh Streamlit GUI Flow.py orchestrates fetch / parse / map / stats Env.py config (reads credentials from the environment) src/ Library.py data model (Library / Artist / Album / Track) LibrarySerializer.py load/save libraries backends/ spotify/ Web API client, OAuth, parser local/ local-file indexer, parser, playlist generator itunes/ iTunes XML parser navidrome/ Navidrome backend mappers/ local↔Spotify matching (fuzzy / search) lyrics/ lyrics fetching work_dir/ fetched data and serialized libraries (gitignored) ``` ## Notes - Data is cached as JSON under `work_dir/` (gitignored); re-running reuses it. - The deprecated Spotify endpoints (audio-features, recommendations, etc.) are not used — only currently-supported endpoints.