A track credited to more than one artist has exactly one navigable artist in this app and the rest are punctuation. `primaryArtist()` string-parses the credit, strips a " feat. " clause and discards the guest; it deliberately does not split on "&", "with" or "," because those live inside real artist names. Measured on a real 26,069-file library plus an 80+80 MusicBrainz sample: 13% of recordings are multi-artist upstream, while only 0.86% of files carry any structured multi-artist tag — mp3 carries zero files with multiple MUSICBRAINZ_ARTISTID across 19,840. Of 1,286 files saying "feat.", 90% have nothing structured behind it, and a sample of 80 such files was multi-artist in MB 80 times out of 80. CLAUDE.md justified plan 013's removal of the credit tables with "3 credits of 2,823 listed more than one artist". That measured our own *writer* — cachedLinkArtist was called once per credit, so a collaboration could never have been recorded. Dropping the join table was still right on cost; the evidence for "multi-artist is rare" was not. A credit is ordered parts and the credit string is derived from them, so join phrases are assembly instructions, not disassembly ones. Nothing here reconstructs a credit by searching a name inside a credit string: the stored text may come from tags while the parts come from the catalog, and those disagree for ~1 in 3 multi-artist credits. Where it comes from, after two dead ends: the canonical dump CI already streams has no join phrases and no as-credited names, and the JSON dumps cover 153,691 recordings of ~35M with *zero* overlap against a real library. So mbdump.tar.bz2 — 7.1 GB, ~13.7 min in pure-Go bzip2, whose members are alphabetical, which is what lets one pass resolve an entity's credit without buffering 35M recordings. - artist_credit_part / artist_credit_ref, multi-artist credits only: a single-artist credit is already explore_index's own artist_name. - Column layouts verified against the real 20260815 export; ErrDumpShape makes a wrong guess a failed build, not a wrong catalog. - The pass runs on every mode, not just a build. The job picks its mode from the index's own state, and a complete import means "refresh", which never enters the importer — so credits could otherwise only arrive via a rebuild that re-downloads ~205 GB. It reports whether it populated anything, which is what flips `changed` and republishes. - The importer asks whether an artifact carries the tables, on the writer where `core` is attached, so the artifact already published still imports. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AfVYUVExXsx1nSWrXN8mAh
465 lines
11 KiB
TypeScript
465 lines
11 KiB
TypeScript
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
|
// This file is automatically generated. DO NOT EDIT
|
|
|
|
/**
|
|
* AlbumCompleteFunc answers "is the local album with this id complete",
|
|
* i.e. do its files declare a track total the library actually has.
|
|
*/
|
|
export type AlbumCompleteFunc = any;
|
|
|
|
/**
|
|
* CreditPart is one credited artist within a credit, in credit order.
|
|
*
|
|
* CreditedName is the name *as credited*, which is not the artist's own
|
|
* name: MusicBrainz credits "Snoop Dogg" on a track by the artist
|
|
* called "Snoop Doggy Dogg". Display uses it; navigation uses
|
|
* ArtistMBID. JoinPhrase is the literal connector that follows this
|
|
* part, so a credit renders by concatenation and never by searching a
|
|
* name inside a credit string.
|
|
*/
|
|
export interface CreditPart {
|
|
"position": number;
|
|
"artistMbid": string;
|
|
"creditedName": string;
|
|
"joinPhrase": string;
|
|
}
|
|
|
|
/**
|
|
* IndexStatus is the full index build status, exposed to the frontend.
|
|
*/
|
|
export interface IndexStatus {
|
|
"building": boolean;
|
|
"ready": boolean;
|
|
|
|
/**
|
|
* RFC3339 timestamp of last complete build
|
|
*/
|
|
"lastBuilt"?: string;
|
|
"tiers": TierStatus[] | null;
|
|
"artists": number;
|
|
"recordings": number;
|
|
"releaseGroups": number;
|
|
"totalRows": number;
|
|
}
|
|
|
|
/**
|
|
* LBSimilarArtist represents a similar artist from the
|
|
* ListenBrainz labs API.
|
|
*/
|
|
export interface LBSimilarArtist {
|
|
"artistMbid": string;
|
|
"name": string;
|
|
"score": number;
|
|
}
|
|
|
|
/**
|
|
* LBTopRecording represents a popular recording from the
|
|
* ListenBrainz popularity API.
|
|
*
|
|
* JSON tags use camelCase for Wails→frontend serialization.
|
|
* The API response uses snake_case, so we unmarshal into
|
|
* lbTopRecordingWire first, then convert.
|
|
*/
|
|
export interface LBTopRecording {
|
|
"recordingMbid": string;
|
|
"artistName": string;
|
|
"trackName": string;
|
|
"totalListenCount": number;
|
|
"caaReleaseMbid": string;
|
|
|
|
/**
|
|
* ReleaseGroupMBID is resolved from CAAReleaseMBID so a top-track
|
|
* row can link to its album page with the track highlighted.
|
|
*/
|
|
"releaseGroupMbid"?: string;
|
|
"releaseName": string;
|
|
|
|
/**
|
|
* milliseconds (from LB API)
|
|
*/
|
|
"length": number;
|
|
"inLibrary": boolean;
|
|
"localId"?: number;
|
|
}
|
|
|
|
/**
|
|
* LBTopReleaseGroup represents a popular release group from the
|
|
* ListenBrainz popularity API.
|
|
*/
|
|
export interface LBTopReleaseGroup {
|
|
"releaseGroupMbid": string;
|
|
"title": string;
|
|
"artistName": string;
|
|
"type": string;
|
|
"date": string;
|
|
"totalListenCount": number;
|
|
"caaReleaseMbid": string;
|
|
"inLibrary": boolean;
|
|
"localId"?: number;
|
|
}
|
|
|
|
/**
|
|
* LyricsResult is a single lyric-search hit, mapped from the DB layer
|
|
* into the camelCase shape the frontend consumes.
|
|
*/
|
|
export interface LyricsResult {
|
|
"audioFileId": number;
|
|
"filePath": string;
|
|
"lengthMs": number;
|
|
"title": string;
|
|
"artist": string;
|
|
"album": string;
|
|
}
|
|
|
|
/**
|
|
* MBArtist is a Wails-friendly projection of a MusicBrainz artist.
|
|
*/
|
|
export interface MBArtist {
|
|
"mbid": string;
|
|
"name": string;
|
|
"sortName": string;
|
|
"englishName"?: string;
|
|
"type": string;
|
|
"country": string;
|
|
"disambiguation": string;
|
|
"score": number;
|
|
|
|
/**
|
|
* raw LB listen count (0 if unknown)
|
|
*/
|
|
"popularity": number;
|
|
"listenerCount": number;
|
|
|
|
/**
|
|
* true if the user owns music by this artist
|
|
*/
|
|
"inLibrary": boolean;
|
|
|
|
/**
|
|
* local artist row ID for navigation
|
|
*/
|
|
"localId"?: number;
|
|
}
|
|
|
|
/**
|
|
* MBRecording is a Wails-friendly projection of a MusicBrainz
|
|
* recording.
|
|
*/
|
|
export interface MBRecording {
|
|
"mbid": string;
|
|
"title": string;
|
|
"length": number;
|
|
"artistCredit": string;
|
|
|
|
/**
|
|
* for linking the artist to its detail page
|
|
*/
|
|
"artistMbid"?: string;
|
|
"score": number;
|
|
|
|
/**
|
|
* raw LB listen count (0 if unknown)
|
|
*/
|
|
"popularity": number;
|
|
"listenerCount": number;
|
|
|
|
/**
|
|
* parent release, for album navigation
|
|
*/
|
|
"caaReleaseMbid"?: string;
|
|
|
|
/**
|
|
* ReleaseGroupMBID is resolved from CAAReleaseMBID so a track can
|
|
* link to its album page with the track highlighted, matching how
|
|
* tracks behave everywhere else.
|
|
*/
|
|
"releaseGroupMbid"?: string;
|
|
|
|
/**
|
|
* album title
|
|
*/
|
|
"releaseName"?: string;
|
|
|
|
/**
|
|
* true if the user owns this recording
|
|
*/
|
|
"inLibrary": boolean;
|
|
|
|
/**
|
|
* local recording row ID
|
|
*/
|
|
"localId"?: number;
|
|
}
|
|
|
|
/**
|
|
* MBRelease is a Wails-friendly projection of a MusicBrainz release.
|
|
*/
|
|
export interface MBRelease {
|
|
"mbid": string;
|
|
"title": string;
|
|
"date": string;
|
|
"country": string;
|
|
"status": string;
|
|
"artistCredit"?: string;
|
|
"tracks"?: MBTrack[] | null;
|
|
|
|
/**
|
|
* ReleaseGroupMBID is the parent release group's MBID. Empty unless
|
|
* the lookup requested the "release-groups" include (LookupRelease
|
|
* does); used to resolve a release-level MBID (what many taggers
|
|
* write) back to the release-group MBID everything else on the
|
|
* album page is keyed by.
|
|
*/
|
|
"releaseGroupMbid"?: string;
|
|
}
|
|
|
|
/**
|
|
* MBReleaseGroup is a Wails-friendly projection of a MusicBrainz
|
|
* release group.
|
|
*/
|
|
export interface MBReleaseGroup {
|
|
"mbid": string;
|
|
"title": string;
|
|
"primaryType": string;
|
|
"secondaryTypes"?: string[] | null;
|
|
"firstReleaseDate": string;
|
|
"artistCredit": string;
|
|
|
|
/**
|
|
* for linking the artist to its detail page
|
|
*/
|
|
"artistMbid"?: string;
|
|
|
|
/**
|
|
* raw LB listen count (0 if unknown)
|
|
*/
|
|
"popularity": number;
|
|
"listenerCount": number;
|
|
|
|
/**
|
|
* true if the user owns this album
|
|
*/
|
|
"inLibrary": boolean;
|
|
|
|
/**
|
|
* local release_group row ID
|
|
*/
|
|
"localId"?: number;
|
|
|
|
/**
|
|
* TotalTracks is the catalog's track count for this release group,
|
|
* or 0 for "the catalog does not say". It answers "how much of
|
|
* this album do I have" for an album whose files declared no total
|
|
* -- the case GetAlbumCompleteness cannot answer -- and it is not
|
|
* filled by the MusicBrainz path below, which has the real
|
|
* tracklist and does not need a denominator.
|
|
*/
|
|
"totalTracks": number;
|
|
}
|
|
|
|
/**
|
|
* MBSearchResult aggregates the three searchable entity types
|
|
* returned by the MusicBrainz search API.
|
|
*/
|
|
export interface MBSearchResult {
|
|
"artists"?: MBArtist[] | null;
|
|
"releaseGroups"?: MBReleaseGroup[] | null;
|
|
"recordings"?: MBRecording[] | null;
|
|
"topResults"?: TopResult[] | null;
|
|
}
|
|
|
|
/**
|
|
* MBTrack is a Wails-friendly projection of a MusicBrainz track.
|
|
*/
|
|
export interface MBTrack {
|
|
"position": number;
|
|
"discNumber": number;
|
|
"title": string;
|
|
"length": number;
|
|
"mbid": string;
|
|
"inLibrary": boolean;
|
|
"localId"?: number;
|
|
}
|
|
|
|
/**
|
|
* Shelf is one horizontal row on the Explore page.
|
|
*
|
|
* A shelf carries albums or artists, never both: they route to
|
|
* different pages and render as different cards, and a row that is
|
|
* sometimes one and sometimes the other is two components pretending to
|
|
* be one.
|
|
*/
|
|
export interface Shelf {
|
|
"id": string;
|
|
"kind": ShelfKind;
|
|
|
|
/**
|
|
* Title is the row heading.
|
|
*/
|
|
"title": string;
|
|
|
|
/**
|
|
* Subtitle says why these are here. As on Home it is not
|
|
* decoration: without it a shelf is indistinguishable from a
|
|
* random grid.
|
|
*/
|
|
"subtitle": string;
|
|
"albums"?: MBReleaseGroup[] | null;
|
|
"artists"?: MBArtist[] | null;
|
|
}
|
|
|
|
/**
|
|
* ShelfKind identifies what a shelf is built from, so the frontend can
|
|
* pick an icon and a spec can assert on a shelf without matching
|
|
* display copy.
|
|
*/
|
|
export enum ShelfKind {
|
|
/**
|
|
* The Go zero value for the underlying type of the enum.
|
|
*/
|
|
$zero = "",
|
|
|
|
/**
|
|
* Shelf kinds.
|
|
*/
|
|
ShelfPopularAlbums = "popular-albums",
|
|
ShelfPopularArtists = "popular-artists",
|
|
ShelfMoreFromOwned = "more-from-owned",
|
|
};
|
|
|
|
/**
|
|
* ShelfPage is what Explore renders before a query.
|
|
*
|
|
* State exists because "no shelves" has three different causes here and
|
|
* the page must not present them identically — a blank panel is the bug
|
|
* this whole feature is fixing, and a blank panel that says nothing
|
|
* about why is the same bug with more code behind it.
|
|
*/
|
|
export interface ShelfPage {
|
|
"shelves": Shelf[] | null;
|
|
|
|
/**
|
|
* State is one of:
|
|
*
|
|
* "ready" — the catalog is here and the shelves are below.
|
|
* "building" — it is being fetched or built right now.
|
|
* "no-index" — there is no catalog. Search still works over
|
|
* whatever is in the index, which may be nothing;
|
|
* the page says so and points at Settings.
|
|
*/
|
|
"state": string;
|
|
}
|
|
|
|
/**
|
|
* ThumbnailRequest is a single item in a batch thumbnail request.
|
|
*/
|
|
export interface ThumbnailRequest {
|
|
"mbid": string;
|
|
"albumName": string;
|
|
"artistName": string;
|
|
}
|
|
|
|
/**
|
|
* TierStatus represents the state of a single index tier.
|
|
*/
|
|
export interface TierStatus {
|
|
"name": string;
|
|
|
|
/**
|
|
* "pending", "running", "complete", "error", "skipped"
|
|
*/
|
|
"state": string;
|
|
"total": number;
|
|
"completed": number;
|
|
"error"?: string;
|
|
|
|
/**
|
|
* Detail is a human-readable progress line for stages whose raw
|
|
* completed/total numbers say little on their own — the listens
|
|
* stream reports "42.3 / 205.1 GB · 18 MB/s · ~3h20m left" here.
|
|
*/
|
|
"detail"?: string;
|
|
}
|
|
|
|
/**
|
|
* TopResult represents a single top-result card shown above the
|
|
* categorized search lists. Computed by intent scoring after all
|
|
* reranking is complete.
|
|
*/
|
|
export interface TopResult {
|
|
/**
|
|
* "artist", "release_group", "recording"
|
|
*/
|
|
"entityType": string;
|
|
"mbid": string;
|
|
"name": string;
|
|
|
|
/**
|
|
* for tracks/albums
|
|
*/
|
|
"artistCredit"?: string;
|
|
|
|
/**
|
|
* for linking the artist subtitle
|
|
*/
|
|
"artistMbid"?: string;
|
|
"intentScore": number;
|
|
|
|
/**
|
|
* Artist-specific
|
|
* "Group", "Person"
|
|
*/
|
|
"artistType"?: string;
|
|
"country"?: string;
|
|
|
|
/**
|
|
* Album-specific
|
|
*/
|
|
"primaryType"?: string;
|
|
"year"?: string;
|
|
|
|
/**
|
|
* Track-specific. ReleaseGroupMBID is resolved (from CAAReleaseMBID)
|
|
* so a track click can open its album page with the track highlighted,
|
|
* matching how tracks behave everywhere else. ReleaseName is the album
|
|
* title used for the album page header.
|
|
*/
|
|
"length"?: number;
|
|
"caaReleaseMbid"?: string;
|
|
"releaseGroupMbid"?: string;
|
|
"releaseName"?: string;
|
|
|
|
/**
|
|
* Library status — populated from index cross-reference columns.
|
|
*/
|
|
"inLibrary": boolean;
|
|
}
|
|
|
|
/**
|
|
* TrackLyrics is the stored or freshly-fetched lyrics for one track.
|
|
* Source is "embedded" (from the file's tags / library DB), "lrclib"
|
|
* (fetched on demand), or "" when none are available.
|
|
*/
|
|
export interface TrackLyrics {
|
|
"plain": string;
|
|
"synced": string;
|
|
"instrumental": boolean;
|
|
"source": string;
|
|
}
|
|
|
|
/**
|
|
* TrackThumbnailRequest is a single item in a batch track thumbnail
|
|
* request. Either ReleaseMBID or ReleaseGroupMBID may be empty;
|
|
* the proxy tries whichever is present.
|
|
*/
|
|
export interface TrackThumbnailRequest {
|
|
/**
|
|
* stable key used in the returned map
|
|
*/
|
|
"key": string;
|
|
"releaseMbid": string;
|
|
"releaseGroupMbid": string;
|
|
"albumName": string;
|
|
"artistName": string;
|
|
}
|