Skip to content

Fix per-user Last.fm integration - #80

Closed
Darep wants to merge 23 commits into
masterfrom
fix/per-user-lastfm
Closed

Fix per-user Last.fm integration#80
Darep wants to merge 23 commits into
masterfrom
fix/per-user-lastfm

Conversation

@Darep

@Darep Darep commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • persist Last.fm tokens and sessions on each Beatstream user
  • add connect, complete, disconnect, now-playing, and scrobble API endpoints
  • wire Settings and playback scrobbling into the React frontend
  • document the required Last.fm API credentials

Verification

  • npm run typecheck
  • npm run build
  • docker build -f Dockerfile.hub -t beatstream-lastfm-check .
  • docker run --rm beatstream-lastfm-test go test ./...

Repository-wide frontend lint still reports pre-existing violations outside this change.

Comment thread lastfm.go Dismissed
@Darep
Darep force-pushed the fix/per-user-lastfm branch from e1b303b to 6d1699e Compare August 9, 2026 19:46
@Darep
Darep force-pushed the fix/per-user-lastfm branch from 6d1699e to 858a75a Compare August 29, 2026 20:12
Comment thread frontend/src/store.ts Outdated
Comment on lines +27 to +28
/** Increments whenever a new track playback starts, including repeats */
playbackInstance: number;

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"instance" sounds like it's an instance of a playback while this is a counter. Right?

My suggestion:

Suggested change
/** Increments whenever a new track playback starts, including repeats */
playbackInstance: number;
/** Increments whenever a new track playback starts, including repeats. Used by Last.fm to keep track of new plays. */
playbackCount: number;

Also, do we have comprehensive tests to make sure this is incremented correctly in every situation?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Random irrelevant interesting question, no need to act: Can this overflow over time…? If someone keeps player open for a LONG TIME?

Comment thread frontend/src/store.ts Outdated
}

return {
playbackInstance: isResume ? state.playbackInstance : state.playbackInstance + 1,

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's inline the isResume, easier to read the flow of the code:

Suggested change
playbackInstance: isResume ? state.playbackInstance : state.playbackInstance + 1,
// Increase playback count when we are playing new jams.
playbackCount: state.state === 'paused' ? state.playbackCount : state.playbackCount + 1,

Comment thread auth.go Outdated
Comment on lines +18 to +22
Username string `json:"username"`
Password string `json:"password"`
LastFMUsername string `json:"lastfm_username,omitempty"`
LastFMSession string `json:"lastfm_session,omitempty"`
LastFMToken string `json:"lastfm_token,omitempty"`

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Username string `json:"username"`
Password string `json:"password"`
LastFMUsername string `json:"lastfm_username,omitempty"`
LastFMSession string `json:"lastfm_session,omitempty"`
LastFMToken string `json:"lastfm_token,omitempty"`
Username string `json:"username"`
Password string `json:"password"`
LastFMUsername string `json:"lastfm_username,omitempty"`
LastFMSession string `json:"lastfm_session,omitempty"`
LastFMToken string `json:"lastfm_token,omitempty"`

Comment thread README.md
Comment thread frontend/src/components/LastFMScrobbler.tsx
}),
}).catch((error: unknown) => {
console.error(`Could not scrobble ${song.artist} — ${song.title}`, error);
if (error instanceof ApiError && error.status === 409) void mutate('/api/lastfm');

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are we doing here and why? Add comment, and also add { }

Comment thread frontend/src/components/LastFMScrobbler.tsx

export const LastFMScrobbler = () => {
const { data: lastFM } = useLastFM();
const scrobbledInstances = useRef(new Map<string, number>());

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's simplify this, we won't need multi-user in-memory support – we can easily reload the page on logout (and we should, for memory-security, but let's fix that separately).

Suggested change
const scrobbledInstances = useRef(new Map<string, number>());
const scrobbleCounter = useRef<number>();

Comment thread frontend/src/components/LastFMScrobbler.tsx Outdated
const [changingPassword, setChangingPassword] = useState(false);
const { data: lastFM } = useLastFM();
const [busy, setBusy] = useState(false);
const [error, setError] = useState('');

@Darep Darep Aug 30, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename:

Suggested change
const [error, setError] = useState('');
const [lastfmError, setLastfmError] = useState('');

Comment thread lastfm.go
Comment thread api.go
http.Error(w, "Invalid password", http.StatusBadRequest)
return
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undo this removal of a newline.

Comment thread frontend/src/store.ts Outdated
@Darep

Darep commented Aug 30, 2026

Copy link
Copy Markdown
Owner Author

Squashed to master manually, closing.

@Darep Darep closed this Aug 30, 2026
@Darep
Darep deleted the fix/per-user-lastfm branch August 30, 2026 12:02
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.

2 participants