diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeChannelLinkHandlerFactory.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeChannelLinkHandlerFactory.java index 0eb03085..2dc8fc42 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeChannelLinkHandlerFactory.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/linkHandler/YoutubeChannelLinkHandlerFactory.java @@ -1,5 +1,6 @@ package org.schabi.newpipe.extractor.services.youtube.linkHandler; +import java.util.regex.Pattern; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper; @@ -32,6 +33,9 @@ public class YoutubeChannelLinkHandlerFactory extends ListLinkHandlerFactory { private static final YoutubeChannelLinkHandlerFactory instance = new YoutubeChannelLinkHandlerFactory(); + private static final Pattern excludedSegments = + Pattern.compile("playlist|watch|attribution_link|watch_popup|embed|feed|select_site"); + public static YoutubeChannelLinkHandlerFactory getInstance() { return instance; } @@ -48,11 +52,22 @@ public class YoutubeChannelLinkHandlerFactory extends ListLinkHandlerFactory { public String getUrl(String id, List contentFilters, String searchFilter) { return "https://www.youtube.com/" + id; } + + /** + * Returns true if path conform to + * custom short channel URLs like youtube.com/yourcustomname + * + * @param splitPath path segments array + * @return true - if value conform to short channel URL, false - not + */ + private boolean isCustomShortChannelUrl(final String[] splitPath) { + return splitPath.length == 1 && !excludedSegments.matcher(splitPath[0]).matches(); + } @Override public String getId(String url) throws ParsingException { try { - URL urlObj = Utils.stringToURL(url); + final URL urlObj = Utils.stringToURL(url); String path = urlObj.getPath(); if (!Utils.isHTTP(urlObj) || !(YoutubeParsingHelper.isYoutubeURL(urlObj) || @@ -60,15 +75,21 @@ public class YoutubeChannelLinkHandlerFactory extends ListLinkHandlerFactory { throw new ParsingException("the URL given is not a Youtube-URL"); } - if (!path.startsWith("/user/") && !path.startsWith("/channel/") && !path.startsWith("/c/")) { + // remove leading "/" + path = path.substring(1); + String[] splitPath = path.split("/"); + + // Handle custom short channel URLs like youtube.com/yourcustomname + if (isCustomShortChannelUrl(splitPath)) { + path = "c/" + path; + splitPath = path.split("/"); + } + + if (!path.startsWith("user/") && !path.startsWith("channel/") && !path.startsWith("c/")) { throw new ParsingException("the URL given is neither a channel nor an user"); } - // remove leading "/" - path = path.substring(1); - - String[] splitPath = path.split("/"); - String id = splitPath[1]; + final String id = splitPath[1]; if (id == null || !id.matches("[A-Za-z0-9_-]+")) { throw new ParsingException("The given id is not a Youtube-Video-ID"); diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLinkHandlerFactoryTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLinkHandlerFactoryTest.java index fc409ffa..12bcb804 100644 --- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLinkHandlerFactoryTest.java +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelLinkHandlerFactoryTest.java @@ -8,6 +8,7 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** @@ -30,6 +31,8 @@ public class YoutubeChannelLinkHandlerFactoryTest { assertTrue(linkHandler.acceptUrl("https://www.youtube.com/c/creatoracademy")); + assertTrue(linkHandler.acceptUrl("https://youtube.com/DIMENSI0N")); + assertTrue(linkHandler.acceptUrl("https://www.youtube.com/channel/UClq42foiSgl7sSpLupnugGA")); assertTrue(linkHandler.acceptUrl("https://www.youtube.com/channel/UClq42foiSgl7sSpLupnugGA/videos?disable_polymer=1")); @@ -44,6 +47,18 @@ public class YoutubeChannelLinkHandlerFactoryTest { assertTrue(linkHandler.acceptUrl("https://invidio.us/channel/UClq42foiSgl7sSpLupnugGA")); assertTrue(linkHandler.acceptUrl("https://invidio.us/channel/UClq42foiSgl7sSpLupnugGA/videos?disable_polymer=1")); + assertTrue(linkHandler.acceptUrl("https://www.youtube.com/watchismo")); + + + // do not accept URLs which are not channels + assertFalse(linkHandler.acceptUrl("https://www.youtube.com/watch?v=jZViOEv90dI&t=100")); + assertFalse(linkHandler.acceptUrl("http://www.youtube.com/watch_popup?v=uEJuoEs1UxY")); + assertFalse(linkHandler.acceptUrl("http://www.youtube.com/attribution_link?a=JdfC0C9V6ZI&u=%2Fwatch%3Fv%3DEhxJLojIE_o%26feature%3Dshare")); + assertFalse(linkHandler.acceptUrl("https://www.youtube.com/playlist?list=PLW5y1tjAOzI3orQNF1yGGVL5x-pR2K1d")); + assertFalse(linkHandler.acceptUrl("https://www.youtube.com/embed/jZViOEv90dI")); + assertFalse(linkHandler.acceptUrl("https://www.youtube.com/feed/subscriptions?list=PLz8YL4HVC87WJQDzVoY943URKQCsHS9XV")); + assertFalse(linkHandler.acceptUrl("https://www.youtube.com/?app=desktop&persist_app=1")); + assertFalse(linkHandler.acceptUrl("https://m.youtube.com/select_site")); } @Test