parsePlaylistItem function

JsonMap? parsePlaylistItem(
  1. JsonMap data, {
  2. bool isAlbum = false,
  3. bool isCollaborative = false,
})

Parses item from playlist.

Implementation

JsonMap? parsePlaylistItem(
  JsonMap data, {
  bool isAlbum = false,
  bool isCollaborative = false,
}) {
  String? videoId;
  String? setVideoId;
  String? creditsBrowseId;
  String? like;

  // If the item has a menu, find its setVideoId
  if (data.containsKey('menu')) {
    for (final item in List<JsonMap>.from(nav(data, MENU_ITEMS) as List)) {
      if (item.containsKey('menuServiceItemRenderer')) {
        final menuService = nav(item, MENU_SERVICE) as JsonMap;

        if (menuService.containsKey('playlistEditEndpoint')) {
          setVideoId =
              nav(menuService, [
                    'playlistEditEndpoint',
                    'actions',
                    0,
                    'setVideoId',
                  ], nullIfAbsent: true)
                  as String?;

          videoId =
              nav(menuService, [
                    'playlistEditEndpoint',
                    'actions',
                    0,
                    'removedVideoId',
                  ], nullIfAbsent: true)
                  as String?;
        }
      } else if (item.containsKey(MNIR)) {
        final maybeCreditsBrowseId =
            nav(item, [MNIR, ...NAVIGATION_BROWSE_ID], nullIfAbsent: true)
                as String?;

        if (maybeCreditsBrowseId != null &&
            maybeCreditsBrowseId.startsWith('MPTC')) {
          creditsBrowseId = maybeCreditsBrowseId;
        }
      }
    }
  }

  final songMenuData = <String, dynamic>{
    'inLibrary': null,
    'pinnedToListenAgain': null,
    ...parseSongMenuData(data),
  };

  final playButton = nav(data, PLAY_BUTTON, nullIfAbsent: true) as JsonMap?;

  if (playButton != null && playButton.containsKey('playNavigationEndpoint')) {
    videoId =
        nav(data, [
              ...PLAY_BUTTON,
              'playNavigationEndpoint',
              'watchEndpoint',
              'videoId',
            ])
            as String;

    if (data.containsKey('menu')) {
      like = nav(data, MENU_LIKE_STATUS, nullIfAbsent: true) as String?;
    }
  }

  var isAvailable = true;

  if (data.containsKey('musicItemRendererDisplayPolicy')) {
    isAvailable =
        data['musicItemRendererDisplayPolicy'] !=
        'MUSIC_ITEM_RENDERER_DISPLAY_POLICY_GREY_OUT';
  }

  final usePresetColumns = (!isAvailable || isAlbum) ? true : null;

  int? titleIndex = usePresetColumns == true ? 0 : null;
  int? artistIndex = usePresetColumns == true ? 1 : null;
  int? durationIndex;
  int? albumIndex = isCollaborative ? 3 : (usePresetColumns == true ? 2 : null);

  final userChannelIndexes = <int>[];
  int? unrecognizedIndex;

  final flexColumns = data['flexColumns'] as List;

  for (var index = 0; index < flexColumns.length; index++) {
    final flexColumnItem = getFlexColumnItem(data, index);

    final navigationEndpoint =
        nav(flexColumnItem, [
              ...TEXT_RUN,
              'navigationEndpoint',
            ], nullIfAbsent: true)
            as JsonMap?;

    if (navigationEndpoint == null) {
      final run = nav(flexColumnItem, TEXT_RUN, nullIfAbsent: true) as JsonMap?;

      if (run != null && run.containsKey('text')) {
        final parsed = parseSongRun(run);

        if (parsed['type'] == 'duration') {
          durationIndex = index;
        } else {
          unrecognizedIndex ??= index;
        }
      }

      continue;
    }

    if (navigationEndpoint.containsKey('watchEndpoint')) {
      titleIndex = index;
    } else if (navigationEndpoint.containsKey('browseEndpoint')) {
      final pageType = nav(navigationEndpoint, [
        'browseEndpoint',
        'browseEndpointContextSupportedConfigs',
        'browseEndpointContextMusicConfig',
        'pageType',
      ]);

      if (pageType == 'MUSIC_PAGE_TYPE_ARTIST' ||
          pageType == 'MUSIC_PAGE_TYPE_UNKNOWN') {
        artistIndex = index;
      } else if (pageType == 'MUSIC_PAGE_TYPE_ALBUM' ||
          pageType == 'MUSIC_PAGE_TYPE_AUDIOBOOK') {
        albumIndex = index;
      } else if (pageType == 'MUSIC_PAGE_TYPE_USER_CHANNEL') {
        userChannelIndexes.add(index);
      } else if (pageType == 'MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE') {
        titleIndex = index;
      }
    }
  }

  artistIndex ??= unrecognizedIndex;

  if (artistIndex == null && userChannelIndexes.isNotEmpty) {
    artistIndex = userChannelIndexes.last;
  }

  final title = titleIndex != null ? getItemText(data, titleIndex) : null;

  if (title == 'Song deleted') {
    return null;
  }

  final artists =
      artistIndex != null ? parseSongArtists(data, artistIndex) : null;

  final album = albumIndex != null ? parseSongAlbum(data, albumIndex) : null;

  final views = isAlbum ? getItemText(data, 2) : null;

  String? duration =
      durationIndex != null ? getItemText(data, durationIndex) : null;

  if (data.containsKey('fixedColumns')) {
    final fixedColumn = getFixedColumnItem(data, 0);

    if (nav(fixedColumn, ['text', 'simpleText'], nullIfAbsent: true) != null) {
      duration = nav(fixedColumn, ['text', 'simpleText']) as String;
    } else {
      duration = nav(fixedColumn, TEXT_RUN_TEXT) as String;
    }
  }

  final thumbnails = nav(data, THUMBNAILS, nullIfAbsent: true);

  final isExplicit = nav(data, BADGE_LABEL, nullIfAbsent: true) != null;

  final videoType = nav(data, [
    ...MENU_ITEMS,
    0,
    MNIR,
    'navigationEndpoint',
    ...NAVIGATION_VIDEO_TYPE,
  ], nullIfAbsent: true);

  final votingStatus =
      nav(data, ENGAGEMENT_BAR, nullIfAbsent: true) as JsonMap?;

  final communityVoteStatus =
      votingStatus == null
          ? null
          : {
            'netVoteValue': votingStatus['votes'],
            'status': VoteStatus.fromValue(votingStatus['status'] as String),
          };

  final song = <String, dynamic>{
    'videoId': videoId,
    'title': title,
    'artists': artists,
    'album': album,
    'likeStatus': like,
    ...songMenuData,
    'thumbnails': thumbnails,
    'isAvailable': isAvailable,
    'isExplicit': isExplicit,
    'videoType': videoType,
    'views': views,
    'communityVoteStatus': communityVoteStatus,
  };

  if (isAlbum) {
    song['trackNumber'] =
        isAvailable
            ? int.parse(nav(data, ['index', 'runs', 0, 'text']) as String)
            : null;
  }

  if (duration != null && duration.isNotEmpty) {
    song['duration'] = duration;
    song['duration_seconds'] = parseDuration(duration);
  }

  if (setVideoId != null) {
    song['setVideoId'] = setVideoId;
  }

  if (creditsBrowseId != null) {
    song['creditsBrowseId'] = creditsBrowseId;
  }

  return song;
}