Skip to content

Commit bc0cda6

Browse files
authored
Merge pull request #570 from TiA4f8R/fix-yt-channels-playlists
Fix YouTube channels contination
2 parents a3c6fce + 440a808 commit bc0cda6

30 files changed

Lines changed: 1656 additions & 244 deletions

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
import com.grack.nanojson.JsonArray;
44
import com.grack.nanojson.JsonObject;
5+
import com.grack.nanojson.JsonWriter;
6+
57
import org.schabi.newpipe.extractor.Page;
68
import org.schabi.newpipe.extractor.StreamingService;
79
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
810
import org.schabi.newpipe.extractor.downloader.Downloader;
11+
import org.schabi.newpipe.extractor.downloader.Response;
912
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
1013
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
1114
import org.schabi.newpipe.extractor.exceptions.ParsingException;
@@ -15,13 +18,20 @@
1518
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory;
1619
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
1720
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
21+
import org.schabi.newpipe.extractor.utils.JsonUtils;
1822
import org.schabi.newpipe.extractor.utils.Utils;
1923

2024
import javax.annotation.Nonnull;
2125
import java.io.IOException;
2226

23-
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.*;
27+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.fixThumbnailUrl;
28+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getClientVersion;
29+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonResponse;
30+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
31+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey;
32+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getValidJsonResponseBody;
2433
import static org.schabi.newpipe.extractor.utils.Utils.EMPTY_STRING;
34+
import static org.schabi.newpipe.extractor.utils.Utils.UTF_8;
2535
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
2636

2737
/*
@@ -226,7 +236,7 @@ public boolean isVerified() throws ParsingException {
226236

227237
@Nonnull
228238
@Override
229-
public InfoItemsPage<StreamInfoItem> getInitialPage() throws ExtractionException {
239+
public InfoItemsPage<StreamInfoItem> getInitialPage() throws IOException, ExtractionException {
230240
final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
231241

232242
Page nextPage = null;
@@ -254,27 +264,44 @@ public InfoItemsPage<StreamInfoItem> getPage(final Page page) throws IOException
254264
// as they don't deliver enough information on their own (the channel name, for example).
255265
fetchPage();
256266

267+
// @formatter:off
268+
byte[] json = JsonWriter.string()
269+
.object()
270+
.object("context")
271+
.object("client")
272+
.value("clientName", "1")
273+
.value("clientVersion", getClientVersion())
274+
.end()
275+
.end()
276+
.value("continuation", page.getId())
277+
.end()
278+
.done()
279+
.getBytes(UTF_8);
280+
// @formatter:on
281+
257282
StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
258-
final JsonArray ajaxJson = getJsonResponse(page.getUrl(), getExtractorLocalization());
283+
final Response response = getDownloader().post(page.getUrl(), null, json, getExtractorLocalization());
284+
285+
final JsonObject ajaxJson = JsonUtils.toJsonObject(getValidJsonResponseBody(response));
259286

260-
JsonObject sectionListContinuation = ajaxJson.getObject(1).getObject("response")
261-
.getArray("onResponseReceivedActions").getObject(0).getObject("appendContinuationItemsAction");
287+
JsonObject sectionListContinuation = ajaxJson.getArray("onResponseReceivedActions")
288+
.getObject(0)
289+
.getObject("appendContinuationItemsAction");
262290

263291
final JsonObject continuation = collectStreamsFrom(collector, sectionListContinuation.getArray("continuationItems"));
264292

265293
return new InfoItemsPage<>(collector, getNextPageFrom(continuation));
266294
}
267295

268-
private Page getNextPageFrom(final JsonObject continuations) {
296+
private Page getNextPageFrom(final JsonObject continuations) throws IOException, ExtractionException {
269297
if (isNullOrEmpty(continuations)) {
270298
return null;
271299
}
272300

273301
final JsonObject continuationEndpoint = continuations.getObject("continuationEndpoint");
274302
final String continuation = continuationEndpoint.getObject("continuationCommand").getString("token");
275-
final String clickTrackingParams = continuationEndpoint.getString("clickTrackingParams");
276-
return new Page("https://www.youtube.com/browse_ajax?ctoken=" + continuation
277-
+ "&continuation=" + continuation + "&itct=" + clickTrackingParams);
303+
return new Page("https://www.youtube.com/youtubei/v1/browse?key=" + getKey(),
304+
continuation);
278305
}
279306

280307
/**

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/channel/VSauce/generated_mock_0.json

Lines changed: 6 additions & 6 deletions
Large diffs are not rendered by default.

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/channel/VSauce/generated_mock_1.json

Lines changed: 6 additions & 6 deletions
Large diffs are not rendered by default.

extractor/src/test/resources/org/schabi/newpipe/extractor/services/youtube/extractor/channel/VSauce/generated_mock_2.json

Lines changed: 16 additions & 24 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)