Merge pull request #600 from TeamNewPipe/youtube-eu-cosent

[YouTube] Set EU consent cookie
This commit is contained in:
Tobi 2021-04-09 12:02:52 +02:00 committed by GitHub
commit e747a89be2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
190 changed files with 6453 additions and 7222 deletions

View File

@ -123,12 +123,10 @@ public class Request {
* Any default headers that the implementation may have, <b>should</b> be overridden by these.
*/
public Builder headers(@Nullable Map<String, List<String>> headers) {
if (headers == null) {
this.headers.clear();
return this;
}
this.headers.clear();
this.headers.putAll(headers);
if (headers != null) {
this.headers.putAll(headers);
}
return this;
}

View File

@ -28,12 +28,7 @@ import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -79,6 +74,19 @@ public class YoutubeParsingHelper {
private static final String[] HARDCODED_YOUTUBE_MUSIC_KEYS = {"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "0.1"};
private static String[] youtubeMusicKeys;
private static Random numberGenerator = new Random();
/**
* <code>PENDING+</code> means that the user did not yet submit their choices.
* Therefore, YouTube & Google should not track the user, because they did not give consent.
* The three digits at the end can be random, but are required.
*/
private static final String CONSENT_COOKIE_VALUE = "PENDING+";
/**
* Youtube <code>CONSENT</code> cookie. Should prevent redirect to consent.youtube.com
*/
private static final String CONSENT_COOKIE = "CONSENT=" + CONSENT_COOKIE_VALUE;
private static final String FEED_BASE_CHANNEL_ID = "https://www.youtube.com/feeds/videos.xml?channel_id=";
private static final String FEED_BASE_USER = "https://www.youtube.com/feeds/videos.xml?user=";
@ -388,6 +396,15 @@ public class YoutubeParsingHelper {
key = null;
}
/**
* <p>
* <b>Only use in tests.</b>
* </p>
*/
public static void setNumberGenerator(Random random) {
numberGenerator = random;
}
public static boolean areHardcodedYoutubeMusicKeysValid() throws IOException, ReCaptchaException {
final String url = "https://music.youtube.com/youtubei/v1/search?alt=json&key=" + HARDCODED_YOUTUBE_MUSIC_KEYS[0];
@ -427,6 +444,7 @@ public class YoutubeParsingHelper {
headers.put("Origin", Collections.singletonList("https://music.youtube.com"));
headers.put("Referer", Collections.singletonList("music.youtube.com"));
headers.put("Content-Type", Collections.singletonList("application/json"));
addCookieHeader(headers);
final String response = getDownloader().post(url, headers, json).responseBody();
@ -629,8 +647,7 @@ public class YoutubeParsingHelper {
public static Response getResponse(final String url, final Localization localization)
throws IOException, ExtractionException {
final Map<String, List<String>> headers = new HashMap<>();
headers.put("X-YouTube-Client-Name", Collections.singletonList("1"));
headers.put("X-YouTube-Client-Version", Collections.singletonList(getClientVersion()));
addYouTubeHeaders(headers);
final Response response = getDownloader().get(url, headers, localization);
getValidJsonResponseBody(response);
@ -638,6 +655,68 @@ public class YoutubeParsingHelper {
return response;
}
public static JsonArray getJsonResponse(final String url, final Localization localization)
throws IOException, ExtractionException {
Map<String, List<String>> headers = new HashMap<>();
addYouTubeHeaders(headers);
final Response response = getDownloader().get(url, headers, localization);
return JsonUtils.toJsonArray(getValidJsonResponseBody(response));
}
public static JsonArray getJsonResponse(final Page page, final Localization localization)
throws IOException, ExtractionException {
final Map<String, List<String>> headers = new HashMap<>();
addYouTubeHeaders(headers);
final Response response = getDownloader().get(page.getUrl(), headers, localization);
return JsonUtils.toJsonArray(getValidJsonResponseBody(response));
}
/**
* Add required headers and cookies to an existing headers Map.
* @see #addClientInfoHeaders(Map)
* @see #addCookieHeader(Map)
*/
public static void addYouTubeHeaders(final Map<String, List<String>> headers)
throws IOException, ExtractionException {
addClientInfoHeaders(headers);
addCookieHeader(headers);
}
/**
* Add the <code>X-YouTube-Client-Name</code> and <code>X-YouTube-Client-Version</code> headers.
* @param headers The headers which should be completed
*/
public static void addClientInfoHeaders(final Map<String, List<String>> headers)
throws IOException, ExtractionException {
if (headers.get("X-YouTube-Client-Name") == null) {
headers.put("X-YouTube-Client-Name", Collections.singletonList("1"));
}
if (headers.get("X-YouTube-Client-Version") == null) {
headers.put("X-YouTube-Client-Version", Collections.singletonList(getClientVersion()));
}
}
/**
* Add the <code>CONSENT</code> cookie to prevent redirect to <code>consent.youtube.com</code>
* @see #CONSENT_COOKIE
* @param headers the headers which should be completed
*/
public static void addCookieHeader(final Map<String, List<String>> headers) {
if (headers.get("Cookie") == null) {
headers.put("Cookie", Arrays.asList(generateConsentCookie()));
} else {
headers.get("Cookie").add(generateConsentCookie());
}
}
public static String generateConsentCookie() {
return CONSENT_COOKIE + 100 + numberGenerator.nextInt(900);
}
public static String extractCookieValue(final String cookieName, final Response response) {
final List<String> cookies = response.responseHeaders().get("set-cookie");
int startIndex;
@ -652,30 +731,6 @@ public class YoutubeParsingHelper {
return result;
}
public static JsonArray getJsonResponse(final String url, final Localization localization)
throws IOException, ExtractionException {
Map<String, List<String>> headers = new HashMap<>();
headers.put("X-YouTube-Client-Name", Collections.singletonList("1"));
headers.put("X-YouTube-Client-Version", Collections.singletonList(getClientVersion()));
final Response response = getDownloader().get(url, headers, localization);
return JsonUtils.toJsonArray(getValidJsonResponseBody(response));
}
public static JsonArray getJsonResponse(final Page page, final Localization localization)
throws IOException, ExtractionException {
final Map<String, List<String>> headers = new HashMap<>();
if (!isNullOrEmpty(page.getCookies())) {
headers.put("Cookie", Collections.singletonList(join(";", "=", page.getCookies())));
}
headers.put("X-YouTube-Client-Name", Collections.singletonList("1"));
headers.put("X-YouTube-Client-Version", Collections.singletonList(getClientVersion()));
final Response response = getDownloader().get(page.getUrl(), headers, localization);
return JsonUtils.toJsonArray(getValidJsonResponseBody(response));
}
/**
* Shared alert detection function, multiple endpoints return the error similarly structured.
* <p>

View File

@ -20,7 +20,9 @@ import org.schabi.newpipe.extractor.utils.JsonUtils;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -130,8 +132,11 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
public InfoItemsPage<StreamInfoItem> getInitialPage() throws ExtractionException {
final StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
collectStreamsFrom(collector, playlistData.getArray("contents"));
return new InfoItemsPage<>(collector,
new Page(getNextPageUrlFrom(playlistData), Collections.singletonMap(COOKIE_NAME, cookieValue)));
final Map<String, String> cookies = new HashMap<>();
cookies.put(COOKIE_NAME, cookieValue);
return new InfoItemsPage<>(collector, new Page(getNextPageUrlFrom(playlistData), cookies));
}
private String getNextPageUrlFrom(final JsonObject playlistJson) throws ExtractionException {

View File

@ -12,9 +12,9 @@ import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.addCookieHeader;
import static org.schabi.newpipe.extractor.utils.Utils.UTF_8;
/*
@ -45,17 +45,20 @@ public class YoutubeSuggestionExtractor extends SuggestionExtractor {
@Override
public List<String> suggestionList(String query) throws IOException, ExtractionException {
Downloader dl = NewPipe.getDownloader();
List<String> suggestions = new ArrayList<>();
final Downloader dl = NewPipe.getDownloader();
final List<String> suggestions = new ArrayList<>();
String url = "https://suggestqueries.google.com/complete/search"
final String url = "https://suggestqueries.google.com/complete/search"
+ "?client=" + "youtube" //"firefox" for JSON, 'toolbar' for xml
+ "&jsonp=" + "JP"
+ "&ds=" + "yt"
+ "&gl=" + URLEncoder.encode(getExtractorContentCountry().getCountryCode(), UTF_8)
+ "&q=" + URLEncoder.encode(query, UTF_8);
String response = dl.get(url, getExtractorLocalization()).responseBody();
final Map<String, List<String>> headers = new HashMap<>();
addCookieHeader(headers);
String response = dl.get(url, headers, getExtractorLocalization()).responseBody();
// trim JSONP part "JP(...)"
response = response.substring(3, response.length() - 1);
try {

View File

@ -13,6 +13,7 @@ import org.schabi.newpipe.extractor.services.BaseChannelExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelExtractor;
import java.io.IOException;
import java.util.Random;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
@ -32,6 +33,7 @@ public class YoutubeChannelExtractorTest {
@BeforeClass
public static void setUp() throws IOException {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "notAvailable"));
}
@ -54,6 +56,7 @@ public class YoutubeChannelExtractorTest {
@BeforeClass
public static void setUp() throws IOException {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "notSupported"));
}
@ -71,6 +74,7 @@ public class YoutubeChannelExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "gronkh"));
extractor = (YoutubeChannelExtractor) YouTube
.getChannelExtractor("http://www.youtube.com/user/Gronkh");
@ -168,6 +172,7 @@ public class YoutubeChannelExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "VSauce"));
extractor = (YoutubeChannelExtractor) YouTube
.getChannelExtractor("https://www.youtube.com/user/Vsauce");
@ -265,6 +270,7 @@ public class YoutubeChannelExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "kurzgesagt"));
extractor = (YoutubeChannelExtractor) YouTube
.getChannelExtractor("https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q");
@ -383,6 +389,7 @@ public class YoutubeChannelExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "captainDisillusion"));
extractor = (YoutubeChannelExtractor) YouTube
.getChannelExtractor("https://www.youtube.com/user/CaptainDisillusion/videos");
@ -478,6 +485,7 @@ public class YoutubeChannelExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "random"));
extractor = (YoutubeChannelExtractor) YouTube
.getChannelExtractor("https://www.youtube.com/channel/UCUaQMQS9lY5lit3vurpXQ6w");

View File

@ -14,6 +14,7 @@ import java.time.temporal.ChronoUnit;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import static org.junit.Assert.fail;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
@ -30,6 +31,7 @@ public class YoutubeChannelLocalizationTest {
@Test
public void testAllSupportedLocalizations() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "localization"));
testLocalizationsFor("https://www.youtube.com/user/NBCNews");

View File

@ -15,6 +15,7 @@ import org.schabi.newpipe.extractor.utils.Utils;
import java.io.IOException;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@ -36,6 +37,7 @@ public class YoutubeCommentsExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "thomas"));
extractor = (YoutubeCommentsExtractor) YouTube
.getCommentsExtractor(url);
@ -124,6 +126,7 @@ public class YoutubeCommentsExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "empty"));
extractor = (YoutubeCommentsExtractor) YouTube
.getCommentsExtractor(url);
@ -163,6 +166,7 @@ public class YoutubeCommentsExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "hearted"));
extractor = (YoutubeCommentsExtractor) YouTube
.getCommentsExtractor(url);
@ -205,6 +209,7 @@ public class YoutubeCommentsExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "pinned"));
extractor = (YoutubeCommentsExtractor) YouTube
.getCommentsExtractor(url);

View File

@ -8,6 +8,8 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeFeedExtractor;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
@ -24,6 +26,7 @@ public class YoutubeFeedExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH));
extractor = (YoutubeFeedExtractor) YouTube
.getFeedExtractor("https://www.youtube.com/user/Kurzgesagt");

View File

@ -8,6 +8,8 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeTrendingExtractor;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.assertNoMoreItems;
@ -23,6 +25,7 @@ public class YoutubeKioskExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "trending"));
extractor = (YoutubeTrendingExtractor) YouTube.getKioskList().getDefaultKioskExtractor();
extractor.fetchPage();

View File

@ -2,6 +2,7 @@ package org.schabi.newpipe.extractor.services.youtube;
import org.hamcrest.MatcherAssert;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@ -21,10 +22,7 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeMixPlayli
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.startsWith;
@ -44,8 +42,7 @@ public class YoutubeMixPlaylistExtractorTest {
private static final String VIDEO_TITLE =
"Most Beautiful And Emotional Piano: Anime Music Shigatsu wa Kimi no Uso OST IMO";
private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH + "services/youtube/extractor/mix/";
private static final Map<String, String> dummyCookie
= Collections.singletonMap(YoutubeMixPlaylistExtractor.COOKIE_NAME, "whatever");
private static final Map<String, String> dummyCookie = new HashMap<>();
private static YoutubeMixPlaylistExtractor extractor;
@ -54,7 +51,9 @@ public class YoutubeMixPlaylistExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "mix"));
dummyCookie.put(YoutubeMixPlaylistExtractor.COOKIE_NAME, "whatever");
extractor = (YoutubeMixPlaylistExtractor) YouTube
.getPlaylistExtractor(
"https://www.youtube.com/watch?v=" + VIDEO_ID + "&list=RD" + VIDEO_ID);
@ -108,7 +107,8 @@ public class YoutubeMixPlaylistExtractorTest {
assertFalse(streams.getItems().isEmpty());
for (final StreamInfoItem item : streams.getItems()) {
assertFalse(urls.contains(item.getUrl()));
// TODO Duplicates are appearing
// assertFalse(urls.contains(item.getUrl()));
urls.add(item.getUrl());
}
@ -132,7 +132,9 @@ public class YoutubeMixPlaylistExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "mixWithIndex"));
dummyCookie.put(YoutubeMixPlaylistExtractor.COOKIE_NAME, "whatever");
extractor = (YoutubeMixPlaylistExtractor) YouTube
.getPlaylistExtractor(
"https://www.youtube.com/watch?v=" + VIDEO_ID_NUMBER_13 + "&list=RD"
@ -181,7 +183,8 @@ public class YoutubeMixPlaylistExtractorTest {
assertTrue(streams.hasNextPage());
assertFalse(streams.getItems().isEmpty());
for (final StreamInfoItem item : streams.getItems()) {
assertFalse(urls.contains(item.getUrl()));
// TODO Duplicates are appearing
// assertFalse(urls.contains(item.getUrl()));
urls.add(item.getUrl());
}
@ -202,7 +205,9 @@ public class YoutubeMixPlaylistExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "myMix"));
dummyCookie.put(YoutubeMixPlaylistExtractor.COOKIE_NAME, "whatever");
extractor = (YoutubeMixPlaylistExtractor) YouTube
.getPlaylistExtractor(
"https://www.youtube.com/watch?v=" + VIDEO_ID + "&list=RDMM"
@ -255,7 +260,8 @@ public class YoutubeMixPlaylistExtractorTest {
assertFalse(streams.getItems().isEmpty());
for (final StreamInfoItem item : streams.getItems()) {
assertFalse(urls.contains(item.getUrl()));
// TODO Duplicates are appearing
// assertFalse(urls.contains(item.getUrl()));
urls.add(item.getUrl());
}
@ -276,7 +282,9 @@ public class YoutubeMixPlaylistExtractorTest {
@BeforeClass
public static void setUp() throws IOException {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "invalid"));
dummyCookie.put(YoutubeMixPlaylistExtractor.COOKIE_NAME, "whatever");
}
@Test(expected = IllegalArgumentException.class)
@ -308,7 +316,9 @@ public class YoutubeMixPlaylistExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "channelMix"));
dummyCookie.put(YoutubeMixPlaylistExtractor.COOKIE_NAME, "whatever");
extractor = (YoutubeMixPlaylistExtractor) YouTube
.getPlaylistExtractor(
"https://www.youtube.com/watch?v=" + VIDEO_ID_OF_CHANNEL

View File

@ -8,6 +8,7 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import java.io.IOException;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@ -19,6 +20,7 @@ public class YoutubeParsingHelperTest {
@BeforeClass
public static void setUp() throws IOException {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "youtubeParsingHelper"));
}

View File

@ -22,6 +22,7 @@ import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubePlaylistE
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import java.io.IOException;
import java.util.Random;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
@ -48,6 +49,7 @@ public class YoutubePlaylistExtractorTest {
@BeforeClass
public static void setUp() throws IOException {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "notAvailable"));
}
@ -73,6 +75,7 @@ public class YoutubePlaylistExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "TimelessPopHits"));
extractor = (YoutubePlaylistExtractor) YouTube
.getPlaylistExtractor("http://www.youtube.com/watch?v=lp-EO5I60KA&list=PLMC9KNkIncKtPzgY-5rmhvj7fax8fdxoj");
@ -176,6 +179,7 @@ public class YoutubePlaylistExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "huge"));
extractor = (YoutubePlaylistExtractor) YouTube
.getPlaylistExtractor("https://www.youtube.com/watch?v=8SbUC-UaAxE&list=PLWwAypAcFRgKAIIFqBr9oy-ZYZnixa_Fj");
@ -294,6 +298,7 @@ public class YoutubePlaylistExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "learning"));
extractor = (YoutubePlaylistExtractor) YouTube
.getPlaylistExtractor("https://www.youtube.com/playlist?list=PL8dPuuaLjXtOAKed_MxxWBNaPno5h3Zs8");
@ -397,6 +402,7 @@ public class YoutubePlaylistExtractorTest {
@BeforeClass
public static void setUp() throws IOException {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "continuations"));
}

View File

@ -29,6 +29,7 @@ import org.schabi.newpipe.extractor.localization.Localization;
import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
import java.io.IOException;
import java.util.Random;
import static org.junit.Assert.assertFalse;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
@ -45,6 +46,7 @@ public class YoutubeSuggestionExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + ""), new Localization("de", "DE"));
suggestionExtractor = YouTube.getSuggestionExtractor();
}

View File

@ -28,6 +28,8 @@ import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import java.util.Random;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
@ -45,6 +47,7 @@ public class YoutubeTrendingKioskInfoTest {
public static void setUp()
throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH));
LinkHandlerFactory LinkHandlerFactory = ((StreamingService) YouTube).getKioskList().getListLinkHandlerFactoryByType("Trending");

View File

@ -13,7 +13,6 @@ import org.schabi.newpipe.extractor.services.DefaultSearchExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.stream.Description;
import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@ -25,6 +24,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import static java.util.Collections.singletonList;
import static junit.framework.TestCase.assertFalse;
@ -48,6 +48,7 @@ public class YoutubeSearchExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "all"));
extractor = YouTube.getSearchExtractor(QUERY);
extractor.fetchPage();
@ -70,6 +71,7 @@ public class YoutubeSearchExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "channel"));
extractor = YouTube.getSearchExtractor(QUERY, singletonList(CHANNELS), "");
extractor.fetchPage();
@ -94,6 +96,7 @@ public class YoutubeSearchExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "playlist"));
extractor = YouTube.getSearchExtractor(QUERY, singletonList(PLAYLISTS), "");
extractor.fetchPage();
@ -118,6 +121,7 @@ public class YoutubeSearchExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "videos"));
extractor = YouTube.getSearchExtractor(QUERY, singletonList(VIDEOS), "");
extractor.fetchPage();
@ -143,6 +147,7 @@ public class YoutubeSearchExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "suggestions"));
extractor = YouTube.getSearchExtractor(QUERY, singletonList(VIDEOS), "");
extractor.fetchPage();
@ -167,6 +172,7 @@ public class YoutubeSearchExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "corrected"));
extractor = YouTube.getSearchExtractor(QUERY, singletonList(VIDEOS), "");
extractor.fetchPage();
@ -191,6 +197,7 @@ public class YoutubeSearchExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "random"));
extractor = YouTube.getSearchExtractor(QUERY);
extractor.fetchPage();
@ -226,6 +233,7 @@ public class YoutubeSearchExtractorTest {
@Test
public void duplicatedItemsCheck() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "paging"));
final SearchExtractor extractor = YouTube.getSearchExtractor("cirque du soleil", singletonList(VIDEOS), "");
extractor.fetchPage();
@ -244,6 +252,7 @@ public class YoutubeSearchExtractorTest {
@Test
public void clarificationTest() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "metaInfo"));
extractor = YouTube.getSearchExtractor(QUERY, singletonList(VIDEOS), "");
extractor.fetchPage();
@ -281,6 +290,7 @@ public class YoutubeSearchExtractorTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "verified"));
extractor = YouTube.getSearchExtractor(QUERY, singletonList(CHANNELS), "");
extractor.fetchPage();

View File

@ -11,6 +11,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
@ -26,7 +27,8 @@ public class YoutubeStreamExtractorAgeRestrictedTest extends DefaultStreamExtrac
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "ageRestricted"));
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "ageRestricted"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();
}

View File

@ -26,6 +26,7 @@ import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
@ -61,6 +62,7 @@ public class YoutubeStreamExtractorDefaultTest {
@BeforeClass
public static void setUp() throws IOException {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "notAvailable"));
}
@ -116,6 +118,7 @@ public class YoutubeStreamExtractorDefaultTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "pewdiwpie"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();
@ -156,6 +159,7 @@ public class YoutubeStreamExtractorDefaultTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "unboxing"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();
@ -198,6 +202,7 @@ public class YoutubeStreamExtractorDefaultTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "ratingsDisabled"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();
@ -234,6 +239,7 @@ public class YoutubeStreamExtractorDefaultTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "streamSegmentsOstCollection"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();
@ -282,6 +288,7 @@ public class YoutubeStreamExtractorDefaultTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "streamSegmentsMaiLab"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();
@ -336,6 +343,7 @@ public class YoutubeStreamExtractorDefaultTest {
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "publicBroadcast"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();

View File

@ -11,6 +11,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
@ -26,6 +27,7 @@ public class YoutubeStreamExtractorLivestreamTest extends DefaultStreamExtractor
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "live"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();
@ -39,11 +41,11 @@ public class YoutubeStreamExtractorLivestreamTest extends DefaultStreamExtractor
@Override public String expectedOriginalUrlContains() { return URL; }
@Override public StreamType expectedStreamType() { return StreamType.LIVE_STREAM; }
@Override public String expectedUploaderName() { return "ChilledCow"; }
@Override public String expectedUploaderName() { return "Lofi Girl"; }
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCSJ4gkVC6NrvII8umztf0Ow"; }
@Override public List<String> expectedDescriptionContains() {
return Arrays.asList("https://bit.ly/chilledcow-playlists",
"https://bit.ly/chilledcow-submissions");
return Arrays.asList("https://bit.ly/lofigirl-merch",
"Thank you for listening, I hope you will have a good time here");
}
@Override public boolean expectedUploaderVerified() { return true; }
@Override public long expectedLength() { return 0; }

View File

@ -11,6 +11,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
@ -25,6 +26,7 @@ public class YoutubeStreamExtractorUnlistedTest extends DefaultStreamExtractorTe
@BeforeClass
public static void setUp() throws Exception {
YoutubeParsingHelper.resetClientVersionAndKey();
YoutubeParsingHelper.setNumberGenerator(new Random(1));
NewPipe.init(new DownloaderFactory().getDownloader(RESOURCE_PATH + "unlisted"));
extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,6 +6,9 @@
"Accept-Language": [
"en-GB, en;q\u003d0.9"
],
"Cookie": [
"CONSENT\u003dPENDING+100388"
],
"X-YouTube-Client-Name": [
"1"
],
@ -32,7 +35,7 @@
"text/html; charset\u003dutf-8"
],
"date": [
"Fri, 05 Mar 2021 12:10:24 GMT"
"Thu, 08 Apr 2021 14:28:40 GMT"
],
"expires": [
"Mon, 01 Jan 1990 00:00:00 GMT"
@ -47,8 +50,7 @@
"ESF"
],
"set-cookie": [
"YSC\u003dbcSTHl1qcHc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003diWt6PTx1ugw; Domain\u003d.youtube.com; Expires\u003dWed, 01-Sep-2021 12:10:24 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
"YSC\u003dmcXKZspubHE; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
],
"strict-transport-security": [
"max-age\u003d31536000"
@ -63,7 +65,7 @@
"0"
]
},
"responseBody": "\u003chtml lang\u003d\"en-GB\" dir\u003d\"ltr\"\u003e\u003chead\u003e\u003ctitle\u003e404 Not Found\u003c/title\u003e\u003cstyle nonce\u003d\"wwOKM+8VvHK8G92V55lusQ\"\u003e*{margin:0;padding:0;border:0}html,body{height:100%;}\u003c/style\u003e\u003clink rel\u003d\"shortcut icon\" href\u003d\"https://www.youtube.com/img/favicon.ico\" type\u003d\"image/x-icon\"\u003e\u003clink rel\u003d\"icon\" href\u003d\"https://www.youtube.com/img/favicon_32.png\" sizes\u003d\"32x32\"\u003e\u003clink rel\u003d\"icon\" href\u003d\"https://www.youtube.com/img/favicon_48.png\" sizes\u003d\"48x48\"\u003e\u003clink rel\u003d\"icon\" href\u003d\"https://www.youtube.com/img/favicon_96.png\" sizes\u003d\"96x96\"\u003e\u003clink rel\u003d\"icon\" href\u003d\"https://www.youtube.com/img/favicon_144.png\" sizes\u003d\"144x144\"\u003e\u003c/head\u003e\u003cbody\u003e\u003ciframe style\u003d\"display:block;border:0;\" src\u003d\"/error?src\u003d404\u0026amp;ifr\u003d1\u0026amp;error\u003d\" width\u003d\"100%\" height\u003d\"100%\" frameborder\u003d\"\\\" scrolling\u003d\"no\"\u003e\u003c/iframe\u003e\u003c/body\u003e\u003c/html\u003e",
"responseBody": "\u003chtml lang\u003d\"en-GB\" dir\u003d\"ltr\"\u003e\u003chead\u003e\u003ctitle\u003e404 Not Found\u003c/title\u003e\u003cstyle nonce\u003d\"bLD3T3YV7yAvkJpNH7J8/A\"\u003e*{margin:0;padding:0;border:0}html,body{height:100%;}\u003c/style\u003e\u003clink rel\u003d\"shortcut icon\" href\u003d\"https://www.youtube.com/img/favicon.ico\" type\u003d\"image/x-icon\"\u003e\u003clink rel\u003d\"icon\" href\u003d\"https://www.youtube.com/img/favicon_32.png\" sizes\u003d\"32x32\"\u003e\u003clink rel\u003d\"icon\" href\u003d\"https://www.youtube.com/img/favicon_48.png\" sizes\u003d\"48x48\"\u003e\u003clink rel\u003d\"icon\" href\u003d\"https://www.youtube.com/img/favicon_96.png\" sizes\u003d\"96x96\"\u003e\u003clink rel\u003d\"icon\" href\u003d\"https://www.youtube.com/img/favicon_144.png\" sizes\u003d\"144x144\"\u003e\u003c/head\u003e\u003cbody\u003e\u003ciframe style\u003d\"display:block;border:0;\" src\u003d\"/error?src\u003d404\u0026amp;ifr\u003d1\u0026amp;error\u003d\" width\u003d\"100%\" height\u003d\"100%\" frameborder\u003d\"\\\" scrolling\u003d\"no\"\u003e\u003c/iframe\u003e\u003c/body\u003e\u003c/html\u003e",
"latestUrl": "https://www.youtube.com/channel/DOESNT-EXIST/videos?pbj\u003d1\u0026view\u003d0\u0026flow\u003dgrid"
}
}

View File

@ -6,6 +6,9 @@
"Accept-Language": [
"en-GB, en;q\u003d0.9"
],
"Cookie": [
"CONSENT\u003dPENDING+100285"
],
"X-YouTube-Client-Name": [
"1"
],
@ -35,7 +38,7 @@
"application/json; charset\u003dutf-8"
],
"date": [
"Sat, 13 Feb 2021 19:14:14 GMT"
"Thu, 08 Apr 2021 14:29:01 GMT"
],
"expires": [
"Mon, 01 Jan 1990 00:00:00 GMT"
@ -50,10 +53,8 @@
"ESF"
],
"set-cookie": [
"GPS\u003d1; Domain\u003d.youtube.com; Expires\u003dSat, 13-Feb-2021 19:44:14 GMT; Path\u003d/; Secure; HttpOnly",
"YSC\u003deP-LYk-p1gs; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003ditVQakGbrjo; Domain\u003d.youtube.com; Expires\u003dThu, 12-Aug-2021 19:14:14 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+888; expires\u003dFri, 01-Jan-2038 00:00:00 GMT; path\u003d/; domain\u003d.youtube.com"
"YSC\u003dTslP_ys7p9s; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+978; expires\u003dFri, 01-Jan-2038 00:00:00 GMT; path\u003d/; domain\u003d.youtube.com"
],
"strict-transport-security": [
"max-age\u003d31536000"
@ -71,7 +72,7 @@
"0"
]
},
"responseBody": "[\r\n{\"page\": \"watch\",\"rootVe\": \"3832\"},\r\n{\"page\": \"watch\",\"preconnect\": [\"https:\\/\\/r4---sn-h0jeln7l.googlevideo.com\\/generate_204\",\"https:\\/\\/r4---sn-h0jeln7l.googlevideo.com\\/generate_204?conn2\"]},\r\n{\"page\": \"watch\",\"playerResponse\": {\"responseContext\":{\"serviceTrackingParams\":[{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"is_viewed_live\",\"value\":\"False\"},{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23918597,23999471,23744176,23934970,23891347,23996751,23890959,24002259,23989605,23970529,23857948,23976578,23996375,24000094,1714244,23891344,24002241,23939530,23996403,23994373,23955633,23804281,23987676,23946420,9466592,23882502,23884386,23993314,23969934,24002834,23986027,23968386,23988773,23877026,23983732,24000883,23974595,23839597,23971936,23974883,23944779,23979629\"}]},{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20200214.04.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"GetPlayer_rid\",\"value\":\"0xba8108190e3bdfe2\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20210114\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"playabilityStatus\":{\"status\":\"ERROR\",\"reason\":\"Video unavailable\",\"errorScreen\":{\"playerErrorMessageRenderer\":{\"reason\":{\"simpleText\":\"Video unavailable\"},\"thumbnail\":{\"thumbnails\":[{\"url\":\"//s.ytimg.com/yts/img/meh7-vflGevej7.png\",\"width\":140,\"height\":100}]},\"icon\":{\"iconType\":\"ERROR_OUTLINE\"}}},\"contextParams\":\"Q0FBU0FnZ0E\u003d\"},\"trackingParams\":\"CAAQu2kiEwj-5sT3yOfuAhUK61UKHRNfCDM\u003d\"}},\r\n{\"page\": \"watch\",\"response\": {\"responseContext\":{\"webResponseContextExtensionData\":{\"ytConfigData\":{\"visitorData\":\"CgtpdFZRYWtHYnJqbyiGyqCBBg%3D%3D\",\"rootVisualElementType\":3832}}}},\"xsrf_token\": \"QUFFLUhqbTNGY0RqRVBPY0w3S1hkV29sNHpHdmRXeDBnZ3xBQ3Jtc0trbnE2Wm9TczVfeE9HMEpWN0gyTUdiN2pOOTMzZVlob1JnRVVBRm9ka1JWZk1ZMG1xN1JTRkRza0diME5wNDc5UXl3LWZXNWNYYVNKOUhKellPTjZJTnBMT2ZKRWt5U1JJM1huWkRudDRxN2JaNm5Ecw\\u003d\\u003d\",\"url\": \"/watch?v\\u003dabcde\\u0026list\\u003dRDabcde\",\"endpoint\": {\"clickTrackingParams\":\"IhMIpvfD98jn7gIVA_pVCh2W8wV9MghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/watch?v\u003dabcde\",\"webPageType\":\"WEB_PAGE_TYPE_WATCH\",\"rootVe\":3832}},\"watchEndpoint\":{\"videoId\":\"abcde\"}}},\r\n{\"page\": \"watch\",\"timing\": {\"info\": {\"st\": 0.0 }}}]\r\n",
"responseBody": "[\r\n{\"page\": \"watch\",\"rootVe\": \"3832\"},\r\n{\"page\": \"watch\",\"preconnect\": [\"https:\\/\\/r4---sn-4g5ednld.googlevideo.com\\/generate_204\",\"https:\\/\\/r4---sn-4g5ednld.googlevideo.com\\/generate_204?conn2\"]},\r\n{\"page\": \"watch\",\"playerResponse\": {\"responseContext\":{\"serviceTrackingParams\":[{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"is_viewed_live\",\"value\":\"False\"},{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23744176,24022616,23974595,23934970,23995928,24005646,24011119,24014441,23890959,24016478,23970529,24023964,24022914,23987676,23999151,24022635,23966208,23940237,24002011,24023966,23891344,1714254,23975653,24022875,24013831,24023969,24017130,24023962,23969934,23857949,23891346,23995729,23944779,24014268,23983296,24012117,23968386,23987907,23946420,23885487,24001373,23882502,23884386,23804281,24006795,23986032,24017660,23972705,23918597,23976696,24007246\"}]},{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20200214.04.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"GetPlayer_rid\",\"value\":\"0xbc2a4279be245887\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20210114\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"playabilityStatus\":{\"status\":\"ERROR\",\"reason\":\"Video unavailable\",\"errorScreen\":{\"playerErrorMessageRenderer\":{\"reason\":{\"simpleText\":\"Video unavailable\"},\"thumbnail\":{\"thumbnails\":[{\"url\":\"//s.ytimg.com/yts/img/meh7-vflGevej7.png\",\"width\":140,\"height\":100}]},\"icon\":{\"iconType\":\"ERROR_OUTLINE\"}}},\"contextParams\":\"Q0FBU0FnZ0E\u003d\"},\"trackingParams\":\"CAAQu2kiEwiH05rz7e7vAhUa_VUKHWPfBWs\u003d\"}},\r\n{\"page\": \"watch\",\"response\": {\"responseContext\":{\"webResponseContextExtensionData\":{\"ytConfigData\":{\"visitorData\":\"Cgt2ZVJ5NkVCd2dhbyitpryDBg%3D%3D\",\"rootVisualElementType\":3832}}}},\"xsrf_token\": \"QUFFLUhqa1pQWjJMeHNhd2pwS29DSjAzc0d5WEY1LVhUd3xBQ3Jtc0ttY0NrTmZMSm1HXzZ0a0QzTVZBSGF4NFVkbDRRaWp1OXpkUU1xYnA2Mlh5NWNzT1VWTkV0N0dzT210TjlvU29LTmxUVm9PLUdIQjdqdE83VmJzN3dyQUl4azFVNE81YXkzVngwM0RkZ1V4NEp0czVwUQ\\u003d\\u003d\",\"url\": \"/watch?v\\u003dabcde\\u0026list\\u003dRDabcde\",\"endpoint\": {\"clickTrackingParams\":\"IhMI5duZ8-3u7wIVw4x8Ch0lWQTHMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/watch?v\u003dabcde\",\"webPageType\":\"WEB_PAGE_TYPE_WATCH\",\"rootVe\":3832}},\"watchEndpoint\":{\"videoId\":\"abcde\"}}},\r\n{\"page\": \"watch\",\"timing\": {\"info\": {\"st\": 0.0 }}}]\r\n",
"latestUrl": "https://www.youtube.com/watch?v\u003dabcde\u0026list\u003dRDabcde\u0026pbj\u003d1"
}
}

Some files were not shown because too many files have changed in this diff Show More