[YouTube] Parse any playlist (including music mixes) in related items

This commit is contained in:
Stypox 2022-02-28 19:42:34 +01:00
parent 13f7900816
commit 8201b3b90e
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
10 changed files with 61 additions and 34 deletions

View File

@ -11,13 +11,14 @@ import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor;
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
import javax.annotation.Nonnull;
public class YoutubeMixPlaylistInfoItemExtractor implements PlaylistInfoItemExtractor {
public class YoutubeMixOrPlaylistInfoItemExtractor implements PlaylistInfoItemExtractor {
private final JsonObject mixInfoItem;
public YoutubeMixPlaylistInfoItemExtractor(final JsonObject mixInfoItem) {
public YoutubeMixOrPlaylistInfoItemExtractor(final JsonObject mixInfoItem) {
this.mixInfoItem = mixInfoItem;
}
@ -46,14 +47,25 @@ public class YoutubeMixPlaylistInfoItemExtractor implements PlaylistInfoItemExtr
@Override
public String getUploaderName() throws ParsingException {
// YouTube mixes are auto-generated by YouTube
return "YouTube";
// this will be "YouTube" for mixes
return YoutubeParsingHelper.getTextFromObject(mixInfoItem.getObject("longBylineText"));
}
@Override
public long getStreamCount() throws ParsingException {
// Auto-generated playlists always start with 25 videos and are endless
return ListExtractor.ITEM_COUNT_INFINITE;
final String countString = YoutubeParsingHelper.getTextFromObject(
mixInfoItem.getObject("videoCountShortText"));
if (countString == null) {
throw new ParsingException("Could not extract item count for playlist/mix info item");
}
try {
return Integer.parseInt(countString);
} catch (final NumberFormatException ignored) {
// un-parsable integer: this is a mix with infinite items and "50+" as count string
// (though youtube music mixes do not necessarily have an infinite count of songs)
return ListExtractor.ITEM_COUNT_INFINITE;
}
}
@Nonnull

View File

@ -641,8 +641,11 @@ public class YoutubeStreamExtractor extends StreamExtractor {
collector.commit(new YoutubeStreamInfoItemExtractor(
result.getObject("compactVideoRenderer"), timeAgoParser));
} else if (result.has("compactRadioRenderer")) {
collector.commit(new YoutubeMixPlaylistInfoItemExtractor(
collector.commit(new YoutubeMixOrPlaylistInfoItemExtractor(
result.getObject("compactRadioRenderer")));
} else if (result.has("compactPlaylistRenderer")) {
collector.commit(new YoutubeMixOrPlaylistInfoItemExtractor(
result.getObject("compactPlaylistRenderer")));
}
}
return collector;

View File

@ -111,5 +111,17 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
assertContains("list=RD" + ID, streamMix.getUrl());
assertEquals("Mix " + TITLE, streamMix.getName());
assertIsSecureUrl(streamMix.getThumbnailUrl());
final List<PlaylistInfoItem> musicMixes = playlists.stream()
.filter(item -> item.getPlaylistType().equals(PlaylistType.MIX_MUSIC))
.collect(Collectors.toList());
assertEquals(1, musicMixes.size(), "Not found exactly one music mix in related items");
final PlaylistInfoItem musicMix = musicMixes.get(0);
assertSame(InfoItem.InfoType.PLAYLIST, musicMix.getInfoType());
assertEquals(YouTube.getServiceId(), musicMix.getServiceId());
assertContains("list=RDCLAK", musicMix.getUrl());
assertEquals("Hip Hop Essentials", musicMix.getName());
assertIsSecureUrl(musicMix.getThumbnailUrl());
}
}

View File

@ -32,10 +32,10 @@
"cross-origin"
],
"date": [
"Mon, 28 Feb 2022 18:18:09 GMT"
"Mon, 28 Feb 2022 18:41:20 GMT"
],
"expires": [
"Mon, 28 Feb 2022 18:18:09 GMT"
"Mon, 28 Feb 2022 18:41:20 GMT"
],
"p3p": [
"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 @@
"ESF"
],
"set-cookie": [
"YSC\u003dXQZxEN8iFpc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003dPdecpxhX70w; Domain\u003d.youtube.com; Expires\u003dSat, 27-Aug-2022 18:18:09 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+810; expires\u003dWed, 28-Feb-2024 18:18:09 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
"YSC\u003dRRetMyo289w; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d65TC-XopBj0; Domain\u003d.youtube.com; Expires\u003dSat, 27-Aug-2022 18:41:20 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+472; expires\u003dWed, 28-Feb-2024 18:41:20 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
],
"strict-transport-security": [
"max-age\u003d31536000"

View File

@ -20,7 +20,7 @@
"bytes"
],
"age": [
"353237"
"354628"
],
"alt-svc": [
"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\""