/* the banner ahead of the page. A hero picked on this phone is answered from the override with no network at all, exactly as the Rust does — and the field really is snake_case there (no rename_all on it) */ if (cmd === "catalog_artist_hero_seed") { const id = Number(args?.artistId); if (heroes[id]) return Promise.resolve({ banner: heroes[id], banner_custom: true }); const a = id === CAT_ARTIST.id ? CAT_ARTIST : id === CAT_SLOW.id ? CAT_SLOW : RELATED.find((r) => r.id === id); if (!a) return Promise.resolve(null); return new Promise((r) => setTimeout(() => r({ banner: svgArt(210, a.name[0]), banner_custom: false }), 200)); } /* the one-round content stage: the raw first page of releases, before the exhaustive pass classifies them. It goes through checkedArtistPayload, so `artist.id` must equal the argument or the wrapper throws */ if (cmd === "catalog_artist_overview") { const id = Number(args?.artistId); const a = id === CAT_ARTIST.id ? CAT_ARTIST : id === CAT_SLOW.id ? CAT_SLOW : RELATED.find((r) => r.id === id); if (!a) return Promise.reject(new Error("catalog_artist_overview: unknown artist")); const albums = id === CAT_SLOW.id ? SLOW_ALBUMS.slice(0, 4) : id === CAT_ARTIST.id ? CAT_DISCO.slice(0, 4) : []; return new Promise((r) => setTimeout(() => r({ artist: a, popular_tracks: [], albums }), 300)); }