Commit graph

235 commits

Author SHA1 Message Date
Broque Thomas
8cf0950d3b Quality filter: use bitrate density instead of file size, cache Library/Discover pages, extend Beatport cache to 24h 2026-02-19 07:40:49 -08:00
Broque Thomas
e7e939bdd5 Retry errored items and prevent incomplete Deezer matches 2026-02-18 20:04:58 -08:00
Broque Thomas
a7cc558fb3 update ui when metadata worker finishes. 2026-02-18 18:57:00 -08:00
Broque Thomas
7b6e94772e fixed an issue wher ecollaborating artists would have the album listed as their own on library and artist page. 2026-02-18 17:11:53 -08:00
Broque Thomas
2ab52a340b Add Deezer enrichment for artists, albums, and track
Add Deezer as a third metadata enrichment source. Enriches tracks with BPM and explicit flags, albums with
   record labels, explicit flags, and type classification (album/single/EP), and backfills artwork and genres across
  all entities. Includes background worker with priority queue, rate-limited API client, database migration, server
  endpoints, and UI button with purple-themed status tooltip.
2026-02-18 16:41:24 -08:00
Broque Thomas
eee05115e4 Add AudioDB enrichment for artists, albums, and tracks
Integrated TheAudioDB as a metadata enrichment source with a background worker that scans artists, albums,   and tracks in priority order. Stores style, mood, and AudioDB IDs with automatic backfill of artwork and genres.
  Includes artist ID cross-verification from album/track results to correct mismatches caused by same-name artists.
2026-02-18 14:31:30 -08:00
Broque Thomas
1a4395cc95 Add AudioDB enrichment for artists, albums, and tracks
Integrated TheAudioDB as a metadata enrichment source. A background worker scans the library in priority order (artists → albums → tracks), matching entities via fuzzy name comparison and storing style, mood, and AudioDB IDs. Includes rate limiting, 30-day retry for not-found items, and a UI tooltip showing phase-based scan progress.
2026-02-18 14:08:01 -08:00
Broque Thomas
d54f433277 Update spotify_client.py 2026-02-18 12:23:23 -08:00
Broque Thomas
5e61a15f7f Add Spotify disconnect button and cache auth checks
Add a UI button to disconnect Spotify and fall back to iTunes/Apple Music without restarting.    Cache is_spotify_authenticated() with a 60s TTL to reduce redundant API calls (~46 call sites were each
  triggering a live sp.current_user() call). Fix status endpoint calling the auth check twice per poll,
  and ensure both OAuth callback handlers (port 8008 Flask route and port 8888 dedicated server)
  invalidate the status cache so the UI updates immediately after authentication.
2026-02-18 11:40:07 -08:00
Broque Thomas
308f0f9711 Add retry logic and adaptive rate limiting to watchlist scan
Spotify's @rate_limited decorator now retries on 429/5xx with exponential backoff (up to 5 retries) instead of sleeping once and raising. Watchlist scan delays scale dynamically based on lookback setting and artist count to prevent sustained API pressure. A circuit breaker pauses the scan after consecutive rate-limit failures.
2026-02-17 16:45:09 -08:00
Broque Thomas
c6a7c99ad7 additional logging for navidrome troubleshooting connection status 2026-02-17 08:32:51 -08:00
Broque Thomas
40324f4b22 album name in folder path is no weighted more effectively when trying to choose an album with a specific album source. 2026-02-16 17:59:18 -08:00
Broque Thomas
d1259c4b62 Add multi-disc album support with automatic disc subfolder organization
Multi-disc albums (e.g., deluxe editions, double albums) now automatically organize
  tracks into Disc 1/, Disc 2/ subfolders within the album folder. Detection uses the
  disc_number field from Spotify's API — when an album has total_discs > 1, subfolders
  are created. Single-disc albums are completely unaffected.

  - Plumb disc_number through all download paths (enhanced, non-enhanced, download
    missing modal, wishlist)
  - Compute total_discs from album tracklist and store on album context
  - Modify path builder to insert Disc N/ subfolder for multi-disc albums
  - Preserve disc_number when tracks fail and get re-added to wishlist
  - Preserve disc_number when adding tracks to wishlist from library page
  - Add visual disc separators in Soulseek search result track lists
2026-02-16 13:10:03 -08:00
Broque Thomas
1071337659 fix normalization issue on comparison with acoustID 2026-02-16 10:21:29 -08:00
Broque Thomas
f9b0316d0f fix str object has no attribute get error. 2026-02-16 10:13:56 -08:00
Broque Thomas
ff0cfd53c5 fix 404 error due to spotify api changes 2026-02-16 09:25:28 -08:00
Broque Thomas
ff3f547612 update Spotify API search limits for February 2026 changes 2026-02-15 21:01:14 -08:00
Broque Thomas
5f12634f61 fix seasonal discovery showing "Various Artists" and using wrong download mode 2026-02-15 19:29:20 -08:00
Broque Thomas
79b0591b34 fix issue where itunes/spotify seasonal discovery pools were not isolated. 2026-02-15 15:56:43 -08:00
Broque Thomas
0d66f884e6 fix - jellyfin servers can not select a user when determing which library to scan. 2026-02-15 14:09:44 -08:00
Broque Thomas
51515bc8a1 update spotify api in response to their bullshit 2026-02-15 11:46:19 -08:00
Broque Thomas
883b43b015 fix issue where wishlist would not delete entire album.
Also fixed issue where a warning was displayed.
2026-02-15 10:48:58 -08:00
Broque Thomas
a5c4783da6 clean up orphaned downloads before they gunk up the download folder. 2026-02-15 10:03:28 -08:00
Broque Thomas
d907558abf Fixed issue where itunes only watchlist artists would update the 'last scanned' property after watchlist scan 2026-02-13 16:10:19 -08:00
Broque Thomas
f2fb498693 Fix Navidrome incremental update to use getAlbumList2 API for recent albums
Summary: Navidrome incremental updates always found 0 new tracks because _get_recent_albums_navidrome() fetched all artists, sampled only the first 200, collected their albums, and sorted by created date — missing artists beyond the first 200 entirely. Replaced this with a single getAlbumList2?type=newest Subsonic API call that directly returns albums sorted by library addition date, matching how Jellyfin and Plex already use their native "recently added" endpoints.
2026-02-12 13:58:20 -08:00
Broque Thomas
965f93ab31 Fix: Validate iTunes explicit albums have tracks before deduplication
Fixed issue where broken iTunes explicit album IDs were preferred over working clean versions during deduplication. Some iTunes explicit albums (e.g., "Mr. Morale & The Big Steppers" ID 1623854804) report track counts in metadata but return 0 tracks when queried.
Added validation in itunes_client.py get_artist_albums() to verify explicit albums actually have tracks before keeping them. If an explicit version has 0 tracks, it's skipped and the clean version is used instead.
This fixes:
- "No tracks found" error when clicking affected albums
- Incorrect track count mismatches (19/18) caused by broken API data
The validation only runs for explicit albums during deduplication, minimal performance impact.
2026-02-09 21:01:40 -08:00
Broque Thomas
178956afd6 proactive fix for upcoming spotify api changes 2026-02-07 14:54:34 -08:00
Broque Thomas
d08a2e91a2 feat: embed MusicBrainz, Spotify/iTunes IDs, ISRC, and merged genres into audio file tags
Enrich downloaded audio files with external identifiers and improved genre metadata in a single post-processing write. During metadata enhancement, the app now looks up the MusicBrainz recording and artist MBIDs, retrieves the ISRC and MusicBrainz genres from a follow-up detail lookup, merges them with Spotify's artist-level genres (deduplicated, capped at 5), and embeds everything alongside the Spotify/iTunes track, artist, and album IDs. All MusicBrainz API calls are serialized through the existing global rate limiter, making concurrent download workers safe without needing to pause the background worker. Includes a database migration adding Spotify/iTunes ID columns to the library tables.
2026-02-05 21:26:19 -08:00
Broque Thomas
d9efcbdf99 feat: AcoustID audio verification, MusicBrainz enrichment UI, v1.5
Add optional post-download audio fingerprint verification using AcoustID.
  Downloads are verified against expected track/artist using fuzzy string
  matching on AcoustID results. Mismatched files are quarantined and
  automatically added to the wishlist for retry.

  - AcoustID verification with title/artist fuzzy matching (not MBID comparison)
  - Quarantine system with JSON metadata sidecars for failed verifications
  - fpcalc binary auto-download for Windows, macOS (universal), and Linux
  - MusicBrainz enrichment worker with live status UI and track badges
  - Settings page AcoustID section with real-fingerprint connection test
  - Source reuse for album downloads to keep tracks from same Soulseek user
  - Enhanced search queries for better track matching
  - Bug fixes: wishlist tracking, album splitting, regex & handling, log rotation
2026-02-05 16:33:07 -08:00
Broque Thomas
8cdf548561 fix - cleared status too early before it could be read for live status updated. Musicbrainz 2026-02-03 21:26:15 -08:00
Broque Thomas
2a4cab3f96 fix polling for musicbrainz worker 2026-02-03 19:47:31 -08:00
Broque Thomas
cee5590718 feat(ui): add MusicBrainz enrichment status UI with real-time monitoring
MusicBrainz library enrichment with real-time
status monitoring and manual control.
Features:
- Status icon button in dashboard header with glassmorphic design
- Animated loading spinner during active enrichment
- Hover tooltip showing:
  - Worker status (Running/Paused/Idle)
  - Currently processing item
  - Artist matching progress with percentage
- Click-to-toggle pause/resume functionality
- Auto-polling every 2 seconds for live updates
Backend Changes:
- Added GET /api/musicbrainz/status endpoint
- Added POST /api/musicbrainz/pause endpoint
- Added POST /api/musicbrainz/resume endpoint
- Worker tracks current_item for UI display
- get_stats() returns enhanced status data
Frontend Changes:
- New MusicBrainz button component with tooltip
- Premium CSS styling with animations
- JavaScript polling and state management
- Positioned tooltip below button with centered arrow
Files Modified:
- web_server.py: API endpoints and worker initialization
- core/musicbrainz_worker.py: current_item tracking
- webui/index.html: Button and tooltip structure
- webui/static/style.css: Complete styling (240 lines)
- webui/static/script.js: Polling and interaction logic (115 lines)
2026-02-03 15:20:04 -08:00
Broque Thomas
35e65b2106 When downloading albums/EPs from Soulseek, after the first track downloads successfully, browse the source's folder and reuse it for subsequent tracks. This keeps entire albums coming from one source instead of scattering across many users.
- Single-worker mode for album batches (sequential downloads enable clean source reuse)
  - Browse API integration to list files in a source's directory
  - Failed source tracking per-batch to avoid retrying broken sources
  - Graduated quality scoring for upload speed, queue length, and free slots
  - Track number fallback fix (uses Spotify track number instead of hardcoded 1)
  - Duplicate completion guard to prevent double-decrement of active worker count
  - Dedicated logging for source reuse and post-processing diagnostics
2026-02-01 00:42:39 -08:00
Broque Thomas
da44278f12 add fourth search query for enhanced matching with both a cleaned and artist removed search. 2026-01-31 20:53:56 -08:00
Broque Thomas
7d8bb2b88a Revert "Add album-level Soulseek search and fix unbounded log growth"
This reverts commit 258fd7a8ae.
2026-01-31 18:42:37 -08:00
Broque Thomas
bbac51412d Revert "album level search for wishlist albums/eps"
This reverts commit 28ca3f5ce5.
2026-01-31 18:42:17 -08:00
Broque Thomas
28ca3f5ce5 album level search for wishlist albums/eps 2026-01-31 11:21:35 -08:00
Broque Thomas
258fd7a8ae Add album-level Soulseek search and fix unbounded log growth
When downloading an album/EP, perform a single album-level search on Soulseek to find a user with the complete album folder before falling back to per-track  search. This improves album completion rates and ensures consistent quality across tracks.
2026-01-30 12:46:52 -08:00
Broque Thomas
622e95e4df fix tidal auth issue on restart 2026-01-29 11:33:29 -08:00
Broque Thomas
56222b799a Fix ListenBrainz playlists not showing when tables don't exist yet
ListenBrainzManager opens its own raw sqlite3 connection, bypassing MusicDatabase initialization. If it runs   before MusicDatabase creates the tables, all queries fail with "no such table: listenbrainz_playlists". Added _ensure_tables() to ListenBrainzManager init that runs CREATE TABLE IF NOT EXISTS for both ListenBrainz tables — a  no-op when they already exist, but creates them if MusicDatabase hasn't run yet.
2026-01-29 10:16:19 -08:00
Broque Thomas
a74596cdd6 Fix Quality Scanner for Navidrome & expand ListenBrainz playlist limit
- Expose suffix, bitRate, and path fields on NavidromeTrack from the Subsonic API response
  - Add fallback in insert_or_update_media_track() to populate file_path and bitrate for Navidrome tracks, fixing the Quality Scanner
   returning 0 results
  - Increase ListenBrainz playlist cache limit from 4 to 25 per type
  - Add sub-tab grouping in the Recommendations tab (Weekly Jams, Weekly Exploration, Top Discoveries, etc.)
2026-01-29 09:24:55 -08:00
Broque Thomas
6750c20dc4 display all listenbrainz playlsts in unique categories. 2026-01-29 08:55:19 -08:00
Broque Thomas
681d4b3cd2 Fixed an issue where the wishlist wouldn't open if null value is detected 2026-01-27 17:04:31 -08:00
Broque Thomas
8248fab16e Fix iTunes wishlist and remove Single suffix
iTunes tracks now include album field for proper wishlist support.
  Strip " - Single" and " - EP" suffixes from iTunes album names.
2026-01-26 17:00:51 -08:00
Broque Thomas
ceafcdc49f Revert "Fix iTunes wishlist and remove ' - Single' suffix"
This reverts commit d9685364c1.
2026-01-26 16:51:12 -08:00
Broque Thomas
d9685364c1 Fix iTunes wishlist and remove ' - Single' suffix
Two fixes for iTunes integration:

1. iTunes failed tracks now properly added to wishlist
   - Root cause: iTunes tracks had no 'album' field (unlike Spotify)
   - Fix: Added album information to each track in get_album_tracks()
   - Tracks now include: album id, name, images, release_date

2. Remove ' - Single' suffix from iTunes album names
   - Root cause: iTunes API includes ' - Single' in collectionName
   - Fix: Added _clean_album_name() helper method
   - Strips ' - Single' and ' - EP' suffixes from all album names
   - Applied to all 6 locations where collectionName is used

Both Spotify and iTunes sources now work identically for wishlist
auto-processing when tracks fail or are cancelled.
2026-01-26 16:44:42 -08:00
Broque Thomas
9af0be1300 fixed issue where legacy cold was called. 2026-01-26 13:37:42 -08:00
Broque Thomas
db2400b42a fix navidrome sync issue where duplicate playlists are created 2026-01-26 10:25:55 -08:00
Broque Thomas
b9f2344f0f lookup artist name on track/album pull to ensure clean data.
Great for multi artist scenarios
2026-01-25 15:08:08 -08:00
Broque Thomas
48b914a4be Update spotify_client.py 2026-01-25 13:51:29 -08:00