commit
5a94b500d2
|
@ -1,3 +1,6 @@
|
|||
## 1.9.1
|
||||
- Bug fixes (due to youtube changes)
|
||||
|
||||
## 1.9.0
|
||||
- Support nnbd (dart 1.12)
|
||||
- New api: `getQuerySuggestions`: Returns the suggestions youtube provides while making a video search.
|
||||
|
|
|
@ -2,6 +2,8 @@ library _youtube_explode.retry;
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'exceptions/exceptions.dart';
|
||||
|
||||
/// Run the [function] each time an exception is thrown until the retryCount
|
||||
|
@ -28,7 +30,8 @@ Future<T> retry<T>(FutureOr<T> Function() function) async {
|
|||
int getExceptionCost(Exception e) {
|
||||
if (e is TransientFailureException ||
|
||||
e is FormatException ||
|
||||
e is SearchItemSectionException) {
|
||||
e is SearchItemSectionException ||
|
||||
e is ClientException) {
|
||||
return 1;
|
||||
}
|
||||
if (e is RequestLimitExceededException) {
|
||||
|
|
|
@ -12,18 +12,19 @@ class EmbedPage {
|
|||
static final _playerConfigExp =
|
||||
RegExp('[\'""]PLAYER_CONFIG[\'""]\\s*:\\s*(\\{.*\\})');
|
||||
static final _playerConfigExp2 = RegExp(r'yt.setConfig\((\{.*\})');
|
||||
static final _playerConfigExp3 = RegExp(r'ytcfg.set\((\{.*\})');
|
||||
|
||||
final Document root;
|
||||
late final EmbedPlayerConfig? playerConfig = getPlayerConfig();
|
||||
|
||||
///
|
||||
String? get sourceUrl {
|
||||
var url = root
|
||||
.querySelectorAll('*[name="player_ias/base"]')
|
||||
final url = root
|
||||
.querySelectorAll('script')
|
||||
.map((e) => e.attributes['src'])
|
||||
.where((e) => !e.isNullOrWhiteSpace)
|
||||
.firstWhere((e) => e!.contains('player_ias') && e.endsWith('.js'),
|
||||
orElse: () => null);
|
||||
.whereNotNull()
|
||||
.firstWhereOrNull((e) => e.contains('player_ias') && e.endsWith('.js'));
|
||||
|
||||
// _root.querySelector('*[name="player_ias/base"]').attributes['src'];
|
||||
if (url == null) {
|
||||
return null;
|
||||
|
@ -34,7 +35,8 @@ class EmbedPage {
|
|||
///
|
||||
EmbedPlayerConfig? getPlayerConfig() {
|
||||
var playerConfigJson =
|
||||
(_playerConfigJson ?? _playerConfigJson2)?.extractJson();
|
||||
(_playerConfigJson3 ?? _playerConfigJson2 ?? _playerConfigJson)
|
||||
?.extractJson();
|
||||
if (playerConfigJson == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -53,6 +55,12 @@ class EmbedPage {
|
|||
.map((e) => _playerConfigExp2.firstMatch(e)?.group(1))
|
||||
.firstWhereOrNull((e) => !e.isNullOrWhiteSpace);
|
||||
|
||||
String? get _playerConfigJson3 => root
|
||||
.getElementsByTagName('script')
|
||||
.map((e) => e.text)
|
||||
.map((e) => _playerConfigExp3.firstMatch(e)?.group(1))
|
||||
.firstWhereOrNull((e) => !e.isNullOrWhiteSpace);
|
||||
|
||||
///
|
||||
EmbedPage(this.root);
|
||||
|
||||
|
@ -62,6 +70,7 @@ class EmbedPage {
|
|||
///
|
||||
static Future<EmbedPage> get(YoutubeHttpClient httpClient, String videoId) {
|
||||
var url = 'https://youtube.com/embed/$videoId?hl=en';
|
||||
// final url = 'http://localhost:8080/embed/$videoId?hl=en';
|
||||
return retry(() async {
|
||||
var raw = await httpClient.getString(url);
|
||||
return EmbedPage.parse(raw);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:youtube_explode_dart/src/retry.dart';
|
||||
|
||||
import '../exceptions/exceptions.dart';
|
||||
import '../videos/streams/streams.dart';
|
||||
|
@ -12,15 +13,16 @@ class YoutubeHttpClient extends http.BaseClient {
|
|||
final Map<String, String> _defaultHeaders = const {
|
||||
'user-agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
|
||||
'accept-language': 'en-US,en;q=1.0',
|
||||
'x-youtube-client-name': '1',
|
||||
'x-youtube-client-version': '2.20200609.04.02',
|
||||
'x-spf-previous': 'https://www.youtube.com/',
|
||||
'x-spf-referer': 'https://www.youtube.com/',
|
||||
'x-youtube-device':
|
||||
'cbr=Chrome&cbrver=81.0.4044.138&ceng=WebKit&cengver=537.36'
|
||||
'&cos=Windows&cosver=10.0',
|
||||
'x-youtube-page-label': 'youtube.ytfe.desktop_20200617_1_RC1'
|
||||
'cookie': 'CONSENT=YES+cb',
|
||||
'accept':
|
||||
'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
|
||||
'accept-language': 'accept-language: en-US,en;q=0.9',
|
||||
'sec-fetch-dest': 'document',
|
||||
'sec-fetch-mode': 'navigate',
|
||||
'sec-fetch-site': 'none',
|
||||
'sec-fetch-user': '?1',
|
||||
'sec-gpc': '1',
|
||||
'upgrade-insecure-requests': '1'
|
||||
};
|
||||
|
||||
/// Initialize an instance of [YoutubeHttpClient]
|
||||
|
@ -99,7 +101,7 @@ class YoutubeHttpClient extends http.BaseClient {
|
|||
try {
|
||||
final request = http.Request('get', url);
|
||||
request.headers['range'] = 'bytes=$i-${i + 9898989 - 1}';
|
||||
final response = await send(request);
|
||||
final response = await retry(() => send(request));
|
||||
if (validate) {
|
||||
_validateResponse(response, response.statusCode);
|
||||
}
|
||||
|
|
|
@ -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.9.0
|
||||
version: 1.9.1
|
||||
|
||||
homepage: https://github.com/Hexer10/youtube_explode_dart
|
||||
|
||||
|
|
|
@ -14,7 +14,8 @@ void main() {
|
|||
group('Get streams manifest of any video', () {
|
||||
for (final val in {
|
||||
VideoId('9bZkp7q19f0'), // very popular
|
||||
// VideoId('SkRSXFQerZs'), // age restricted (embed allowed) - This is unplayable
|
||||
VideoId(
|
||||
'SkRSXFQerZs'), // age restricted (embed allowed) - This is unplayable
|
||||
VideoId('hySoCSoH-g8'), // age restricted (embed not allowed)
|
||||
VideoId('_kmeFXjjGfk'), // embed not allowed (type 1)
|
||||
VideoId('MeJVWBSsPAY'), // embed not allowed (type 2)
|
||||
|
|
Loading…
Reference in New Issue