Commit graph

357 commits

Author SHA1 Message Date
Broque Thomas
491b89a1d2 Redesign library artist hero with Last.fm integration
- Add get_artist_top_tracks to Last.fm client (up to 100 tracks)
- Include lastfm_listeners, lastfm_playcount, lastfm_tags, lastfm_bio,
  and soul_id in artist detail API response
- New endpoint: /api/artist/<id>/lastfm-top-tracks for lazy loading
- Hero layout: image (160px) | center (name, badges, genres, bio,
  listener/play stats, progress bars) | right card (scrollable top
  100 tracks from Last.fm)
- Badges 36px with hover lift, bio in subtle card with Read More
  toggle, Last.fm tags merged with existing genres
- Numbers formatted: 1234567 → 1.2M
- Graceful degradation: sections hidden when Last.fm data unavailable
2026-03-21 23:04:34 -07:00
Broque Thomas
2d511d0a16 Add SoulID worker with API-based debut year disambiguation
SoulID worker generates deterministic soul IDs for all library entities:
  - Artists: hash(name + debut_year) — searches iTunes + Deezer APIs,
    verifies correct artist by matching discography against local DB
    albums via MusicMatchingEngine, pools years from both sources and
    picks the earliest. Falls back to hash(name) if no match found.
  - Albums: hash(artist + album)
  - Tracks: song ID hash(artist + track) + album ID hash(artist + album + track)

Dashboard button with trans2.png logo, rainbow spinner, hover tooltip.
Worker orb with rainbow effect. SoulSync badge on library artist cards.
DB migration adds soul_id columns with indexes to artists/albums/tracks.
Migration version flag auto-resets artist soul IDs when algorithm changes.
2026-03-21 10:21:06 -07:00
Broque Thomas
efe4561bcb Add per-profile service credentials foundation (DB + API)
DB migration adds 11 columns to profiles table for per-profile Spotify
credentials, Tidal tokens, and media server library selection. All
encrypted, all default NULL (fall back to global config).

API endpoints follow existing ListenBrainz per-profile pattern:
- GET/POST/DELETE /api/profiles/me/spotify
- GET/POST /api/profiles/me/server-library

Foundation only — no frontend UI or client initialization changes yet.
2026-03-20 10:30:56 -07:00
Broque Thomas
6b5e37aded Add preflight track-hash comparison and fix duplicate sync history entries
Preflight: hash track IDs before syncing and compare against last sync.
Skip only if exact same tracks were already synced and all matched.
Replaces the old count-based smart-skip which could miss track swaps.

Sync history: update existing entry for same playlist_id instead of
creating duplicates. Re-syncing the same playlist now refreshes the
existing row with new timestamps and stats.
2026-03-18 18:17:50 -07:00
Broque Thomas
5489af2647 Add defensive album data repair in wishlist add_to_wishlist
If album info is missing, not a dict, or named "Unknown Album",
it gets repaired using the track name as fallback instead of
storing junk display data.
2026-03-18 17:57:33 -07:00
Broque Thomas
2564e6bf4f Fix deep scan wiping track enrichment data and not updating file paths
INSERT OR REPLACE on existing tracks was deleting the entire row and
reinserting only 9 columns, nuking spotify_track_id, deezer_id, isrc,
bpm, musicbrainz IDs, and ~15 other enrichment columns every scan.

Now uses UPDATE for existing tracks (preserves all enrichment) and
INSERT only for new tracks. Also ensures file_path gets updated from
the media server on each scan, fixing stale paths for users whose
files were moved/reorganized.
2026-03-18 10:38:06 -07:00
Broque Thomas
27a0cf8b81 Add Sync History feature with live re-sync progress and source detection
- New sync_history DB table tracks last 100 syncs with full cached context
- Records history for all sync types: Spotify, Tidal, Deezer, YouTube,
  Beatport, ListenBrainz, Mirrored playlists, and Download Missing flows
- Sync History button on sync page with modal showing entries, source
  filter tabs, stats badges, and pagination
- Re-sync button: server syncs expand card inline with live progress bar,
  matched/failed counts, and cancel button; download syncs open download modal
- Re-syncs update the original entry (moves to top) instead of creating duplicates
- Delete button (x) on each entry with smooth remove animation
- Fix mirrored playlist source detection (youtube_mirrored_ matched youtube_)
- Fix broken server import thumbnails with URL validation
2026-03-17 20:39:41 -07:00
Broque Thomas
4c6e2fe1ec Revamp automation page: 2-col grid, duplicate, search/filter, templates, grouping
- Switch user automations to 2-column grid layout (matches system automations)
- Add duplicate button on non-system cards with POST /api/automations/<id>/duplicate
- Add search/filter bar (text search + trigger/action dropdowns) shown at 6+ automations
- Add Inspiration section with 8 starter templates that pre-fill the builder
- Add folder-style automation grouping with group_name DB column, dropdown
  popover for assignment, collapsible group sections, and builder group input
2026-03-17 07:40:14 -07:00
Broque Thomas
7d0df2b9ed Fix discover page Deezer source support
- personalized_playlists._get_active_source() now returns 'deezer' when
  configured instead of always falling back to 'itunes'
- Add deezer_track_id to _build_track_dict() for discovery pool tracks
- Include album_deezer_id and artist_deezer_id in get_discovery_recent_albums()
  response — fixes "No deezer album ID available" error when clicking cards
- Skip Spotify library section entirely when Spotify is not authenticated
2026-03-16 19:35:26 -07:00
Broque Thomas
e02ad6e86e Fix discovery_recent_albums table recreations dropping Deezer columns
Both NOT NULL and profile v2 migrations now include album_deezer_id and
artist_deezer_id columns, use safe shared-column data copy instead of
SELECT *, and add album_deezer_id to UNIQUE constraints.
2026-03-16 13:52:22 -07:00
Broque Thomas
46ac46134b Add Deezer as configurable free metadata fallback source alongside iTunes
Users can now choose between iTunes/Apple Music and Deezer as their free
metadata source in Settings. Spotify always takes priority when authenticated;
the fallback handles all lookups when it's not.

Core changes:
- DeezerClient: full metadata interface (search, albums, artists, tracks)
  matching iTunesClient's API surface with identical dataclass return types
- SpotifyClient: configurable _fallback property switches between iTunes/Deezer
  based on live config reads (no restart needed)
- MetadataService, web_server, watchlist_scanner, api/search, repair_worker,
  seasonal_discovery, personalized_playlists: all direct iTunesClient imports
  replaced with fallback-aware helpers

Database:
- deezer_artist_id on watchlist_artists and similar_artists tables
- deezer_track_id/album_id/artist_id on discovery_pool and discovery_cache
- Full CRUD for Deezer IDs: add, read, update, backfill, metadata enrichment
- Watchlist duplicate detection by artist name prevents re-adding across sources
- SimilarArtist dataclass and all query/insert methods handle Deezer columns

Bug fixes found during review:
- Similar artist backfill was writing Deezer IDs into iTunes columns
- Discover hero was storing resolved Deezer IDs in wrong column
- Status cache not invalidating on settings save (source name lag)
- Watchlist add allowing duplicates when switching metadata sources
2026-03-16 13:12:12 -07:00
Broque Thomas
837c5ff680 Add persistent library history tracking downloads and server imports
New library_history table logs every completed download and every new
track imported from Plex/Jellyfin/Navidrome. A "History" button next
to "Recent Activity" on the dashboard opens a modal with Downloads and
Server Imports tabs, album art thumbnails, quality/source badges, and
pagination.
2026-03-16 09:36:05 -07:00
Broque Thomas
078b1130f8 Fix watchlist migration dropping profile_id & fix profile delete dialog hidden behind overlay
- Watchlist nullable migration now preserves profile_id column and composite
  UNIQUE constraints when rebuilding the table
- Profile support migration always repairs missing profile_id columns on all
  tables, even if the migration metadata key already exists (handles tables
  rebuilt by other migrations)
- Confirm dialog z-index raised to 100000 to appear above profile picker
  overlay (99999), fixing invisible delete confirmation
2026-03-15 15:21:19 -07:00
Broque Thomas
25cc96e120 Fix watchlist NOT NULL constraint failing for iTunes-only artists
The migration to make spotify_artist_id nullable was using fragile string
matching against CREATE TABLE SQL, which silently failed for some databases.
Now uses PRAGMA table_info to reliably detect the NOT NULL flag.
2026-03-15 14:23:42 -07:00
Broque Thomas
264e696fe3 Fix per-profile ListenBrainz playlist cache scoping and stale data recovery 2026-03-14 21:11:59 -07:00
Broque Thomas
8f0b9518bc Add per-profile ListenBrainz support with personal settings modal 2026-03-14 20:12:19 -07:00
Broque Thomas
7e19e66ef3 Add quality enhance button to upgrade existing library tracks & Add iTunes fallback to Quality Enhance endpoint for full metadata source parity 2026-03-14 17:09:08 -07:00
Broque Thomas
16a474ac0d Add DROP TABLE IF EXISTS guards to all table rebuild migrations 2026-03-14 12:04:27 -07:00
Broque Thomas
d6cfb2fdb8 Fix watchlist NOT NULL constraint blocking artists without Spotify ID 2026-03-14 11:49:04 -07:00
Broque Thomas
945f86c643 Library Repair Worker: multi-job background maintenance daemon with 10 jobs, findings system, and management modal 2026-03-14 09:09:18 -07:00
Broque Thomas
6de3ab7cef Add universal metadata cache for Spotify & iTunes API responses with browsable dashboard tool 2026-03-14 01:26:45 -07:00
Broque Thomas
c54e52e18d Add Spotify Library discovery section, instrumental filter, custom exclusion terms & album download modal fixes 2026-03-14 00:21:44 -07:00
Broque Thomas
a5e72cff05 Add instrumental filter & custom exclusion terms to watchlist content filters 2026-03-13 23:09:12 -07:00
Broque Thomas
e3fdb12d78 Preserve watchlist scan timestamps for UI display instead of wiping on lookback changes 2026-03-13 22:46:41 -07:00
Broque Thomas
e1a5bf678a Add library issue reporting system with actionable detail modal 2026-03-13 21:14:57 -07:00
Broque Thomas
d4eadef374 Add interactive REST API docs with full endpoint tester and complete metadata serialization 2026-03-13 17:45:01 -07:00
Broque Thomas
7da7f3b112 Cache similar artist metadata at scan time to eliminate redundant Spotify API calls 2026-03-13 13:35:54 -07:00
Broque Thomas
ae6fb929bf Cache hero slider artist metadata to eliminate Spotify API calls on every page load 2026-03-13 13:13:31 -07:00
Broque Thomas
ded906bef4 Fix false positive track matching & tag writing visibility for library files 2026-03-12 16:08:44 -07:00
Broque Thomas
ecfa30c918 Fix Tidal V2 search endpoint, duration parsing, and library badge display 2026-03-11 22:08:25 -07:00
Broque Thomas
ac2c710a1e Tidal & Qobuz Background Enrichment Workers 2026-03-11 21:26:20 -07:00
Broque Thomas
c06fd044a1 Profile Permissions & Page Access Control 2026-03-10 23:23:43 -07:00
Broque Thomas
927fe6338e Fix Spotify badge icon & compact card badge layout for overflow 2026-03-10 12:54:18 -07:00
Broque Thomas
03442327ee Fix library page showing wrong artist albums due to cross-artist GROUP BY merge 2026-03-10 11:52:15 -07:00
Broque Thomas
e8ddbe3709 Reset all Genius matches to fix blind-fallback search bug & fix css issues 2026-03-10 10:57:50 -07:00
Broque Thomas
f26f6f8266 Last.fm & Genius full worker parity, clickable service badges, and playlist folder race condition fix 2026-03-10 10:35:55 -07:00
Broque Thomas
dc7140c459 Add Last.fm and Genius to on-demand enrichment, settings reload, and enrich dropdown parity 2026-03-10 09:12:36 -07:00
Broque Thomas
b3d607752b Add version tracking to database backup manager & Fix radio mode next track closing modal and losing playback state 2026-03-09 13:10:25 -07:00
Broque Thomas
8d46d3746b Fix Docker upgrade crashes from stale volume mounts and partial DB migrations 2026-03-09 11:44:00 -07:00
Broque Thomas
5f58432ca4 Redesigned media player with expanded Now Playing modal and smart radio 2026-03-09 10:13:42 -07:00
Broque Thomas
7c50f350c0 Add a library management interface to the artist detail page with inline metadata editing, per-service manual matching, bulk operations, and full track/album management. 2026-03-08 23:37:02 -07:00
Broque Thomas
7b933ff97a Fix Plex album completion false positives from leafCount reflecting partial ownership 2026-03-08 19:13:09 -07:00
Broque Thomas
8b3b82702a Add deep library scan automation for enrichment-safe sync 2026-03-07 18:39:45 -08:00
Broque Thomas
b34e348937 keep a history of automation runs 2026-03-07 09:39:08 -08:00
Broque Thomas
5b507d897e Fix similar_artists repair when profile_id column was previously stripped 2026-03-06 22:30:37 -08:00
Broque Thomas
3dcf07807c Fix similar_artists profile_id column being dropped on every startup 2026-03-06 21:54:19 -08:00
Broque Thomas
8b6a2c0adc allow multiple notification calls per automation as well as a new signal fire utility 2026-03-06 18:10:15 -08:00
Broque Thomas
7647ac22ed Add Discovery Pool dashboard tool card and revamp modal with premium category-card design 2026-03-06 11:59:45 -08:00
Broque Thomas
d264ec70f3 Add sync match cache and fix discovery clear to purge cache 2026-03-06 09:41:44 -08:00
Broque Thomas
d57b48a62a Playlist discovery pipeline with official metadata enforcement for automated sync 2026-03-05 18:32:18 -08:00
Broque Thomas
f99f873d60 Replace hardcoded wishlist/watchlist timers with system automations + add Pushbullet & Telegram notifications 2026-03-05 16:50:09 -08:00
Broque Thomas
da707dcf0a Full automation engine expansion with scheduling, triggers, actions, and UI polish 2026-03-05 15:13:32 -08:00
Broque Thomas
b30e1f60bd Add Mirrored Playlists — persistent cross-service playlist archive
Automatically mirrors every parsed playlist (Spotify, Tidal, YouTube, Beatport) to a local database so they're always accessible — even if a service subscription lapses or the browser closes.
  - New "Mirrored" tab on the Sync page with source-branded cards showing discovery/download status
  - Auto-mirrors on successful parse (upsert — re-parsing updates the existing mirror, no duplicates)
  - Click any mirrored playlist to browse its full track list, then run it through the discovery pipeline
  - Cards dynamically reflect live state: Discovering → Discovered → Downloading → Downloaded
  - Download modal rehydrates after page refresh — click a "Downloading..." card to resume viewing progress
  - All phase transitions (start, complete, cancel, error, modal close) keep card and backend state in sync
  - Profile-scoped via profile_id, consistent with other features
2026-03-04 18:27:18 -08:00
Broque Thomas
86a502f556 Enrich the SoulSync API 2026-03-04 13:19:39 -08:00
Broque Thomas
4fee005dee Add multi-profile support with Netflix-style profile picker
Allow multiple users to share a single SoulSync instance with isolated personal data. Each profile gets its own watchlist, wishlist, discovery pool, similar artists, and bubble snapshots — while sharing the same music library, database, and service credentials.

  - Netflix-style profile picker on startup when multiple profiles exist
  - Optional PIN protection per profile; admin PIN required when >1 profiles
  - Admin-only profile management (create, edit, rename, delete)
  - Profile avatar images via URL with colored-initial fallback
  - Zero-downtime SQLite migration — all existing data maps to auto-created
    admin profile
  - Single-user installs see no changes — profile system is invisible until
    a second profile is created
  - WebSocket count emitters scoped to profile rooms (watchlist/wishlist)
  - Background scanners (watchlist, wishlist, discovery) iterate all profiles
2026-03-04 10:46:08 -08:00
Broque Thomas
7b854baba8 Detect and remove deleted content during incremental database updates
Incremental database updates now detect when artists or albums have been removed from your media server (Plex, Jellyfin, or Navidrome) and automatically clean them up from SoulSync's database. Previously, deleted content would persist as ghost entries until you ran a full refresh. Removal counts are reported in the scan results. Includes safety checks to prevent accidental mass deletion if the server is unreachable or returns incomplete data.
2026-03-03 13:13:38 -08:00
Broque Thomas
df33adf6a7 include 'add to watchlist' button to each artist in library. 2026-03-02 10:04:10 -08:00
Broque Thomas
c279f2e4fa Design retag layout 2026-03-01 22:52:27 -08:00
Broque Thomas
4bff57cb70 Handle edit versions, improve cleanup & thresholds
- matching_engine.py: Add 'single edit' and 'album edit' tokens and clarify radio edit comment so edit/cut variants are recognized as different cuts rather than being silently normalized away.
- database/music_database.py: Fix SQL param ordering by appending server_source to params; add a pre-step to strip "(with ...)" / "[with ...]" only when used inside brackets (so titles like "Stay With Me" are preserved); stop removing edit/version tokens in the generic cleanup and document that radio/single/album edits are treated as distinct by the similarity scorer to avoid incorrect matches.
- web_server.py: Increase DB match confidence threshold from 0.70 to 0.80 and update the runtime check accordingly.

These changes prevent edit/cut variants from being conflated with original recordings, improve title normalization for "with" featuring syntax in brackets, and fix a params ordering bug and a too-low match threshold.
2026-02-25 12:09:53 -08:00
Broque Thomas
7261b04950 Add hero cycling for similar artists
Add support for cycling hero/featured similar artists by introducing a last_featured timestamp and using it to prefer least-recently-featured artists. Changes include:

- DB migration: add _add_similar_artists_last_featured_column and call it during migrations to add a last_featured TIMESTAMP column (non-fatal on error).
- Query changes: get_top_similar_artists now excludes watchlist artists via a LEFT JOIN and wa.id IS NULL and orders results by last_featured (nulls first), then by last_featured asc, occurrence_count desc, and similarity_rank asc. The query aliasing was also added for clarity.
- New helper: mark_artists_featured updates similar_artists.last_featured = CURRENT_TIMESTAMP for shown artists.
- Web server: increase fetch limit to 50, remove random shuffle and instead take the top 10 (already ordered by cycling logic), and call mark_artists_featured to rotate featured artists.

These changes aim to provide deterministic, least-recently-shown cycling of hero artists while keeping watchlist artists out of recommendations.
2026-02-24 18:54:21 -08:00
Broque Thomas
fb7b373d71 Improve edition detection and completion logic
Prefer an album's stored track count when owned_tracks meets or exceeds it (avoids marking a complete standard edition as incomplete when an external source reports a larger deluxe count). Add more robust edition-detection regexes and generic catch-alls (parenthesized/bracketed text containing "edition") in music_database.py and web_server.py, and include silver/gold/platinum edition variants. Also tidy related regex handling and comments to improve matching for varied edition naming (e.g. "MMXI Special Edition").
2026-02-24 12:05:12 -08:00
Broque Thomas
317d5c1770 Add Retag tool (DB, backend, frontend)
Introduce a new Retag tool to track and re-tag previously downloaded albums/singles. Changes include:

- Database: add migration hook and create retag_groups and retag_tracks tables, indexes, and many helper methods (add/find/update/delete groups & tracks, stats, trimming).
- Backend (web_server): capture completed album/single downloads into the retag tables, implement retag execution logic (_execute_retag) to fetch album metadata, match tracks, update tags, move files, download cover art, and update DB. Add thread-safe globals, executor, and REST endpoints for stats, listing groups, group tracks, album search, execute, status, and delete.
- Frontend (webui): add Retag Tool card, modals, search UI, JS to list groups/tracks, search albums, start retag operations, poll status, and update UI; include help content. Add CSS for modals and components.

The migration is invoked during DB init to ensure existing installations create the new tables. The tool caps stored groups (default 100) and avoids duplicate track entries.
2026-02-23 20:39:04 -08:00
Broque Thomas
81617b06aa Reset watchlist scan timestamps on clear/period change
When clearing the wishlist or changing the discovery lookback period, reset watchlist_artists.last_scan_timestamp to NULL so subsequent scans can re-discover older releases that were previously filtered by an earlier scan timestamp. clear_wishlist now deletes wishlist_tracks, updates last_scan_timestamp for all watchlist artists, and logs the number of tracks cleared and artists reset. set_discovery_lookback_period also resets last_scan_timestamp and reports how many artists were reset. Minor whitespace cleanups in watchlist_scanner and web_server included.
2026-02-23 16:47:04 -08:00
Broque Thomas
7eee2be38c Add release_date to Track and UI
Add a release_date field to the Track dataclass for both iTunes and Spotify clients (iTunes: parsed from releaseDate, Spotify: from album.release_date). Propagate release_date into enhanced search results in web_server and into the client-side script so album objects include release_date when available. Also broaden playlistId matching in the missing-tracks process to include 'enhanced_search_track_'. Removed SQLite SHM/WAL files from the repo (cleanup of DB temporary files). These changes enable showing and using track release dates across the app.
2026-02-23 16:25:23 -08:00
Broque Thomas
f1fe72ceb2 Add track selection UI and backend mapping
Add per-track selection checkboxes, select-all control and a selection count to download modals (missing/YouTube/Tidal/artist-album). Implement JS helpers (toggleAllTrackSelections, updateTrackSelectionCount) to manage checkbox state, row dimming, button disabling, and to filter/stamp selected tracks with _original_index before sending to the backend. Update start/add-to-wishlist flows to use only selectedTracks and disable controls once analysis starts. Backend _run_full_missing_tracks_process now reads _original_index to preserve original table indices in analysis results. CSS updates (mobile.css and style.css) add styling for checkbox columns, responsive hiding logic for headers/columns, selection visuals (.track-deselected), and small layout/width tweaks.
2026-02-23 15:54:58 -08:00
Broque Thomas
fabec1e455 Handle duplicate artists and ratingKey migrations
Add duplicate-artist detection/merge and handle ratingKey (ID) migrations for artists and albums. Introduces MusicDatabase.merge_duplicate_artists that picks a canonical artist (most enrichment data), merges enrichment fields, migrates albums/tracks, and removes duplicates; DatabaseUpdateWorker now runs this merge during updates (even when no new content) and after orphan cleanup. insert_or_update_artist/album now detect same-name/title + server_source collisions (ratingKey changes), inserting a new record while preserving enrichment and migrating references, with safe deletion of old rows. Also deduplicate artist listing queries so results show a single canonical row per name+server_source while aggregating album/track counts across duplicates. Logging improved to report merge/migration outcomes.
2026-02-23 13:15:06 -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
3644422ab8 Add FLAC bit depth filter to post-download quality gate 2026-02-20 15:05:45 -08:00
Broque Thomas
1d33a37eb2 Fix database migrations to check each column individually, preventing partial migration failures 2026-02-19 17:42:02 -08:00
Broque Thomas
c70cfd335a Fix missing formats key in error path and clean up format query 2026-02-19 10:50:53 -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
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
ae5d77810d Add Deezer & AudioDB source badges to library artist cards and detail page 2026-02-18 21:30:15 -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
0f18b12967 Move bubble snapshots from disk to database 2026-02-17 16:12:22 -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
2179483b95 Fix Unicode diacritics breaking album/track database matching 2026-02-16 23:28:00 -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
c48ac1d4f9 diacritic normalization 2026-02-14 12:03:49 -08:00
Broque Thomas
511f4f77d1 Update music_database.py 2026-02-09 18:36:31 -08:00
Broque Thomas
2a1ceb1438 fix metabrainz column issue in db 2026-02-09 14:00:15 -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
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
22eb62bb77 add musicbrainz icon for items where matched 2026-02-04 21:37:15 -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
abc510b9b9 Fix album detection for split albums and false positive matching
Merge split album entries (e.g. Navidrome assigning different IDs to the same album) by grouping on title+year instead of album ID, so track counts are correctly combined across all entries. Also add a minimum title similarity floor (0.6) to prevent a perfect artist match from carrying unrelated albums over the confidence threshold.
2026-01-29 15:12:13 -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
9af0be1300 fixed issue where legacy cold was called. 2026-01-26 13:37:42 -08:00
Broque Thomas
905e98016f Fix watchlist artist config and add image at insert when Itunes source. 2026-01-25 09:24:28 -08:00
Broque Thomas
4f1dc2c15f force refetch similar artists when Spotify IDs missing
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.
2026-01-24 23:46:01 -08:00
Broque Thomas
3cb88669e3 Fix iTunes-only Discover page not loading data
- 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
2026-01-24 21:48:17 -08:00
Broque Thomas
1d14a8b987 Discover page itunes integration. Spotify and Itunes will have their own pool 2026-01-23 23:05:58 -08:00
Broque Thomas
1560726bbc rebuild discovery pool flow to allow multiprocessing of itunes and spotfiy. each getting their own pool. 2026-01-23 14:25:26 -08:00
Broque Thomas
f12478ee70 Add iTunes fallback and improve artist/album handling
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.
2026-01-22 19:12:14 -08:00
Broque Thomas
f126cf7118 Add cross-provider support for watchlist artists
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.
2026-01-22 17:04:23 -08:00
Broque Thomas
a8766828d9 Add content type filters for watchlist artists
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.
2026-01-11 01:33:39 -08:00
Broque Thomas
99c8f71420 Refine noise removal in track title normalization
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.
2026-01-09 14:17:36 -08:00
Broque Thomas
5dab9e7259 Improve track title cleaning for comparison
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.
2026-01-09 13:35:19 -08:00
Broque Thomas
404f8b254d Add diacritic-normalized artist name variations
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.
2026-01-09 11:26:13 -08:00
Broque Thomas
b269084c7d Improve album title matching with diacritic normalization
Added normalized string comparison for album titles to better handle diacritics, addressing issue #101. Also logs when normalization improves matching accuracy.
2026-01-09 09:22:01 -08:00
Broque Thomas
8620b52709 Improve album search normalization and fallback logic
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.
2026-01-08 16:42:09 -08:00
Broque Thomas
61a698aefa Move database files to /app/data and use env var for path
Updated Dockerfile, entrypoint.sh, and Python code to store database files in /app/data instead of /app/database, avoiding conflicts with the Python package. The database path is now configurable via the DATABASE_PATH environment variable, improving flexibility for container deployments.
2026-01-01 09:53:39 -08:00
Broque Thomas
bab31218bb Improve artist handling and preserve album data in sync
Enhanced handling of artist data to support both string and object formats across the database, sync service, and web server. The sync process now preserves full album and artist objects for tracks, enabling wishlist additions with album cover art. The frontend and API were updated to use the full artist objects, and the UI now formats artist names correctly.
2025-12-09 10:44:54 -08:00
Broque Thomas
bcf62d7de4 Update music_database.py 2025-11-25 17:54:14 -08:00
Broque Thomas
ffe02d5330 listenbrainz discovery fix 2025-11-25 15:13:41 -08:00
Broque Thomas
4684408439 Revert "user selected watchlist settings now connected to backend."
This reverts commit 2c12759dbb.
2025-11-24 19:30:30 -08:00
Broque Thomas
2c12759dbb user selected watchlist settings now connected to backend. 2025-11-24 17:27:50 -08:00
Broque Thomas
1749bb62a5 foundation for allowing user to decide which releases to grab per watchlist artist 2025-11-24 17:16:12 -08:00
Broque Thomas
c46e2c527e search bar for watchlist 2025-11-23 20:23:30 -08:00
Broque Thomas
bc17e9fa2b remove 2025-11-21 16:15:04 -08:00
Broque Thomas
08e3f6c900 fix liked songs 2025-11-21 13:31:26 -08:00
Broque Thomas
69ea705f5d fix wishlist duplicates 2025-11-19 09:47:56 -08:00
Broque Thomas
52c27ce2a9 cache listenbrainz and update with watchlist 2025-11-18 13:41:45 -08:00
Broque Thomas
cc62b3b48e discover page progress 2025-11-17 10:09:08 -08:00
Broque Thomas
76dca2f045 caching for similar artists 2025-11-11 14:04:55 -08:00
Broque Thomas
d399a612ef progress on discover page 2025-11-11 11:38:27 -08:00
Broque Thomas
47f8862fc4 discovery page progress 2025-11-11 10:39:46 -08:00
Broque Thomas
576f151c5c preferred quality updates. 2025-11-09 14:16:38 -08:00
Broque Thomas
8c7cb6d448 manual library selection for plex servers 2025-10-15 15:04:05 -07:00
Broque Thomas
0715c41745 fix library page genre display 2025-10-03 09:15:48 -07:00
Broque Thomas
a24c85378c remove 2025-09-26 23:51:11 -07:00
Broque Thomas
0ba4b6a079 pull genres with imges. 2025-09-26 16:11:50 -07:00
Broque Thomas
cf33e17060 fix database issue 2025-09-26 13:16:58 -07:00
Broque Thomas
93ac55a709 Improve wishlist track sorting and cleanup logic
Wishlist tracks are now sorted by artist and track name for consistent display. The database query for wishlist tracks now orders by date_added instead of randomly. Added logic to remove completed tracks from the wishlist during failed track processing. Updated docker-compose.yml to mount the H: drive for transfer folders.
2025-09-12 15:19:36 -07:00
Broque Thomas
fe84f1dbb8 remove 2025-08-18 16:43:35 -07:00
Broque Thomas
5b6ea29522 updated artist live album check to use server specific data 2025-08-18 15:52:55 -07:00
Broque Thomas
0c90f4f327 multi-server source 2025-08-18 15:32:58 -07:00
Broque Thomas
620c78766b better 2025-08-18 10:36:57 -07:00
Broque Thomas
3bd6a29bfd Included Watchlist functionality.
Watchlist will allow the user to select artist to 'watch' and the app will automatically add new releases by those artists to the wishlist for automatic download.

included version information and modal
2025-08-16 09:27:01 -07:00
Broque Thomas
68584e0923 remove pycache 2025-08-14 14:09:11 -07:00
Broque Thomas
9da7d4a7e0 readme 2025-08-13 11:54:51 -07:00
Broque Thomas
62e78f59f7 youtube playlist functionality. may have bugs. 2025-08-13 11:53:36 -07:00
Broque Thomas
29e413dcf7 readme 2025-08-09 22:42:04 -07:00
Broque Thomas
2394c160f2 readme 2025-08-09 22:38:30 -07:00
Broque Thomas
f4ac2b7d6e KoЯn.... 2025-08-09 16:38:56 -07:00
Broque Thomas
2196ed35f6 fixing database issues 2025-08-08 22:27:02 -07:00
Broque Thomas
a228affd7b database fixes 2025-08-08 20:44:48 -07:00
Broque Thomas
ac4ec88f42 fixed sync issue 2025-08-08 18:23:53 -07:00
Broque Thomas
a5ece58379 randomize wishlist order 2025-08-08 17:02:18 -07:00
Broque Thomas
285809d16f better matching 2025-08-08 13:19:49 -07:00
Broque Thomas
872072fe22 remove these 2025-08-07 23:56:08 -07:00
Broque Thomas
aa7af89d13 code fix 2025-08-07 23:49:37 -07:00
Broque Thomas
b5e3c47051 wishlist functionality 2025-08-07 23:08:05 -07:00
Broque Thomas
2ad0dddba4 recommend database refresh every 1-2weeks
This is needed if users manually correct failed matches on plex when songs are scanned in. If a db sync is done after the scan but before the manual modification,
2025-08-07 20:27:26 -07:00
Broque Thomas
906d0c23b7 incremental update bug fixed 2025-08-07 11:37:13 -07:00
Broque Thomas
66bbfaf9c1 fix incremental update 2025-08-07 11:26:50 -07:00
Broque Thomas
aafc0ca49f consistent matching between sync and artists. 2025-08-07 10:35:56 -07:00
Broque Thomas
86fcdd6869 better matching 2025-08-06 19:44:55 -07:00
Broque Thomas
019253087f better matching on albums 2025-08-06 11:31:35 -07:00
Broque Thomas
78d037cba4 include deep search for artists. 2025-08-06 10:04:10 -07:00
Broque Thomas
7212e9224c include database in search 2025-08-06 09:47:43 -07:00
Broque Thomas
684433d857 update variations 2025-08-06 00:07:12 -07:00
Broque Thomas
b76c0531e5 basic db structure 2025-08-05 22:43:04 -07:00