* feat(agents): Add artist url and top songs to ListenBrainz agent
* add newline at end of file
* respond to some feedback
* add more tests, include more metadata in top songs
* add duration to album info
* add similar artists from labs
* add similar artists and track radio
* fix(client): replace sort with slices.SortFunc for deterministic ordering of recordings with same score
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: typos
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: use struct literal initialization consistently
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: configurable artist and track algorithms
Signed-off-by: Deluan <deluan@navidrome.org>
* test configuration changes
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(subsonic): add OS readonly and validUntil properties
* remove duplicated test
* test: fix and enable disabled child smart playlist tests
Fixed the XContext("child smart playlists") tests that were disabled with
a TODO comment. The tests had several issues: nested playlists were missing
Public: true (required by InPlaylist criteria), the criteria matched no
test fixtures, the "not expired" test set EvaluatedAt on the parent too
(preventing it from refreshing at all), and the "expired" test dereferenced
a nil EvaluatedAt. Added proper cleanup with DeferCleanup and config
restoration via configtest.
* fix(subsonic): always include readonly field in JSON playlist responses
Removed omitempty from the JSON tag of the Readonly field in
OpenSubsonicPlaylist so that readonly: false is always serialized in
JSON responses, per the OpenSubsonic spec requirement that supported
fields must be returned with default values. Added a test case with an
empty OpenSubsonicPlaylist to verify the behavior.
---------
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
* fix(ui): use div for fragment, check lastfm url for artist page
* use span instead of div for better compat
* fix: implement isLastFmURL utility and add tests for URL validation
---------
Co-authored-by: Deluan <deluan@navidrome.org>
* Rework frontend code interacting directly with DOM
Rework frontend code that uses user-supplied data to render things like
comments and notes. In places where using React's built-in sanitization
is possible, the feature is used. In other places, where some markup
might be necessary, DOMPurify is used to sanitize the HTML before
rendering it.
Solves: GHSA-rh3r-8pxm-hg4w
* Remove test post DOM rework
* fixup! Rework frontend code interacting directly with DOM
* ci: add riscv64 builds
This requires at least Debian Trixie base systems, and a cross-taglib version with riscv64 release assets.
Signed-off-by: MichaIng <micha@dietpi.com>
* fix(makefile): add riscv64 to supported platforms and update cross-taglib version
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: MichaIng <micha@dietpi.com>
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* feat(lastfm): support multiple languages for album and artist info retrieval
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(lastfm): improve content validation for album and artist descriptions
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(lastfm): remove single language test and clarify languages field in configuration
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(deezer): support multiple languages for artist bio retrieval
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(lastfm): rename ignoredBiographies to ignoredContent for clarity
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add ISRC support to similar songs matching and plugin interface
Add ISRC (International Standard Recording Code) as a high-priority
identifier in the provider matching algorithm, alongside MBID. The
matching pipeline now uses four strategies in priority order:
ID > MBID > ISRC > Title+Artist fuzzy match.
- Add ISRC field to agents.Song struct
- Add ISRC field to plugin capability SongRef (Go, Rust PDKs)
- Add loadTracksByISRC using json_tree query on tags column
- Integrate ISRC into matchSongsToLibrary, selectBestMatchingSongs,
and buildTitleQueries
https://claude.ai/code/session_01Dd4mTq1VQZag4RNjCVusiF
* chore: regenerate plugin schema after ISRC addition
Run `make gen` to update the generated YAML schema for the
metadata agent capability with the new ISRC field on SongRef.
https://claude.ai/code/session_01Dd4mTq1VQZag4RNjCVusiF
* feat(mediafile): add GetAllByTags method to MediaFileRepository for tag-based retrieval
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(provider): speed up track matching by incorporating prior matches in ISRC and MBID lookups
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Claude <noreply@anthropic.com>
* refactor: integrate duration into matchScore instead of using pre-filter
Duration matching was handled as a binary pre-filter with fallback,
inconsistent with how title, specificity, and album are scored via the
matchScore system. Move duration into matchScore as a boolean field
ranked between title similarity and specificity level, making all
match criteria use the same hierarchical comparison.
https://claude.ai/code/session_01BWJ5aAzbQRvwjB7PvUcNYs
* refactor: remove findBestMatchInTracks function and integrate its logic into findBestMatch
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: use duration proximity score instead of boolean match
Replace the binary durationMatch bool with a continuous durationProximity
float64 (0.0-1.0) using 1/(1+diff). This removes the hard 3-second
tolerance cutoff, so closer durations are always preferred over farther
ones without an arbitrary cliff edge.
https://claude.ai/code/session_01BWJ5aAzbQRvwjB7PvUcNYs
* style: fix gofmt alignment in matchScore struct
https://claude.ai/code/session_01BWJ5aAzbQRvwjB7PvUcNYs
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add duration filtering for similar songs matching
Signed-off-by: Deluan <deluan@navidrome.org>
* test: refactor expectations for similar songs in provider matching tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add functions to retrieve similar songs by track, album, and artist
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): support uint32 in ndpgen
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): update duration field to use seconds as float instead of milliseconds as uint32
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: add helper functions for Rust's skip_serializing_if with numeric types
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(provider): enhance track matching logic to fallback to title match when duration-filtered tracks fail
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: rename ArtistRadio to SimilarSongs for clarity and consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement GetSimilarSongsByTrack and related functionality for song similarity retrieval
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance GetSimilarSongsByTrack to include artist and album details and update tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance song matching by implementing title and artist filtering in loadTracksByTitleAndArtist
Signed-off-by: Deluan <deluan@navidrome.org>
* test: add unit tests for song matching functionality in provider
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: extract song matching functionality into its own file
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: clarify similarSongsFallback function description in provider.go
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: initialize result slice for songs with capacity based on response length
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: simplify agent method calls for retrieving images and similar songs
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: simplify agent method calls for retrieving images and similar songs
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: remove outdated comments in GetSimilarSongs methods
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: use composite key for song matches to handle duplicates by title and artist
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: consolidate expectations setup for similar songs tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add instant mix action to song context menu and update translations
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(provider): handle unknown entity types in GetSimilarSongs
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: move playSimilar action to playbackActions and streamline song processing
Signed-off-by: Deluan <deluan@navidrome.org>
* format
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance instant mix functionality with loading notification and shuffle option
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement fuzzy matching for similar songs based on configurable threshold
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: implement track matching with multiple specificity levels
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance track matching by implementing unified scoring with specificity levels
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance deezer top tracks result with album
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance track matching with fuzzy album similarity for improved scoring
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: document multi-phase song matching algorithm with detailed scoring and prioritization
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): use stock array renderer for plugins config form
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): enforce minimum user tokens and require users field
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): simplify error handling in control state hook
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): remove "None" MenuItem from OutlinedEnumControl
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): enhance error handling by returning field info and path in validation errors
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): update OutlinedEnumControl to handle empty values and remove "None" option when required
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(db): Include items with no annotation for starred=false, handle has_rating=false
* hardcode starred instead
* test: ensure albums and artists without annotations are included in starred and has_rating filters
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: replace starred and has_rating filters with annotationBoolFilter for consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: update annotationBoolFilter to handle boolean values correctly in SQL expressions
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>