* test(e2e): add comprehensive tests for Subsonic API endpoints
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(e2e): improve database handling and snapshot restoration in tests
Signed-off-by: Deluan <deluan@navidrome.org>
* test(e2e): add tests for album sharing and user isolation scenarios
Signed-off-by: Deluan <deluan@navidrome.org>
* test(e2e): add tests for multi-library support and user access control
Signed-off-by: Deluan <deluan@navidrome.org>
* test(e2e): tests are fast, no need to skip on -short
Signed-off-by: Deluan <deluan@navidrome.org>
* address gemini comments
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(tests): prevent MockDataStore from caching repos with stale context
When RealDS is set, MockDataStore previously cached repository instances
on first access, binding them to the initial caller's context. This meant
repos created with an admin context would skip library filtering for all
subsequent non-admin calls, silently masking access control bugs. Changed
MockDataStore to delegate to RealDS on every call without caching, so each
caller gets a fresh repo with the correct context. Removed the pre-warm
calls in e2e setupTestDB that were working around the old caching behavior.
* test(e2e): route subsonic tests through full HTTP middleware stack
Replace direct router method calls with full HTTP round-trips via
router.ServeHTTP(w, r) across all 15 e2e test files. Tests now exercise
the complete chi middleware chain including postFormToQueryParams,
checkRequiredParameters, authenticate, UpdateLastAccessMiddleware,
getPlayer, and sendResponse/sendError serialization.
New helpers (doReq, doReqWithUser, doRawReq, buildReq, parseJSONResponse)
use plaintext password auth and JSON response format. Old helpers that
injected context directly (newReq, newReqWithUser, newRawReq) are removed.
Sharing tests now set conf.Server.EnableSharing before router creation to
ensure sharing routes are registered.
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Added validation to ensure the JSONP callback parameter is a valid
JavaScript identifier before reflecting it into the response. Invalid
callbacks now return a JSON error response instead. This prevents
malicious input from being injected into the response body via the
callback parameter.
Added a warning log when the gotaglib extractor fails to read metadata
from a file. Previously, extraction errors were silently skipped, making
it difficult to diagnose issues with unreadable files during scanning.
Ref: https://github.com/navidrome/navidrome/issues/4604#issuecomment-3865690165
Signed-off-by: Deluan <deluan@navidrome.org>
* 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>