Merge pull request #1022 from AudricV/yt_support-live-urls

[YouTube] Support live URLs
This commit is contained in:
Tobi 2023-01-28 21:52:26 +01:00 committed by GitHub
commit 0e4e6a9bac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 67 deletions

View File

@ -1,3 +1,23 @@
/*
* Created by Christian Schabesberger on 02.02.16.
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeStreamLinkHandlerFactory.java is part of NewPipe Extractor.
*
* NewPipe Extractor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe Extractor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe Extractor. If not, see <https://www.gnu.org/licenses/>.
*/
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isHooktubeURL;
@ -15,33 +35,13 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/*
* Created by Christian Schabesberger on 02.02.16.
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeStreamLinkHandlerFactory.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public final class YoutubeStreamLinkHandlerFactory extends LinkHandlerFactory {
private static final Pattern YOUTUBE_VIDEO_ID_REGEX_PATTERN
@ -49,7 +49,7 @@ public final class YoutubeStreamLinkHandlerFactory extends LinkHandlerFactory {
private static final YoutubeStreamLinkHandlerFactory INSTANCE
= new YoutubeStreamLinkHandlerFactory();
private static final List<String> SUBPATHS
= Arrays.asList("embed/", "shorts/", "watch/", "v/", "w/");
= List.of("embed/", "live/", "shorts/", "watch/", "v/", "w/");
private YoutubeStreamLinkHandlerFactory() {
}
@ -67,21 +67,24 @@ public final class YoutubeStreamLinkHandlerFactory extends LinkHandlerFactory {
return null;
}
@Nonnull
private static String assertIsId(@Nullable final String id) throws ParsingException {
final String extractedId = extractId(id);
if (extractedId != null) {
return extractedId;
} else {
throw new ParsingException("The given string is not a Youtube-Video-ID");
throw new ParsingException("The given string is not a YouTube video ID");
}
}
@Nonnull
@Override
public String getUrl(final String id) {
return "https://www.youtube.com/watch?v=" + id;
}
@SuppressWarnings("AvoidNestedBlocks")
@Nonnull
@Override
public String getId(final String theUrlString)
throws ParsingException, IllegalArgumentException {
@ -124,14 +127,14 @@ public final class YoutubeStreamLinkHandlerFactory extends LinkHandlerFactory {
if (!Utils.isHTTP(url) || !(isYoutubeURL(url) || isYoutubeServiceURL(url)
|| isHooktubeURL(url) || isInvidiousURL(url) || isY2ubeURL(url))) {
if (host.equalsIgnoreCase("googleads.g.doubleclick.net")) {
throw new FoundAdException("Error found ad: " + urlString);
throw new FoundAdException("Error: found ad: " + urlString);
}
throw new ParsingException("The url is not a Youtube-URL");
throw new ParsingException("The URL is not a YouTube URL");
}
if (YoutubePlaylistLinkHandlerFactory.getInstance().acceptUrl(urlString)) {
throw new ParsingException("Error no suitable url: " + urlString);
throw new ParsingException("Error: no suitable URL: " + urlString);
}
// Using uppercase instead of lowercase, because toLowercase replaces some unicode
@ -154,9 +157,9 @@ public final class YoutubeStreamLinkHandlerFactory extends LinkHandlerFactory {
final URL decodedURL;
try {
decodedURL = Utils.stringToURL("http://www.youtube.com" + uQueryValue);
decodedURL = Utils.stringToURL("https://www.youtube.com" + uQueryValue);
} catch (final MalformedURLException e) {
throw new ParsingException("Error no suitable url: " + urlString);
throw new ParsingException("Error: no suitable URL: " + urlString);
}
final String viewQueryValue = Utils.getQueryValue(decodedURL, "v");
@ -231,7 +234,7 @@ public final class YoutubeStreamLinkHandlerFactory extends LinkHandlerFactory {
}
}
throw new ParsingException("Error no suitable url: " + urlString);
throw new ParsingException("Error: no suitable URL: " + urlString);
}
@Override
@ -246,7 +249,8 @@ public final class YoutubeStreamLinkHandlerFactory extends LinkHandlerFactory {
}
}
private String getIdFromSubpathsInPath(final String path) throws ParsingException {
@Nullable
private String getIdFromSubpathsInPath(@Nonnull final String path) throws ParsingException {
for (final String subpath : SUBPATHS) {
if (path.startsWith(subpath)) {
final String id = path.substring(subpath.length());

View File

@ -11,14 +11,14 @@ import org.schabi.newpipe.extractor.exceptions.FoundAdException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test for {@link YoutubeStreamLinkHandlerFactory}
*/
@SuppressWarnings("HttpUrlsUsage")
public class YoutubeStreamLinkHandlerFactoryTest {
private static YoutubeStreamLinkHandlerFactory linkHandler;
@ -53,25 +53,25 @@ public class YoutubeStreamLinkHandlerFactoryTest {
@ParameterizedTest
@ValueSource(strings = {
"https://www.youtube.com/watch?v=jZViOEv90dI",
"https://www.youtube.com/watch?v=jZViOEv90dI&t=100",
"https://WWW.YouTube.com/watch?v=jZViOEv90dI&t=100",
"HTTPS://www.youtube.com/watch?v=jZViOEv90dI&t=100",
"https://youtu.be/jZViOEv90dI?t=9s",
"HTTPS://Youtu.be/jZViOEv90dI?t=9s",
"https://www.youtube.com/embed/jZViOEv90dI",
"https://www.youtube-nocookie.com/embed/jZViOEv90dI",
"http://www.youtube.com/watch?v=jZViOEv90dI",
"http://youtube.com/watch?v=jZViOEv90dI",
"http://youtu.be/jZViOEv90dI?t=9s",
"http://www.youtube.com/embed/jZViOEv90dI",
"http://www.Youtube.com/embed/jZViOEv90dI",
"http://www.youtube-nocookie.com/embed/jZViOEv90dI",
"vnd.youtube://www.youtube.com/watch?v=jZViOEv90dI",
"vnd.youtube:jZViOEv90dI"
"https://www.youtube.com/watch?v=9Dpqou5cI08",
"https://www.youtube.com/watch?v=9Dpqou5cI08&t=100",
"https://WWW.YouTube.com/watch?v=9Dpqou5cI08&t=100",
"HTTPS://www.youtube.com/watch?v=9Dpqou5cI08&t=100",
"https://youtu.be/9Dpqou5cI08?t=9s",
"HTTPS://Youtu.be/9Dpqou5cI08?t=9s",
"https://www.youtube.com/embed/9Dpqou5cI08",
"https://www.youtube-nocookie.com/embed/9Dpqou5cI08",
"http://www.youtube.com/watch?v=9Dpqou5cI08",
"http://youtube.com/watch?v=9Dpqou5cI08",
"http://youtu.be/9Dpqou5cI08?t=9s",
"http://www.youtube.com/embed/9Dpqou5cI08",
"http://www.Youtube.com/embed/9Dpqou5cI08",
"http://www.youtube-nocookie.com/embed/9Dpqou5cI08",
"vnd.youtube://www.youtube.com/watch?v=9Dpqou5cI08",
"vnd.youtube:9Dpqou5cI08"
})
void getId_jZViOEv90dI_fromYt(final String url) throws Exception {
assertEquals("jZViOEv90dI", linkHandler.fromUrl(url).getId());
void getId_9Dpqou5cI08_fromYt(final String url) throws Exception {
assertEquals("9Dpqou5cI08", linkHandler.fromUrl(url).getId());
}
@ParameterizedTest
@ -117,27 +117,28 @@ public class YoutubeStreamLinkHandlerFactoryTest {
@ParameterizedTest
@ValueSource(strings = {
"https://www.youtube.com/watch?v=jZViOEv90dI",
"https://www.youtube.com/watch?v=jZViOEv90dI&t=100",
"https://WWW.YouTube.com/watch?v=jZViOEv90dI&t=100",
"HTTPS://www.youtube.com/watch?v=jZViOEv90dI&t=100",
"https://youtu.be/jZViOEv90dI?t=9s",
"https://www.youtube.com/embed/jZViOEv90dI",
"https://www.youtube-nocookie.com/embed/jZViOEv90dI",
"http://www.youtube.com/watch?v=jZViOEv90dI",
"http://youtu.be/jZViOEv90dI?t=9s",
"http://www.youtube.com/embed/jZViOEv90dI",
"http://www.youtube-nocookie.com/embed/jZViOEv90dI",
"https://www.youtube.com/watch?v=9Dpqou5cI08",
"https://www.youtube.com/watch?v=9Dpqou5cI08&t=100",
"https://WWW.YouTube.com/watch?v=9Dpqou5cI08&t=100",
"HTTPS://www.youtube.com/watch?v=9Dpqou5cI08&t=100",
"https://youtu.be/9Dpqou5cI08?t=9s",
"https://www.youtube.com/embed/9Dpqou5cI08",
"https://www.youtube-nocookie.com/embed/9Dpqou5cI08",
"http://www.youtube.com/watch?v=9Dpqou5cI08",
"http://youtu.be/9Dpqou5cI08?t=9s",
"http://www.youtube.com/embed/9Dpqou5cI08",
"http://www.youtube-nocookie.com/embed/9Dpqou5cI08",
"http://www.youtube.com/attribution_link?a=JdfC0C9V6ZI&u=%2Fwatch%3Fv%3DEhxJLojIE_o%26feature%3Dshare",
"vnd.youtube://www.youtube.com/watch?v=jZViOEv90dI",
"vnd.youtube:jZViOEv90dI",
"vnd.youtube.launch:jZViOEv90dI",
"vnd.youtube://www.youtube.com/watch?v=9Dpqou5cI08",
"vnd.youtube:9Dpqou5cI08",
"vnd.youtube.launch:9Dpqou5cI08",
"https://music.youtube.com/watch?v=O0EDx9WAelc",
"https://www.youtube.com/shorts/IOS2fqxwYbA",
"http://www.youtube.com/shorts/IOS2fqxwYbA",
"http://www.youtube.com/v/IOS2fqxwYbA",
"https://www.youtube.com/w/IOS2fqxwYbA",
"https://www.youtube.com/watch/IOS2fqxwYbA"
"https://www.youtube.com/watch/IOS2fqxwYbA",
"https://www.youtube.com/live/rUxyKA_-grg"
})
void acceptYtUrl(final String url) throws ParsingException {
assertTrue(linkHandler.acceptUrl(url));