Commit graph

352 commits

Author SHA1 Message Date
Broque Thomas
666e65ed3b Add repair scanning, tracklist fallbacks, UI polling
Introduce deferred album repair scanning and robust tracklist resolution plus UI/presentation tweaks.

- core/repair_worker.py: Add lazy MusicBrainz and AudioDB client accessors, per-batch folder queues, and register_folder/process_batch to defer folder scans until a batch completes. Implement cascading tracklist resolution (_resolve_album_tracklist) using Spotify/iTunes IDs, Spotify track→album lookup, album search, MusicBrainz release lookup, and AudioDB→MusicBrainz fallback. Add helpers to read Spotify track IDs, MusicBrainz album IDs, album/artist tags from files, MB/AudioDB fetchers, placeholder-ID filtering, and rename associated .lrc files when renaming audio files. Cache/locking and background-threaded scanning included. Improves resilience to missing/placeholder IDs and avoids circular imports.

- web_server.py: Register album folders for repair in post-processing and trigger repair_worker.process_batch when batches complete (multiple completion paths) so scans run after downloads finish.

- webui/static/script.js: Reduce unnecessary background work by skipping many fetches when the tab is hidden, and refresh dashboard-specific data on visibility change to ensure UI updates after OAuth or tab switch.

- webui/static/style.css: Replace glassmorphic backdrop-filters with opaque dark gradients for sidebar and main content to improve GPU rendering and visual consistency.

Overall: Adds reliable post-download album repair scanning using multiple metadata sources and reduces unnecessary client polling and heavy CSS effects for better performance and robustness.
2026-02-23 10:18:31 -08:00
Broque Thomas
129f69fce9 Add Blasphemy Mode to delete FLAC after MP3
Introduce an optional "Blasphemy Mode" that deletes the original FLAC after a verified MP3 copy is created.

- config: add lossy_copy.delete_original (default: false).
- webui/index.html & static script: add checkbox and warning in settings UI and persist the setting.
- web_server.py: make _create_lossy_copy return the MP3 path when it deletes the FLAC (otherwise None); validate the MP3 using mutagen before removing the FLAC; rename associated .lrc files if present; update post-processing to use the final processed path in logs and wishlist checks and to consider .mp3 variants when FLAC may have been removed.

Behavior is off by default and includes safety checks and logging to avoid accidental deletion of originals.
2026-02-22 23:23:52 -08:00
Broque Thomas
24bfc2462d Add Spotify & iTunes workers; update repair worker
Add full-featured SpotifyWorker and iTunesWorker background workers to enrich artists, albums, and tracks with external metadata using batch cascading searches, fuzzy name matching, ID validation, and DB backfills. Update RepairWorker to re-read the transfer path from the database each scan, resolve host paths when running in Docker, and trigger immediate rescans when the transfer path changes; remove the static config_manager dependency. Also include supporting changes to the database layer and web UI/server (stats, controls, and styles) to integrate the new workers and reflect updated worker status.
2026-02-22 22:29:10 -08:00
Broque Thomas
ce474749d5 Add library repair worker and UI
Introduce a RepairWorker to scan the transfer folder and automatically detect/repair broken album track numbers (e.g. the "all tracks = 01" bug). The worker uses mutagen to read/write tags, fuzzy-matches titles against an album tracklist (Spotify/iTunes via a SpotifyClient), updates filenames and the tracks DB file_path when renamed, and caches album tracklists. It also adds DB schema support (repair_status, repair_last_checked, and an index).

Integrates the worker into the web server: initializes and starts the worker, and exposes /api/repair/status, /api/repair/pause and /api/repair/resume endpoints. Adds UI elements (button, tooltip), client-side JS to poll and control the worker, CSS for visuals/animations, and a new image asset (whisoul.png).
2026-02-21 15:00:23 -08:00
Broque Thomas
e7dfb423dc Add Active Downloads dashboard and UI fixes
Introduce an "Active Downloads" section to the dashboard and wire up client-side plumbing to populate and update it. Adds escapeForInlineJs to safely embed values into inline JS attributes and replaces several inline onclick usages (search/genre/listenbrainz/artist buttons) to prevent quoting issues. Implements updateDashboardDownloads, createDashboardDiscoverBubble, and integrates dashboard updates into artist/search/discover flows (including register/discover download persistence and monitor hooks). Adds dashboard-specific CSS for discover/artist bubbles and minor style fixes (artist image sizing, keyframe formatting) plus a mobile CSS tweak for artist images.
2026-02-21 08:51:51 -08:00
Broque Thomas
49a6c58ea8 Add Hydrabase P2P mirror worker
Introduce a Hydrabase P2P mirror worker and integrate it into the web UI and server flows. Adds core/hydrabase_worker.py: a background thread with a capped queue (1000), enqueue API, rate limiting, basic stats (sent/dropped/errors), and logic to send JSON requests over a provided WebSocket (responses received and discarded). Integrates the worker into web_server.py (import, startup init, status/pause/resume endpoints, and enqueues queries from multiple search endpoints when dev mode is enabled). Adds UI elements, JavaScript polling/toggle logic, and CSS styling for a Hydrabase status button in webui (index.html, static/script.js, static/style.css) to display and control worker state.
2026-02-21 02:15:43 -08:00
Broque Thomas
35fd7bb294 Add Hydrabase dev UI and WebSocket support
Introduce a developer-only Hydrabase testing UI and backend WebSocket integration. Adds a simple dev-mode toggle (password 'hydratest') and new API endpoints (/api/dev-mode, /api/hydrabase/connect, /api/hydrabase/disconnect, /api/hydrabase/status, /api/hydrabase/send) that use websocket-client to connect/send raw JSON to a Hydrabase instance. Frontend changes include a Hydrabase nav/page, payload editors, response panel, dev-mode UI in Settings, associated JS handlers, CSS styling, and an icon asset. Also add websocket-client to requirements.
2026-02-21 00:32:04 -08:00
Broque Thomas
cfa4a0c59f Add $artistletter and multi-disc support
Introduce $artistletter and $disc template variables across config, UI, and backend to support artist-first-letter tokens and multi-disc albums. Update web_server.py to include disc_number in template context, prefer user-controlled $disc in templates, and create configurable disc subfolders using a new file_organization.disc_label setting. Update example and active config, web UI to expose the new variable and disc label selector, and script.js to validate, load, and save the new settings and substitutions.
2026-02-20 22:53:15 -08:00
Broque Thomas
d2adf17ca5 Add lossy MP3 copy of downloaded FLACs
Introduce a configurable "lossy_copy" feature that creates an MP3 copy alongside downloaded FLAC files. Adds default config (example and runtime) and UI controls for enabling the feature and selecting an MP3 bitrate. Implements _create_lossy_copy in web_server.py which checks the FLAC extension, respects the configured bitrate (default 320 kbps), locates ffmpeg (including a local tools/ffmpeg fallback), performs conversion, and attempts to update the QUALITY tag via mutagen. The feature is invoked after post-processing/moving downloads. Logs and graceful failures (missing ffmpeg, timeouts, tag errors) are included.
2026-02-20 22:16:00 -08:00
Broque Thomas
d858a7c85f Add $quality template var (filename only)
Introduce a new $quality template variable that is only substituted into filenames to avoid splitting album folders when tracks of mixed qualities are present. Updates include:

- web_server.py: populate template contexts with 'quality' (from context['_audio_quality']), strip $quality from folder components, substitute it only in the filename, and clean up empty brackets/parentheses/dashes when the variable is empty.
- config/config.example.json and config/config.json: document the new variable in the file_organization template variables string.
- webui/index.html and webui/static/script.js: update UI help text and client-side template validation to include $quality.

This prevents folder fragmentation for albums with mixed-quality files while still allowing quality information in filenames.
2026-02-20 20:18:01 -08:00
Broque Thomas
3644422ab8 Add FLAC bit depth filter to post-download quality gate 2026-02-20 15:05:45 -08:00
Broque Thomas
2c56b23c27 Progressive track list rendering for large playlists 2026-02-20 09:15:15 -08:00
Broque Thomas
ed184f9bb8 rearrange the download modal 2026-02-19 23:15:33 -08:00
Broque Thomas
1a29073d4e Fix quality profile priorities being reset to default order on save 2026-02-19 17:24:06 -08:00
Broque Thomas
d73f91ea1c Combine MP3 format and bitrate into single quality badge 2026-02-19 12:55:03 -08:00
Broque Thomas
c018c5fd98 Differentiate "not found" from download errors with distinct status and UI 2026-02-19 12:05:20 -08:00
Broque Thomas
6c6651b879 Add format summary tags to library release cards, wishlist modal, and artist hero 2026-02-19 10:20:30 -08:00
Broque Thomas
3663a75769 Show track ownership indicators and file metadata in wishlist modal for all releases 2026-02-19 09:39:56 -08:00
Broque Thomas
1d50ece62c debounced saving on settings page for all drop-down, tick boxes, input boxes and sliders. 2026-02-19 08:37:27 -08:00
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
acb26777ca fix images 2026-02-18 22:06:08 -08:00
Broque Thomas
ae5d77810d Add Deezer & AudioDB source badges to library artist cards and detail page 2026-02-18 21:30:15 -08:00
Broque Thomas
8f9851c50f add image fallback to library artists 2026-02-18 21:13:03 -08:00
Broque Thomas
a7cc558fb3 update ui when metadata worker finishes. 2026-02-18 18:57:00 -08:00
Broque Thomas
e2351eaa5c backup image for library artists 2026-02-18 17:27:01 -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
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
9457235080 clean up artist bubbles from past downloads 2026-02-18 12:03:59 -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
0c40a922e6 Add batch remove to watchlist modal 2026-02-17 11:28:44 -08:00
Broque Thomas
139b8530f4 Add watchlist filter to library page 2026-02-17 11:21:41 -08:00
Broque Thomas
93d65b1ad3 add watchlist indicator to artists listed on the library page that are in the user watchlist 2026-02-17 11:08:33 -08:00
Broque Thomas
801274deb3 Add error reason tooltips to failed downloads in missing tracks modal
When a download fails in the Download Missing Tracks modal, hovering over the "Failed" status now shows a   tooltip explaining why. The backend already tracked error_message on tasks internally but never sent it to the frontend. This surfaces those reasons and enriches them with detailed context — search diagnostics break down what happened per query (no results, filtered out, search error), retry failures include source counts and likely cause, and timeout/stuck messages name the state and duration. The tooltip uses a fixed-position popup to avoid clipping by the modal's scroll container, with scroll and visibility-aware dismissal.
2026-02-17 10:28:12 -08:00
Broque Thomas
1ed66c120e Fix Soulseek connection status showing false positive on test
The Soulseek "Test Connection" button could report success while the dashboard status remained              "Disconnected" because the status endpoint only checked if slskd was configured (is_configured()), not actually
reachable (check_connection()). Switched to a real connection check with TTL caching (matching the existing
Spotify/media server pattern), update the status cache after successful tests, and refresh the UI immediately on success.
2026-02-16 14:42:17 -08:00
Broque Thomas
96f991a833 multi cd post processing is now possible. No longer treated as single cd. 2026-02-16 11:49:26 -08:00
Broque Thomas
08e34c31b5 allow user to open download modal on completed items 2026-02-16 10:17:21 -08:00
Broque Thomas
1fd8e59a17 css changes and lazyload changes to increase site speed.
Also fixed a docker path bug, well a potential bug.
2026-02-16 09:08:32 -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
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
e66ed32463 fix the 'fix' modal on discovery modal if track is incorrect 2026-02-14 21:32:10 -08:00
Broque Thomas
a91c10bee5 css changes for enhanced search results for desktop and mobile 2026-02-13 10:24:20 -08:00
Broque Thomas
40be502a98 Enhanced search: separate albums from singles/EPs and improve UX
Split the enhanced search dropdown into distinct Albums and Singles & EPs sections using the album_type field. Changed the zero-tracks error from a cryptic red error toast to a clear warning message. Fixed the loading text to show the actual music source name instead of hardcoded "Spotify".
2026-02-13 08:53:19 -08:00
Broque Thomas
20c7aa33a3 Add per-track ownership indicators to Library wishlist modal
When clicking a partially-complete album on the Library page, the wishlist modal now shows which tracks are owned (dimmed with checkmark) and which are missing (orange border). Ownership data lazy-loads after the modal opens to avoid blocking the UI, using a batch DB query for speed. Also fixes albums like DAMN. showing "14/15" when all available tracks are owned — the frontend now trusts the backend's "completed" status instead of doing raw track count math against potentially inaccurate Spotify metadata.
2026-02-12 13:09:42 -08:00
Broque Thomas
f7c929abec Library page: lazy-load artist discography with SSE streaming
Replace blocking DB matching in the Library artist detail view with a two-phase render pattern. The page now renders album cards instantly from Spotify/Itunes data , then streams per-release ownership results via SSE that update cards one-by-one.
2026-02-12 10:54:42 -08:00
Broque Thomas
cac3cfab92 redesign import button 2026-02-07 09:59:40 -08:00
Broque Thomas
d674b999e5 feat: Import Music from local staging folder
Added an Import feature that lets users process local audio files through the existing post-processing pipeline (metadata enrichment, cover art, lyrics, library organization). Files are placed in a configurable Staging folder and imported via two modes: Album mode (search/match files to a Spotify tracklist) and Singles mode (select individual files for processing). Includes auto-suggested albums based on staging folder contents and real-time per-track progress tracking.
2026-02-06 23:29:05 -08:00
Broque Thomas
48b188446b feat: discovery match cache, mobile sync layout fixes
- Add global discovery_match_cache table to cache successful track matches
    (title+artist+provider -> matched result) across all discovery sources
  - Cache check before API search in YouTube, ListenBrainz, Tidal, and Beatport
    discovery workers; cache write after high-confidence matches
  - Re-discovering playlists or overlapping tracks across sources skips API lookups
  - Fix Spotify tab sidebar forcing 2-column grid on mobile via inline JS styles
  - Add mobile responsive styles for Spotify playlist cards (stack layout vertically)
2026-02-06 09:24:50 -08:00
Broque Thomas
4f56cdf365 mobile responsive layout 2026-02-06 08:18:40 -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
2d97d5c7d2 refactor musicbrainz badge 2026-02-05 07:34:47 -08:00