parent
f15a8b3c23
commit
7e01cfbb4c
|
@ -18,3 +18,8 @@
|
|||
## 0.0.5
|
||||
|
||||
- Implement Search Api (`SearchExtension`)
|
||||
|
||||
## 0.0.6
|
||||
|
||||
- Implement Caption Api ('CaptionExtension`)
|
||||
- Add Custom Exceptions
|
|
@ -1,6 +1,8 @@
|
|||
library youtube_explode.cipher;
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../exceptions/exceptions.dart';
|
||||
import '../extensions/helpers_extension.dart';
|
||||
import 'cipher_operations.dart';
|
||||
|
||||
|
@ -27,7 +29,9 @@ Future<List<CipherOperation>> getCipherOperations(
|
|||
var deciphererFuncName = _deciphererFuncNameExp.firstMatch(raw)?.group(1);
|
||||
|
||||
if (deciphererFuncName.isNullOrWhiteSpace) {
|
||||
throw Exception('Could not find decipherer name.');
|
||||
throw UnrecognizedStructureException(
|
||||
'Could not find decipherer name. Please report this issue on GitHub.',
|
||||
raw);
|
||||
}
|
||||
|
||||
var exp = RegExp(r'(?!h\.)'
|
||||
|
@ -35,7 +39,9 @@ Future<List<CipherOperation>> getCipherOperations(
|
|||
r'=function\(\w+\)\{(.*?)\}');
|
||||
var decipherFuncBody = exp.firstMatch(raw)?.group(1);
|
||||
if (decipherFuncBody.isNullOrWhiteSpace) {
|
||||
throw Exception('Could not find decipherer body.');
|
||||
throw UnrecognizedStructureException(
|
||||
'Could not find decipherer body. Please report this issue on GitHub.',
|
||||
raw);
|
||||
}
|
||||
|
||||
var deciphererFuncBodyStatements = decipherFuncBody.split(';');
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
export 'unrecognized_structure_exception.dart';
|
||||
export 'video_requires_purchase_exception.dart';
|
||||
export 'video_unavailable_exception.dart';
|
||||
export 'video_unplayable_exception.dart';
|
|
@ -0,0 +1,18 @@
|
|||
/// Thrown when YoutubeExplode fails to extract required information.
|
||||
/// This usually happens when YouTube makes changes that break YoutubeExplode.
|
||||
class UnrecognizedStructureException implements FormatException {
|
||||
///A message describing the format error.
|
||||
@override
|
||||
final String message;
|
||||
|
||||
/// The actual source input which caused the error.
|
||||
@override
|
||||
final String source;
|
||||
|
||||
/// Initializes an instance of [UnrecognizedStructureException]
|
||||
const UnrecognizedStructureException([this.message, this.source]);
|
||||
|
||||
/// Unimplemented
|
||||
@override
|
||||
int get offset => throw UnsupportedError('Offset not supported');
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/// Thrown when a video is not playable because it requires purchase.
|
||||
class VideoRequiresPurchaseException implements Exception {
|
||||
/// ID of the preview video.
|
||||
final String previewVideoId;
|
||||
|
||||
/// Initializes an instance of [VideoRequiresPurchaseException]
|
||||
const VideoRequiresPurchaseException(this.previewVideoId);
|
||||
|
||||
@override
|
||||
String toString() => 'VideoRequiresPurchaseException: The video '
|
||||
'$previewVideoId requires a purchase';
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/// Thrown when a video is not available and cannot be processed.
|
||||
/// This can happen because the video does not exist, is deleted,
|
||||
/// is private, or due to other reasons.
|
||||
class VideoUnavailableException implements Exception {
|
||||
/// ID of the video.
|
||||
final String videoId;
|
||||
|
||||
/// Initializes an instance of [VideoUnavailableException]
|
||||
const VideoUnavailableException(this.videoId);
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'VideoUnavailableException: Video $videoId is unavailable.';
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/// Thrown when a video is not playable and its streams cannot be resolved.
|
||||
/// This can happen because the video requires purchase,
|
||||
/// is blocked in your country, is controversial, or due to other reasons.
|
||||
class VideoUnplayableException {
|
||||
/// ID of the video.
|
||||
final String videoId;
|
||||
|
||||
/// Initializes an instance of [VideoUnplayableException]
|
||||
const VideoUnplayableException(this.videoId);
|
||||
|
||||
String toString() =>
|
||||
'VideoUnplayableException: Video $videoId couldn\'t be played';
|
||||
}
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:xml/xml.dart' as xml;
|
||||
|
||||
import '../exceptions/exceptions.dart';
|
||||
import '../models/models.dart';
|
||||
import '../youtube_explode_base.dart';
|
||||
import 'helpers_extension.dart';
|
||||
|
@ -22,7 +23,7 @@ extension CaptionExtension on YoutubeExplode {
|
|||
var playAbility = playerResponseJson['playabilityStatus'];
|
||||
|
||||
if (playAbility['status'].toLowerCase() == 'error') {
|
||||
throw Exception('Video [$videoId] is unavailable');
|
||||
throw VideoUnavailableException(videoId);
|
||||
}
|
||||
|
||||
var trackInfos = <ClosedCaptionTrackInfo>[];
|
||||
|
@ -41,7 +42,8 @@ extension CaptionExtension on YoutubeExplode {
|
|||
|
||||
var isAutoGenerated = trackJson['vssId'].toLowerCase().startsWith('a.');
|
||||
|
||||
trackInfos.add(ClosedCaptionTrackInfo(url, language, isAutoGenerated));
|
||||
trackInfos.add(ClosedCaptionTrackInfo(url, language,
|
||||
isAutoGenerated: isAutoGenerated));
|
||||
}
|
||||
return trackInfos;
|
||||
}
|
||||
|
|
|
@ -2,16 +2,15 @@ import 'models.dart';
|
|||
|
||||
/// Metadata associated with a certain [ClosedCaptionTrack]
|
||||
class ClosedCaptionTrackInfo {
|
||||
|
||||
/// Manifest URL of the associated track.
|
||||
final Uri url;
|
||||
|
||||
/// Language of the associated track.
|
||||
/// Language of the associated track.
|
||||
final Language language;
|
||||
|
||||
/// Whether the associated track was automatically generated.
|
||||
/// Whether the associated track was automatically generated.
|
||||
final bool isAutoGenerated;
|
||||
|
||||
/// Initializes an instance of [ClosedCaptionTrackInfo]
|
||||
const ClosedCaptionTrackInfo(this.url, this.language, this.isAutoGenerated);
|
||||
/// Initializes an instance of [ClosedCaptionTrackInfo]
|
||||
const ClosedCaptionTrackInfo(this.url, this.language, {this.isAutoGenerated});
|
||||
}
|
|
@ -6,6 +6,7 @@ import 'package:http/http.dart' as http;
|
|||
import 'package:http_parser/http_parser.dart' show MediaType;
|
||||
|
||||
import 'cipher/cipher.dart';
|
||||
import 'exceptions/exceptions.dart';
|
||||
import 'extensions/extensions.dart';
|
||||
import 'models/models.dart';
|
||||
import 'parser.dart' as parser;
|
||||
|
@ -212,7 +213,7 @@ class YoutubeExplode {
|
|||
var playAbility = playerResponseJson['playabilityStatus'];
|
||||
|
||||
if (playAbility['status'].toString().toLowerCase() == 'error') {
|
||||
throw Exception('Video [$videoId] is unavailable');
|
||||
throw VideoUnavailableException(videoId);
|
||||
}
|
||||
|
||||
var errorReason = playAbility['reason'] as String;
|
||||
|
@ -288,7 +289,7 @@ class YoutubeExplode {
|
|||
?.toLowerCase() as String;
|
||||
|
||||
if (status.isNullOrWhiteSpace || status == 'error') {
|
||||
throw Exception('Video [$videoId] is unavailable');
|
||||
throw VideoUnavailableException(videoId);
|
||||
}
|
||||
|
||||
var details = playerResponseJson['videoDetails'];
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
library youtube_explode;
|
||||
|
||||
export 'src/exceptions/exceptions.dart';
|
||||
export 'src/extensions/extensions.dart'
|
||||
hide StringUtility, ListDecipher, ListFirst; // Hide helper extensions.
|
||||
export 'src/models/models.dart';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: youtube_explode_dart
|
||||
description: A port in dart of the youtube explode library. Support serveral API functions.
|
||||
version: 0.0.5
|
||||
version: 0.0.6
|
||||
homepage: https://github.com/Hexer10/youtube_explode_dart
|
||||
|
||||
environment:
|
||||
|
|
Loading…
Reference in New Issue