forked from Keelrleek/SoulStream
discography: drop guest appearances, but only where MusicBrainz can arbitrate
Deezer's /artist/{id}/albums returns records the artist merely contributed to,
alongside their own. Mid-Air Thief's page carried four Rooby Jeantal lo-fi EPs
that way -- his real discography is two albums.
This is not the namesake bug that was hardened in July. Every identity step here
is correct: MusicBrainz links the artist to Deezer 51082452, that is the id we
open, and the MB supplement injects both real albums. The leak is credit ROLE,
which is why an identity fix never touched it.
Deezer cannot answer it alone. Album details expose the primary artist, so a
guest spot is visible -- but every contributor is marked role "Main", so Kanye
West on "Watch the Throne" (primary artist JAY-Z) is byte-for-byte the same
shape as a guest EP. A "not primary, therefore drop" rule deletes a real album.
MusicBrainz separates them, because it credits a genuine collaboration under
BOTH artists: Kanye's own MBID returns "Watch the Throne", Mid-Air Thief's
returns only his two albums. So the backend only FLAGS (`appears_on`, set from
the details pass where the release's primary artist is finally visible) and the
frontend drops a flagged row at the identity merge only when MB answered for
this artist and does not credit the row. No MB albums means no arbiter and
every row is kept -- thin-coverage artists never silently lose real releases.
EPs now enter the album-details pass, which is what made this invisible: the
pass was album-only, and all four guest releases are typed "ep". They already
sort ahead of singles for the details cap.
Replay recipe bumped to v2: pages cached before this are stamped
identity_merged and would skip the pass that drops the rows.
Verified live -- Mid-Air Thief 6 albums -> 2 (무너지기/Crumbling, 공중도덕);
Kanye West keeps "Watch The Throne (Deluxe)", flagged appears_on but MB-credited,
with all 58 rows intact.
This commit is contained in:
1 parent
9cd03a6ecc
commit
e536e96180
2 files changed
+72
-3
No files matched your search
+32
-3
@@ -1015,7 +1015,11 @@ export function invalidateCatalogArtist(artistId) {
|
||||
// `art_preview: true` (the full page still lands) and set `replayed: true`
|
||||
// (the overview stage must not overwrite final classified albums with its
|
||||
// raw first-50).
|
||||
const PAGE_REPLAY_RECIPE = "replay-v1";
|
||||
// v2: pages saved before guest appearances were filtered are stamped
|
||||
// `identity_merged`, so they would skip the pass that drops them and keep
|
||||
// rendering another artist's records. Cheap to discard — the replay only buys
|
||||
// an instant first paint, and a miss is one ordinary load.
|
||||
const PAGE_REPLAY_RECIPE = "replay-v2";
|
||||
const PAGE_REPLAY_LIMIT = 16;
|
||||
// Matches the backend's provider disk-cache TTL on purpose: a replay must
|
||||
// never outlive the MusicBrainz warmth it was saved with, or the identity
|
||||
@@ -1483,13 +1487,38 @@ async function applyArtistIdentity(artistId, active) {
|
||||
// to displayed releases by title and re-files any the provider
|
||||
// mislabeled "album" (compilations, soundtracks…).
|
||||
const typeHints = identity?.type_hints ?? [];
|
||||
// Guest appearances, dropped only where MusicBrainz can arbitrate.
|
||||
//
|
||||
// Deezer's /artist/{id}/albums returns records the artist merely
|
||||
// contributed to — four Rooby Jeantal lo-fi releases sat in Mid-Air
|
||||
// Thief's discography that way. The backend flags them (`appears_on`:
|
||||
// the release's primary artist is someone else), but that flag ALONE
|
||||
// must never delete a row: Deezer marks every contributor "Main", so a
|
||||
// guest spot looks exactly like a genuine joint album — Kanye West's
|
||||
// "Watch the Throne" carries primary artist JAY-Z and would be wrongly
|
||||
// erased from his page.
|
||||
//
|
||||
// MusicBrainz separates them, because it credits a real collaboration
|
||||
// under BOTH artists: querying Kanye's own MBID returns "Watch the
|
||||
// Throne", while Mid-Air Thief's returns only his two real albums. So a
|
||||
// flagged row survives if MB credits it and is dropped if MB does not
|
||||
// — and ONLY when MB actually answered for this artist. No MB albums
|
||||
// means no arbiter, and every row is kept rather than guessed at, which
|
||||
// keeps thin-coverage artists (the obscure end, where this matters
|
||||
// most) from losing real releases.
|
||||
const mbTitles = new Set(identityAlbums.map((a) => normText(a.title)));
|
||||
const ownAlbums = identityAlbums.length
|
||||
? (current.albums ?? []).filter(
|
||||
(a) => !a?.appears_on || mbTitles.has(normText(a.title)),
|
||||
)
|
||||
: (current.albums ?? []);
|
||||
const merged = {
|
||||
...current,
|
||||
identity_merged: true,
|
||||
albums: extra.length
|
||||
? [...current.albums, ...extra].sort((a, b) =>
|
||||
? [...ownAlbums, ...extra].sort((a, b) =>
|
||||
(b.release_date ?? "").localeCompare(a.release_date ?? ""))
|
||||
: current.albums,
|
||||
: ownAlbums,
|
||||
socials: socials.length ? socials : current.socials,
|
||||
typeHints: typeHints.length ? typeHints : current.typeHints,
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user