youtube_explode/lib/src/extensions/helpers_extension.dart

191 lines
4.7 KiB
Dart
Raw Normal View History

2020-06-03 23:02:21 +02:00
library _youtube_explode.extensions;
import 'dart:convert';
import 'package:collection/collection.dart';
2020-04-18 23:22:13 +02:00
import '../reverse_engineering/cipher/cipher_operations.dart';
2020-02-20 19:50:10 +01:00
/// Utility for Strings.
extension StringUtility on String {
2020-06-03 13:18:37 +02:00
/// Returns null if this string is whitespace.
2021-03-04 12:20:00 +01:00
String? get nullIfWhitespace => trim().isEmpty ? null : this;
2020-02-20 19:50:10 +01:00
2020-06-03 13:18:37 +02:00
/// Returns null if this string is a whitespace.
String substringUntil(String separator) => substring(0, indexOf(separator));
///
2021-03-18 22:22:55 +01:00
String substringAfter(String separator) =>
substring(indexOf(separator) + separator.length);
2020-06-03 13:18:37 +02:00
2020-02-20 19:50:10 +01:00
static final _exp = RegExp(r'\D');
/// Strips out all non digit characters.
2020-06-03 13:18:37 +02:00
String stripNonDigits() => replaceAll(_exp, '');
2020-10-27 14:44:11 +01:00
/// Extract and decode json from a string
Map<String, dynamic>? extractJson([String separator = '']) {
final index = indexOf(separator) + separator.length;
if (index > length) {
return null;
}
2020-10-27 14:44:11 +01:00
final str = substring(index);
2020-10-27 14:44:11 +01:00
final startIdx = str.indexOf('{');
var endIdx = str.lastIndexOf('}');
2020-10-27 14:44:11 +01:00
while (true) {
try {
2021-03-18 22:22:55 +01:00
return json.decode(str.substring(startIdx, endIdx + 1))
as Map<String, dynamic>;
} on FormatException {
endIdx = str.lastIndexOf(str.substring(0, endIdx));
if (endIdx == 0) {
return null;
}
2020-10-27 14:44:11 +01:00
}
}
}
2021-03-11 14:20:10 +01:00
DateTime parseDateTime() => DateTime.parse(this);
2020-02-20 19:50:10 +01:00
}
2021-03-04 12:20:00 +01:00
/// Utility for Strings.
extension StringUtility2 on String? {
/// Parses this value as int stripping the non digit characters,
/// returns null if this fails.
int? parseInt() => int.tryParse(this?.stripNonDigits() ?? '');
/// Returns true if the string is null or empty.
bool get isNullOrWhiteSpace {
if (this == null) {
return true;
}
if (this!.trim().isEmpty) {
return true;
}
return false;
}
}
2020-02-20 19:50:10 +01:00
/// List decipher utility.
2020-06-03 13:18:37 +02:00
extension ListDecipher on Iterable<CipherOperation> {
/// Apply every CipherOperation on the [signature]
2020-02-20 19:50:10 +01:00
String decipher(String signature) {
2021-03-11 14:20:10 +01:00
for (final operation in this) {
2020-02-20 19:50:10 +01:00
signature = operation.decipher(signature);
}
return signature;
}
}
/// List Utility.
2021-03-04 10:46:37 +01:00
extension ListUtil<E> on Iterable<E> {
/// Same as [elementAt] but if the index is higher than the length returns
/// null
2021-03-04 12:20:00 +01:00
E? elementAtSafe(int index) {
2021-03-04 10:46:37 +01:00
if (index >= length) {
return null;
}
return elementAt(index);
}
2020-02-20 19:50:10 +01:00
}
2020-06-03 13:18:37 +02:00
/// Uri utility
extension UriUtility on Uri {
/// Returns a new Uri with the new query parameters set.
Uri setQueryParam(String key, String value) {
var query = Map<String, String>.from(queryParameters);
query[key] = value;
return replace(queryParameters: query);
}
}
2020-06-05 16:17:08 +02:00
///
extension GetOrNull<K, V> on Map<K, V> {
2020-06-05 20:08:04 +02:00
/// Get a value from a map
2021-03-04 12:20:00 +01:00
V? getValue(K key) {
2020-06-05 16:17:08 +02:00
var v = this[key];
if (v == null) {
return null;
}
return v;
}
}
///
extension GetOrNullMap on Map {
2020-06-05 20:08:04 +02:00
/// Get a map inside a map
2021-03-04 12:20:00 +01:00
Map<String, dynamic>? get(String key) {
2020-06-05 16:17:08 +02:00
var v = this[key];
if (v == null) {
return null;
}
return v;
}
2021-03-04 10:46:37 +01:00
/// Get a value inside a map.
/// If it is null this returns null, if of another type this throws.
2021-03-04 12:20:00 +01:00
T? getT<T>(String key) {
2021-03-04 10:46:37 +01:00
var v = this[key];
if (v == null) {
return null;
}
if (v is! T) {
throw Exception('Invalid type: ${v.runtimeType} should be $T');
}
return v;
}
/// Get a List<Map<String, dynamic>>> from a map.
2021-03-04 12:20:00 +01:00
List<Map<String, dynamic>>? getList(String key) {
2021-03-04 10:46:37 +01:00
var v = this[key];
if (v == null) {
return null;
}
if (v is! List<dynamic>) {
throw Exception('Invalid type: ${v.runtimeType} should be of type List');
}
2021-03-04 12:20:00 +01:00
return (v.toList()).cast<Map<String, dynamic>>();
2021-03-04 10:46:37 +01:00
}
2020-06-05 16:17:08 +02:00
}
2020-11-01 15:05:19 +01:00
///
extension UriUtils on Uri {
///
Uri replaceQueryParameters(Map<String, String> parameters) {
var query = Map<String, String>.from(queryParameters);
query.addAll(parameters);
return replace(queryParameters: query);
}
}
2021-03-04 10:46:37 +01:00
2021-03-04 12:20:00 +01:00
/// Parse properties with `text` method.
2021-03-04 10:46:37 +01:00
extension RunsParser on List<dynamic> {
2021-03-04 12:20:00 +01:00
///
2021-03-11 14:20:10 +01:00
String parseRuns() => map((e) => e['text']).join();
2021-03-04 10:46:37 +01:00
}
extension GenericExtract on List<String> {
/// Used to extract initial data that start with `var ytInitialData = ` or 'window["ytInitialData"] ='.
2021-03-18 22:22:55 +01:00
T extractGenericData<T>(
T Function(Map<String, dynamic>) builder, Exception Function() orThrow) {
var initialData =
firstWhereOrNull((e) => e.contains('var ytInitialData = '))
?.extractJson('var ytInitialData = ');
initialData ??=
firstWhereOrNull((e) => e.contains('window["ytInitialData"] ='))
?.extractJson('window["ytInitialData"] =');
if (initialData != null) {
return builder(initialData);
}
throw orThrow();
}
}