Skip to content

Commit f91454d

Browse files
litetexTobiGr
authored andcommitted
[YT] Correctly resolve redirects when resolving channel ids
1 parent 4701c56 commit f91454d

1 file changed

Lines changed: 41 additions & 17 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelHelper.java

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
package org.schabi.newpipe.extractor.services.youtube;
22

3+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.defaultAlertsCheck;
4+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
5+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
6+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.hasArtistOrVerifiedIconBadgeAttachment;
7+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
8+
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
9+
310
import com.grack.nanojson.JsonObject;
411
import com.grack.nanojson.JsonWriter;
12+
513
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
614
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
715
import org.schabi.newpipe.extractor.exceptions.ParsingException;
816
import org.schabi.newpipe.extractor.localization.ContentCountry;
917
import org.schabi.newpipe.extractor.localization.Localization;
1018

11-
import javax.annotation.Nonnull;
12-
import javax.annotation.Nullable;
1319
import java.io.IOException;
1420
import java.io.Serializable;
1521
import java.nio.charset.StandardCharsets;
1622
import java.util.Optional;
1723

18-
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.defaultAlertsCheck;
19-
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
20-
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
21-
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.hasArtistOrVerifiedIconBadgeAttachment;
22-
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
23-
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
24+
import javax.annotation.Nonnull;
25+
import javax.annotation.Nullable;
2426

2527
/**
2628
* Shared functions for extracting YouTube channel pages and tabs.
@@ -65,25 +67,42 @@ public static String resolveChannelId(@Nonnull final String idOrPath)
6567
// URL, then no information about the channel associated with this URL was found,
6668
// so the unresolved url will be returned.
6769
if (!channelId[0].equals("channel")) {
68-
final byte[] body = JsonWriter.string(
69-
prepareDesktopJsonBuilder(Localization.DEFAULT, ContentCountry.DEFAULT)
70-
.value("url", "https://www.youtube.com/" + idOrPath)
70+
String urlToResolve = "https://www.youtube.com/" + idOrPath;
71+
72+
JsonObject endpoint = new JsonObject();
73+
String webPageType = "";
74+
// Try to resolve YT channel redirects
75+
// It works like that:
76+
// @TheDailyShow
77+
// -> resolves to thedailyshow
78+
// -> resolves to the id: UCwWhs_6x42TyRM4Wstoq8HA
79+
for (int tries = 0;
80+
urlToResolve != null && tries < 3;
81+
tries++) {
82+
final byte[] body = JsonWriter.string(
83+
prepareDesktopJsonBuilder(Localization.DEFAULT, ContentCountry.DEFAULT)
84+
.value("url", urlToResolve)
7185
.done())
7286
.getBytes(StandardCharsets.UTF_8);
7387

74-
final JsonObject jsonResponse = getJsonPostResponse(
88+
final JsonObject jsonResponse = getJsonPostResponse(
7589
"navigation/resolve_url", body, Localization.DEFAULT);
7690

77-
checkIfChannelResponseIsValid(jsonResponse);
91+
checkIfChannelResponseIsValid(jsonResponse);
7892

79-
final JsonObject endpoint = jsonResponse.getObject("endpoint");
93+
endpoint = jsonResponse.getObject("endpoint");
8094

81-
final String webPageType = endpoint.getObject("commandMetadata")
95+
webPageType = endpoint.getObject("commandMetadata")
8296
.getObject("webCommandMetadata")
8397
.getString("webPageType", "");
8498

85-
final JsonObject browseEndpoint = endpoint.getObject(BROWSE_ENDPOINT);
86-
final String browseId = browseEndpoint.getString(BROWSE_ID, "");
99+
urlToResolve = "WEB_PAGE_TYPE_UNKNOWN".equals(webPageType)
100+
? endpoint.getObject("urlEndpoint").getString("url")
101+
: null;
102+
}
103+
104+
final String browseId = endpoint.getObject(BROWSE_ENDPOINT)
105+
.getString(BROWSE_ID, "");
87106

88107
if (webPageType.equalsIgnoreCase("WEB_PAGE_TYPE_BROWSE")
89108
|| webPageType.equalsIgnoreCase("WEB_PAGE_TYPE_CHANNEL")
@@ -94,6 +113,11 @@ public static String resolveChannelId(@Nonnull final String idOrPath)
94113

95114
return browseId;
96115
}
116+
117+
// Otherwise the code after that will run into an IndexOutOfBoundsException
118+
if (channelId.length < 2) {
119+
throw new ExtractionException("Failed to resolve channelId for " + idOrPath);
120+
}
97121
}
98122

99123
// return the unresolved URL

0 commit comments

Comments
 (0)