getAlbum method

Future<JsonMap> getAlbum(
  1. String browseId, {
  2. JsonMap? requestData,
})

Get information and tracks of an album.

Returns Map with album and track metadata.

The result is in the following format:

{
  "title": "Revival",
  "type": "Album",
  "thumbnails": [...],
  "description": "Revival is the...",
  "artists": [
    {
      "name": "Eminem",
      "id": "UCedvOgsKFzcK3hA5taf3KoQ"
    }
  ],
  "year": "2017",
  "trackCount": 19,
  "duration": "1 hour, 17 minutes",
  "audioPlaylistId": "OLAK5uy_nMr9h2VlS-2PULNz3M3XVXQj_P3C2bqaY",
  "tracks": [
    {
      "videoId": "iKLU7z_xdYQ",
      "title": "Walk On Water (feat. Beyoncé)",
      "artists": [
        {
          "name": "Eminem",
          "id": "UCedvOgsKFzcK3hA5taf3KoQ"
        }
      ],
      "album": "Revival",
      "likeStatus": "INDIFFERENT",
      "thumbnails": null,
      "isAvailable": true,
      "isExplicit": true,
      "duration": "5:03",
      "duration_seconds": 303,
      "trackNumber": 0,
      "feedbackTokens": {
        "add": "AB9zfpK...",
        "remove": "AB9zfpK..."
      }
    }
  ],
  "other_versions": [
    {
      "title": "Revival",
      "year": "Eminem",
      "browseId": "MPREb_fefKFOTEZSp",
      "thumbnails": [...],
      "isExplicit": false
    }
  ],
  "duration_seconds": 4657
}

Implementation

Future<JsonMap> getAlbum(String browseId, {JsonMap? requestData}) async {
  if (browseId.isEmpty || !browseId.startsWith('MPRE')) {
    throw Exception('Invalid album browseId provided, must start with MPRE.');
  }
  final body = <String, dynamic>{'browseId': browseId};
  const endpoint = 'browse';
  final response = requestData ?? await sendRequest(endpoint, body);

  final album = parseAlbumHeader2024(response);

  final results = JsonMap.from(
    nav(response, [
          ...TWO_COLUMN_RENDERER,
          'secondaryContents',
          ...SECTION_LIST_ITEM,
          ...MUSIC_SHELF,
        ])
        as Map,
  );
  album['tracks'] = parsePlaylistItems(
    List<JsonMap>.from(results['contents'] as List),
    isAlbum: true,
  );

  final secondaryCarousels =
      nav(response, [
            ...TWO_COLUMN_RENDERER,
            'secondaryContents',
            ...SECTION_LIST,
          ], nullIfAbsent: true)
          as List? ??
      [];
  for (final section in secondaryCarousels.skip(1)) {
    final carousel = nav(section, CAROUSEL) as JsonMap;
    final key =
        {
          'COLLECTION_STYLE_ITEM_SIZE_SMALL': 'related_recommendations',
          'COLLECTION_STYLE_ITEM_SIZE_MEDIUM': 'other_versions',
        }[carousel['itemSize']]!;
    album[key] = await parseContentList(
      List<JsonMap>.from(carousel['contents'] as List),
      parseAlbum,
    );
  }

  album['duration_seconds'] = sumTotalDuration(album);
  for (var i = 0; i < (album['tracks'] as List).length; i++) {
    (album['tracks'] as List<JsonMap>)[i]['album'] = album['title'];
    (album['tracks'] as List<JsonMap>)[i]['artists'] =
        ((album['tracks'] as List<JsonMap>)[i]['artists'] != null &&
                ((album['tracks'] as List<JsonMap>)[i]['artists'] as List)
                    .isNotEmpty)
            ? (album['tracks'] as List<JsonMap>)[i]['artists']
            : album['artists'];
  }
  return album;
}