Skip to content

Commit 8201b3b

Browse files
committed
[YouTube] Parse any playlist (including music mixes) in related items
1 parent 13f7900 commit 8201b3b

File tree

10 files changed

+61
-34
lines changed

10 files changed

+61
-34
lines changed
Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
import org.schabi.newpipe.extractor.exceptions.ParsingException;
1212
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
1313
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor;
14+
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
1415

1516
import javax.annotation.Nonnull;
1617

17-
public class YoutubeMixPlaylistInfoItemExtractor implements PlaylistInfoItemExtractor {
18+
public class YoutubeMixOrPlaylistInfoItemExtractor implements PlaylistInfoItemExtractor {
1819
private final JsonObject mixInfoItem;
1920

20-
public YoutubeMixPlaylistInfoItemExtractor(final JsonObject mixInfoItem) {
21+
public YoutubeMixOrPlaylistInfoItemExtractor(final JsonObject mixInfoItem) {
2122
this.mixInfoItem = mixInfoItem;
2223
}
2324

@@ -46,14 +47,25 @@ public String getThumbnailUrl() throws ParsingException {
4647

4748
@Override
4849
public String getUploaderName() throws ParsingException {
49-
// YouTube mixes are auto-generated by YouTube
50-
return "YouTube";
50+
// this will be "YouTube" for mixes
51+
return YoutubeParsingHelper.getTextFromObject(mixInfoItem.getObject("longBylineText"));
5152
}
5253

5354
@Override
5455
public long getStreamCount() throws ParsingException {
55-
// Auto-generated playlists always start with 25 videos and are endless
56-
return ListExtractor.ITEM_COUNT_INFINITE;
56+
final String countString = YoutubeParsingHelper.getTextFromObject(
57+
mixInfoItem.getObject("videoCountShortText"));
58+
if (countString == null) {
59+
throw new ParsingException("Could not extract item count for playlist/mix info item");
60+
}
61+
62+
try {
63+
return Integer.parseInt(countString);
64+
} catch (final NumberFormatException ignored) {
65+
// un-parsable integer: this is a mix with infinite items and "50+" as count string
66+
// (though youtube music mixes do not necessarily have an infinite count of songs)
67+
return ListExtractor.ITEM_COUNT_INFINITE;
68+
}
5769
}
5870

5971
@Nonnull

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,8 +641,11 @@ public MultiInfoItemsCollector getRelatedItems() throws ExtractionException {
641641
collector.commit(new YoutubeStreamInfoItemExtractor(
642642
result.getObject("compactVideoRenderer"), timeAgoParser));
643643
} else if (result.has("compactRadioRenderer")) {
644-
collector.commit(new YoutubeMixPlaylistInfoItemExtractor(
644+
collector.commit(new YoutubeMixOrPlaylistInfoItemExtractor(
645645
result.getObject("compactRadioRenderer")));
646+
} else if (result.has("compactPlaylistRenderer")) {
647+
collector.commit(new YoutubeMixOrPlaylistInfoItemExtractor(
648+
result.getObject("compactPlaylistRenderer")));
646649
}
647650
}
648651
return collector;

extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorRelatedMixTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,17 @@ public void testRelatedItems() throws Exception {
111111
assertContains("list=RD" + ID, streamMix.getUrl());
112112
assertEquals("Mix – " + TITLE, streamMix.getName());
113113
assertIsSecureUrl(streamMix.getThumbnailUrl());
114+
115+
final List<PlaylistInfoItem> musicMixes = playlists.stream()
116+
.filter(item -> item.getPlaylistType().equals(PlaylistType.MIX_MUSIC))
117+
.collect(Collectors.toList());
118+
assertEquals(1, musicMixes.size(), "Not found exactly one music mix in related items");
119+
120+
final PlaylistInfoItem musicMix = musicMixes.get(0);
121+
assertSame(InfoItem.InfoType.PLAYLIST, musicMix.getInfoType());
122+
assertEquals(YouTube.getServiceId(), musicMix.getServiceId());
123+
assertContains("list=RDCLAK", musicMix.getUrl());
124+
assertEquals("Hip Hop Essentials", musicMix.getName());
125+
assertIsSecureUrl(musicMix.getThumbnailUrl());
114126
}
115127
}

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/stream/relatedMix/generated_mock_0.json

Lines changed: 4 additions & 4 deletions
Large diffs are not rendered by default.

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/stream/relatedMix/generated_mock_1.json

Lines changed: 4 additions & 4 deletions
Large diffs are not rendered by default.

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/stream/relatedMix/generated_mock_2.json

Lines changed: 5 additions & 5 deletions
Large diffs are not rendered by default.

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/stream/relatedMix/generated_mock_3.json

Lines changed: 4 additions & 4 deletions
Large diffs are not rendered by default.

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/stream/relatedMix/generated_mock_4.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
"cross-origin"
3333
],
3434
"date": [
35-
"Mon, 28 Feb 2022 18:18:09 GMT"
35+
"Mon, 28 Feb 2022 18:41:20 GMT"
3636
],
3737
"expires": [
38-
"Mon, 28 Feb 2022 18:18:09 GMT"
38+
"Mon, 28 Feb 2022 18:41:20 GMT"
3939
],
4040
"p3p": [
4141
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
@@ -50,9 +50,9 @@
5050
"ESF"
5151
],
5252
"set-cookie": [
53-
"YSC\u003dXQZxEN8iFpc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
54-
"VISITOR_INFO1_LIVE\u003dPdecpxhX70w; Domain\u003d.youtube.com; Expires\u003dSat, 27-Aug-2022 18:18:09 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
55-
"CONSENT\u003dPENDING+810; expires\u003dWed, 28-Feb-2024 18:18:09 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
53+
"YSC\u003dRRetMyo289w; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
54+
"VISITOR_INFO1_LIVE\u003d65TC-XopBj0; Domain\u003d.youtube.com; Expires\u003dSat, 27-Aug-2022 18:41:20 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
55+
"CONSENT\u003dPENDING+472; expires\u003dWed, 28-Feb-2024 18:41:20 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
5656
],
5757
"strict-transport-security": [
5858
"max-age\u003d31536000"

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/stream/relatedMix/generated_mock_5.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"bytes"
2121
],
2222
"age": [
23-
"353237"
23+
"354628"
2424
],
2525
"alt-svc": [
2626
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000,h3-Q050\u003d\":443\"; ma\u003d2592000,h3-Q046\u003d\":443\"; ma\u003d2592000,h3-Q043\u003d\":443\"; ma\u003d2592000,quic\u003d\":443\"; ma\u003d2592000; v\u003d\"46,43\""

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/stream/relatedMix/generated_mock_6.json

Lines changed: 4 additions & 4 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)