youtube_explode/lib/src/reverse_engineering/responses/playlist_response.dart

123 lines
2.9 KiB
Dart

import 'dart:convert';
import '../../channels/channel_id.dart';
import '../../common/common.dart';
import '../../exceptions/exceptions.dart';
import '../../extensions/helpers_extension.dart';
import '../../retry.dart';
import '../youtube_http_client.dart';
import 'generated/playlist_response.g.dart';
///
class PlaylistResponse {
List<_Video> _videos;
// Json parsed map
PlaylistResponseJson _root;
///
String get title => _root.title;
///
String get author => _root.author;
///
String get description => _root.description;
///
ThumbnailSet get thumbnails => ThumbnailSet(videos.firstOrNull.id);
///
int get viewCount => _root.views;
///
int get likeCount => _root.likes;
///
int get dislikeCount => _root.dislikes;
///
List<_Video> get videos =>
_videos ??= _root.video.map((e) => _Video(e)).toList();
///
PlaylistResponse.parse(String raw) {
final t = json.tryDecode(raw);
if (t == null) {
throw TransientFailureException('Playerlist response is broken.');
}
_root = PlaylistResponseJson.fromJson(t);
}
///
static Future<PlaylistResponse> get(YoutubeHttpClient httpClient, String id,
{int index = 0}) {
var url =
'https://youtube.com/list_ajax?style=json&action_get_list=1&list=$id&index=$index&hl=en';
return retry(() async {
var raw = await httpClient.getString(url);
return PlaylistResponse.parse(raw);
});
}
///
static Future<PlaylistResponse> searchResults(
YoutubeHttpClient httpClient, String query,
{int page = 0}) {
var url = 'https://youtube.com/search_ajax?style=json&search_query='
'${Uri.encodeQueryComponent(query)}&page=$page&hl=en';
return retry(() async {
var raw = await httpClient.getString(url,
validate: false,
headers: const {
'x-youtube-client-name': '56',
'x-youtube-client-version': '20200911'
});
return PlaylistResponse.parse(raw);
});
}
}
class _Video {
// Json parsed map
final Video root;
_Video(this.root);
String get id => root.encryptedId;
String get author => root.author;
ChannelId get channelId => ChannelId('UC${root.userId}');
DateTime get uploadDate =>
DateTime.fromMillisecondsSinceEpoch(root.timeCreated * 1000);
String get title => root.title;
String get description => root.description;
Duration get duration => Duration(seconds: root.lengthSeconds);
int get viewCount => int.parse(root.views.stripNonDigits());
int get likes => root.likes;
int get dislikes => root.dislikes;
Iterable<String> get keywords => RegExp(r'"[^\"]+"|\S+')
.allMatches(root.keywords)
.map((e) => e.group(0))
.toList(growable: false);
}
extension on JsonCodec {
dynamic tryDecode(String source) {
try {
return json.decode(source);
} on FormatException {
return null;
}
}
}