Apple Music added as fallback metadata source if Spotify is not available. Spotify is always preferred if it is available with its richer data responses. Will easily swap from Spotify to Apple Music on the fly if you are rate limited by Spotify or worse, temp banned.
Apple Music and Spotify will now each have their own discovery pool for the discover page. Both will always be updated on every watchlist scan so long as Spotify is authorized, otherwise only Apple Music data is pulled.
**Known issues:**
Any artist image pulled while Apple Music is the primary source will only pull album art for that artist since they do not provide artist images :( This can, very rarely, lead to cases where the album image that is pulled could have another another artist displayed if it's some collab single, EP or something. Seen it happen once with an indie artist so it's possible.
Looking for a great api / website to parse easily specifically for artist names and a huge db to pull from.
- Added global currentMusicSourceName variable to track active source
- Updated discovery modal to show "Apple Music" when iTunes is active
- Replaced hardcoded "Spotify" in modal titles, headers, and descriptions
- Discovery modals now automatically reflect the correct music source (Spotify/Apple Music)
- Display "Apple Music" instead of "Spotify" in UI when iTunes is active source
- Enhanced connection test messages to indicate Spotify config/auth status
- Fixed similar artists requiring Spotify re-scan when Spotify becomes available
- Fixed hero slider buttons failing for iTunes-only artists
- Updated activity feed items to show correct source name dynamically
When Spotify is enabled after populating similar artists with only iTunes IDs, the freshness check now detects missing Spotify IDs and triggers a refetch. This fixes the Discover page not showing data when switching from iTunes-only mode.
- Add similar artists fetching to web UI scan loop
- Add database migration for UNIQUE constraint on similar_artists table - Add source-agnostic /api/discover/album endpoint for iTunes support
- Fix NOT NULL constraint on discovery_recent_albums blocking iTunes albums
- Add fallback to watchlist artists when no similar artists exist
- Add /api/discover/refresh and /api/discover/diagnose endpoints
- Add retry logic with exponential backoff for iTunes API calls
- Ensure cache_discovery_recent_albums runs even when pool population skips
- Fix platform detection to include is_listenbrainz_playlist check when generating fix buttons
- Update openDiscoveryFixModal to check both listenbrainzPlaylistStates and youtubePlaylistStates
- Update searchDiscoveryFix to detect discovery_source and use appropriate search API
- Add /api/itunes/search_tracks endpoint for manual track search when using iTunes source
- Update selectDiscoveryFixTrack state lookup to include ListenBrainz
Fix button now works correctly for all platforms (YouTube, ListenBrainz, Tidal, Beatport) with both Spotify
and iTunes discovery sources.
- Update _search_spotify_for_tidal_track to accept use_spotify and itunes_client parameters for dual-source
support
- Update _run_tidal_discovery_worker to check is_spotify_authenticated() and fall back to iTunes when Spotify
unavailable
- Update _run_beatport_discovery_worker with same iTunes fallback pattern
- Add discovery_source field to state and results for frontend awareness
- Activity messages now indicate which provider (SPOTIFY/ITUNES) completed discovery
All four discovery modals (YouTube, ListenBrainz, Tidal, Beatport) now support the dual-source architecture:
Spotify preferred, iTunes fallback.
Implement dual-source architecture where iTunes serves as always-available
primary source and Spotify as preferred source when authenticated.
- Make watchlist scans provider-aware (manual and auto paths)
- Update discovery pool population to process both sources
- Update recent albums caching for both sources
- Create source-specific curated playlists (Fresh Tape, Archives)
- Add on-the-fly iTunes ID resolution for similar artists
- Add iTunes ID check to similar artists freshness validation
- Fix sqlite3.Row compatibility in personalized playlists
- Fix iTunes ISO 8601 date format parsing
- Update API endpoints to serve source-appropriate data
This ensures the app remains fully functional if Spotify becomes
unavailable (rate limits, auth issues, bans) by seamlessly falling
back to iTunes data that has been building in parallel.
Implements lazy loading of artist images in search results, artist pages, and similar artist bubbles to improve performance and user experience. Updates the iTunes client to prefer explicit album versions and deduplicate albums accordingly. Adds a new API endpoint to fetch artist images, and updates frontend logic to asynchronously fetch and display images where missing.
Adds iTunes fallback to SpotifyClient for search and metadata when Spotify is not authenticated. Updates album type logic to distinguish EPs, singles, and albums more accurately. Refactors watchlist database methods to support both Spotify and iTunes artist IDs. Improves deduplication and normalization of album names from iTunes. Updates web server and frontend to use new album type logic and support both ID types. Adds artist bubble snapshot example data.
Refactored artist scanning logic to use the active metadata provider (Spotify or iTunes) for fetching artist data, discography, and album tracks. Introduced helper methods to select the correct client and artist ID based on the provider, and updated image and similar artist handling accordingly. This enables watchlist scanning to work with iTunes when Spotify is not authenticated, improving flexibility and provider support.
Updated get_album, get_album_tracks, and get_artist methods to return data structures compatible with Spotify's API format. This includes normalizing image arrays, artist and album fields, and adding synthetic URIs and external URLs for better interoperability.
Introduces iTunes artist ID support to WatchlistArtist and database schema, enabling proactive backfilling of missing provider IDs (Spotify/iTunes) for watchlist artists. Updates WatchlistScanner to use MetadataService for provider-agnostic scanning and ID matching, and modifies web_server to support scans with either provider. Includes new database migration and update methods for iTunes and Spotify artist IDs.
Introduces core/itunes_client.py implementing an iTunes Search API client for music metadata, providing search and lookup for tracks, albums, and artists with rate limiting. Adds METADATA-FALLBACK-IMPLEMENTATION.md, a comprehensive guide comparing fallback strategies for music metadata, including anonymous Spotify access and iTunes, and outlines integration approaches for seamless user experience without requiring Spotify credentials.
Updates the method for obtaining the next cursor during track pagination to use the approach from PR #113, retrieving it from 'links.meta.nextCursor' instead of 'meta.nextCursor'. This ensures correct pagination behavior.
Eliminated unnecessary filtering of playlists by owner or collaboration status, as the Spotify API already returns all accessible playlists. This simplifies the code and ensures all relevant playlists are processed.
Rewrites playlist and track fetching to use Tidal's JSON:API endpoints with cursor-based pagination and batch track hydration. Adds robust rate limiting with retry logic, and introduces ISO-8601 duration parsing. This improves reliability, performance, and compatibility with Tidal's latest API structure.
Changed stuck flag detection for wishlist and watchlist auto-processing from 2 hours to 15 minutes for faster recovery. Updated log messages and related logic to reflect the new timeout and display stuck duration in minutes. Also updated wishlist stats to use the improved stuck detection function.
Added backend support for reporting current auto-processing state and cycle in the wishlist stats API. Updated frontend to detect and handle auto-processing start, close modals, and notify users, as well as improved countdown timer updates and conflict handling when starting manual processing.
Refactored wishlist and watchlist auto-processing scheduling to use atomic timer updates and retry logic, preventing stuck timers and improving reliability. Removed excessive debug logging and improved error handling throughout related functions. Added checks to prevent concurrent wishlist processing and ensured timer state is managed consistently.
Added a call to self.soulseek._setup_client() in DownloadOrchestrator to ensure the Soulseek client configuration is reloaded when the orchestrator is initialized. This helps keep the client settings in sync with the latest configuration.
Added logic to remove duplicate tracks based on their Spotify track ID during both the sanitization and category filtering steps in get_wishlist_tracks(). This ensures the frontend receives a deduplicated list and improves data consistency. A warning is printed if duplicates are found and removed during sanitization.
Enhanced wishlist and watchlist processing to deduplicate tracks during both sanitization and filtering, preventing duplicate downloads and processing. Added explicit resets of next run timer variables to ensure accurate scheduling after each cycle. Updated countdown timer display in the UI to show '0s' when timer reaches zero instead of hiding it.
Introduces new filters for live versions, remixes, acoustic versions, and compilation albums to the watchlist artist configuration. Updates the database schema, backend API, and web UI to support these options, allowing users to customize which content types are included for each artist in their watchlist.
Standardizes the use of extract_filename() for context keys to ensure consistent lookup and storage across download and post-processing flows. Increases fuzzy match thresholds in file search to reduce false positives. Adds per-file threading locks to prevent concurrent metadata writes, improving thread safety during metadata enhancement.
Updated the normalization logic to only remove metadata markers that do not indicate different recordings (e.g., 'radio edit', 'remaster'), while preserving markers like 'live', 'remix', 'acoustic', and 'instrumental' that represent distinct versions. This improves matching accuracy by ensuring only equivalent recordings are compared, delegating version differentiation to the matching engine.
Expanded and refined the noise and version marker removal in _clean_track_title_for_comparison to better normalize track titles. This improves matching by handling more cases such as edits, remasters, live versions, soundtracks, and various collaboration markers.
Enhances artist name matching by including diacritic-normalized variations, allowing names like 'Subcarpaţi' to match 'Subcarpati' in SQL LIKE queries. This addresses issue #101 and improves search robustness.
Added normalized string comparison for album titles to better handle diacritics, addressing issue #101. Also logs when normalization improves matching accuracy.
Introduced _sanitize_context_values to clean all string values in the context dictionary before applying path templates. This prevents unsafe characters (like '/') in metadata (e.g., artist names) from creating unintended path components during template substitution.
Enhanced normalization by using _matching_engine when available for both search input and database values. Improved album search by considering artist name variations and deduplicating results. Added a fallback mechanism to search all albums by artist to address SQL accent sensitivity issues, increasing robustness in album matching.
Adds a check for the presence of 'load_config' in config_manager. If not found, uses a fallback method to support older settings.py files, improving compatibility with legacy Docker volumes.
Bump version to 1.3 and update the version info modal to highlight the new YouTube download engine, Docker and system reliability fixes, and general improvements. Update the web UI to display v1.3 and apply minor formatting and accessibility improvements throughout index.html.
Updated _find_downloaded_file to resolve download paths for Docker environments, ensuring compatibility with host-mounted directories. Also updated README to clarify YouTube integration and sources.
Enhanced the Tidal authentication page to provide clearer, step-by-step instructions for users accessing the app remotely or via Docker. The new flow helps users update the callback URL as needed, improving the authentication experience in non-localhost environments.
Adds critical fixes to reschedule timers after stuck flag recovery for wishlist and watchlist processes, preventing deadlocks and ensuring continuity. Refines album classification by prioritizing Spotify's album_type over track count heuristics, and ensures album_type is included in API responses. Updates frontend logic to pass and use fresh album/artist context for discover_album modals, improving metadata accuracy and display.