import 'package:collection/collection.dart'; import 'package:html/parser.dart' as parser; import '../../../youtube_explode_dart.dart'; import '../../extensions/helpers_extension.dart'; import '../../retry.dart'; import '../models/initial_data.dart'; import '../models/youtube_page.dart'; import '../youtube_http_client.dart'; /// class PlaylistPage extends YoutubePage<_InitialData> { /// final String playlistId; late final List<_Video> videos = initialData.playlistVideos; late final String? title = initialData.title; late final String? description = initialData.description; late final String? author = initialData.author; late final int? viewCount = initialData.viewCount; late final int? videoCount = initialData.videoCount; /// InitialData PlaylistPage.id(this.playlistId, _InitialData initialData) : super(null, null, initialData); /// Future nextPage(YoutubeHttpClient httpClient) async { if (initialData.continuationToken?.isEmpty == null) { return null; } final data = await httpClient.sendPost('browse', initialData.continuationToken!); return PlaylistPage.id(playlistId, _InitialData(data)); } /// static Future get( YoutubeHttpClient httpClient, String id, ) async { var url = 'http://127.0.0.1:8080/www.youtube.com:443/playlist?list=$id&hl=en&persist_hl=1'; return retry(httpClient, () async { var raw = await httpClient.getString(url); return PlaylistPage.parse(raw, id); }); } /// PlaylistPage.parse(String raw, this.playlistId) : super(parser.parse(raw), (root) => _InitialData(root)); } class _InitialData extends InitialData { _InitialData(JsonMap root) : super(root); late final String? title = root .get('metadata') ?.get('playlistMetadataRenderer') ?.getT('title'); late final String? author = root .get('sidebar') ?.get('playlistSidebarRenderer') ?.getList('items') ?.elementAtSafe(1) ?.get('playlistSidebarSecondaryInfoRenderer') ?.get('videoOwner') ?.get('videoOwnerRenderer') ?.get('title') ?.getT>('runs') ?.cast>() .parseRuns(); late final String? description = root .get('metadata') ?.get('playlistMetadataRenderer') ?.getT('description'); late final int? viewCount = root .get('sidebar') ?.get('playlistSidebarRenderer') ?.getList('items') ?.firstOrNull ?.get('playlistSidebarPrimaryInfoRenderer') ?.getList('stats') ?.elementAtSafe(1) ?.getT('simpleText') ?.parseInt(); // sidebar.playlistSidebarRenderer.items[0].playlistSidebarPrimaryInfoRenderer.stats late final int? videoCount = root .get('sidebar') ?.get('playlistSidebarRenderer') ?.getList('items') ?.firstOrNull ?.get('playlistSidebarPrimaryInfoRenderer') ?.getList('stats') ?.elementAtSafe(0) ?.getList('runs') ?.firstOrNull ?.getT('text') ?.parseInt(); late final String? continuationToken = (videosContent ?? playlistVideosContent) ?.firstWhereOrNull((e) => e['continuationItemRenderer'] != null) ?.get('continuationItemRenderer') ?.get('continuationEndpoint') ?.get('continuationCommand') ?.getT('token'); List? get playlistVideosContent => root .get('contents') ?.get('twoColumnBrowseResultsRenderer') ?.getList('tabs') ?.firstOrNull ?.get('tabRenderer') ?.get('content') ?.get('sectionListRenderer') ?.getList('contents') ?.firstOrNull ?.get('itemSectionRenderer') ?.getList('contents') ?.firstOrNull ?.get('playlistVideoListRenderer') ?.getList('contents') ?? root .getList('onResponseReceivedActions') ?.firstOrNull ?.get('appendContinuationItemsAction') ?.getList('continuationItems'); late final List? videosContent = root .get('contents') ?.get('twoColumnSearchResultsRenderer') ?.get('primaryContents') ?.get('sectionListRenderer') ?.getList('contents') ?? root .getList('onResponseReceivedCommands') ?.firstOrNull ?.get('appendContinuationItemsAction') ?.getList('continuationItems'); List<_Video> get playlistVideos => playlistVideosContent ?.where((e) => e['playlistVideoRenderer'] != null) .map((e) => _Video(e['playlistVideoRenderer'])) .toList() ?? const []; /* List<_Video> get videos => videosContent?.firstOrNull ?.get('itemSectionRenderer') ?.getList('contents') ?.where((e) => e['videoRenderer'] != null) .map((e) => _Video(e)) .toList() ?? const [];*/ } class _Video { // Json parsed map final JsonMap root; _Video(this.root); String get id => root.getT('videoId')!; String get author => root .get('ownerText') ?.getT>('runs') ?.cast>() .parseRuns() ?? root .get('shortBylineText') ?.getT>('runs') ?.cast>() .parseRuns() ?? ''; String get channelId => root .get('ownerText') ?.getList('runs') ?.firstOrNull ?.get('navigationEndpoint') ?.get('browseEndpoint') ?.getT('browseId') ?? root .get('shortBylineText') ?.getList('runs') ?.firstOrNull ?.get('navigationEndpoint') ?.get('browseEndpoint') ?.getT('browseId') ?? ''; String get title => root.get('title')?.getList('runs')?.parseRuns() ?? ''; String get description => root.getList('descriptionSnippet')?.parseRuns() ?? ''; Duration? get duration => root.get('lengthText')?.getT('simpleText')?.toDuration(); int get viewCount => root.get('viewCountText')?.getT('simpleText')?.parseInt() ?? 0; }