Version 1.9.10

Closes #139
This commit is contained in:
Mattia 2021-07-14 22:36:25 +02:00
parent 9d50d205ec
commit 7cb41f8018
6 changed files with 75 additions and 4 deletions

View File

@ -1,3 +1,6 @@
## 1.9.10
- Close #139: Implement Channel.subscribersCount.
## 1.9.9
- Fix issue #134 (Error when getting the hls manifest from a livestream)

View File

@ -16,8 +16,11 @@ class Channel with EquatableMixin {
/// URL of the channel's logo image.
final String logoUrl;
/// The (approximate) channel subscriber's count.
final int? subscribersCount;
/// Initializes an instance of [Channel]
Channel(this.id, this.title, this.logoUrl);
Channel(this.id, this.title, this.logoUrl, this.subscribersCount);
@override
String toString() => 'Channel ($title)';

View File

@ -30,7 +30,8 @@ class ChannelClient {
id = ChannelId.fromString(id);
var channelPage = await ChannelPage.get(_httpClient, id.value);
return Channel(id, channelPage.channelTitle, channelPage.channelLogoUrl);
return Channel(id, channelPage.channelTitle, channelPage.channelLogoUrl,
channelPage.subscribersCount);
}
/// Gets the metadata associated with the channel of the specified user.
@ -42,7 +43,7 @@ class ChannelClient {
var channelPage =
await ChannelPage.getByUsername(_httpClient, username.value);
return Channel(ChannelId(channelPage.channelId), channelPage.channelTitle,
channelPage.channelLogoUrl);
channelPage.channelLogoUrl, channelPage.subscribersCount);
}
/// Gets the info found on a YouTube Channel About page.

View File

@ -31,6 +31,22 @@ class ChannelPage {
_root.querySelector('meta[property="og:image"]')?.attributes['content'] ??
'';
int? get subscribersCount => initialData.subscribersCount;
///
late final _InitialData initialData = _getInitialData();
_InitialData _getInitialData() {
final scriptText = _root
.querySelectorAll('script')
.map((e) => e.text)
.toList(growable: false);
return scriptText.extractGenericData(
(obj) => _InitialData(obj),
() => TransientFailureException(
'Failed to retrieve initial data from the channel about page, please report this to the project GitHub page.'));
}
///
ChannelPage(this._root);
@ -68,3 +84,50 @@ class ChannelPage {
});
}
}
class _InitialData {
static final RegExp _subCountExp = RegExp(r'(\d+(?:\.\d+)?)(K|M|\s)');
// Json parsed map
final Map<String, dynamic> root;
_InitialData(this.root);
int? get subscribersCount {
final renderer = root.get('header')?.get('c4TabbedHeaderRenderer');
if (renderer?['subscriberCountText'] == null) {
return null;
}
final subText =
renderer?.get('subscriberCountText')?.getT<String>('simpleText');
if (subText == null) {
return null;
}
final match = _subCountExp.firstMatch(subText);
if (match == null) {
return null;
}
if (match.groupCount != 2) {
return null;
}
final count = double.tryParse(match.group(1) ?? '');
if (count == null) {
return null;
}
final multiplierText = match.group(2);
if (multiplierText == null) {
return null;
}
var multiplier = 1;
if (multiplierText == 'K') {
multiplier = 1000;
} else if (multiplierText == 'M') {
multiplier = 1000000;
}
return (count * multiplier).toInt();
}
}

View File

@ -1,6 +1,6 @@
name: youtube_explode_dart
description: A port in dart of the youtube explode library. Supports several API functions without the need of Youtube API Key.
version: 1.9.9
version: 1.9.10
homepage: https://github.com/Hexer10/youtube_explode_dart

View File

@ -18,6 +18,7 @@ void main() {
expect(channel.title, 'Tyrrrz');
expect(channel.logoUrl, isNotEmpty);
expect(channel.logoUrl, isNot(equalsIgnoringWhitespace('')));
expect(channel.subscribersCount, greaterThanOrEqualTo(190));
});
group('Get metadata of any channel', () {