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 81e9fdc60..a6a5deffd 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
@@ -822,7 +822,7 @@ public final class YoutubeParsingHelper {
try {
final String url = "https://music.youtube.com/sw.js";
- final var headers = getOriginReferrerHeaders("https://music.youtube.com");
+ final var headers = getOriginReferrerHeaders(YOUTUBE_MUSIC_URL);
final String response = getDownloader().get(url, headers).responseBody();
musicClientVersion = getStringResultFromRegexArray(response,
INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES, 1);
@@ -843,18 +843,11 @@ public final class YoutubeParsingHelper {
}
@Nullable
- public static String getUrlFromNavigationEndpoint(@Nonnull final JsonObject navigationEndpoint)
- throws ParsingException {
- if (navigationEndpoint.has("webCommandMetadata")) {
- // this case needs to be handled before the browseEndpoint,
- // e.g. for hashtags in comments
- final JsonObject metadata = navigationEndpoint.getObject("webCommandMetadata");
- if (metadata.has("url")) {
- return "https://www.youtube.com" + metadata.getString("url");
- }
- }
+ public static String getUrlFromNavigationEndpoint(
+ @Nonnull final JsonObject navigationEndpoint) {
if (navigationEndpoint.has("urlEndpoint")) {
- String internUrl = navigationEndpoint.getObject("urlEndpoint").getString("url");
+ String internUrl = navigationEndpoint.getObject("urlEndpoint")
+ .getString("url");
if (internUrl.startsWith("https://www.youtube.com/redirect?")) {
// remove https://www.youtube.com part to fall in the next if block
internUrl = internUrl.substring(23);
@@ -879,7 +872,9 @@ public final class YoutubeParsingHelper {
|| internUrl.startsWith("/watch")) {
return "https://www.youtube.com" + internUrl;
}
- } else if (navigationEndpoint.has("browseEndpoint")) {
+ }
+
+ if (navigationEndpoint.has("browseEndpoint")) {
final JsonObject browseEndpoint = navigationEndpoint.getObject("browseEndpoint");
final String canonicalBaseUrl = browseEndpoint.getString("canonicalBaseUrl");
final String browseId = browseEndpoint.getString("browseId");
@@ -892,26 +887,39 @@ public final class YoutubeParsingHelper {
if (!isNullOrEmpty(canonicalBaseUrl)) {
return "https://www.youtube.com" + canonicalBaseUrl;
}
+ }
- throw new ParsingException("canonicalBaseUrl is null and browseId is not a channel (\""
- + browseEndpoint + "\")");
- } else if (navigationEndpoint.has("watchEndpoint")) {
+ if (navigationEndpoint.has("watchEndpoint")) {
final StringBuilder url = new StringBuilder();
- url.append("https://www.youtube.com/watch?v=").append(navigationEndpoint
- .getObject("watchEndpoint").getString(VIDEO_ID));
+ url.append("https://www.youtube.com/watch?v=")
+ .append(navigationEndpoint.getObject("watchEndpoint")
+ .getString(VIDEO_ID));
if (navigationEndpoint.getObject("watchEndpoint").has("playlistId")) {
url.append("&list=").append(navigationEndpoint.getObject("watchEndpoint")
.getString("playlistId"));
}
if (navigationEndpoint.getObject("watchEndpoint").has("startTimeSeconds")) {
- url.append("&t=").append(navigationEndpoint.getObject("watchEndpoint")
+ url.append("&t=")
+ .append(navigationEndpoint.getObject("watchEndpoint")
.getInt("startTimeSeconds"));
}
return url.toString();
- } else if (navigationEndpoint.has("watchPlaylistEndpoint")) {
- return "https://www.youtube.com/playlist?list="
- + navigationEndpoint.getObject("watchPlaylistEndpoint").getString("playlistId");
}
+
+ if (navigationEndpoint.has("watchPlaylistEndpoint")) {
+ return "https://www.youtube.com/playlist?list="
+ + navigationEndpoint.getObject("watchPlaylistEndpoint")
+ .getString("playlistId");
+ }
+
+ if (navigationEndpoint.has("commandMetadata")) {
+ final JsonObject metadata = navigationEndpoint.getObject("commandMetadata")
+ .getObject("webCommandMetadata");
+ if (metadata.has("url")) {
+ return "https://www.youtube.com" + metadata.getString("url");
+ }
+ }
+
return null;
}
@@ -924,8 +932,7 @@ public final class YoutubeParsingHelper {
* @return text in the JSON object or {@code null}
*/
@Nullable
- public static String getTextFromObject(final JsonObject textObject, final boolean html)
- throws ParsingException {
+ public static String getTextFromObject(final JsonObject textObject, final boolean html) {
if (isNullOrEmpty(textObject)) {
return null;
}
@@ -944,12 +951,12 @@ public final class YoutubeParsingHelper {
String text = run.getString("text");
if (html) {
- text = Entities.escape(text);
if (run.has("navigationEndpoint")) {
- final String url = getUrlFromNavigationEndpoint(run
- .getObject("navigationEndpoint"));
+ final String url = getUrlFromNavigationEndpoint(
+ run.getObject("navigationEndpoint"));
if (!isNullOrEmpty(url)) {
- text = "" + text + "";
+ text = "" + Entities.escape(text)
+ + "";
}
}
@@ -1015,11 +1022,12 @@ public final class YoutubeParsingHelper {
}
final String content = attributedDescription.getString("content");
- final JsonArray commandRuns = attributedDescription.getArray("commandRuns");
if (content == null) {
return null;
}
+ final JsonArray commandRuns = attributedDescription.getArray("commandRuns");
+
final StringBuilder textBuilder = new StringBuilder();
int textStart = 0;
@@ -1038,12 +1046,7 @@ public final class YoutubeParsingHelper {
continue;
}
- final String url;
- try {
- url = getUrlFromNavigationEndpoint(navigationEndpoint);
- } catch (final ParsingException e) {
- continue;
- }
+ final String url = getUrlFromNavigationEndpoint(navigationEndpoint);
if (url == null) {
continue;
@@ -1062,9 +1065,9 @@ public final class YoutubeParsingHelper {
.replaceFirst("^[/•] *", "");
textBuilder.append("")
- .append(linkText)
+ .append(Entities.escape(linkText))
.append("");
textStart = startIndex + length;
@@ -1081,13 +1084,12 @@ public final class YoutubeParsingHelper {
}
@Nullable
- public static String getTextFromObject(final JsonObject textObject) throws ParsingException {
+ public static String getTextFromObject(final JsonObject textObject) {
return getTextFromObject(textObject, false);
}
@Nullable
- public static String getUrlFromObject(final JsonObject textObject) throws ParsingException {
-
+ public static String getUrlFromObject(final JsonObject textObject) {
if (isNullOrEmpty(textObject)) {
return null;
}
@@ -1108,8 +1110,7 @@ public final class YoutubeParsingHelper {
}
@Nullable
- public static String getTextAtKey(@Nonnull final JsonObject jsonObject, final String theKey)
- throws ParsingException {
+ public static String getTextAtKey(@Nonnull final JsonObject jsonObject, final String theKey) {
if (jsonObject.isString(theKey)) {
return jsonObject.getString(theKey);
} else {
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelInfoItemExtractor.java
index c683e3af7..e01f0cfb9 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelInfoItemExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelInfoItemExtractor.java
@@ -45,13 +45,10 @@ public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor
this.channelInfoItem = channelInfoItem;
boolean wHandle = false;
- try {
- final String subscriberCountText = getTextFromObject(
- channelInfoItem.getObject("subscriberCountText"));
- if (subscriberCountText != null) {
- wHandle = subscriberCountText.startsWith("@");
- }
- } catch (final ParsingException ignored) {
+ final String subscriberCountText = getTextFromObject(
+ channelInfoItem.getObject("subscriberCountText"));
+ if (subscriberCountText != null) {
+ wHandle = subscriberCountText.startsWith("@");
}
this.withHandle = wHandle;
}
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java
index 150acf87b..183c6f608 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java
@@ -168,11 +168,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
title = playerResponse.getObject("videoDetails").getString("title");
if (isNullOrEmpty(title)) {
- try {
- title = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("title"));
- } catch (final ParsingException ignored) {
- // Age-restricted videos cause a ParsingException here
- }
+ title = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("title"));
if (isNullOrEmpty(title)) {
throw new ParsingException("Could not get name");
@@ -285,21 +281,17 @@ public class YoutubeStreamExtractor extends StreamExtractor {
public Description getDescription() throws ParsingException {
assertPageFetched();
// Description with more info on links
- try {
- final String description = getTextFromObject(
- getVideoSecondaryInfoRenderer().getObject("description"),
- true);
- if (!isNullOrEmpty(description)) {
- return new Description(description, Description.HTML);
- }
+ final String videoSecondaryInfoRendererDescription = getTextFromObject(
+ getVideoSecondaryInfoRenderer().getObject("description"),
+ true);
+ if (!isNullOrEmpty(videoSecondaryInfoRendererDescription)) {
+ return new Description(videoSecondaryInfoRendererDescription, Description.HTML);
+ }
- final String attributedDescription = getAttributedDescription(
- getVideoSecondaryInfoRenderer().getObject("attributedDescription"));
- if (!isNullOrEmpty(attributedDescription)) {
- return new Description(attributedDescription, Description.HTML);
- }
- } catch (final ParsingException ignored) {
- // Age-restricted videos cause a ParsingException here
+ final String attributedDescription = getAttributedDescription(
+ getVideoSecondaryInfoRenderer().getObject("attributedDescription"));
+ if (!isNullOrEmpty(attributedDescription)) {
+ return new Description(attributedDescription, Description.HTML);
}
String description = playerResponse.getObject("videoDetails")
@@ -400,14 +392,8 @@ public class YoutubeStreamExtractor extends StreamExtractor {
@Override
public long getViewCount() throws ParsingException {
- String views = null;
-
- try {
- views = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("viewCount")
- .getObject("videoViewCountRenderer").getObject("viewCount"));
- } catch (final ParsingException ignored) {
- // Age-restricted videos cause a ParsingException here
- }
+ String views = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("viewCount")
+ .getObject("videoViewCountRenderer").getObject("viewCount"));
if (isNullOrEmpty(views)) {
views = playerResponse.getObject("videoDetails").getString("viewCount");
@@ -795,7 +781,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
return getTextFromObject(playerResponse.getObject("playabilityStatus")
.getObject("errorScreen").getObject("playerErrorMessageRenderer")
.getObject("reason"));
- } catch (final ParsingException | NullPointerException e) {
+ } catch (final NullPointerException e) {
return null; // No error message
}
}
diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java
index 50f37ca1a..4d5d2ab93 100644
--- a/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java
+++ b/extractor/src/test/java/org/schabi/newpipe/extractor/services/youtube/stream/YoutubeStreamExtractorDefaultTest.java
@@ -183,10 +183,10 @@ public class YoutubeStreamExtractorDefaultTest {
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCsTcErHg8oDvUnTzoqsYeNw"; }
@Override public long expectedUploaderSubscriberCountAtLeast() { return 18_000_000; }
@Override public List expectedDescriptionContains() {
- return Arrays.asList("https://www.youtube.com/watch?v=X7FLCHVXpsA&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34",
- "https://www.youtube.com/watch?v=Lqv6G0pDNnw&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34",
- "https://www.youtube.com/watch?v=XxaRBPyrnBU&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34",
- "https://www.youtube.com/watch?v=U-9tUEOFKNU&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34");
+ return Arrays.asList("https://www.youtube.com/watch?v=X7FLCHVXpsA&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34",
+ "https://www.youtube.com/watch?v=Lqv6G0pDNnw&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34",
+ "https://www.youtube.com/watch?v=XxaRBPyrnBU&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34",
+ "https://www.youtube.com/watch?v=U-9tUEOFKNU&list=PL7u4lWXQ3wfI_7PgX0C-VTiwLeu0S4v34");
}
@Override public long expectedLength() { return 434; }
@Override public long expectedViewCountAtLeast() { return 21229200; }