diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/exceptions/AccountTerminatedException.java b/extractor/src/main/java/org/schabi/newpipe/extractor/exceptions/AccountTerminatedException.java new file mode 100644 index 00000000..5524798d --- /dev/null +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/exceptions/AccountTerminatedException.java @@ -0,0 +1,31 @@ +package org.schabi.newpipe.extractor.exceptions; + +public class AccountTerminatedException extends ContentNotAvailableException { + + private Reason reason = Reason.UNKNOWN; + + public AccountTerminatedException(final String message) { + super(message); + } + + public AccountTerminatedException(final String message, final Reason reason) { + super(message); + this.reason = reason; + } + + public AccountTerminatedException(final String message, final Throwable cause) { + super(message, cause); + } + + /** + * The reason for the violation. There should also be more info in the exception's message. + */ + public Reason getReason() { + return reason; + } + + public enum Reason { + UNKNOWN, + VIOLATION + } +} diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java index 796a4da7..522e641d 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java @@ -10,10 +10,7 @@ import com.grack.nanojson.JsonWriter; import org.schabi.newpipe.extractor.MetaInfo; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.downloader.Response; -import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; -import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.exceptions.ParsingException; -import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; +import org.schabi.newpipe.extractor.exceptions.*; import org.schabi.newpipe.extractor.localization.Localization; import org.schabi.newpipe.extractor.stream.Description; import org.schabi.newpipe.extractor.utils.JsonUtils; @@ -762,6 +759,16 @@ public class YoutubeParsingHelper { final String alertText = getTextFromObject(alertRenderer.getObject("text")); final String alertType = alertRenderer.getString("type", EMPTY_STRING); if (alertType.equalsIgnoreCase("ERROR")) { + if (alertText != null && alertText.contains("This account has been terminated")) { + if (alertText.contains("violation") || alertText.contains("violating")) { + // possible error messages: + // "This account has been terminated for violating YouTube's Community Guidelines." + // "This account has been terminated for a violation of YouTube's Terms of Service." + throw new AccountTerminatedException(alertText, AccountTerminatedException.Reason.VIOLATION); + } else { + throw new AccountTerminatedException(alertText); + } + } throw new ContentNotAvailableException("Got error: \"" + alertText + "\""); } } diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedExtractor.java index 65a0ffd6..dc9f60b4 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedExtractor.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeFeedExtractor.java @@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.extractor.downloader.Response; +import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.feed.FeedExtractor; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; @@ -33,6 +34,9 @@ public class YoutubeFeedExtractor extends FeedExtractor { final String feedUrl = YoutubeParsingHelper.getFeedUrlFrom(channelIdOrUser); final Response response = downloader.get(feedUrl); + if (response.responseCode() == 404) { + throw new ContentNotAvailableException("Could not get feed: 404 - not found"); + } document = Jsoup.parse(response.responseBody()); } 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 059c6097..e04a29fb 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 @@ -6,6 +6,7 @@ import org.schabi.newpipe.downloader.DownloaderFactory; import org.schabi.newpipe.downloader.DownloaderTestImpl; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelExtractor; +import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; import org.schabi.newpipe.extractor.exceptions.ParsingException; @@ -50,6 +51,13 @@ public class YoutubeChannelExtractorTest { YouTube.getChannelExtractor("https://www.youtube.com/channel/DOESNT-EXIST"); extractor.fetchPage(); } + + @Test(expected = AccountTerminatedException.class) + public void accountTerminatedFetch() throws Exception { + final ChannelExtractor extractor = + YouTube.getChannelExtractor("https://www.youtube.com/channel/UC0AuOxCr9TZ0TtEgL1zpIgA"); + extractor.fetchPage(); + } } public static class NotSupported { diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeFeedExtractorTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeFeedExtractorTest.java index 8303cf9a..6edd334b 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeFeedExtractorTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeFeedExtractorTest.java @@ -4,10 +4,13 @@ import org.junit.BeforeClass; import org.junit.Test; import org.schabi.newpipe.downloader.DownloaderFactory; import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException; +import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.BaseListExtractorTest; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeFeedExtractor; +import java.io.IOException; import java.util.Random; import static org.junit.Assert.assertEquals; @@ -77,4 +80,20 @@ public class YoutubeFeedExtractorTest { assertNoMoreItems(extractor); } } + + public static class NotAvailable { + + @BeforeClass + public static void setUp() throws IOException { + NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "notAvailable/")); + } + + @Test(expected = ContentNotAvailableException.class) + public void AccountTerminatedFetch() throws Exception { + YoutubeFeedExtractor extractor = (YoutubeFeedExtractor) YouTube + .getFeedExtractor("https://www.youtube.com/channel/UCTGjY2I-ZUGnwVoWAGRd7XQ"); + extractor.fetchPage(); + } + + } } \ No newline at end of file