Code reformatting & refactoring.
Throw exception on error code 403.
This commit is contained in:
parent
9a063bdb51
commit
d36aa68486
|
@ -65,4 +65,8 @@
|
|||
|
||||
- Workaround (#15): Now when a video is not available a `VideoUnavailable` exception is thrown
|
||||
- Removed disable_polymer parameter when requests ( https://github.com/Tyrrrz/YoutubeExplode/issues/341 )
|
||||
- Removed `dart:io` dependency
|
||||
- Removed `dart:io` dependency
|
||||
|
||||
## 0.0.16
|
||||
|
||||
- When a video is not available(403) a `VideoStreamUnavailableException`
|
|
@ -119,4 +119,4 @@ More features are provided through extensions.
|
|||
[MediaStreamsInfoSet]: https://pub.dev/documentation/youtube_explode_dart/latest/youtube_explode/MediaStreamInfoSet-class.html
|
||||
[VidExample]: https://github.com/Hexer10/youtube_explode_dart/blob/master/example/video_download.dart
|
||||
[API]: https://pub.dev/documentation/youtube_explode_dart/latest/youtube_explode/youtube_explode-library.html
|
||||
[Examples][https://github.com/Hexer10/youtube_explode_dart/tree/master/example]
|
||||
[Examples]: [https://github.com/Hexer10/youtube_explode_dart/tree/master/example]
|
|
@ -2,5 +2,6 @@ library youtube_explode.exceptions;
|
|||
|
||||
export 'unrecognized_structure_exception.dart';
|
||||
export 'video_requires_purchase_exception.dart';
|
||||
export 'video_stream_unavailable_exception.dart';
|
||||
export 'video_unavailable_exception.dart';
|
||||
export 'video_unplayable_exception.dart';
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
|
||||
/// Thrown when a video stream is not available
|
||||
/// and returns a status code not equal to 200 OK.
|
||||
class VideoStreamUnavailableException implements Exception {
|
||||
|
||||
/// The returned status code.
|
||||
final int statusCode;
|
||||
|
||||
/// Url
|
||||
final Uri url;
|
||||
|
||||
/// Initializes an instance of [VideoStreamUnavailableException]
|
||||
VideoStreamUnavailableException(this.statusCode, this.url);
|
||||
|
||||
@override
|
||||
String toString() => 'VideoStreamUnavailableException: '
|
||||
'The video stream in not availble (status code: $statusCode).\n'
|
||||
'Url: $url';
|
||||
}
|
|
@ -22,11 +22,11 @@ extension ChannelExtension on YoutubeExplode {
|
|||
channelId, 'channelId', 'Invalid YouTube channel id');
|
||||
}
|
||||
|
||||
var channelPageHtml = await getChannelPage(channelId);
|
||||
var channelTitle = channelPageHtml
|
||||
var channelPage = await getChannelPage(channelId);
|
||||
var channelTitle = channelPage
|
||||
.querySelector('meta[property="og:title"]')
|
||||
.attributes['content'];
|
||||
var channelImage = channelPageHtml
|
||||
var channelImage = channelPage
|
||||
.querySelector('meta[property="og:image"]')
|
||||
.attributes['content'];
|
||||
|
||||
|
@ -34,18 +34,20 @@ extension ChannelExtension on YoutubeExplode {
|
|||
}
|
||||
|
||||
/// Get a channel id from a username.
|
||||
/// Might not work properly.
|
||||
/// Returns null if the username is not found.
|
||||
Future<String> getChannelId(String username) async {
|
||||
if (!validateUsername(username)) {
|
||||
throw ArgumentError.value(
|
||||
username, 'username', 'Invalid YouTube username');
|
||||
}
|
||||
|
||||
var userPageHtml = await _getUserPageHtml(username);
|
||||
var userPage = await _getUserPage(username);
|
||||
if (userPage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var channelUrl = userPageHtml
|
||||
.querySelector('meta[property="og:url"]')
|
||||
.attributes['content'];
|
||||
var channelUrl =
|
||||
userPage.querySelector('meta[property="og:url"]').attributes['content'];
|
||||
|
||||
return channelUrl.replaceFirst('/channel/', '');
|
||||
}
|
||||
|
@ -85,11 +87,14 @@ extension ChannelExtension on YoutubeExplode {
|
|||
return html.parse(raw);
|
||||
}
|
||||
|
||||
Future<Document> _getUserPageHtml(String username) async {
|
||||
Future<Document> _getUserPage(String username) async {
|
||||
var url = 'https://www.youtube.com/user/$username?hl=en';
|
||||
var raw = (await client.get(url)).body;
|
||||
var req = await client.get(url);
|
||||
if (req.statusCode != 200) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return html.parse(raw);
|
||||
return html.parse(req);
|
||||
}
|
||||
|
||||
/// Returns true if [username] is a valid Youtube username.
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../exceptions/exceptions.dart';
|
||||
import '../models/models.dart';
|
||||
|
||||
/// Download extension for [MediaStreamInfo]
|
||||
|
@ -12,6 +13,11 @@ extension DownloadExtension on MediaStreamInfo {
|
|||
/// The download is split in multiple requests using the `range` parameter.
|
||||
///
|
||||
Stream<List<int>> downloadStream() async* {
|
||||
var req = await http.head(url);
|
||||
if (req.statusCode != 200) {
|
||||
throw VideoStreamUnavailableException(req.statusCode, url);
|
||||
}
|
||||
|
||||
var maxSize = _rateBypassExp.hasMatch(url.toString()) ? 9898989 : size + 1;
|
||||
var total = 0;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ extension StringUtility on String {
|
|||
|
||||
/// List decipher utility.
|
||||
extension ListDecipher on List<CipherOperation> {
|
||||
/// Apply the every CipherOperation on the [signature]
|
||||
/// Apply every CipherOperation on the [signature]
|
||||
String decipher(String signature) {
|
||||
for (var operation in this) {
|
||||
signature = operation.decipher(signature);
|
||||
|
|
|
@ -203,8 +203,7 @@ class YoutubeExplode {
|
|||
}
|
||||
|
||||
Future<PlayerConfiguration> _getPlayerConfigEmbed(String videoId) async {
|
||||
var req = await client.get(
|
||||
'https://www.youtube.com/embed/$videoId?&hl=en');
|
||||
var req = await client.get('https://www.youtube.com/embed/$videoId?&hl=en');
|
||||
if (req.statusCode != 200) {
|
||||
return null;
|
||||
}
|
||||
|
@ -297,17 +296,17 @@ class YoutubeExplode {
|
|||
}
|
||||
|
||||
Future<PlayerConfiguration> _getPlayerConfigWatchPage(String videoId) async {
|
||||
var videoWatchPageHtml = await getVideoWatchPage(videoId);
|
||||
if (videoWatchPageHtml == null) {
|
||||
var videoWatchPage = await getVideoWatchPage(videoId);
|
||||
if (videoWatchPage == null) {
|
||||
return null;
|
||||
}
|
||||
var playerConfigScript = videoWatchPageHtml
|
||||
var playerConfigScript = videoWatchPage
|
||||
.querySelectorAll('script')
|
||||
.map((e) => e.text)
|
||||
.firstWhere((e) => e.contains('ytplayer.config ='));
|
||||
if (playerConfigScript == null) {
|
||||
var errorReason =
|
||||
videoWatchPageHtml.querySelector('#unavailable-message').text.trim();
|
||||
videoWatchPage.querySelector('#unavailable-message').text.trim();
|
||||
throw VideoUnplayableException(videoId, errorReason);
|
||||
}
|
||||
|
||||
|
@ -458,8 +457,7 @@ class YoutubeExplode {
|
|||
|
||||
/// Returns the video watch page document.
|
||||
Future<Document> getVideoWatchPage(String videoId) async {
|
||||
var url =
|
||||
'https://youtube.com/watch?v=$videoId&bpctr=9999999999&hl=en';
|
||||
var url = 'https://youtube.com/watch?v=$videoId&bpctr=9999999999&hl=en';
|
||||
var req = await client.get(url);
|
||||
if (req.statusCode != 200) {
|
||||
return null;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: youtube_explode_dart
|
||||
description: A port in dart of the youtube explode library. Supports several API functions.
|
||||
version: 0.0.15
|
||||
version: 0.0.16
|
||||
homepage: https://github.com/Hexer10/youtube_explode_dart
|
||||
|
||||
environment:
|
||||
|
|
Loading…
Reference in New Issue