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

118 lines
2.8 KiB
Dart
Raw Normal View History

2020-05-31 23:36:23 +02:00
import 'dart:convert';
2020-06-30 01:00:37 +02:00
import '../../channels/channel_id.dart';
import '../../common/common.dart';
2020-06-03 23:02:21 +02:00
import '../../exceptions/exceptions.dart';
2020-06-05 16:17:08 +02:00
import '../../extensions/helpers_extension.dart';
2020-06-03 23:02:21 +02:00
import '../../retry.dart';
import '../youtube_http_client.dart';
2020-05-31 23:36:23 +02:00
2020-07-16 20:02:54 +02:00
///
2020-05-31 23:36:23 +02:00
class PlaylistResponse {
2020-06-30 15:00:00 +02:00
Iterable<_Video> _videos;
2020-05-31 23:36:23 +02:00
// Json parsed map
final Map<String, dynamic> _root;
2020-07-16 20:02:54 +02:00
///
2020-05-31 23:36:23 +02:00
String get title => _root['title'];
2020-07-16 20:02:54 +02:00
///
2020-05-31 23:36:23 +02:00
String get author => _root['author'];
2020-07-16 20:02:54 +02:00
///
2020-05-31 23:36:23 +02:00
String get description => _root['description'];
2020-07-16 20:02:54 +02:00
///
2020-06-30 15:00:00 +02:00
ThumbnailSet get thumbnails => ThumbnailSet(videos.firstOrNull.id);
2020-07-16 20:02:54 +02:00
///
2020-06-05 16:17:08 +02:00
int get viewCount => _root['views'];
2020-05-31 23:36:23 +02:00
2020-07-16 20:02:54 +02:00
///
2020-06-05 16:17:08 +02:00
int get likeCount => _root['likes'];
2020-05-31 23:36:23 +02:00
2020-07-16 20:02:54 +02:00
///
2020-06-05 16:17:08 +02:00
int get dislikeCount => _root['dislikes'];
2020-05-31 23:36:23 +02:00
2020-07-16 20:02:54 +02:00
///
2020-06-30 15:00:00 +02:00
Iterable<_Video> get videos => _videos ??=
2020-06-05 16:17:08 +02:00
_root['video']?.map((e) => _Video(e))?.cast<_Video>() ?? const <_Video>[];
2020-05-31 23:36:23 +02:00
2020-07-16 20:02:54 +02:00
///
2020-06-22 17:40:57 +02:00
PlaylistResponse(this._root);
2020-07-16 20:02:54 +02:00
///
2020-05-31 23:36:23 +02:00
PlaylistResponse.parse(String raw) : _root = json.tryDecode(raw) {
if (_root == null) {
throw TransientFailureException('Playerlist response is broken.');
}
}
2020-07-16 20:02:54 +02:00
///
2020-05-31 23:36:23 +02:00
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);
});
}
2020-07-16 20:02:54 +02:00
///
2020-05-31 23:36:23 +02:00
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);
return PlaylistResponse.parse(raw);
});
}
}
2020-06-03 23:02:21 +02:00
class _Video {
2020-05-31 23:36:23 +02:00
// Json parsed map
final Map<String, dynamic> _root;
2020-06-03 23:02:21 +02:00
_Video(this._root);
2020-05-31 23:36:23 +02:00
String get id => _root['encrypted_id'];
String get author => _root['author'];
2020-06-30 01:02:58 +02:00
ChannelId get channelId => ChannelId('UC${_root['user_id']}');
2020-06-30 01:00:37 +02:00
2020-05-31 23:36:23 +02:00
DateTime get uploadDate =>
DateTime.fromMillisecondsSinceEpoch(_root['time_created'] * 1000);
String get title => _root['title'];
String get description => _root['description'];
Duration get duration => Duration(seconds: _root['length_seconds']);
2020-06-05 16:17:08 +02:00
int get viewCount => int.parse((_root['views'] as String).stripNonDigits());
2020-05-31 23:36:23 +02:00
2020-06-05 16:17:08 +02:00
int get likes => _root['likes'];
2020-05-31 23:36:23 +02:00
2020-06-05 16:17:08 +02:00
int get dislikes => _root['dislikes'];
2020-05-31 23:36:23 +02:00
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;
}
}
}