diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 873e2f7..0439702 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -1,6 +1,9 @@ name: Dart CI -on: [push] +on: + push: + schedule: + - cron: '0 0 * * * ' jobs: build: diff --git a/lib/src/reverse_engineering/responses/embed_page.dart b/lib/src/reverse_engineering/responses/embed_page.dart index 36989b6..24a597d 100644 --- a/lib/src/reverse_engineering/responses/embed_page.dart +++ b/lib/src/reverse_engineering/responses/embed_page.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:html/dom.dart'; import 'package:html/parser.dart' as parser; +import 'package:youtube_explode_dart/src/reverse_engineering/responses/player_config_base.dart'; import '../../extensions/helpers_extension.dart'; import '../../retry.dart'; @@ -14,7 +15,7 @@ class EmbedPage { static final _playerConfigExp2 = RegExp(r'yt.setConfig\((\{.*\})'); final Document _root; - _PlayerConfig _playerConfig; + EmbedPlayerConfig _playerConfig; /// String get sourceUrl { @@ -32,7 +33,7 @@ class EmbedPage { } /// - _PlayerConfig get playerConfig { + EmbedPlayerConfig get playerConfig { if (_playerConfig != null) { return _playerConfig; } @@ -41,7 +42,7 @@ class EmbedPage { return null; } return _playerConfig = - _PlayerConfig(json.decode(playerConfigJson.extractJson())); + EmbedPlayerConfig(json.decode(playerConfigJson.extractJson())); } String get _playerConfigJson => _root @@ -72,11 +73,14 @@ class EmbedPage { } } -class _PlayerConfig { - // Json parsed map. - final Map _root; +/// Used internally +class EmbedPlayerConfig implements PlayerConfigBase> { + @override + final Map root; - _PlayerConfig(this._root); + /// + EmbedPlayerConfig(this.root); - String get sourceUrl => 'https://youtube.com${_root['assets']['js']}'; + @override + String get sourceUrl => 'https://youtube.com${root['assets']['js']}'; } diff --git a/lib/src/reverse_engineering/responses/player_config_base.dart b/lib/src/reverse_engineering/responses/player_config_base.dart new file mode 100644 index 0000000..a91ac70 --- /dev/null +++ b/lib/src/reverse_engineering/responses/player_config_base.dart @@ -0,0 +1,12 @@ +/// Base class for PlayerConfig. +abstract class PlayerConfigBase { + + /// Root node. + final T root; + + /// + PlayerConfigBase(this.root); + + /// Player source url. + String get sourceUrl; +} \ No newline at end of file diff --git a/lib/src/reverse_engineering/responses/watch_page.dart b/lib/src/reverse_engineering/responses/watch_page.dart index a69196d..4f5bdf5 100644 --- a/lib/src/reverse_engineering/responses/watch_page.dart +++ b/lib/src/reverse_engineering/responses/watch_page.dart @@ -1,5 +1,6 @@ import 'package:html/dom.dart'; import 'package:html/parser.dart' as parser; +import 'package:youtube_explode_dart/src/reverse_engineering/responses/player_config_base.dart'; import '../../../youtube_explode_dart.dart'; import '../../extensions/helpers_extension.dart'; @@ -34,7 +35,7 @@ class WatchPage { _InitialData _initialData; String _xsfrToken; - _PlayerConfig _playerConfig; + WatchPlayerConfig _playerConfig; /// String get sourceUrl { @@ -125,7 +126,7 @@ class WatchPage { static final _playerConfigExp = RegExp(r'ytplayer\.config\s*=\s*(\{.*\})'); /// - _PlayerConfig get playerConfig => _playerConfig ??= _PlayerConfig( + WatchPlayerConfig get playerConfig => _playerConfig ??= WatchPlayerConfig( PlayerConfigJson.fromRawJson(_playerConfigExp .firstMatch(_root.getElementsByTagName('html').first.text) ?.group(1) @@ -172,14 +173,18 @@ class WatchPage { } } -class _PlayerConfig { - // Json parsed map +/// Used internally +class WatchPlayerConfig implements PlayerConfigBase { + @override final PlayerConfigJson root; - _PlayerConfig(this.root); + /// + WatchPlayerConfig(this.root); + @override String get sourceUrl => 'https://youtube.com${root.assets.js}'; + /// PlayerResponse get playerResponse => PlayerResponse.parse(root.args.playerResponse); } diff --git a/lib/src/videos/streams/streams_client.dart b/lib/src/videos/streams/streams_client.dart index 6aee3aa..31e08f2 100644 --- a/lib/src/videos/streams/streams_client.dart +++ b/lib/src/videos/streams/streams_client.dart @@ -79,7 +79,7 @@ class StreamsClient { Future _getStreamContextFromWatchPage(VideoId videoId) async { var watchPage = await WatchPage.get(_httpClient, videoId.toString()); - dynamic /* _PlayerConfig */ playerConfig; + WatchPlayerConfig playerConfig; try { playerConfig = watchPage.playerConfig; } on FormatException { @@ -92,13 +92,13 @@ class StreamsClient { } var previewVideoId = playerResponse.previewVideoId; - if (!((previewVideoId as String)?.isNullOrWhiteSpace ?? true)) { + if (!(previewVideoId.isNullOrWhiteSpace ?? true)) { throw VideoRequiresPurchaseException.preview( videoId, VideoId(previewVideoId)); } var playerSourceUrl = - watchPage.sourceUrl ?? playerConfig?.sourceUrl as String; + watchPage.sourceUrl ?? playerConfig?.sourceUrl; var playerSource = !playerSourceUrl.isNullOrWhiteSpace ? await PlayerSource.get(_httpClient, playerSourceUrl) : null; diff --git a/pubspec.yaml b/pubspec.yaml index abf89db..f229f52 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: 1.7.5 +version: 1.7.6 homepage: https://github.com/Hexer10/youtube_explode_dart environment: diff --git a/test/streams_test.dart b/test/streams_test.dart index 4f85318..ba9c044 100644 --- a/test/streams_test.dart +++ b/test/streams_test.dart @@ -55,7 +55,7 @@ void main() { VideoId('5VGm0dczmHc'), // rating not allowed VideoId('ZGdLIwrGHG8'), // unlisted VideoId('rsAAeyAr-9Y'), // recording of a live stream - VideoId('AI7ULzgf8RU'), // has DASH manifest + VideoId('AI7ULzgf8RU'), // has DASH manifest TODO: Test timesout VideoId('-xNN-bJQ4vI'), // 360° video }) { test('VideoId - ${val.value}', () async {