navidrome/core
Deluan Quintão 82fde00ecc
feat(scrobbler): add per-user scrobble filter (#5964)
* feat(scrobbler): add scrobble_filter column to user

* feat(scrobbler): validate scrobble filter criteria on user save

* refactor(persistence): make smart playlist join helpers package-level

* feat(scrobbler): add MediaFileRepository.MatchesCriteria

* feat(scrobbler): filter external scrobbles with per-user criteria

* feat(ui): add scrobble filter field to user form

* fix(scrobbler): default scrobble_filter to empty string for existing users

* refactor(scrobbler): also gate playback reports on the scrobble filter

Playback reports carry the same track metadata to plugin scrobblers, so a
filtered track leaked through that third dispatch path. Skip the filter
evaluation entirely when no scrobbler is active.

* refactor(persistence): move criteria join building into criteria_sql.go

The join set a criteria needs was decided in criteria_sql.go but built in
smart_playlist_repository.go, so both callers had to pair the two by hand.

* refactor(persistence): unexport smartPlaylistCriteria methods

The type never leaves the package, so the exported names advertised an API
that callers outside persistence could never reach. Also disambiguates
where/orderBy from squirrel's SelectBuilder methods of the same name.

* fix(ui): cap the scrobble filter field width

fullWidth stretched it across the whole page next to 256px inputs. Bounded
at 40em, with two rows and a resize handle so JSON rules stay readable.

* refactor(ui): move scrobble filter input in UserEdit component

* feat(ui): add pt-BR translations for the scrobble filter

* fix(scrobbler): take the filter verdict before incPlay

incPlay mutates play counts and dates a filter can test on, so evaluating at
dispatch time let one play decide differently on either side of the increment:
a track could be scrobbled despite matching, or lose only its stopped report
and strand presence plugins. Reject limit/offset too, rather than silently
ignoring part of a rule copied from a smart playlist.

* fix(scrobbler): filter the report from an expired session

The expiry callback runs with a stub user carrying no filter, so evaluating
there always returned false and leaked the track to plugin scrobblers. That is
the normal path for clients that never send stopped, such as legacy Subsonic
now-playing. Carry the last verdict on the session instead.

* refactor(scrobbler): skip the now-playing enqueue instead of threading the verdict

Queuing an entry only to drop it at dispatch also cancelled a pending
announcement for the previous, unfiltered track, since the queue is keyed by
player and a new entry replaces the old one.

* fix(scrobbler): evaluate the filter regardless of active scrobblers

The verdict is stored on the session and dispatched at expiry, so skipping
evaluation when no scrobbler was active let a plugin enabled mid-session
receive a filtered track. The empty-filter guard above already gives servers
without scrobbling the same free path, so the shortcut only ever applied to
users who had a filter set.
2026-08-15 16:10:53 -04:00
..
agents fix(plugins): stop reporting plugin call failures as not-found (#5953) 2026-08-13 22:56:09 -04:00
artwork fix(plugins): load plugin agents in CLI commands (#5959) 2026-08-15 11:01:36 -04:00
auth refactor(db): migrate all ids to a uniform canonical 128-bit base62 encoding (#5824) 2026-08-02 12:58:53 -04:00
external fix(instant-mix): top short mixes up instead of returning what the first source found (#5951) 2026-08-13 18:50:34 -04:00
ffmpeg fix(streaming): surface why a transcode decision failed (#5820) 2026-07-19 18:51:32 -04:00
lyrics fix(scanner): stop logging expected lyrics sniff misses as warnings (#5702) 2026-07-02 09:46:57 -04:00
matcher feat(listenbrainz): match collaboration top-songs via all credited artist MBIDs (#5670) 2026-06-26 17:06:14 -04:00
metrics feat(insights): report the app store or hosting platform via ND_PLATFORM (#5956) 2026-08-14 13:46:52 -04:00
playback refactor: more warnings clean up 2026-05-20 17:43:12 -03:00
playlists feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00
publicurl refactor(db): migrate all ids to a uniform canonical 128-bit base62 encoding (#5824) 2026-08-02 12:58:53 -04:00
scrobbler feat(scrobbler): add per-user scrobble filter (#5964) 2026-08-15 16:10:53 -04:00
sonic feat(jellyfin): AudioMuse-AI compatible sonic endpoints (#5782) 2026-07-15 20:44:56 -04:00
storage fix(scanner): resolve file symlinks with the production local storage FS (#5755) 2026-07-10 10:52:05 -04:00
stream fix(subsonic): omit bit depth for lossy targets in transcode decision (#5768) 2026-07-12 13:27:01 -04:00
archiver.go feat(artist): add Share and Download actions to the Artist detail page (#5944) 2026-08-12 11:59:56 -04:00
archiver_test.go feat(artist): add Share and Download actions to the Artist detail page (#5944) 2026-08-12 11:59:56 -04: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
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 feat(artwork): new artwork pipeline with background resolution and Low Quality Image Placeholders (#5847) 2026-08-09 15:03:27 -04:00