[Youtube] Add _ITEMS constants and improve code style

Move thumbnail id exctraction code to getThumbnailUrlFromId
Add test for "My mix" detection to service tests
Use ITEM_COUNT_UNKNOWN everywhere instead of -1 and add some tests
This commit is contained in:
Xiang Rong Lin 2020-03-17 14:04:46 +01:00 committed by XiangRongLin
parent df38b1926c
commit 822cf307f7
5 changed files with 55 additions and 38 deletions

View File

@ -1,6 +1,8 @@
package org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems; package org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems;
import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonObject;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
@ -23,7 +25,7 @@ public class MediaCCCConferenceInfoItemExtractor implements ChannelInfoItemExtra
@Override @Override
public long getStreamCount() { public long getStreamCount() {
return -1; return ListExtractor.ITEM_COUNT_UNKNOWN;
} }
@Override @Override

View File

@ -2,6 +2,7 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonObject;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory;
@ -86,7 +87,7 @@ public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor
try { try {
if (!channelInfoItem.has("videoCountText")) { if (!channelInfoItem.has("videoCountText")) {
// Video count is not available, channel probably has no public uploads. // Video count is not available, channel probably has no public uploads.
return -1; return ListExtractor.ITEM_COUNT_UNKNOWN;
} }
return Long.parseLong(Utils.removeNonDigitCharacters(getTextFromObject( return Long.parseLong(Utils.removeNonDigitCharacters(getTextFromObject(

View File

@ -7,6 +7,8 @@ import com.grack.nanojson.JsonObject;
import java.io.IOException; import java.io.IOException;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.downloader.Downloader;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@ -23,6 +25,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
*/ */
public class YoutubeMixPlaylistExtractor extends PlaylistExtractor { public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
private final static String CONTENTS = "contents"; private final static String CONTENTS = "contents";
private final static String RESPONSE = "response"; private final static String RESPONSE = "response";
private final static String PLAYLIST = "playlist"; private final static String PLAYLIST = "playlist";
@ -41,44 +44,25 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
final String url = getUrl() + "&pbj=1"; final String url = getUrl() + "&pbj=1";
final JsonArray ajaxJson = getJsonResponse(url, getExtractorLocalization()); final JsonArray ajaxJson = getJsonResponse(url, getExtractorLocalization());
JsonObject initialData = ajaxJson.getObject(3).getObject(RESPONSE); JsonObject initialData = ajaxJson.getObject(3).getObject(RESPONSE);
try { playlistData = initialData.getObject(CONTENTS).getObject(TWO_COLUMN_WATCH_NEXT_RESULTS)
playlistData = initialData.getObject(CONTENTS).getObject(TWO_COLUMNS_WATCH_NEXT_RESULTS) .getObject(PLAYLIST).getObject(PLAYLIST);
.getObject(PLAYLIST).getObject(PLAYLIST);
} catch (NullPointerException e) {
throw new ExtractionException(e);
}
} }
@Nonnull @Nonnull
@Override @Override
public String getName() throws ParsingException { public String getName() throws ParsingException {
try { final String name = playlistData.getString("title");
final String name = playlistData.getString("title"); if (name == null) {
if (name != null) { throw new ParsingException("Could not get playlist name");
return name;
} else {
return "";
}
} catch (Exception e) {
throw new ParsingException("Could not get playlist name", e);
} }
return name;
} }
@Override @Override
public String getThumbnailUrl() throws ParsingException { public String getThumbnailUrl() throws ParsingException {
try { try {
final String playlistId = playlistData.getString("playlistId"); final String playlistId = playlistData.getString("playlistId");
final String videoId; return getThumbnailUrlFromId(playlistId);
if (playlistId.startsWith("RDMM")) {
videoId = playlistId.substring(4);
} else {
videoId = playlistId.substring(2);
}
if (videoId.isEmpty()) {
throw new ParsingException("");
}
return getThumbnailUrlFromId(videoId);
} catch (Exception e) { } catch (Exception e) {
throw new ParsingException("Could not get playlist thumbnail", e); throw new ParsingException("Could not get playlist thumbnail", e);
} }
@ -97,20 +81,20 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
@Override @Override
public String getUploaderName() { public String getUploaderName() {
//Youtube mix are auto-generated //Youtube mix are auto-generated by YouTube
return ""; return "YouTube";
} }
@Override @Override
public String getUploaderAvatarUrl() { public String getUploaderAvatarUrl() {
//Youtube mix are auto-generated //Youtube mix are auto-generated by YouTube
return ""; return "";
} }
@Override @Override
public long getStreamCount() { public long getStreamCount() {
// Auto-generated playlist always start with 25 videos and are endless // Auto-generated playlist always start with 25 videos and are endless
return 25; return ListExtractor.ITEM_COUNT_INFINITE;
} }
@Nonnull @Nonnull
@ -135,7 +119,7 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
@Override @Override
public InfoItemsPage<StreamInfoItem> getPage(final String pageUrl) public InfoItemsPage<StreamInfoItem> getPage(final String pageUrl)
throws ExtractionException, IOException { throws ExtractionException, IOException {
if (pageUrl == null || pageUrl.isEmpty()) { if (pageUrl == null || pageUrl.isEmpty()) {
throw new ExtractionException( throw new ExtractionException(
new IllegalArgumentException("Page url is empty or null")); new IllegalArgumentException("Page url is empty or null"));
@ -145,7 +129,7 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
final JsonArray ajaxJson = getJsonResponse(pageUrl, getExtractorLocalization()); final JsonArray ajaxJson = getJsonResponse(pageUrl, getExtractorLocalization());
playlistData = playlistData =
ajaxJson.getObject(3).getObject(RESPONSE).getObject(CONTENTS) ajaxJson.getObject(3).getObject(RESPONSE).getObject(CONTENTS)
.getObject(TWO_COLUMNS_WATCH_NEXT_RESULTS).getObject(PLAYLIST) .getObject(TWO_COLUMN_WATCH_NEXT_RESULTS).getObject(PLAYLIST)
.getObject(PLAYLIST); .getObject(PLAYLIST);
final JsonArray streams = playlistData.getArray(CONTENTS); final JsonArray streams = playlistData.getArray(CONTENTS);
//Because continuation requests are created with the last video of previous request as start //Because continuation requests are created with the last video of previous request as start
@ -155,8 +139,8 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
} }
private void collectStreamsFrom( private void collectStreamsFrom(
@Nonnull StreamInfoItemsCollector collector, @Nonnull StreamInfoItemsCollector collector,
@Nullable JsonArray streams) { @Nullable JsonArray streams) {
collector.reset(); collector.reset();
if (streams == null) { if (streams == null) {
@ -176,7 +160,16 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
} }
} }
private String getThumbnailUrlFromId(String videoId) { private String getThumbnailUrlFromId(String playlistId) throws ParsingException {
final String videoId;
if (playlistId.startsWith("RDMM")) {
videoId = playlistId.substring(4);
} else {
videoId = playlistId.substring(2);
}
if (videoId.isEmpty()) {
throw new ParsingException("videoId is empty");
}
return "https://i.ytimg.com/vi/" + videoId + "/hqdefault.jpg"; return "https://i.ytimg.com/vi/" + videoId + "/hqdefault.jpg";
} }
} }

View File

@ -93,6 +93,11 @@ public class YoutubeMixPlaylistExtractorTest {
public void getStreamCount() throws Exception { public void getStreamCount() throws Exception {
assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount()); assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount());
} }
@Test
public void getStreamCount() throws Exception {
assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount());
}
} }
public static class MixWithIndex { public static class MixWithIndex {
@ -165,6 +170,11 @@ public class YoutubeMixPlaylistExtractorTest {
public void getStreamCount() { public void getStreamCount() {
assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount()); assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount());
} }
@Test
public void getStreamCount() throws Exception {
assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount());
}
} }
public static class MyMix { public static class MyMix {
@ -319,5 +329,10 @@ public class YoutubeMixPlaylistExtractorTest {
public void getStreamCount() throws Exception { public void getStreamCount() throws Exception {
assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount()); assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount());
} }
@Test
public void getStreamCount() throws Exception {
assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount());
}
} }
} }

View File

@ -75,7 +75,13 @@ public class YoutubeServiceTest {
assertTrue(extractor instanceof YoutubeMixPlaylistExtractor); assertTrue(extractor instanceof YoutubeMixPlaylistExtractor);
extractor = YouTube.getPlaylistExtractor( extractor = YouTube.getPlaylistExtractor(
"https://www.youtube.com/watch?v=" + videoId + "&list=RD" + videoId); "https://www.youtube.com/watch?v=" + videoId + "&list=RDMM" + videoId);
assertTrue(extractor instanceof YoutubeMixPlaylistExtractor);
final String mixVideoId = "qHtzO49SDmk";
extractor = YouTube.getPlaylistExtractor(
"https://www.youtube.com/watch?v=" + mixVideoId + "&list=RD" + videoId);
assertTrue(extractor instanceof YoutubeMixPlaylistExtractor); assertTrue(extractor instanceof YoutubeMixPlaylistExtractor);
} }
} }