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 ## 1.9.9
- Fix issue #134 (Error when getting the hls manifest from a livestream) - 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. /// URL of the channel's logo image.
final String logoUrl; final String logoUrl;
/// The (approximate) channel subscriber's count.
final int? subscribersCount;
/// Initializes an instance of [Channel] /// Initializes an instance of [Channel]
Channel(this.id, this.title, this.logoUrl); Channel(this.id, this.title, this.logoUrl, this.subscribersCount);
@override @override
String toString() => 'Channel ($title)'; String toString() => 'Channel ($title)';

View File

@ -30,7 +30,8 @@ class ChannelClient {
id = ChannelId.fromString(id); id = ChannelId.fromString(id);
var channelPage = await ChannelPage.get(_httpClient, id.value); 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. /// Gets the metadata associated with the channel of the specified user.
@ -42,7 +43,7 @@ class ChannelClient {
var channelPage = var channelPage =
await ChannelPage.getByUsername(_httpClient, username.value); await ChannelPage.getByUsername(_httpClient, username.value);
return Channel(ChannelId(channelPage.channelId), channelPage.channelTitle, return Channel(ChannelId(channelPage.channelId), channelPage.channelTitle,
channelPage.channelLogoUrl); channelPage.channelLogoUrl, channelPage.subscribersCount);
} }
/// Gets the info found on a YouTube Channel About page. /// 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'] ?? _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); 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 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. 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 homepage: https://github.com/Hexer10/youtube_explode_dart

View File

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