diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c1dacb..5e4d07f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.0 +- BREAKING CHANGE: + - In `getUploadsFromPage`: the `videoSorting` parameter is now a named parameter +- Shorts filter possibility added in `getUploadsFromPage`. + ## 2.0.4 - Fix issue when parsing dates formatted as "Streamed ago" due to a leading whitespace. #265 diff --git a/lib/src/channels/channel_client.dart b/lib/src/channels/channel_client.dart index fe78374..6737e24 100644 --- a/lib/src/channels/channel_client.dart +++ b/lib/src/channels/channel_client.dart @@ -1,3 +1,5 @@ +import 'video_type.dart'; + import '../common/common.dart'; import '../extensions/helpers_extension.dart'; import '../playlists/playlists.dart'; @@ -137,14 +139,16 @@ class ChannelClient { /// /// Use .nextPage() to fetch the next batch of videos. Future getUploadsFromPage( - dynamic channelId, [ + dynamic channelId, { VideoSorting videoSorting = VideoSorting.newest, - ]) async { + VideoType videoType = VideoType.normal, + }) async { channelId = ChannelId.fromString(channelId); final page = await ChannelUploadPage.get( _httpClient, (channelId as ChannelId).value, videoSorting.code, + videoType, ); final channel = await get(channelId); diff --git a/lib/src/channels/channels.dart b/lib/src/channels/channels.dart index c882cb2..aabeac6 100644 --- a/lib/src/channels/channels.dart +++ b/lib/src/channels/channels.dart @@ -13,3 +13,4 @@ export 'channel_uploads_list.dart'; export 'channel_video.dart'; export 'username.dart'; export 'video_sorting.dart'; +export 'video_type.dart'; diff --git a/lib/src/channels/video_type.dart b/lib/src/channels/video_type.dart new file mode 100644 index 0000000..fad7446 --- /dev/null +++ b/lib/src/channels/video_type.dart @@ -0,0 +1,14 @@ +/// The type of the video you want to get. +/// +/// Will filter only by the type you want. +enum VideoType { + /// Default horizontal video + normal('videos', 'videoRenderer'), + + /// Youtube shorts video + shorts('shorts', 'reelItemRenderer'); + + final String name; + final String youtubeRenderText; + const VideoType(this.name, this.youtubeRenderText); +} diff --git a/lib/src/extensions/helpers_extension.dart b/lib/src/extensions/helpers_extension.dart index 7986f5d..15f0139 100644 --- a/lib/src/extensions/helpers_extension.dart +++ b/lib/src/extensions/helpers_extension.dart @@ -172,7 +172,10 @@ extension StringUtility2 on String? { // Streamed x y ago parts = parts.skip(1).toList(); } - assert(parts.length == 3); + + if (parts.length != 3) { + return null; + } final qty = int.parse(parts.first); diff --git a/lib/src/reverse_engineering/pages/channel_upload_page.dart b/lib/src/reverse_engineering/pages/channel_upload_page.dart index 1963c82..3675eb1 100644 --- a/lib/src/reverse_engineering/pages/channel_upload_page.dart +++ b/lib/src/reverse_engineering/pages/channel_upload_page.dart @@ -1,5 +1,6 @@ import 'package:collection/collection.dart'; import 'package:html/parser.dart' as parser; +import '../../channels/video_type.dart'; import '../../channels/channel_video.dart'; import '../../exceptions/exceptions.dart'; @@ -15,10 +16,12 @@ class ChannelUploadPage extends YoutubePage<_InitialData> { /// final String channelId; + final VideoType type; + late final List uploads = initialData.uploads; /// InitialData - ChannelUploadPage.id(this.channelId, super.initialData) + ChannelUploadPage.id(this.channelId, this.type, super.initialData) : super.fromInitialData(); /// @@ -28,7 +31,7 @@ class ChannelUploadPage extends YoutubePage<_InitialData> { } final data = await httpClient.sendContinuation('browse', initialData.token); - return ChannelUploadPage.id(channelId, _InitialData(data)); + return ChannelUploadPage.id(channelId, type, _InitialData(data, type)); } /// @@ -36,22 +39,25 @@ class ChannelUploadPage extends YoutubePage<_InitialData> { YoutubeHttpClient httpClient, String channelId, String sorting, + VideoType type, ) { final url = - 'https://www.youtube.com/channel/$channelId/videos?view=0&sort=$sorting&flow=grid'; + 'https://www.youtube.com/channel/$channelId/${type.name}?view=0&sort=$sorting&flow=grid'; return retry(httpClient, () async { final raw = await httpClient.getString(url); - return ChannelUploadPage.parse(raw, channelId); + return ChannelUploadPage.parse(raw, channelId, type); }); } /// - ChannelUploadPage.parse(String raw, this.channelId) - : super(parser.parse(raw), (root) => _InitialData(root)); + ChannelUploadPage.parse(String raw, this.channelId, this.type) + : super(parser.parse(raw), (root) => _InitialData(root, type)); } class _InitialData extends InitialData { - _InitialData(super.root); + _InitialData(super.root, this.type); + + final VideoType type; late final JsonMap? continuationContext = getContinuationContext(); @@ -175,8 +181,10 @@ class _InitialData extends InitialData { if (content.containsKey('gridVideoRenderer')) { video = content.get('gridVideoRenderer'); } else if (content.containsKey('richItemRenderer')) { - video = - content.get('richItemRenderer')?.get('content')?.get('videoRenderer'); + video = content + .get('richItemRenderer') + ?.get('content') + ?.get(type.youtubeRenderText); } if (video == null) { diff --git a/pubspec.yaml b/pubspec.yaml index f2e5e71..f4b6881 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: youtube_explode_dart description: A port in dart of the youtube explode library. Supports several API functions without the need of Youtube API Key. -version: 2.0.4 +version: 2.1.0 homepage: https://github.com/Hexer10/youtube_explode_dart topics: