Skip to content

Add opt-in ListenBrainz scrobbling with custom server support - #66

Merged
lostf1sh merged 3 commits into
fix/processing-action-notificationfrom
feature/listenbrainz-scrobbling
Jul 31, 2026
Merged

Add opt-in ListenBrainz scrobbling with custom server support#66
lostf1sh merged 3 commits into
fix/processing-action-notificationfrom
feature/listenbrainz-scrobbling

Conversation

@lostf1sh

@lostf1sh lostf1sh commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Fixes #55

Stacked on #65.

What

Opt-in, default-off ListenBrainz scrobbling with an optional custom server URL for self-hosted ListenBrainz-compatible servers (Maloja, self-hosted ListenBrainz).

  • Account: connect from the Accounts screen by pasting a user token; the token is validated on connect and stored in EncryptedSharedPreferences (same pattern as the Navidrome credentials). Disconnecting deletes the token and any queued listens — consent revocation is a clean boundary.
  • Custom server URL: an optional URL field routes every API call to a ListenBrainz-compatible endpoint. Path prefixes are preserved (Maloja serves the API under /apis/listenbrainz/), the scheme defaults to https, and the token is validated against the entered server before anything is stored.
  • Listen threshold: a listen is queued when accumulated (pause-aware) listening time reaches min(4 min, duration/2), hooked into ListeningStatsTracker.finalizeCurrentSession() so every teardown path is covered. listened_at is the session start.
  • Per-source toggles: Local / Subsonic / Jellyfin, all on once connected, so users whose Navidrome server already scrobbles server-side can avoid double submission.
  • Offline queue: new Room table listenbrainz_pending_listens (MIGRATION_2_3, schema exported) storing a metadata snapshot at enqueue, capped at 3000 rows. A HiltWorker flushes with network constraint and exponential backoff, honoring Retry-After on 429, dropping invalid rows on 400, and pausing on 401 with a reconnect prompt on the Accounts card.
  • Now-playing submissions while scrobbling is enabled.
  • Docs updated in lockstep: PRIVACY.md opt-in disclosure, docs/FDROID.md anti-feature item 7, CHANGELOG.md.

MusicBrainz identifier columns are added to the library database as shared groundwork; the manual tag-lookup feature is intentionally not part of this PR.

UI

The Accounts screen gains a ListenBrainz card (connect dialog with token + optional server URL, per-source toggles, queued-listen count, reauth prompt). No screenshots — implemented without an attached device; happy to add some before merge if wanted.

Testing

  • :app:compileDebugKotlin
  • :app:lintDebug ✅ (clean)
  • :app:testDebugUnitTest ✅ (new: ScrobbleManagerTest threshold/source cases, ListenBrainzEndpointTest URL normalization and request re-rooting, ListeningStatsTrackerTest updated for the scrobble hook)

lostf1sh added 2 commits July 30, 2026 23:14
Issue #55 explicitly asks for a custom endpoint so self-hosted servers
like Maloja can receive scrobbles. Route every ListenBrainz request
through an endpoint holder that re-roots the API path under a stored
custom base URL (path prefixes like Maloja's /apis/listenbrainz are
preserved), validate the token against the entered server on connect,
and persist the URL alongside the token. The Accounts dialog gains an
optional server URL field with its own validation error.
@lostf1sh lostf1sh changed the title feature/listenbrainz scrobbling Add opt-in ListenBrainz scrobbling with custom server support Jul 30, 2026
The Accounts page opens straight into linked services now that the
Connected Accounts hero and its stat tiles are gone. The ListenBrainz
card instead shows the account's total listen count and a server-
confirmed "Scrobbling now" row polled from playing-now while the
screen is open, with a shimmer skeleton during the first fetch. Both
degrade gracefully on ListenBrainz-compatible servers that only
implement submission, like Maloja.
@lostf1sh
lostf1sh merged commit fd78210 into main Jul 31, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Built-in Scrobbling support with custom URL

1 participant