navidrome/core
Deluan Quintão 7b7721f002
feat(matcher): match similar/top songs by multiple artists (#5668)
* feat(matcher): add Song.Artists (agents.Artist) and field-wise song dedup

* refactor(matcher): make song equality an agents.Song.Equals method via hashstructure

Move the sameSong free function from core/matcher into an Equals method on
agents.Song, following the model.MediaFile/Album.Equals convention. Uses strict
hashstructure hashing (nil opts, no IgnoreZeroValue) to preserve the original
whole-value equality contract. Tests moved to core/agents.

* feat(matcher): match by multiple artists with overlap ranking and artist-ID fast-path

* refactor(matcher): rank artist overlap and specificity above the preferred-track flag

Identity signals (specificityLevel, artistOverlap) now outrank the taste
signal (preferredMatch) in betterThan. A starred/4-star track that is a worse
identity match no longer beats a more specific or higher-overlap track.
PreferStarred still breaks ties when specificity and overlap are equal.

* fix(matcher): score artist-MBID specificity against all credited artists, not just the last

sanitizedTrack.artistMBID (string) replaced with artistMBIDs (map[string]struct{}) so
bucketTracks collects all credited owned MBIDs per query instead of last-write-wins.
computeSpecificityLevel tests set membership, letting each of a collaboration's
MBID-bearing artists reach the proper specificity level (4/5) independently.

* feat(plugins): carry multiple artists (with IDs) through SongRef conversions

* feat(plugins): regenerate schemas and PDK wrappers for multi-artist SongRef

* refactor(matcher): tidy bucketTracks accumulator and artist resolution

Replace bucketTracks' two parallel per-track maps (overlapByQuery/mbidsByQuery)
with a named queryAccum struct (F2). Collapse resolveArtists' four hand-mutated
parallel maps into a pendingArtist slice with derived nameToQueries/mbidToQueries
maps (F1). Replace the own() method on resolvedArtists with a package-level
addToSet helper that drops the method/receiver indirection (F3).

* docs(matcher): trim comments that restate the code

* fix(plugins): use Vec::is_empty for slice fields in generated Rust PDK

* fix(matcher): treat a resolved artist ID as an identity match for specificity

* docs(matcher): reflect artist-ID identity in the specificity ladder
2026-06-26 14:46:09 -04:00
..
agents feat(matcher): match similar/top songs by multiple artists (#5668) 2026-06-26 14:46:09 -04:00
artwork perf(artwork): faster image resize + update gen2brain/webp to v0.6.0 (#5652) 2026-06-22 16:33:01 -04:00
auth refactor: more warnings clean up 2026-05-20 17:43:12 -03:00
external fix(matcher): match by artist credit so artist-MBID specificity works and collaborators match (#5637) 2026-06-21 11:05:58 -04:00
ffmpeg fix(transcoding): preserve source metadata when transcoding downloads (#5628) 2026-06-18 09:58:43 -04:00
lyrics refactor(lyrics): single ParseLyrics entry point + all-format plugin lyrics (#5632) 2026-06-19 18:25:35 -04:00
matcher feat(matcher): match similar/top songs by multiple artists (#5668) 2026-06-26 14:46:09 -04:00
metrics refactor(conf): replace eager dir creation with lazy Dir type (#5495) 2026-05-13 17:44:22 -03:00
playback refactor: more warnings clean up 2026-05-20 17:43:12 -03:00
playlists fix(playlists): preserve unchanged fields on partial REST updates (#5542) 2026-05-27 23:29:17 -03:00
publicurl fix(shares): honor path component of ShareURL config 2026-04-05 12:12:15 -04:00
scrobbler fix(scrobbler): proxy NowPlaying even when ignoreScrobble is set (#5559) 2026-06-03 20:03:08 -04:00
sonic feat(subsonic): add sonicSimilarity extension as plugin capability (#5419) 2026-04-27 17:50:09 -04:00
storage test(storage): re-enable local storage tests on Windows (#5654) 2026-06-22 21:33:14 -04:00
stream fix(transcoding): honor player forced format on the WebUI transcode flow (#5613) 2026-06-14 20:52:19 -04:00
archiver.go fix(transcoding): cap concurrent transcodes to prevent ffmpeg DoS (#5522) 2026-05-24 00:24:30 -03:00
archiver_test.go fix(transcoding): cap concurrent transcodes to prevent ffmpeg DoS (#5522) 2026-05-24 00:24:30 -03:00
common.go feat(bfr): Big Refactor: new scanner, lots of new fields and tags, improvements and DB schema changes (#2709) 2025-02-19 20:35:17 -05:00
common_test.go ci: run Go tests on Windows (#5380) 2026-04-19 13:16:47 -04:00
core_suite_test.go Rename log.LevelCritical to log.LevelFatal 2022-12-21 14:53:36 -05:00
image_upload.go feat: add artist image uploads and image-folder artwork source (#5198) 2026-03-15 22:19:55 -04:00
image_upload_test.go refactor(conf): replace eager dir creation with lazy Dir type (#5495) 2026-05-13 17:44:22 -03:00
inspect.go refactor: multiple syntax updates for Go 1.26 2026-05-19 18:02:36 -03:00
library.go perf(subsonic): speed up artist search3 deep-offset pagination (#5620) 2026-06-16 21:47:15 -04:00
library_test.go feat: add go-taglib pure Go metadata extractor (#4902) 2026-01-18 14:42:53 -05:00
maintenance.go refactor: run Go modernize (#5002) 2026-02-08 09:57:30 -05:00
maintenance_test.go feat(scanner): implement selective folder scanning and file system watcher improvements (#4674) 2025-11-14 22:15:43 -05:00
players.go feat(server): group Subsonic config options together 2025-03-05 12:29:30 -08:00
players_test.go Use userId in player, other fixes (#3182) 2024-08-03 13:37:21 -04:00
share.go chore: go fix 2026-05-28 22:13:05 -03:00
share_test.go refactor: extract TruncateRunes function for safe string truncation with suffix 2025-11-06 14:27:38 -05:00
user.go refactor: run Go modernize (#5002) 2026-02-08 09:57:30 -05:00
user_test.go feat(plugins): New Plugin System with multi-language PDK support (#4833) 2026-01-14 19:22:48 -05:00
wire_providers.go refactor: extract song-to-library matcher to core/matcher package (#5348) 2026-04-12 16:47:22 -04:00