From 093762e793810bcdded4167fd615ade6639a0d59 Mon Sep 17 00:00:00 2001 From: bopol Date: Mon, 30 Mar 2020 11:48:00 +0200 Subject: [PATCH 1/4] throw ContentNotSupportedException when content is know to be unsupported --- .../exceptions/ContentNotSupportedException.java | 11 +++++++++++ .../soundcloud/SoundcloudStreamExtractor.java | 5 +++++ .../YoutubePlaylistLinkHandlerFactory.java | 3 ++- .../schabi/newpipe/extractor/stream/StreamInfo.java | 5 ++++- 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 extractor/src/main/java/org/schabi/newpipe/extractor/exceptions/ContentNotSupportedException.java diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/exceptions/ContentNotSupportedException.java b/extractor/src/main/java/org/schabi/newpipe/extractor/exceptions/ContentNotSupportedException.java new file mode 100644 index 0000000000..c32575b451 --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/exceptions/ContentNotSupportedException.java @@ -0,0 +1,11 @@ +package org.schabi.newpipe.extractor.exceptions; + +public class ContentNotSupportedException extends ParsingException { + public ContentNotSupportedException(String message) { + super(message); + } + + public ContentNotSupportedException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java index 16eaad012a..eb7d57429b 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java @@ -10,6 +10,7 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; +import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.LinkHandler; @@ -196,6 +197,10 @@ public List getAudioStreams() throws IOException, ExtractionExcepti throw new ExtractionException("Could not get SoundCloud's track audio url", e); } + if (audioStreams.isEmpty()) { + throw new ContentNotSupportedException("HLS audio streams / opus streams are not yet supported"); + } + return audioStreams; } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubePlaylistLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubePlaylistLinkHandlerFactory.java index cf51281b37..1950f697b1 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubePlaylistLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubePlaylistLinkHandlerFactory.java @@ -1,5 +1,6 @@ package org.schabi.newpipe.extractor.services.youtube.linkHandler; +import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import org.schabi.newpipe.extractor.utils.Utils; @@ -47,7 +48,7 @@ public String getId(String url) throws ParsingException { // Don't accept auto-generated "Mix" playlists but auto-generated YouTube Music playlists if (listID.startsWith("RD") && !listID.startsWith("RDCLAK")) { - throw new ParsingException("YouTube Mix playlists are not yet supported"); + throw new ContentNotSupportedException("YouTube Mix playlists are not yet supported"); } return listID; diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java index 580f9c2136..0e5ff08085 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/stream/StreamInfo.java @@ -5,6 +5,7 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; +import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.localization.DateWrapper; import org.schabi.newpipe.extractor.utils.DashMpdParser; @@ -47,7 +48,7 @@ public static class StreamExtractException extends ExtractionException { } public StreamInfo(int serviceId, String url, String originalUrl, StreamType streamType, String id, String name, - int ageLimit) { + int ageLimit) { super(serviceId, id, url, originalUrl, name); this.streamType = streamType; this.ageLimit = ageLimit; @@ -131,6 +132,8 @@ private static StreamInfo extractStreams(StreamInfo streamInfo, StreamExtractor /* Load and extract audio */ try { streamInfo.setAudioStreams(extractor.getAudioStreams()); + } catch (ContentNotSupportedException e) { + throw e; } catch (Exception e) { streamInfo.addError(new ExtractionException("Couldn't get audio streams", e)); } From a22104cbda19fa98b8238addd0425613dcddb665 Mon Sep 17 00:00:00 2001 From: bopol Date: Wed, 1 Apr 2020 21:50:28 +0200 Subject: [PATCH 2/4] add tests for ContentNotSupportedException --- .../SoundcloudStreamExtractorDefaultTest.java | 230 ++++++++++-------- 1 file changed, 129 insertions(+), 101 deletions(-) diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java index 86203f4c3c..75178c4c9c 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractorDefaultTest.java @@ -5,6 +5,7 @@ import org.junit.Test; import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.stream.StreamExtractor; @@ -25,107 +26,134 @@ * Test for {@link StreamExtractor} */ public class SoundcloudStreamExtractorDefaultTest { - private static SoundcloudStreamExtractor extractor; - @BeforeClass - public static void setUp() throws Exception { - NewPipe.init(DownloaderTestImpl.getInstance()); - extractor = (SoundcloudStreamExtractor) SoundCloud.getStreamExtractor("https://soundcloud.com/liluzivert/do-what-i-want-produced-by-maaly-raw-don-cannon"); - extractor.fetchPage(); - } - - @Test - public void testGetInvalidTimeStamp() throws ParsingException { - assertTrue(extractor.getTimeStamp() + "", - extractor.getTimeStamp() <= 0); - } - - @Test - public void testGetValidTimeStamp() throws IOException, ExtractionException { - StreamExtractor extractor = SoundCloud.getStreamExtractor("https://soundcloud.com/liluzivert/do-what-i-want-produced-by-maaly-raw-don-cannon#t=69"); - assertEquals("69", extractor.getTimeStamp() + ""); - } - - @Test - public void testGetTitle() throws ParsingException { - assertEquals("Do What I Want [Produced By Maaly Raw + Don Cannon]", extractor.getName()); - } - - @Test - public void testGetDescription() throws ParsingException { - assertEquals("The Perfect LUV Tape®️", extractor.getDescription().getContent()); - } - - @Test - public void testGetUploaderName() throws ParsingException { - assertEquals("LIL UZI VERT", extractor.getUploaderName()); - } - - @Test - public void testGetLength() throws ParsingException { - assertEquals(175, extractor.getLength()); - } - - @Test - public void testGetViewCount() throws ParsingException { - assertTrue(Long.toString(extractor.getViewCount()), - extractor.getViewCount() > 44227978); - } - - @Test - public void testGetTextualUploadDate() throws ParsingException { - Assert.assertEquals("2016-07-31 18:18:07", extractor.getTextualUploadDate()); - } - - @Test - public void testGetUploadDate() throws ParsingException, ParseException { - final Calendar instance = Calendar.getInstance(); - instance.setTime(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse("2016/07/31 18:18:07 +0000")); - assertEquals(instance, requireNonNull(extractor.getUploadDate()).date()); - } - - @Test - public void testGetUploaderUrl() throws ParsingException { - assertIsSecureUrl(extractor.getUploaderUrl()); - assertEquals("https://soundcloud.com/liluzivert", extractor.getUploaderUrl()); - } - - @Test - public void testGetThumbnailUrl() throws ParsingException { - assertIsSecureUrl(extractor.getThumbnailUrl()); - } - - @Test - public void testGetUploaderAvatarUrl() throws ParsingException { - assertIsSecureUrl(extractor.getUploaderAvatarUrl()); - } - - @Test - public void testGetAudioStreams() throws IOException, ExtractionException { - assertFalse(extractor.getAudioStreams().isEmpty()); - } - - @Test - public void testStreamType() throws ParsingException { - assertTrue(extractor.getStreamType() == StreamType.AUDIO_STREAM); - } - - @Test - public void testGetRelatedVideos() throws ExtractionException, IOException { - StreamInfoItemsCollector relatedVideos = extractor.getRelatedStreams(); - assertFalse(relatedVideos.getItems().isEmpty()); - assertTrue(relatedVideos.getErrors().isEmpty()); - } - - @Test - public void testGetSubtitlesListDefault() throws IOException, ExtractionException { - // Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null - assertTrue(extractor.getSubtitlesDefault().isEmpty()); - } - - @Test - public void testGetSubtitlesList() throws IOException, ExtractionException { - // Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null - assertTrue(extractor.getSubtitlesDefault().isEmpty()); + public static class LilUziVertDoWhatIWant { + private static SoundcloudStreamExtractor extractor; + + @BeforeClass + public static void setUp() throws Exception { + NewPipe.init(DownloaderTestImpl.getInstance()); + extractor = (SoundcloudStreamExtractor) SoundCloud.getStreamExtractor("https://soundcloud.com/liluzivert/do-what-i-want-produced-by-maaly-raw-don-cannon"); + extractor.fetchPage(); + } + + @Test + public void testGetInvalidTimeStamp() throws ParsingException { + assertTrue(extractor.getTimeStamp() + "", + extractor.getTimeStamp() <= 0); + } + + @Test + public void testGetValidTimeStamp() throws IOException, ExtractionException { + StreamExtractor extractor = SoundCloud.getStreamExtractor("https://soundcloud.com/liluzivert/do-what-i-want-produced-by-maaly-raw-don-cannon#t=69"); + assertEquals("69", extractor.getTimeStamp() + ""); + } + + @Test + public void testGetTitle() throws ParsingException { + assertEquals("Do What I Want [Produced By Maaly Raw + Don Cannon]", extractor.getName()); + } + + @Test + public void testGetDescription() throws ParsingException { + assertEquals("The Perfect LUV Tape®️", extractor.getDescription().getContent()); + } + + @Test + public void testGetUploaderName() throws ParsingException { + assertEquals("LIL UZI VERT", extractor.getUploaderName()); + } + + @Test + public void testGetLength() throws ParsingException { + assertEquals(175, extractor.getLength()); + } + + @Test + public void testGetViewCount() throws ParsingException { + assertTrue(Long.toString(extractor.getViewCount()), + extractor.getViewCount() > 44227978); + } + + @Test + public void testGetTextualUploadDate() throws ParsingException { + Assert.assertEquals("2016-07-31 18:18:07", extractor.getTextualUploadDate()); + } + + @Test + public void testGetUploadDate() throws ParsingException, ParseException { + final Calendar instance = Calendar.getInstance(); + instance.setTime(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse("2016/07/31 18:18:07 +0000")); + assertEquals(instance, requireNonNull(extractor.getUploadDate()).date()); + } + + @Test + public void testGetUploaderUrl() throws ParsingException { + assertIsSecureUrl(extractor.getUploaderUrl()); + assertEquals("https://soundcloud.com/liluzivert", extractor.getUploaderUrl()); + } + + @Test + public void testGetThumbnailUrl() throws ParsingException { + assertIsSecureUrl(extractor.getThumbnailUrl()); + } + + @Test + public void testGetUploaderAvatarUrl() throws ParsingException { + assertIsSecureUrl(extractor.getUploaderAvatarUrl()); + } + + @Test + public void testGetAudioStreams() throws IOException, ExtractionException { + assertFalse(extractor.getAudioStreams().isEmpty()); + } + + @Test + public void testStreamType() throws ParsingException { + assertTrue(extractor.getStreamType() == StreamType.AUDIO_STREAM); + } + + @Test + public void testGetRelatedVideos() throws ExtractionException, IOException { + StreamInfoItemsCollector relatedVideos = extractor.getRelatedStreams(); + assertFalse(relatedVideos.getItems().isEmpty()); + assertTrue(relatedVideos.getErrors().isEmpty()); + } + + @Test + public void testGetSubtitlesListDefault() throws IOException, ExtractionException { + // Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null + assertTrue(extractor.getSubtitlesDefault().isEmpty()); + } + + @Test + public void testGetSubtitlesList() throws IOException, ExtractionException { + // Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null + assertTrue(extractor.getSubtitlesDefault().isEmpty()); + } + } + + public static class ContentNotSupported { + @BeforeClass + public static void setUp() { + NewPipe.init(DownloaderTestImpl.getInstance()); + } + + @Test(expected = ContentNotSupportedException.class) + public void hlsAudioStream() throws Exception { + final StreamExtractor extractor = + SoundCloud.getStreamExtractor("https://soundcloud.com/dualipa/cool"); + extractor.fetchPage(); + extractor.getAudioStreams(); + } + + @Test(expected = ContentNotSupportedException.class) + public void bothHlsAndOpusAudioStreams() throws Exception { + final StreamExtractor extractor = + SoundCloud.getStreamExtractor("https://soundcloud.com/lil-baby-4pf/no-sucker"); + extractor.fetchPage(); + extractor.getAudioStreams(); + } } } + From 9a7c6b7ab00c0f5b8337232fc66d3d9b538c229f Mon Sep 17 00:00:00 2001 From: bopol Date: Wed, 1 Apr 2020 22:31:53 +0200 Subject: [PATCH 3/4] use ContentNotSupportedException for channels without tabs --- .../extractors/YoutubeChannelExtractor.java | 3 ++- .../youtube/YoutubeChannelExtractorTest.java | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java index 3859807450..6a570da53a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java @@ -5,6 +5,7 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelExtractor; import org.schabi.newpipe.extractor.downloader.Downloader; +import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; @@ -310,7 +311,7 @@ private JsonObject getVideoTab() throws ParsingException { } if (videoTab == null) { - throw new ParsingException("Could not find Videos tab"); + throw new ContentNotSupportedException("This channel has no Videos tab"); } try { diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractorTest.java index 3615bc63c3..a916c5602b 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractorTest.java @@ -5,13 +5,14 @@ import org.schabi.newpipe.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelExtractor; -import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; +import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; +import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.BaseChannelExtractorTest; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelExtractor; -import java.util.List; +import java.io.IOException; import static org.junit.Assert.*; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmpty; @@ -45,6 +46,20 @@ public void nonExistentFetch() throws Exception { } } + public static class NotSupported { + @BeforeClass + public static void setUp() { + NewPipe.init(DownloaderTestImpl.getInstance()); + } + + @Test(expected = ContentNotSupportedException.class) + public void noVideoTab() throws Exception { + final ChannelExtractor extractor = YouTube.getChannelExtractor("https://invidio.us/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ"); + extractor.fetchPage(); + extractor.getInitialPage(); + } + } + public static class Gronkh implements BaseChannelExtractorTest { private static YoutubeChannelExtractor extractor; From a20d53dd98b8bfd55818fc5cb8f611608d27f8e4 Mon Sep 17 00:00:00 2001 From: bopol Date: Wed, 8 Apr 2020 15:30:39 +0200 Subject: [PATCH 4/4] remove the mention of Opus on wb9688 advise when ContentNotSupportedException is thrown --- .../services/soundcloud/SoundcloudStreamExtractor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java index eb7d57429b..9ebb3dd6ee 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java @@ -198,7 +198,7 @@ public List getAudioStreams() throws IOException, ExtractionExcepti } if (audioStreams.isEmpty()) { - throw new ContentNotSupportedException("HLS audio streams / opus streams are not yet supported"); + throw new ContentNotSupportedException("HLS audio streams are not yet supported"); } return audioStreams;