Merge pull request #1127 from AudricV/yt_improvements-and-fixes
[YouTube] Make some improvements and fixes
This commit is contained in:
commit
678c98f24c
|
@ -152,7 +152,7 @@ public final class YoutubeParsingHelper {
|
|||
* The client version for InnerTube requests with the {@code WEB} client, used as the last
|
||||
* fallback if the extraction of the real one failed.
|
||||
*/
|
||||
private static final String HARDCODED_CLIENT_VERSION = "2.20220809.02.00";
|
||||
private static final String HARDCODED_CLIENT_VERSION = "2.20231208.01.00";
|
||||
|
||||
/**
|
||||
* The InnerTube API key which should be used by YouTube's desktop website, used as a fallback
|
||||
|
@ -169,7 +169,7 @@ public final class YoutubeParsingHelper {
|
|||
* such as <a href="https://www.apkmirror.com/apk/google-inc/youtube/">APKMirror</a>.
|
||||
* </p>
|
||||
*/
|
||||
private static final String ANDROID_YOUTUBE_CLIENT_VERSION = "17.31.35";
|
||||
private static final String ANDROID_YOUTUBE_CLIENT_VERSION = "18.48.37";
|
||||
|
||||
/**
|
||||
* The InnerTube API key used by the {@code ANDROID} client. Found with the help of
|
||||
|
@ -187,7 +187,7 @@ public final class YoutubeParsingHelper {
|
|||
* Store page of the YouTube app</a>, in the {@code What’s New} section.
|
||||
* </p>
|
||||
*/
|
||||
private static final String IOS_YOUTUBE_CLIENT_VERSION = "17.31.4";
|
||||
private static final String IOS_YOUTUBE_CLIENT_VERSION = "18.48.3";
|
||||
|
||||
/**
|
||||
* The InnerTube API key used by the {@code iOS} client. Found with the help of
|
||||
|
@ -204,7 +204,7 @@ public final class YoutubeParsingHelper {
|
|||
private static String key;
|
||||
|
||||
private static final String[] HARDCODED_YOUTUBE_MUSIC_KEY =
|
||||
{"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "1.20220808.01.00"};
|
||||
{"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "1.20231204.01.00"};
|
||||
private static String[] youtubeMusicKey;
|
||||
|
||||
private static boolean keyAndVersionExtracted = false;
|
||||
|
@ -228,14 +228,14 @@ public final class YoutubeParsingHelper {
|
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
||||
/**
|
||||
* The device machine id for the iPhone 13, used to get 60fps with the {@code iOS} client.
|
||||
* The device machine id for the iPhone 15, used to get 60fps with the {@code iOS} client.
|
||||
*
|
||||
* <p>
|
||||
* See <a href="https://gist.github.com/adamawolf/3048717">this GitHub Gist</a> for more
|
||||
* information.
|
||||
* </p>
|
||||
*/
|
||||
private static final String IOS_DEVICE_MODEL = "iPhone14,5";
|
||||
private static final String IOS_DEVICE_MODEL = "iPhone15,4";
|
||||
|
||||
private static Random numberGenerator = new Random();
|
||||
|
||||
|
@ -260,21 +260,6 @@ public final class YoutubeParsingHelper {
|
|||
private static final Set<String> YOUTUBE_URLS = Set.of("youtube.com", "www.youtube.com",
|
||||
"m.youtube.com", "music.youtube.com");
|
||||
|
||||
/**
|
||||
* Determines how the consent cookie (that is required for YouTube) will be generated.
|
||||
*
|
||||
* <p>
|
||||
* {@code false} (default) will use {@code PENDING+}.
|
||||
* {@code true} will use {@code YES+}.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Setting this value to <code>true</code> is currently needed if you want to watch
|
||||
* Mix Playlists in some countries (EU).
|
||||
* </p>
|
||||
*
|
||||
* @see #generateConsentCookie()
|
||||
*/
|
||||
private static boolean consentAccepted = false;
|
||||
|
||||
private static boolean isGoogleURL(final String url) {
|
||||
|
@ -551,12 +536,21 @@ public final class YoutubeParsingHelper {
|
|||
.value("gl", "GB")
|
||||
.value("clientName", "WEB")
|
||||
.value("clientVersion", HARDCODED_CLIENT_VERSION)
|
||||
.value("platform", "DESKTOP")
|
||||
.value("utcOffsetMinutes", 0)
|
||||
.end()
|
||||
.object("request")
|
||||
.array("internalExperimentFlags")
|
||||
.end()
|
||||
.value("useSsl", true)
|
||||
.end()
|
||||
.object("user")
|
||||
// TODO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.object("user")
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.value("fetchLiveState", true)
|
||||
.end()
|
||||
.end().done().getBytes(StandardCharsets.UTF_8);
|
||||
// @formatter:on
|
||||
|
||||
|
@ -770,7 +764,7 @@ public final class YoutubeParsingHelper {
|
|||
public static boolean isHardcodedYoutubeMusicKeyValid() throws IOException,
|
||||
ReCaptchaException {
|
||||
final String url =
|
||||
"https://music.youtube.com/youtubei/v1/music/get_search_suggestions?alt=json&key="
|
||||
"https://music.youtube.com/youtubei/v1/music/get_search_suggestions?key="
|
||||
+ HARDCODED_YOUTUBE_MUSIC_KEY[0] + DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
|
||||
// @formatter:off
|
||||
|
@ -782,19 +776,18 @@ public final class YoutubeParsingHelper {
|
|||
.value("clientVersion", HARDCODED_YOUTUBE_MUSIC_KEY[2])
|
||||
.value("hl", "en-GB")
|
||||
.value("gl", "GB")
|
||||
.array("experimentIds").end()
|
||||
.value("experimentsToken", "")
|
||||
.object("locationInfo").end()
|
||||
.object("musicAppInfo").end()
|
||||
.value("platform", "DESKTOP")
|
||||
.value("utcOffsetMinutes", 0)
|
||||
.end()
|
||||
.object("capabilities").end()
|
||||
.object("request")
|
||||
.array("internalExperimentFlags").end()
|
||||
.object("sessionIndex").end()
|
||||
.array("internalExperimentFlags")
|
||||
.end()
|
||||
.value("useSsl", true)
|
||||
.end()
|
||||
.object("activePlayers").end()
|
||||
.object("user")
|
||||
.value("enableSafetyMode", false)
|
||||
// TODO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.end()
|
||||
.value("input", "")
|
||||
|
@ -1296,7 +1289,8 @@ public final class YoutubeParsingHelper {
|
|||
.value("clientName", "WEB")
|
||||
.value("clientVersion", getClientVersion())
|
||||
.value("originalUrl", "https://www.youtube.com")
|
||||
.value("platform", "DESKTOP");
|
||||
.value("platform", "DESKTOP")
|
||||
.value("utcOffsetMinutes", 0);
|
||||
|
||||
if (visitorData != null) {
|
||||
builder.value("visitorData", visitorData);
|
||||
|
@ -1309,8 +1303,8 @@ public final class YoutubeParsingHelper {
|
|||
.value("useSsl", true)
|
||||
.end()
|
||||
.object("user")
|
||||
// TO DO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
// TODO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.end();
|
||||
|
@ -1329,25 +1323,31 @@ public final class YoutubeParsingHelper {
|
|||
.value("clientVersion", ANDROID_YOUTUBE_CLIENT_VERSION)
|
||||
.value("platform", "MOBILE")
|
||||
.value("osName", "Android")
|
||||
.value("osVersion", "12")
|
||||
.value("osVersion", "14")
|
||||
/*
|
||||
A valid Android SDK version is required to be sure to get a valid player
|
||||
response
|
||||
If this parameter is not provided, the player response may be replaced by
|
||||
the one of a 5-minute video saying the message "The following content is
|
||||
not available on this app. Watch this content on the latest version on
|
||||
YouTube"
|
||||
If this parameter is not provided, the player response is replaced by an
|
||||
error saying the message "The following content is not available on this
|
||||
app. Watch this content on the latest version on YouTube" (it was
|
||||
previously a 5-minute video with this message)
|
||||
See https://github.com/TeamNewPipe/NewPipe/issues/8713
|
||||
The Android SDK version corresponding to the Android version used in
|
||||
requests is sent
|
||||
*/
|
||||
.value("androidSdkVersion", 31)
|
||||
.value("androidSdkVersion", 34)
|
||||
.value("hl", localization.getLocalizationCode())
|
||||
.value("gl", contentCountry.getCountryCode())
|
||||
.value("utcOffsetMinutes", 0)
|
||||
.end()
|
||||
.object("request")
|
||||
.array("internalExperimentFlags")
|
||||
.end()
|
||||
.value("useSsl", true)
|
||||
.end()
|
||||
.object("user")
|
||||
// TO DO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
// TODO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.end();
|
||||
|
@ -1369,17 +1369,26 @@ public final class YoutubeParsingHelper {
|
|||
.value("deviceModel", IOS_DEVICE_MODEL)
|
||||
.value("platform", "MOBILE")
|
||||
.value("osName", "iOS")
|
||||
// The value of this field seems to use the following structure:
|
||||
// "iOS version.0.build version"
|
||||
// The build version corresponding to the iOS version used can be found on
|
||||
// https://www.theiphonewiki.com/wiki/Firmware/iPhone/15.x#iPhone_13
|
||||
.value("osVersion", "15.6.0.19G71")
|
||||
/*
|
||||
The value of this field seems to use the following structure:
|
||||
"iOS major version.minor version.patch version.build version", where
|
||||
"patch version" is equal to 0 if it isn't set
|
||||
The build version corresponding to the iOS version used can be found on
|
||||
https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15
|
||||
*/
|
||||
.value("osVersion", "17.1.2.21B101")
|
||||
.value("hl", localization.getLocalizationCode())
|
||||
.value("gl", contentCountry.getCountryCode())
|
||||
.value("utcOffsetMinutes", 0)
|
||||
.end()
|
||||
.object("request")
|
||||
.array("internalExperimentFlags")
|
||||
.end()
|
||||
.value("useSsl", true)
|
||||
.end()
|
||||
.object("user")
|
||||
// TO DO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
// TODO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.end();
|
||||
|
@ -1401,13 +1410,19 @@ public final class YoutubeParsingHelper {
|
|||
.value("platform", "TV")
|
||||
.value("hl", localization.getLocalizationCode())
|
||||
.value("gl", contentCountry.getCountryCode())
|
||||
.value("utcOffsetMinutes", 0)
|
||||
.end()
|
||||
.object("thirdParty")
|
||||
.value("embedUrl", "https://www.youtube.com/watch?v=" + videoId)
|
||||
.end()
|
||||
.object("request")
|
||||
.array("internalExperimentFlags")
|
||||
.end()
|
||||
.value("useSsl", true)
|
||||
.end()
|
||||
.object("user")
|
||||
// TO DO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
// TODO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.end();
|
||||
|
@ -1458,9 +1473,9 @@ public final class YoutubeParsingHelper {
|
|||
*/
|
||||
@Nonnull
|
||||
public static String getAndroidUserAgent(@Nullable final Localization localization) {
|
||||
// Spoofing an Android 12 device with the hardcoded version of the Android app
|
||||
// Spoofing an Android 14 device with the hardcoded version of the Android app
|
||||
return "com.google.android.youtube/" + ANDROID_YOUTUBE_CLIENT_VERSION
|
||||
+ " (Linux; U; Android 12; "
|
||||
+ " (Linux; U; Android 14; "
|
||||
+ (localization != null ? localization : Localization.DEFAULT).getCountryCode()
|
||||
+ ") gzip";
|
||||
}
|
||||
|
@ -1480,9 +1495,9 @@ public final class YoutubeParsingHelper {
|
|||
*/
|
||||
@Nonnull
|
||||
public static String getIosUserAgent(@Nullable final Localization localization) {
|
||||
// Spoofing an iPhone 13 running iOS 15.6 with the hardcoded version of the iOS app
|
||||
// Spoofing an iPhone 15 running iOS 17.1.2 with the hardcoded version of the iOS app
|
||||
return "com.google.ios.youtube/" + IOS_YOUTUBE_CLIENT_VERSION
|
||||
+ "(" + IOS_DEVICE_MODEL + "; U; CPU iOS 15_6 like Mac OS X; "
|
||||
+ "(" + IOS_DEVICE_MODEL + "; U; CPU iOS 17_1_2 like Mac OS X; "
|
||||
+ (localization != null ? localization : Localization.DEFAULT).getCountryCode()
|
||||
+ ")";
|
||||
}
|
||||
|
@ -1553,13 +1568,15 @@ public final class YoutubeParsingHelper {
|
|||
|
||||
@Nonnull
|
||||
public static String generateConsentCookie() {
|
||||
return "CONSENT=" + (isConsentAccepted()
|
||||
// YES+ means that the user did submit their choices and allows tracking.
|
||||
? "YES+"
|
||||
// PENDING+ means that the user did not yet submit their choices.
|
||||
// YT & Google should not track the user, because they did not give consent.
|
||||
// The three digits at the end can be random, but are required.
|
||||
: "PENDING+" + (100 + numberGenerator.nextInt(900)));
|
||||
return "SOCS=" + (isConsentAccepted()
|
||||
// CAISAiAD means that the user configured manually cookies YouTube, regardless of
|
||||
// the consent values
|
||||
// This value surprisingly allows to extract mixes and some YouTube Music playlists
|
||||
// in the same way when a user allows all cookies
|
||||
? "CAISAiAD"
|
||||
// CAE= means that the user rejected all non-necessary cookies with the "Reject
|
||||
// all" button on the consent page
|
||||
: "CAE=");
|
||||
}
|
||||
|
||||
public static String extractCookieValue(final String cookieName,
|
||||
|
@ -1851,14 +1868,28 @@ public final class YoutubeParsingHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see #consentAccepted
|
||||
* Determines how the consent cookie that is required for YouTube, {@code SOCS}, will be
|
||||
* generated.
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code false} (the default value) will use {@code CAE=};</li>
|
||||
* <li>{@code true} will use {@code CAISAiAD}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Setting this value to {@code true} is needed to extract mixes and some YouTube Music
|
||||
* playlists in some countries such as the EU ones.
|
||||
* </p>
|
||||
*/
|
||||
public static void setConsentAccepted(final boolean accepted) {
|
||||
consentAccepted = accepted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #consentAccepted
|
||||
* Get the value of the consent's acceptance.
|
||||
*
|
||||
* @see #setConsentAccepted(boolean)
|
||||
* @return the consent's acceptance value
|
||||
*/
|
||||
public static boolean isConsentAccepted() {
|
||||
return consentAccepted;
|
||||
|
|
|
@ -448,9 +448,6 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
case "playlists":
|
||||
addNonVideosTab.accept(ChannelTabs.PLAYLISTS);
|
||||
break;
|
||||
case "channels":
|
||||
addNonVideosTab.accept(ChannelTabs.CHANNELS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -80,10 +80,9 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
return "EgdzdHJlYW1z8gYECgJ6AA%3D%3D";
|
||||
case ChannelTabs.PLAYLISTS:
|
||||
return "EglwbGF5bGlzdHPyBgQKAkIA";
|
||||
case ChannelTabs.CHANNELS:
|
||||
return "EghjaGFubmVsc_IGBAoCUgA%3D";
|
||||
default:
|
||||
throw new ParsingException("Unsupported channel tab: " + name);
|
||||
}
|
||||
throw new ParsingException("Unsupported channel tab: " + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -313,9 +312,6 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
} else if (item.has("gridPlaylistRenderer")) {
|
||||
getCommitPlaylistConsumer(collector, channelIds,
|
||||
item.getObject("gridPlaylistRenderer"));
|
||||
} else if (item.has("gridChannelRenderer")) {
|
||||
collector.commit(new YoutubeChannelInfoItemExtractor(
|
||||
item.getObject("gridChannelRenderer")));
|
||||
} else if (item.has("shelfRenderer")) {
|
||||
return collectItem(collector, item.getObject("shelfRenderer")
|
||||
.getObject("content"), channelIds);
|
||||
|
|
|
@ -54,7 +54,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||
throws IOException, ExtractionException {
|
||||
final String[] youtubeMusicKeys = YoutubeParsingHelper.getYoutubeMusicKey();
|
||||
|
||||
final String url = "https://music.youtube.com/youtubei/v1/search?alt=json&key="
|
||||
final String url = "https://music.youtube.com/youtubei/v1/search?key="
|
||||
+ youtubeMusicKeys[0] + DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
|
||||
final String params;
|
||||
|
@ -89,20 +89,18 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||
.value("clientVersion", youtubeMusicKeys[2])
|
||||
.value("hl", "en-GB")
|
||||
.value("gl", getExtractorContentCountry().getCountryCode())
|
||||
.array("experimentIds").end()
|
||||
.value("experimentsToken", "")
|
||||
.object("locationInfo").end()
|
||||
.object("musicAppInfo").end()
|
||||
.value("platform", "DESKTOP")
|
||||
.value("utcOffsetMinutes", 0)
|
||||
.end()
|
||||
.object("capabilities").end()
|
||||
.object("request")
|
||||
.array("internalExperimentFlags").end()
|
||||
.object("sessionIndex").end()
|
||||
.array("internalExperimentFlags")
|
||||
.end()
|
||||
.value("useSsl", true)
|
||||
.end()
|
||||
.object("activePlayers").end()
|
||||
.object("user")
|
||||
// TO DO: provide a way to enable restricted mode with:
|
||||
.value("enableSafetyMode", false)
|
||||
// TODO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.end()
|
||||
.value("query", getSearchString())
|
||||
|
@ -219,20 +217,18 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||
.value("clientVersion", youtubeMusicKeys[2])
|
||||
.value("hl", "en-GB")
|
||||
.value("gl", getExtractorContentCountry().getCountryCode())
|
||||
.array("experimentIds").end()
|
||||
.value("experimentsToken", "")
|
||||
.value("platform", "DESKTOP")
|
||||
.value("utcOffsetMinutes", 0)
|
||||
.object("locationInfo").end()
|
||||
.object("musicAppInfo").end()
|
||||
.end()
|
||||
.object("capabilities").end()
|
||||
.object("request")
|
||||
.array("internalExperimentFlags").end()
|
||||
.object("sessionIndex").end()
|
||||
.array("internalExperimentFlags")
|
||||
.end()
|
||||
.value("useSsl", true)
|
||||
.end()
|
||||
.object("activePlayers").end()
|
||||
.object("user")
|
||||
.value("enableSafetyMode", false)
|
||||
// TODO: provide a way to enable restricted mode with:
|
||||
// .value("enableSafetyMode", boolean)
|
||||
.value("lockedSafetyMode", false)
|
||||
.end()
|
||||
.end()
|
||||
.end().done().getBytes(StandardCharsets.UTF_8);
|
||||
|
@ -310,7 +306,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||
final String continuation = nextContinuationData.getString("continuation");
|
||||
|
||||
return new Page("https://music.youtube.com/youtubei/v1/search?ctoken=" + continuation
|
||||
+ "&continuation=" + continuation + "&alt=json" + "&key="
|
||||
+ YoutubeParsingHelper.getYoutubeMusicKey()[0]);
|
||||
+ "&continuation=" + continuation + "&key="
|
||||
+ YoutubeParsingHelper.getYoutubeMusicKey()[0] + DISABLE_PRETTY_PRINT_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,10 @@ import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper
|
|||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.ALL;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.CHANNELS;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.PLAYLISTS;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.VIDEOS;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.getSearchParameter;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
|
@ -32,6 +36,7 @@ import org.schabi.newpipe.extractor.utils.JsonUtils;
|
|||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -57,11 +62,29 @@ import javax.annotation.Nullable;
|
|||
*/
|
||||
|
||||
public class YoutubeSearchExtractor extends SearchExtractor {
|
||||
|
||||
@Nullable
|
||||
private final String searchType;
|
||||
private final boolean extractVideoResults;
|
||||
private final boolean extractChannelResults;
|
||||
private final boolean extractPlaylistResults;
|
||||
|
||||
private JsonObject initialData;
|
||||
|
||||
public YoutubeSearchExtractor(final StreamingService service,
|
||||
final SearchQueryHandler linkHandler) {
|
||||
super(service, linkHandler);
|
||||
final List<String> contentFilters = linkHandler.getContentFilters();
|
||||
searchType = isNullOrEmpty(contentFilters) ? null : contentFilters.get(0);
|
||||
// Save whether we should extract video, channel and playlist results depending on the
|
||||
// requested search type, as YouTube returns sometimes videos inside channel search results
|
||||
// If no search type is provided or ALL filter is requested, extract everything
|
||||
extractVideoResults = searchType == null || ALL.equals(searchType)
|
||||
|| VIDEOS.equals(searchType);
|
||||
extractChannelResults = searchType == null || ALL.equals(searchType)
|
||||
|| CHANNELS.equals(searchType);
|
||||
extractPlaylistResults = searchType == null || ALL.equals(searchType)
|
||||
|| PLAYLISTS.equals(searchType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,16 +92,7 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
|||
ExtractionException {
|
||||
final String query = super.getSearchString();
|
||||
final Localization localization = getExtractorLocalization();
|
||||
|
||||
// Get the search parameter of the request
|
||||
final List<String> contentFilters = super.getLinkHandler().getContentFilters();
|
||||
final String params;
|
||||
if (!isNullOrEmpty(contentFilters)) {
|
||||
final String searchType = contentFilters.get(0);
|
||||
params = getSearchParameter(searchType);
|
||||
} else {
|
||||
params = "";
|
||||
}
|
||||
final String params = getSearchParameter(searchType);
|
||||
|
||||
final JsonBuilder<JsonObject> jsonBody = prepareDesktopJsonBuilder(localization,
|
||||
getExtractorContentCountry())
|
||||
|
@ -111,18 +125,17 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
|||
final JsonObject didYouMeanRenderer = itemSectionRenderer.getArray("contents")
|
||||
.getObject(0)
|
||||
.getObject("didYouMeanRenderer");
|
||||
final JsonObject showingResultsForRenderer = itemSectionRenderer.getArray("contents")
|
||||
.getObject(0)
|
||||
.getObject("showingResultsForRenderer");
|
||||
|
||||
if (!didYouMeanRenderer.isEmpty()) {
|
||||
return JsonUtils.getString(didYouMeanRenderer,
|
||||
"correctedQueryEndpoint.searchEndpoint.query");
|
||||
} else if (showingResultsForRenderer != null) {
|
||||
return getTextFromObject(showingResultsForRenderer.getObject("correctedQuery"));
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
return Objects.requireNonNullElse(
|
||||
getTextFromObject(itemSectionRenderer.getArray("contents")
|
||||
.getObject(0)
|
||||
.getObject("showingResultsForRenderer")
|
||||
.getObject("correctedQuery")), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -211,7 +224,7 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
|||
|
||||
private void collectStreamsFrom(final MultiInfoItemsCollector collector,
|
||||
@Nonnull final JsonArray contents)
|
||||
throws NothingFoundException, ParsingException {
|
||||
throws NothingFoundException {
|
||||
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
||||
|
||||
for (final Object content : contents) {
|
||||
|
@ -220,13 +233,13 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
|||
throw new NothingFoundException(
|
||||
getTextFromObject(item.getObject("backgroundPromoRenderer")
|
||||
.getObject("bodyText")));
|
||||
} else if (item.has("videoRenderer")) {
|
||||
} else if (extractVideoResults && item.has("videoRenderer")) {
|
||||
collector.commit(new YoutubeStreamInfoItemExtractor(
|
||||
item.getObject("videoRenderer"), timeAgoParser));
|
||||
} else if (item.has("channelRenderer")) {
|
||||
} else if (extractChannelResults && item.has("channelRenderer")) {
|
||||
collector.commit(new YoutubeChannelInfoItemExtractor(
|
||||
item.getObject("channelRenderer")));
|
||||
} else if (item.has("playlistRenderer")) {
|
||||
} else if (extractPlaylistResults && item.has("playlistRenderer")) {
|
||||
collector.commit(new YoutubePlaylistInfoItemExtractor(
|
||||
item.getObject("playlistRenderer")));
|
||||
}
|
||||
|
|
|
@ -388,57 +388,43 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||
|
||||
// If ratings are not allowed, there is no like count available
|
||||
if (!playerResponse.getObject("videoDetails").getBoolean("allowRatings")) {
|
||||
return -1;
|
||||
return -1L;
|
||||
}
|
||||
|
||||
String likesString = "";
|
||||
final JsonArray topLevelButtons = getVideoPrimaryInfoRenderer()
|
||||
.getObject("videoActions")
|
||||
.getObject("menuRenderer")
|
||||
.getArray("topLevelButtons");
|
||||
|
||||
try {
|
||||
final JsonArray topLevelButtons = getVideoPrimaryInfoRenderer()
|
||||
.getObject("videoActions")
|
||||
.getObject("menuRenderer")
|
||||
.getArray("topLevelButtons");
|
||||
return parseLikeCountFromLikeButtonViewModel(topLevelButtons);
|
||||
} catch (final ParsingException ignored) {
|
||||
// A segmentedLikeDislikeButtonRenderer could be returned instead of a
|
||||
// segmentedLikeDislikeButtonViewModel, so ignore extraction errors relative to
|
||||
// segmentedLikeDislikeButtonViewModel object
|
||||
}
|
||||
|
||||
// Try first with the new video actions buttons data structure
|
||||
JsonObject likeToggleButtonRenderer = topLevelButtons.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.map(button -> button.getObject("segmentedLikeDislikeButtonRenderer")
|
||||
.getObject("likeButton")
|
||||
.getObject("toggleButtonRenderer"))
|
||||
.filter(toggleButtonRenderer -> !isNullOrEmpty(toggleButtonRenderer))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
try {
|
||||
return parseLikeCountFromLikeButtonRenderer(topLevelButtons);
|
||||
} catch (final ParsingException e) {
|
||||
throw new ParsingException("Could not get like count", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the old video actions buttons data structure if the new one isn't returned
|
||||
if (likeToggleButtonRenderer == null) {
|
||||
/*
|
||||
In the old video actions buttons data structure, there are 3 ways to detect whether
|
||||
a button is the like button, using its toggleButtonRenderer:
|
||||
- checking whether toggleButtonRenderer.targetId is equal to watch-like;
|
||||
- checking whether toggleButtonRenderer.defaultIcon.iconType is equal to LIKE;
|
||||
- checking whether
|
||||
toggleButtonRenderer.toggleButtonSupportedData.toggleButtonIdData.id
|
||||
is equal to TOGGLE_BUTTON_ID_TYPE_LIKE.
|
||||
*/
|
||||
likeToggleButtonRenderer = topLevelButtons.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.map(topLevelButton -> topLevelButton.getObject("toggleButtonRenderer"))
|
||||
.filter(toggleButtonRenderer -> toggleButtonRenderer.getString("targetId")
|
||||
.equalsIgnoreCase("watch-like")
|
||||
|| toggleButtonRenderer.getObject("defaultIcon")
|
||||
.getString("iconType")
|
||||
.equalsIgnoreCase("LIKE")
|
||||
|| toggleButtonRenderer.getObject("toggleButtonSupportedData")
|
||||
.getObject("toggleButtonIdData")
|
||||
.getString("id")
|
||||
.equalsIgnoreCase("TOGGLE_BUTTON_ID_TYPE_LIKE"))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new ParsingException(
|
||||
"The like button is missing even though ratings are enabled"));
|
||||
}
|
||||
private static long parseLikeCountFromLikeButtonRenderer(
|
||||
@Nonnull final JsonArray topLevelButtons) throws ParsingException {
|
||||
String likesString = null;
|
||||
final JsonObject likeToggleButtonRenderer = topLevelButtons.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.map(button -> button.getObject("segmentedLikeDislikeButtonRenderer")
|
||||
.getObject("likeButton")
|
||||
.getObject("toggleButtonRenderer"))
|
||||
.filter(toggleButtonRenderer -> !isNullOrEmpty(toggleButtonRenderer))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (likeToggleButtonRenderer != null) {
|
||||
// Use one of the accessibility strings available (this one has the same path as the
|
||||
// one used for comments' like count extraction)
|
||||
likesString = likeToggleButtonRenderer.getObject("accessibilityData")
|
||||
|
@ -460,23 +446,58 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||
.getString("label");
|
||||
}
|
||||
|
||||
// If ratings are allowed and the likes string is null, it means that we couldn't
|
||||
// extract the (real) like count from accessibility data
|
||||
if (likesString == null) {
|
||||
throw new ParsingException("Could not get like count from accessibility data");
|
||||
}
|
||||
|
||||
// This check only works with English localizations!
|
||||
if (likesString.toLowerCase().contains("no likes")) {
|
||||
if (likesString != null && likesString.toLowerCase().contains("no likes")) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return Integer.parseInt(Utils.removeNonDigitCharacters(likesString));
|
||||
} catch (final NumberFormatException nfe) {
|
||||
throw new ParsingException("Could not parse \"" + likesString + "\" as an Integer",
|
||||
nfe);
|
||||
} catch (final Exception e) {
|
||||
throw new ParsingException("Could not get like count", e);
|
||||
// If ratings are allowed and the likes string is null, it means that we couldn't extract
|
||||
// the full like count from accessibility data
|
||||
if (likesString == null) {
|
||||
throw new ParsingException("Could not get like count from accessibility data");
|
||||
}
|
||||
|
||||
try {
|
||||
return Long.parseLong(Utils.removeNonDigitCharacters(likesString));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new ParsingException("Could not parse \"" + likesString + "\" as a long", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static long parseLikeCountFromLikeButtonViewModel(
|
||||
@Nonnull final JsonArray topLevelButtons) throws ParsingException {
|
||||
// Try first with the current video actions buttons data structure
|
||||
final JsonObject likeToggleButtonViewModel = topLevelButtons.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.map(button -> button.getObject("segmentedLikeDislikeButtonViewModel")
|
||||
.getObject("likeButtonViewModel")
|
||||
.getObject("likeButtonViewModel")
|
||||
.getObject("toggleButtonViewModel")
|
||||
.getObject("toggleButtonViewModel")
|
||||
.getObject("defaultButtonViewModel")
|
||||
.getObject("buttonViewModel"))
|
||||
.filter(buttonViewModel -> !isNullOrEmpty(buttonViewModel))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (likeToggleButtonViewModel == null) {
|
||||
throw new ParsingException("Could not find buttonViewModel object");
|
||||
}
|
||||
|
||||
final String accessibilityText = likeToggleButtonViewModel.getString("accessibilityText");
|
||||
if (accessibilityText == null) {
|
||||
throw new ParsingException("Could not find buttonViewModel's accessibilityText string");
|
||||
}
|
||||
|
||||
// The like count is always returned as a number in this element, even for videos with no
|
||||
// likes
|
||||
try {
|
||||
return Long.parseLong(Utils.removeNonDigitCharacters(accessibilityText));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new ParsingException(
|
||||
"Could not parse \"" + accessibilityText + "\" as a long", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,9 @@ public final class YoutubeChannelTabLinkHandlerFactory extends ListLinkHandlerFa
|
|||
return "/streams";
|
||||
case ChannelTabs.PLAYLISTS:
|
||||
return "/playlists";
|
||||
case ChannelTabs.CHANNELS:
|
||||
return "/channels";
|
||||
default:
|
||||
throw new UnsupportedTabException(tab);
|
||||
}
|
||||
throw new UnsupportedTabException(tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,8 +65,7 @@ public final class YoutubeChannelTabLinkHandlerFactory extends ListLinkHandlerFa
|
|||
ChannelTabs.VIDEOS,
|
||||
ChannelTabs.SHORTS,
|
||||
ChannelTabs.LIVESTREAMS,
|
||||
ChannelTabs.PLAYLISTS,
|
||||
ChannelTabs.CHANNELS
|
||||
ChannelTabs.PLAYLISTS
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,11 +45,14 @@ public final class YoutubeSearchQueryHandlerFactory extends SearchQueryHandlerFa
|
|||
final String contentFilter = contentFilters.get(0);
|
||||
switch (contentFilter) {
|
||||
case VIDEOS:
|
||||
return SEARCH_URL + encodeUrlUtf8(searchString) + "&sp=EgIQAQ%253D%253D";
|
||||
return SEARCH_URL + encodeUrlUtf8(searchString)
|
||||
+ "&sp=EgIQAfABAQ%253D%253D";
|
||||
case CHANNELS:
|
||||
return SEARCH_URL + encodeUrlUtf8(searchString) + "&sp=EgIQAg%253D%253D";
|
||||
return SEARCH_URL + encodeUrlUtf8(searchString)
|
||||
+ "&sp=EgIQAvABAQ%253D%253D";
|
||||
case PLAYLISTS:
|
||||
return SEARCH_URL + encodeUrlUtf8(searchString) + "&sp=EgIQAw%253D%253D";
|
||||
return SEARCH_URL + encodeUrlUtf8(searchString)
|
||||
+ "&sp=EgIQA_ABAQ%253D%253D";
|
||||
case MUSIC_SONGS:
|
||||
case MUSIC_VIDEOS:
|
||||
case MUSIC_ALBUMS:
|
||||
|
@ -59,7 +62,7 @@ public final class YoutubeSearchQueryHandlerFactory extends SearchQueryHandlerFa
|
|||
}
|
||||
}
|
||||
|
||||
return SEARCH_URL + encodeUrlUtf8(searchString);
|
||||
return SEARCH_URL + encodeUrlUtf8(searchString) + "&sp=8AEB";
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
throw new ParsingException("Could not encode query", e);
|
||||
}
|
||||
|
@ -83,24 +86,24 @@ public final class YoutubeSearchQueryHandlerFactory extends SearchQueryHandlerFa
|
|||
@Nonnull
|
||||
public static String getSearchParameter(final String contentFilter) {
|
||||
if (isNullOrEmpty(contentFilter)) {
|
||||
return "";
|
||||
return "8AEB";
|
||||
}
|
||||
|
||||
switch (contentFilter) {
|
||||
case VIDEOS:
|
||||
return "EgIQAQ%3D%3D";
|
||||
return "EgIQAfABAQ%3D%3D";
|
||||
case CHANNELS:
|
||||
return "EgIQAg%3D%3D";
|
||||
return "EgIQAvABAQ%3D%3D";
|
||||
case PLAYLISTS:
|
||||
return "EgIQAw%3D%3D";
|
||||
case ALL:
|
||||
return "EgIQA_ABAQ%3D%3D";
|
||||
case MUSIC_SONGS:
|
||||
case MUSIC_VIDEOS:
|
||||
case MUSIC_ALBUMS:
|
||||
case MUSIC_PLAYLISTS:
|
||||
case MUSIC_ARTISTS:
|
||||
default:
|
||||
return "";
|
||||
default:
|
||||
return "8AEB";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@ package org.schabi.newpipe.extractor.services.youtube;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains;
|
||||
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmpty;
|
||||
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertNotBlank;
|
||||
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertNotEmpty;
|
||||
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain;
|
||||
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
|
||||
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor;
|
||||
|
@ -231,7 +232,7 @@ public class YoutubeChannelExtractorTest {
|
|||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS,
|
||||
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
|
||||
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS);
|
||||
assertTrue(extractor.getTabs().stream()
|
||||
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
|
||||
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
|
||||
|
@ -324,7 +325,7 @@ public class YoutubeChannelExtractorTest {
|
|||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.LIVESTREAMS,
|
||||
ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
|
||||
ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS);
|
||||
assertTrue(extractor.getTabs().stream()
|
||||
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
|
||||
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
|
||||
|
@ -420,7 +421,7 @@ public class YoutubeChannelExtractorTest {
|
|||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS,
|
||||
ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
|
||||
ChannelTabs.PLAYLISTS);
|
||||
assertTrue(extractor.getTabs().stream()
|
||||
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
|
||||
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
|
||||
|
@ -539,8 +540,7 @@ public class YoutubeChannelExtractorTest {
|
|||
@Test
|
||||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS,
|
||||
ChannelTabs.CHANNELS);
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS);
|
||||
assertTrue(extractor.getTabs().stream()
|
||||
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
|
||||
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
|
||||
|
@ -632,8 +632,7 @@ public class YoutubeChannelExtractorTest {
|
|||
@Test
|
||||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS,
|
||||
ChannelTabs.CHANNELS);
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS);
|
||||
assertTrue(extractor.getTabs().stream()
|
||||
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
|
||||
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
|
||||
|
@ -654,7 +653,7 @@ public class YoutubeChannelExtractorTest {
|
|||
YoutubeTestsUtils.ensureStateless();
|
||||
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "carouselHeader"));
|
||||
extractor = (YoutubeChannelExtractor) YouTube
|
||||
.getChannelExtractor("https://www.youtube.com/channel/UCHF66aWLOxBW4l6VkSrS3cQ");
|
||||
.getChannelExtractor("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw");
|
||||
extractor.fetchPage();
|
||||
}
|
||||
|
||||
|
@ -669,22 +668,22 @@ public class YoutubeChannelExtractorTest {
|
|||
|
||||
@Test
|
||||
public void testName() throws Exception {
|
||||
assertEquals("Coachella", extractor.getName());
|
||||
assertEquals("Sports", extractor.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testId() throws Exception {
|
||||
assertEquals("UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getId());
|
||||
assertEquals("UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUrl() throws ParsingException {
|
||||
assertEquals("https://www.youtube.com/channel/UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getUrl());
|
||||
assertEquals("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOriginalUrl() throws ParsingException {
|
||||
assertEquals("https://www.youtube.com/channel/UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getOriginalUrl());
|
||||
assertEquals("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getOriginalUrl());
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -694,7 +693,7 @@ public class YoutubeChannelExtractorTest {
|
|||
@Test
|
||||
@Override
|
||||
public void testDescription() throws ParsingException {
|
||||
assertNotBlank(extractor.getDescription());
|
||||
assertNull(extractor.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -710,12 +709,12 @@ public class YoutubeChannelExtractorTest {
|
|||
|
||||
@Test
|
||||
public void testFeedUrl() throws Exception {
|
||||
assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getFeedUrl());
|
||||
assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getFeedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriberCount() throws Exception {
|
||||
ExtractorAsserts.assertGreaterOrEqual(2_900_000, extractor.getSubscriberCount());
|
||||
ExtractorAsserts.assertGreaterOrEqual(70_000_000, extractor.getSubscriberCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -726,18 +725,13 @@ public class YoutubeChannelExtractorTest {
|
|||
@Test
|
||||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS,
|
||||
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
|
||||
assertTrue(extractor.getTabs().stream()
|
||||
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
|
||||
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
|
||||
assertEmpty(extractor.getTabs());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testTags() throws Exception {
|
||||
assertTrue(extractor.getTags().containsAll(List.of("coachella", "music", "california",
|
||||
"festival", "arts")));
|
||||
assertEmpty(extractor.getTags());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -881,10 +875,9 @@ public class YoutubeChannelExtractorTest {
|
|||
@Test
|
||||
@Override
|
||||
public void testDescription() throws Exception {
|
||||
final String description = extractor.getDescription();
|
||||
assertContains("Minecraft", description);
|
||||
assertContains("game", description);
|
||||
assertContains("Mojang", description);
|
||||
// The description changes frequently and there is no significant common word, so only
|
||||
// check if it is not empty
|
||||
assertNotEmpty(extractor.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -68,28 +68,6 @@ class YoutubeChannelTabExtractorTest {
|
|||
@Override public boolean expectedHasMoreItems() { return true; }
|
||||
}
|
||||
|
||||
static class Channels extends DefaultListExtractorTest<ChannelTabExtractor> {
|
||||
private static YoutubeChannelTabExtractor extractor;
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() throws IOException, ExtractionException {
|
||||
YoutubeTestsUtils.ensureStateless();
|
||||
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "channels"));
|
||||
extractor = (YoutubeChannelTabExtractor) YouTube.getChannelTabExtractorFromId(
|
||||
"channel/UC2DjFE7Xf11URZqWBigcVOQ", ChannelTabs.CHANNELS);
|
||||
extractor.fetchPage();
|
||||
}
|
||||
|
||||
@Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
|
||||
@Override public StreamingService expectedService() throws Exception { return YouTube; }
|
||||
@Override public String expectedName() throws Exception { return ChannelTabs.CHANNELS; }
|
||||
@Override public String expectedId() throws Exception { return "UC2DjFE7Xf11URZqWBigcVOQ"; }
|
||||
@Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/channels"; }
|
||||
@Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/channels"; }
|
||||
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.CHANNEL; }
|
||||
@Override public boolean expectedHasMoreItems() { return true; }
|
||||
}
|
||||
|
||||
static class Livestreams extends DefaultListExtractorTest<ChannelTabExtractor> {
|
||||
private static YoutubeChannelTabExtractor extractor;
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.schabi.newpipe.extractor.NewPipe;
|
|||
import org.schabi.newpipe.extractor.Page;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeMixPlaylistExtractor;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
|
@ -454,7 +453,8 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey(), null, null, dummyCookie, body));
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
null, null, dummyCookie, body));
|
||||
assertFalse(streams.getItems().isEmpty());
|
||||
assertTrue(streams.hasNextPage());
|
||||
}
|
||||
|
@ -542,7 +542,8 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey(), null, null, dummyCookie, body));
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
null, null, dummyCookie, body));
|
||||
assertFalse(streams.getItems().isEmpty());
|
||||
assertTrue(streams.hasNextPage());
|
||||
}
|
||||
|
@ -570,7 +571,7 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void getStreamCount() throws ParsingException {
|
||||
void getStreamCount() {
|
||||
assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount());
|
||||
}
|
||||
|
||||
|
|
|
@ -342,10 +342,9 @@ public class YoutubePlaylistExtractorTest {
|
|||
defaultTestRelatedItems(extractor);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
public void testMoreRelatedItems() throws Exception {
|
||||
defaultTestMoreItems(extractor);
|
||||
assertFalse(extractor.getInitialPage().hasNextPage());
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -15,7 +15,6 @@ import static java.util.Collections.singletonList;
|
|||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.schabi.newpipe.downloader.DownloaderFactory;
|
||||
import org.schabi.newpipe.downloader.MockOnly;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
import org.schabi.newpipe.extractor.MetaInfo;
|
||||
|
@ -28,12 +27,11 @@ import org.schabi.newpipe.extractor.services.DefaultSearchExtractorTest;
|
|||
import org.schabi.newpipe.extractor.services.youtube.YoutubeTestsUtils;
|
||||
import org.schabi.newpipe.extractor.stream.Description;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.utils.Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -139,15 +137,15 @@ public class YoutubeSearchExtractorTest {
|
|||
|
||||
/**
|
||||
* Test for YT's "Did you mean...".
|
||||
*
|
||||
* <p>
|
||||
* Hint: YT mostly shows "did you mean..." when you are searching in another language.
|
||||
* </p>
|
||||
*/
|
||||
@MockOnly("Currently constantly switching between \"Did you mean\" and \"Showing results for ...\" occurs")
|
||||
public static class Suggestion extends DefaultSearchExtractorTest {
|
||||
private static SearchExtractor extractor;
|
||||
private static final String QUERY = "algorythm";
|
||||
private static final String EXPECTED_SUGGESTION = "algorithm";
|
||||
private static final String QUERY = "on board ing";
|
||||
private static final String EXPECTED_SUGGESTION = "on boarding";
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp() throws Exception {
|
||||
|
@ -161,8 +159,8 @@ public class YoutubeSearchExtractorTest {
|
|||
@Override public StreamingService expectedService() { return YouTube; }
|
||||
@Override public String expectedName() { return QUERY; }
|
||||
@Override public String expectedId() { return QUERY; }
|
||||
@Override public String expectedUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
|
||||
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + QUERY; }
|
||||
@Override public String expectedUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
|
||||
@Override public String expectedOriginalUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
|
||||
@Override public String expectedSearchString() { return QUERY; }
|
||||
@Nullable @Override public String expectedSearchSuggestion() { return EXPECTED_SUGGESTION; }
|
||||
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
|
||||
|
@ -396,20 +394,12 @@ public class YoutubeSearchExtractorTest {
|
|||
extractor.fetchPage();
|
||||
}
|
||||
|
||||
private String getUrlEncodedQuery() {
|
||||
try {
|
||||
return URLEncoder.encode(QUERY, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public SearchExtractor extractor() { return extractor; }
|
||||
@Override public StreamingService expectedService() { return YouTube; }
|
||||
@Override public String expectedName() { return QUERY; }
|
||||
@Override public String expectedId() { return QUERY; }
|
||||
@Override public String expectedUrlContains() { return "youtube.com/results?search_query=" + getUrlEncodedQuery(); }
|
||||
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + getUrlEncodedQuery(); }
|
||||
@Override public String expectedUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
|
||||
@Override public String expectedOriginalUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
|
||||
@Override public String expectedSearchString() { return QUERY; }
|
||||
@Nullable @Override public String expectedSearchSuggestion() { return null; }
|
||||
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
|
||||
|
@ -424,4 +414,37 @@ public class YoutubeSearchExtractorTest {
|
|||
.anyMatch(StreamInfoItem::isShortFormContent));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SearchExtractor} test to check if crisis resources preventing search results to be
|
||||
* returned are bypassed (searches with content filters are not tested in this test, even if
|
||||
* they should work as bypasses are used with them too).
|
||||
*
|
||||
* <p>
|
||||
* See <a href="https://support.google.com/youtube/answer/10726080?hl=en">
|
||||
* https://support.google.com/youtube/answer/10726080?hl=en</a> for more info on crisis
|
||||
* resources.
|
||||
* </p>
|
||||
*/
|
||||
public static class CrisisResources extends DefaultSearchExtractorTest {
|
||||
private static SearchExtractor extractor;
|
||||
private static final String QUERY = "blue whale";
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp() throws Exception {
|
||||
YoutubeTestsUtils.ensureStateless();
|
||||
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "crisis_resources"));
|
||||
extractor = YouTube.getSearchExtractor(QUERY);
|
||||
extractor.fetchPage();
|
||||
}
|
||||
|
||||
@Override public SearchExtractor extractor() { return extractor; }
|
||||
@Override public StreamingService expectedService() { return YouTube; }
|
||||
@Override public String expectedName() { return QUERY; }
|
||||
@Override public String expectedId() { return QUERY; }
|
||||
@Override public String expectedUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
|
||||
@Override public String expectedOriginalUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
|
||||
@Override public String expectedSearchString() { return QUERY; }
|
||||
@Nullable @Override public String expectedSearchSuggestion() { return null; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ public class YoutubeSearchQHTest {
|
|||
|
||||
@Test
|
||||
public void testRegularValues() throws Exception {
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf", YouTube.getSearchQHFactory().fromQuery("asdf").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=hans", YouTube.getSearchQHFactory().fromQuery("hans").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=Poifj%26jaijf", YouTube.getSearchQHFactory().fromQuery("Poifj&jaijf").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=G%C3%BCl%C3%BCm", YouTube.getSearchQHFactory().fromQuery("Gülüm").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=%3Fj%24%29H%C2%A7B", YouTube.getSearchQHFactory().fromQuery("?j$)H§B").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("asdf").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=hans&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("hans").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=Poifj%26jaijf&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("Poifj&jaijf").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=G%C3%BCl%C3%BCm&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("Gülüm").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=%3Fj%24%29H%C2%A7B&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("?j$)H§B").getUrl());
|
||||
|
||||
assertEquals("https://music.youtube.com/search?q=asdf", YouTube.getSearchQHFactory().fromQuery("asdf", asList(new String[]{MUSIC_SONGS}), "").getUrl());
|
||||
assertEquals("https://music.youtube.com/search?q=hans", YouTube.getSearchQHFactory().fromQuery("hans", asList(new String[]{MUSIC_SONGS}), "").getUrl());
|
||||
|
@ -40,13 +40,13 @@ public class YoutubeSearchQHTest {
|
|||
|
||||
@Test
|
||||
public void testWithContentfilter() throws Exception {
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAQ%253D%253D", YouTube.getSearchQHFactory()
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAfABAQ%253D%253D", YouTube.getSearchQHFactory()
|
||||
.fromQuery("asdf", asList(new String[]{VIDEOS}), "").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAg%253D%253D", YouTube.getSearchQHFactory()
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAvABAQ%253D%253D", YouTube.getSearchQHFactory()
|
||||
.fromQuery("asdf", asList(new String[]{CHANNELS}), "").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAw%253D%253D", YouTube.getSearchQHFactory()
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQA_ABAQ%253D%253D", YouTube.getSearchQHFactory()
|
||||
.fromQuery("asdf", asList(new String[]{PLAYLISTS}), "").getUrl());
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf", YouTube.getSearchQHFactory()
|
||||
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=8AEB", YouTube.getSearchQHFactory()
|
||||
.fromQuery("asdf", asList(new String[]{"fjiijie"}), "").getUrl());
|
||||
|
||||
assertEquals("https://music.youtube.com/search?q=asdf", YouTube.getSearchQHFactory()
|
||||
|
|
|
@ -48,8 +48,8 @@ public class YoutubeStreamExtractorAgeRestrictedTest extends DefaultStreamExtrac
|
|||
@Override public long expectedLength() { return 10; }
|
||||
@Override public long expectedTimestamp() { return TIMESTAMP; }
|
||||
@Override public long expectedViewCountAtLeast() { return 232_000; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2018-03-11 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2018-03-11"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2018-03-11 19:22:08.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2018-03-11T12:22:08-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 3_700; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public boolean expectedHasRelatedItems() { return false; } // no related videos (!)
|
||||
|
|
|
@ -52,8 +52,8 @@ public class YoutubeStreamExtractorControversialTest extends DefaultStreamExtrac
|
|||
}
|
||||
@Override public long expectedLength() { return 219; }
|
||||
@Override public long expectedViewCountAtLeast() { return 285000; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2010-09-09 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2010-09-09"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2010-09-09 15:40:44.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2010-09-09T08:40:44-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 13300; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public List<String> expectedTags() { return Arrays.asList("Books", "Burning", "Jones", "Koran", "Qur'an", "Terry", "the amazing atheist"); }
|
||||
|
|
|
@ -151,8 +151,8 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
@Override public long expectedLength() { return 381; }
|
||||
@Override public long expectedTimestamp() { return TIMESTAMP; }
|
||||
@Override public long expectedViewCountAtLeast() { return 26682500; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2019-08-24 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2019-08-24"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2019-08-24 15:39:57.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2019-08-24T08:39:57-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 5212900; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public int expectedStreamSegmentsCount() { return 0; }
|
||||
|
@ -194,8 +194,8 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
}
|
||||
@Override public long expectedLength() { return 434; }
|
||||
@Override public long expectedViewCountAtLeast() { return 21229200; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2018-06-19 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2018-06-19"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2018-06-19 19:41:34.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2018-06-19T12:41:34-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 340100; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public boolean expectedUploaderVerified() { return true; }
|
||||
|
@ -212,9 +212,8 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
// @formatter:on
|
||||
}
|
||||
|
||||
@Disabled("Test broken, video was made private")
|
||||
public static class RatingsDisabledTest extends DefaultStreamExtractorTest {
|
||||
private static final String ID = "HRKu0cvrr_o";
|
||||
private static final String ID = "it3OtbTxQk0";
|
||||
private static final int TIMESTAMP = 17;
|
||||
private static final String URL = BASE_URL + ID + "&t=" + TIMESTAMP;
|
||||
private static StreamExtractor extractor;
|
||||
|
@ -230,22 +229,25 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
// @formatter:off
|
||||
@Override public StreamExtractor extractor() { return extractor; }
|
||||
@Override public StreamingService expectedService() { return YouTube; }
|
||||
@Override public String expectedName() { return "AlphaOmegaSin Fanboy Logic: Likes/Dislikes Disabled = Point Invalid Lol wtf?"; }
|
||||
@Override public String expectedName() { return "Introduction to Doodle for Google 2023"; }
|
||||
@Override public String expectedId() { return ID; }
|
||||
@Override public String expectedUrlContains() { return BASE_URL + ID; }
|
||||
@Override public String expectedOriginalUrlContains() { return URL; }
|
||||
|
||||
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
|
||||
@Override public String expectedUploaderName() { return "YouTuber PrinceOfFALLEN"; }
|
||||
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCQT2yul0lr6Ie9qNQNmw-sg"; }
|
||||
@Override public List<String> expectedDescriptionContains() { return Arrays.asList("dislikes", "Alpha", "wrong"); }
|
||||
@Override public long expectedLength() { return 84; }
|
||||
@Override public String expectedUploaderName() { return "GoogleDoodles"; }
|
||||
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCdq61m8s_48EhJ5OM_MCeGw"; }
|
||||
@Override public long expectedUploaderSubscriberCountAtLeast() { return 2270000; }
|
||||
@Override public List<String> expectedDescriptionContains() { return Arrays.asList("Doodle", "Google", "video"); }
|
||||
@Override public long expectedLength() { return 145; }
|
||||
@Override public long expectedTimestamp() { return TIMESTAMP; }
|
||||
@Override public long expectedViewCountAtLeast() { return 190; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2019-01-02 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2019-01-02"; }
|
||||
@Override public long expectedViewCountAtLeast() { return 40000; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2023-01-13 21:53:57.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2023-01-13T13:53:57-08:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return -1; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public String expectedLicence() { return YOUTUBE_LICENCE; }
|
||||
@Override public String expectedCategory() { return "Education"; }
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
@ -281,8 +283,8 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
}
|
||||
@Override public long expectedLength() { return 953; }
|
||||
@Override public long expectedViewCountAtLeast() { return 270000; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2021-03-17 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2021-03-17"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2021-03-17 19:56:59.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2021-03-17T12:56:59-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 2300; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public boolean expectedHasSubtitles() { return false; }
|
||||
|
@ -340,11 +342,10 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
@Override public boolean expectedUploaderVerified() { return true; }
|
||||
@Override public long expectedLength() { return 1010; }
|
||||
@Override public long expectedViewCountAtLeast() { return 815500; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2020-11-18 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2020-11-18"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2020-11-19 05:30:01.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2020-11-18T21:30:01-08:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 48500; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public boolean expectedHasSubtitles() { return true; }
|
||||
@Override public int expectedStreamSegmentsCount() { return 7; }
|
||||
@Override public String expectedLicence() { return YOUTUBE_LICENCE; }
|
||||
@Override public String expectedCategory() { return "Science & Technology"; }
|
||||
|
@ -408,8 +409,8 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
@Override public long expectedLength() { return 45; }
|
||||
@Override public long expectedTimestamp() { return TIMESTAMP; }
|
||||
@Override public long expectedViewCountAtLeast() { return 20_000; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2023-07-07 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2023-07-07"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2023-07-07 15:30:08.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2023-07-07T08:30:08-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 1000; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public List<MetaInfo> expectedMetaInfo() throws MalformedURLException {
|
||||
|
@ -453,8 +454,8 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
@Override public List<String> expectedDescriptionContains() { return Arrays.asList("Makani", "prototype", "rotors"); }
|
||||
@Override public long expectedLength() { return 175; }
|
||||
@Override public long expectedViewCountAtLeast() { return 88_000; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2017-05-16 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2017-05-16"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2017-05-16 14:50:53.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2017-05-16T07:50:53-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return -1; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public StreamExtractor extractor() { return extractor; }
|
||||
|
|
|
@ -57,8 +57,8 @@ public class YoutubeStreamExtractorLivestreamTest extends DefaultStreamExtractor
|
|||
@Override public long expectedLength() { return 0; }
|
||||
@Override public long expectedTimestamp() { return TIMESTAMP; }
|
||||
@Override public long expectedViewCountAtLeast() { return 0; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2022-07-12 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2022-07-12"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2022-07-12 12:12:29.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2022-07-12T05:12:29-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 340_000; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public boolean expectedHasSubtitles() { return false; }
|
||||
|
|
|
@ -4,11 +4,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains;
|
||||
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertGreaterOrEqual;
|
||||
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.stream.YoutubeStreamExtractorDefaultTest.YOUTUBE_LICENCE;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.schabi.newpipe.downloader.DownloaderFactory;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
|
@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.StreamingService;
|
|||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo.PlaylistType;
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
|
||||
import org.schabi.newpipe.extractor.services.DefaultStreamExtractorTest;
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeTestsUtils;
|
||||
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
|
@ -30,14 +31,15 @@ import javax.annotation.Nullable;
|
|||
|
||||
public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractorTest {
|
||||
private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH + "services/youtube/extractor/stream/";
|
||||
static final String ID = "K4DyBUG242c";
|
||||
static final String URL = YoutubeStreamExtractorDefaultTest.BASE_URL + ID;
|
||||
static final String TITLE = "Cartoon - On & On (feat. Daniel Levi) [NCS Release]";
|
||||
private static final String ID = "K4DyBUG242c";
|
||||
private static final String URL = YoutubeStreamExtractorDefaultTest.BASE_URL + ID;
|
||||
private static final String TITLE = "Cartoon - On & On (feat. Daniel Levi) | Electronic Pop | NCS - Copyright Free Music";
|
||||
private static StreamExtractor extractor;
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp() throws Exception {
|
||||
YoutubeTestsUtils.ensureStateless();
|
||||
YoutubeParsingHelper.setConsentAccepted(true);
|
||||
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "relatedMix"));
|
||||
extractor = YouTube.getStreamExtractor(URL);
|
||||
extractor.fetchPage();
|
||||
|
@ -60,30 +62,26 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
|
|||
@Override public boolean expectedUploaderVerified() { return true; }
|
||||
@Override public long expectedUploaderSubscriberCountAtLeast() { return 32_000_000; }
|
||||
@Override public long expectedLength() { return 208; }
|
||||
@Override public long expectedTimestamp() { return 0; }
|
||||
@Override public long expectedViewCountAtLeast() { return 449_000_000; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2015-07-09 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2015-07-09"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2015-07-09 16:34:35.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2015-07-09T09:34:35-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 6_400_000; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public boolean expectedHasSubtitles() { return true; }
|
||||
@Override public int expectedStreamSegmentsCount() { return 0; }
|
||||
@Override public String expectedLicence() { return YOUTUBE_LICENCE; }
|
||||
@Override public String expectedCategory() { return "Music"; }
|
||||
@Override public List<String> expectedTags() {
|
||||
return Arrays.asList("Cartoon", "Cartoon - On & On", "Cartoon Baboon",
|
||||
"Cartoon NCS Release", "Cartoon On & On (feat. Daniel Levi)", "Cartoon best songs",
|
||||
"Copyright Free Music", "Daniel Levi", "NCS", "NCS Best Songs",
|
||||
"NCS Cartoon Daniel Levi", "NCS Cartoon On & On", "NCS On & On", "NCS On and On",
|
||||
"NCS Release", "NCS Release Daniel Levi", "NCS release Cartoon", "Official",
|
||||
"On & On", "On & On NCS", "On and on", "Royalty Free Cartoon", "Royalty Free Music",
|
||||
"electronic", "no copyright sounds", "nocopyrightsounds", "on & on lyrics",
|
||||
"on and on lyrics");
|
||||
return Arrays.asList("Cartoon On & On (feat. Daniel Levi)", "Cartoon - On & On", "Cartoon",
|
||||
"On & On", "NCS", "nocopyrightsounds", "no copyright sounds", "NCS release Cartoon",
|
||||
"NCS Release Daniel Levi", "Daniel Levi", "NCS Release", "NCS Cartoon On & On",
|
||||
"NCS On and On", "NCS On & On", "NCS Best Songs", "NCS Cartoon Daniel Levi",
|
||||
"music", "songs", "ncs", "edm", "best music", "top music", "free music",
|
||||
"club music", "dance music", "no copyright music", "electronic music",
|
||||
"royalty free music", "copyright free music", "gaming music", "electronic pop");
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
@Test
|
||||
@Disabled("Mixes are not available in related items anymore, see https://github.com/TeamNewPipe/NewPipeExtractor/issues/820")
|
||||
@Override
|
||||
public void testRelatedItems() throws Exception {
|
||||
super.testRelatedItems();
|
||||
|
@ -100,7 +98,7 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
|
|||
final List<PlaylistInfoItem> streamMixes = playlists.stream()
|
||||
.filter(item -> item.getPlaylistType().equals(PlaylistType.MIX_STREAM))
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(1, streamMixes.size(), "Not found exactly one stream mix in related items");
|
||||
assertGreaterOrEqual(1, streamMixes.size(), "Not found one or more stream mix in related items");
|
||||
|
||||
final PlaylistInfoItem streamMix = streamMixes.get(0);
|
||||
assertSame(InfoItem.InfoType.PLAYLIST, streamMix.getInfoType());
|
||||
|
@ -109,17 +107,5 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
|
|||
assertContains("list=RD" + ID, streamMix.getUrl());
|
||||
assertEquals("Mix – " + TITLE, streamMix.getName());
|
||||
YoutubeTestsUtils.testImages(streamMix.getThumbnails());
|
||||
|
||||
final List<PlaylistInfoItem> musicMixes = playlists.stream()
|
||||
.filter(item -> item.getPlaylistType().equals(PlaylistType.MIX_MUSIC))
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(1, musicMixes.size(), "Not found exactly one music mix in related items");
|
||||
|
||||
final PlaylistInfoItem musicMix = musicMixes.get(0);
|
||||
assertSame(InfoItem.InfoType.PLAYLIST, musicMix.getInfoType());
|
||||
assertEquals(YouTube.getServiceId(), musicMix.getServiceId());
|
||||
assertContains("list=RDCLAK", musicMix.getUrl());
|
||||
assertEquals("Hip Hop Essentials", musicMix.getName());
|
||||
YoutubeTestsUtils.testImages(musicMix.getThumbnails());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,8 @@ public class YoutubeStreamExtractorUnlistedTest extends DefaultStreamExtractorTe
|
|||
}
|
||||
@Override public long expectedLength() { return 2488; }
|
||||
@Override public long expectedViewCountAtLeast() { return 1500; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2017-09-22 00:00:00.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2017-09-22"; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2017-09-22 12:15:21.000"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2017-09-22T05:15:21-07:00"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 110; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return -1; }
|
||||
@Override public StreamExtractor.Privacy expectedPrivacy() { return UNLISTED; }
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sun, 16 Apr 2023 17:42:25 GMT"
|
||||
"Fri, 08 Dec 2023 19:39:00 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sun, 16 Apr 2023 17:42:25 GMT"
|
||||
"Fri, 08 Dec 2023 19:39:00 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -53,7 +53,7 @@
|
|||
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
|
||||
],
|
||||
"permissions-policy": [
|
||||
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
|
||||
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-form-factor\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
|
||||
],
|
||||
"report-to": [
|
||||
"{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003deNq1o5_KNzg; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 20-Jul-2020 17:42:25 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+549; expires\u003dTue, 15-Apr-2025 17:42:25 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dnlRwmbCXdxA; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:39:00 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+731; expires\u003dSun, 07-Dec-2025 19:39:00 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:07:42 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:59 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:07:42 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:59 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003d6HVY0O6Qgzk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:07:42 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+865; expires\u003dMon, 14-Jul-2025 22:07:42 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003diKlrQNgJqEI; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:59 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+197; expires\u003dSun, 07-Dec-2025 19:37:59 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3,17 +3,17 @@
|
|||
"httpMethod": "POST",
|
||||
"url": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Cookie": [
|
||||
"CONSENT\u003dPENDING+488"
|
||||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20230714.00.00"
|
||||
"2.20231208.01.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -104,6 +104,27 @@
|
|||
58,
|
||||
123,
|
||||
34,
|
||||
117,
|
||||
116,
|
||||
99,
|
||||
79,
|
||||
102,
|
||||
102,
|
||||
115,
|
||||
101,
|
||||
116,
|
||||
77,
|
||||
105,
|
||||
110,
|
||||
117,
|
||||
116,
|
||||
101,
|
||||
115,
|
||||
34,
|
||||
58,
|
||||
48,
|
||||
44,
|
||||
34,
|
||||
104,
|
||||
108,
|
||||
34,
|
||||
|
@ -208,13 +229,13 @@
|
|||
48,
|
||||
50,
|
||||
51,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
52,
|
||||
50,
|
||||
48,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
48,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
48,
|
||||
|
@ -341,11 +362,20 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:07:43 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:59 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:59 GMT"
|
||||
],
|
||||
"p3p": [
|
||||
"CP\u003d\"This is not a P3P policy! See g.co/p3phelp for more info.\""
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
],
|
||||
"set-cookie": [
|
||||
"CONSENT\u003dPENDING+602; expires\u003dSun, 07-Dec-2025 19:37:59 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"vary": [
|
||||
"Origin",
|
||||
"X-Origin",
|
||||
|
@ -361,7 +391,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtVYTNwX0RQclVkNCivscylBg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20230714.00.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x302b0c7f330dbc2b\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"9407156,23804281,23930656,23946420,23966208,23983296,23986027,23998056,24004644,24007246,24034168,24036947,24077241,24080738,24120819,24135310,24140247,24166867,24181174,24187377,24211178,24216872,24219713,24241378,24255543,24255545,24262346,24279930,24288664,24290971,24291857,24362099,24362687,24364439,24364789,24365607,24366011,24366065,24366917,24367686,24367742,24368306,24370597,24371398,24371637,24372103,24372108,24373977,24374313,24379041,24379065,24379129,24379354,24379527,24379542,24379964,24379967,24380264,24381717,24382551,24383022,24383135,24383600,24383853,24384531,24385289,24385612,24386397,24386797,24388532,24388704,24388718,24388731,24388750,24388761,24389132,24390675,24404640,24407191,24415864,24416291,24428788,24437577,24439361,24440132,24451319,24453989,24457384,24457856,24458839,24459435,24466371,24466624,24468724,24469818,24485421,24490423,24495060,24498300,24499532,24502747,24503257,24504481,24504573,24506691,24506784,24506907,24506924,24509766,24515366,24515388,24515423,24518452,24519102,24520237,24522902,24523472,24524131,24525366,24525926,24526198,24526574,24528693,24537200,24550285,24550458,24550952,24551130,24552606,24553434,24554040,24554048,24557645,24559261,24559328,24690006,24691334,24695664,24696752,24698453,24698880,24699598,24699860,24699899,39324156\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20230714\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"24379967,24696752,9407156,24416291,24386797,24528693,24537200,24506784,24385289,23804281,23946420,24506907,24698880,24506691,24407191,24499532,24390675,24386397,24255545,24453989,24120819,24004644,24466371,24372103,24526198,24553434,24290971,24385612,23983296,24388704,24383600,24519102,24379041,24371398,24077241,24550285,24140247,24388532,24368306,24187377,24550458,24381717,24279930,24382551,24552606,24495060,24036947,24525926,23998056,24504481,24007246,24388750,24380264,24699598,24135310,24457384,24695664,24459435,24255543,24520237,24362099,24166867,24440132,24262346,24690006,24364789,24525366,24526574,24502747,24550952,24372108,24466624,24504573,24379129,24490423,24523472,24366917,24367686,24366011,24383853,24503257,24439361,24468724,24379065,23930656,24518452,24370597,24458839,24367742,24373977,24559328,24699899,24379964,24557645,24691334,24383135,24485421,24384531,24365607,24524131,24515388,24415864,24389132,24522902,24698453,24551130,24509766,24379354,24469818,24362687,24241378,24383022,24216872,24288664,24374313,24515423,24379527,24428788,24498300,24080738,24364439,24388761,24515366,24404640,24554048,24451319,24559261,24388718,24219713,24437577,23966208,24034168,24379542,39324156,24388731,24211178,24554040,24371637,24457856,24181174,24506924,23986027,24366065,24699860,24291857\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIppyt29yRgAMVwj3xBR20xA8jMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UC6nSFpj9HTCZ5t-N3Rm3-HA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtVb3ZBRFhqU1NOTSiX4c2rBjIICgJGUhICEgA%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20231208.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x918e2dd007736ced\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23946420,23966208,23983296,23986028,23998056,24004644,24007246,24034168,24036948,24060815,24077241,24080738,24120819,24135310,24140247,24166867,24181174,24187377,24241378,24255543,24255545,24288664,24290971,24291857,24367579,24371778,24377598,24377910,24382552,24385728,24387949,24390675,24428788,24428941,24428945,24428949,24439361,24451319,24453989,24458839,24468724,24485421,24506515,24506784,24515423,24518452,24524098,24526515,24537200,24539025,24542367,24542452,24546075,24548627,24548629,24549786,24550458,24559327,24560416,24563005,24566293,24566687,24583802,24585907,24589493,24694842,24697069,24698452,24699899,39324156,51000012,51003636,51004018,51006176,51006181,51009781,51009900,51010235,51012165,51012291,51012659,51014091,51016856,51017346,51019626,51020570,51021953,51024416,51025415,51026715,51027696,51027870,51028271,51029412,51033399,51033577,51036511,51037540,51038399,51038805,51039200,51039493,51041497,51041809,51043774,51045888,51045969,51047579,51048489,51049006,51051343,51053689,51053957,51055917,51056262,51056268,51057501,51057534,51057746,51059323,51059572,51061018,51061427,51061926,51063327,51063643,51065651,51066749,51068528,51068752,51069269,51069319,51069593,51070193,51070203,51070731,51071181,51071412,51072197,51072748,51073039,51073316,51073892,51074183,51074391,51074661,51074821,51076265,51076445,51078467,51079353,51080181\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20231208\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"24377910,51026715,51073039,51045888,24255545,24036948,39324156,51070731,24241378,51057746,24518452,51043774,24559327,24485421,51074391,51027870,51053957,24367579,51041497,51009781,51072197,23998056,51047579,51059572,51016856,24542367,24506784,51057501,24428945,51078467,51010235,51028271,24255543,51069269,51071412,51069593,51069319,51068528,51059323,24526515,51074821,24007246,24428949,24549786,51027696,24699899,51012291,24371778,24583802,24135310,24548629,24506515,51033399,24524098,24560416,51019626,51073892,24166867,24542452,51070203,51068752,51045969,51037540,24385728,51036511,24120819,51017346,24453989,51012659,51076445,24546075,51071181,24077241,24439361,24060815,51076265,51038805,51079353,24187377,24390675,23804281,51039200,51073316,24004644,51051343,51063327,51014091,51074661,24694842,24382552,51006181,24548627,51029412,24034168,51057534,24537200,24585907,24563005,24698452,51033577,51072748,51065651,51056268,51080181,24428941,24291857,24566687,24468724,51012165,51025415,24515423,24288664,23946420,24377598,51020570,51061926,51049006,51004018,24181174,51024416,51053689,24140247,51061427,51021953,51039493,51041809,51000012,23966208,23986028,51009900,51048489,24589493,51006176,24080738,51003636,24451319,24697069,51038399,24428788,24550458,24539025,23983296,51061018,24566293,24387949,51055917,24458839,51074183,51063643,51056262,24290971,51066749,51070193\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMI4OydxsuAgwMVNFRPBB3OEgkqMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UC6nSFpj9HTCZ5t-N3Rm3-HA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:08:17 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:52 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:08:17 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:52 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dN_LdAqhQwJo; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:08:17 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+052; expires\u003dMon, 14-Jul-2025 22:08:17 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dZrg1hMAzzPk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:52 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+514; expires\u003dSun, 07-Dec-2025 19:37:52 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -29,7 +29,7 @@
|
|||
"https://www.youtube.com"
|
||||
],
|
||||
"alt-svc": [
|
||||
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000,h3-Q050\u003d\":443\"; ma\u003d2592000,h3-Q046\u003d\":443\"; ma\u003d2592000,h3-Q043\u003d\":443\"; ma\u003d2592000,quic\u003d\":443\"; ma\u003d2592000; v\u003d\"46,43\""
|
||||
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000"
|
||||
],
|
||||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
|
@ -37,20 +37,23 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Tue, 22 Nov 2022 10:40:04 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:53 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Tue, 22 Nov 2022 10:40:04 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:53 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
],
|
||||
"p3p": [
|
||||
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
|
||||
],
|
||||
"permissions-policy": [
|
||||
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
|
||||
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-form-factor\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
|
||||
],
|
||||
"report-to": [
|
||||
"{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}"
|
||||
|
@ -59,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003diUDF-c9d_Kc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dWed, 26-Feb-2020 10:40:04 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+907; expires\u003dThu, 21-Nov-2024 10:40:04 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003d5WwUdkHli5g; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:53 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+301; expires\u003dSun, 07-Dec-2025 19:37:53 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:08:06 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:54 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:08:06 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:54 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dQz7A-y6TpO8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:08:06 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+310; expires\u003dMon, 14-Jul-2025 22:08:06 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003d7gHwLK-eIns; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:54 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+450; expires\u003dSun, 07-Dec-2025 19:37:54 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -37,14 +37,14 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:06:59 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:55 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:06:59 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:55 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dg_ag4hAONhk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:06:59 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+229; expires\u003dMon, 14-Jul-2025 22:06:59 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dB5TY0jJCRl4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:55 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+987; expires\u003dSun, 07-Dec-2025 19:37:55 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -37,14 +37,14 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Tue, 08 Aug 2023 17:04:33 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:55 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Tue, 08 Aug 2023 17:04:33 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:55 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dV1ZtomDP-24; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dWed, 11-Nov-2020 17:04:33 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+547; expires\u003dThu, 07-Aug-2025 17:04:33 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dFFmfosvsq8M; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:55 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+549; expires\u003dSun, 07-Dec-2025 19:37:55 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:07:17 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:56 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:07:17 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:56 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dk1Kj8R4lxGo; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:07:17 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+518; expires\u003dMon, 14-Jul-2025 22:07:17 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dnZE8WYkAbSk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:56 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+860; expires\u003dSun, 07-Dec-2025 19:37:56 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -37,14 +37,14 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:00:51 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:00 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:00:51 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:00 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dq9uvkrxFtSk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:00:51 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+377; expires\u003dMon, 14-Jul-2025 22:00:51 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dwO2i4ilbfqc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:00 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+031; expires\u003dSun, 07-Dec-2025 19:38:00 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -37,14 +37,14 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:06:37 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:57 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:06:37 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:57 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dyO7EGB-OaZE; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:06:37 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+510; expires\u003dMon, 14-Jul-2025 22:06:37 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003d45cg5Fq7qO4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:57 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+095; expires\u003dSun, 07-Dec-2025 19:37:57 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,17 +3,17 @@
|
|||
"httpMethod": "POST",
|
||||
"url": "https://www.youtube.com/youtubei/v1/browse?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Cookie": [
|
||||
"CONSENT\u003dPENDING+578"
|
||||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20230714.00.00"
|
||||
"2.20231208.01.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -130,6 +130,27 @@
|
|||
58,
|
||||
123,
|
||||
34,
|
||||
117,
|
||||
116,
|
||||
99,
|
||||
79,
|
||||
102,
|
||||
102,
|
||||
115,
|
||||
101,
|
||||
116,
|
||||
77,
|
||||
105,
|
||||
110,
|
||||
117,
|
||||
116,
|
||||
101,
|
||||
115,
|
||||
34,
|
||||
58,
|
||||
48,
|
||||
44,
|
||||
34,
|
||||
104,
|
||||
108,
|
||||
34,
|
||||
|
@ -234,13 +255,13 @@
|
|||
48,
|
||||
50,
|
||||
51,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
52,
|
||||
50,
|
||||
48,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
48,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
48,
|
||||
|
@ -355,7 +376,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:06:39 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
|
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:07:31 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:07:31 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003db1xMQwJhIlw; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:07:31 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+426; expires\u003dMon, 14-Jul-2025 22:07:31 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dnZmCsp9t2-E; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:58 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+525; expires\u003dSun, 07-Dec-2025 19:37:58 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -37,14 +37,14 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 15 Jul 2023 22:07:11 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 15 Jul 2023 22:07:11 GMT"
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dRvUxcEUa94o; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:07:11 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+576; expires\u003dMon, 14-Jul-2025 22:07:11 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dmGbVRaILdW8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:58 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+013; expires\u003dSun, 07-Dec-2025 19:37:58 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,9 +34,6 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy-report-only": [
|
||||
"require-trusted-types-for \u0027script\u0027;report-uri /cspreport"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -44,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sun, 06 Aug 2023 11:54:54 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:01 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sun, 06 Aug 2023 11:54:54 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:01 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -65,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dIXSPROQ-CH8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 09-Nov-2020 11:54:54 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+942; expires\u003dTue, 05-Aug-2025 11:54:54 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dslesUy90N9c; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:01 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+003; expires\u003dSun, 07-Dec-2025 19:38:01 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -37,14 +37,14 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sun, 06 Aug 2023 11:55:07 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:01 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sun, 06 Aug 2023 11:55:07 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:01 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dqCdA3bmpLFQ; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 09-Nov-2020 11:55:07 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+717; expires\u003dTue, 05-Aug-2025 11:55:07 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dyB7TaAiyiec; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:01 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+001; expires\u003dSun, 07-Dec-2025 19:38:01 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,9 +34,6 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy-report-only": [
|
||||
"require-trusted-types-for \u0027script\u0027;report-uri /cspreport"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -44,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sun, 16 Jul 2023 18:52:14 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:02 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sun, 16 Jul 2023 18:52:14 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:02 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -65,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003d9JX-39itmDs; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 19-Oct-2020 18:52:14 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+644; expires\u003dTue, 15-Jul-2025 18:52:14 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dsYYTQ2nPvgM; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:02 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+164; expires\u003dSun, 07-Dec-2025 19:38:02 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -37,14 +37,14 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sun, 16 Jul 2023 18:52:40 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:03 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sun, 16 Jul 2023 18:52:40 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:03 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dq_DT7lNw0D4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 19-Oct-2020 18:52:40 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+204; expires\u003dTue, 15-Jul-2025 18:52:40 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dnA0Qd2uyByw; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:03 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+819; expires\u003dSun, 07-Dec-2025 19:38:03 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -37,14 +37,14 @@
|
|||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
"cross-origin-opener-policy-report-only": [
|
||||
"cross-origin-opener-policy": [
|
||||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Tue, 18 Jul 2023 23:55:38 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:04 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Tue, 18 Jul 2023 23:55:38 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:04 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dFes-x1Jw3Yk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dWed, 21-Oct-2020 23:55:38 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+486; expires\u003dThu, 17-Jul-2025 23:55:38 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dXVJaGz18ttE; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:04 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+916; expires\u003dSun, 07-Dec-2025 19:38:04 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sun, 16 Jul 2023 18:51:54 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:05 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sun, 16 Jul 2023 18:51:54 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:05 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,9 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dgnERa_YMa0w; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 19-Oct-2020 18:51:54 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+072; expires\u003dTue, 15-Jul-2025 18:51:54 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dO2iOuaMhLuc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:05 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+851; expires\u003dSun, 07-Dec-2025 19:38:05 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -10,10 +10,10 @@
|
|||
"https://www.youtube.com"
|
||||
],
|
||||
"Cookie": [
|
||||
"CONSENT\u003dPENDING+488"
|
||||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20230714.00.00"
|
||||
"2.20231208.01.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -104,6 +104,27 @@
|
|||
58,
|
||||
123,
|
||||
34,
|
||||
117,
|
||||
116,
|
||||
99,
|
||||
79,
|
||||
102,
|
||||
102,
|
||||
115,
|
||||
101,
|
||||
116,
|
||||
77,
|
||||
105,
|
||||
110,
|
||||
117,
|
||||
116,
|
||||
101,
|
||||
115,
|
||||
34,
|
||||
58,
|
||||
48,
|
||||
44,
|
||||
34,
|
||||
104,
|
||||
108,
|
||||
34,
|
||||
|
@ -208,13 +229,13 @@
|
|||
48,
|
||||
50,
|
||||
51,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
52,
|
||||
50,
|
||||
48,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
48,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
48,
|
||||
|
@ -350,11 +371,20 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Sun, 16 Jul 2023 18:51:56 GMT"
|
||||
"Fri, 08 Dec 2023 19:38:05 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:38:05 GMT"
|
||||
],
|
||||
"p3p": [
|
||||
"CP\u003d\"This is not a P3P policy! See g.co/p3phelp for more info.\""
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
],
|
||||
"set-cookie": [
|
||||
"CONSENT\u003dPENDING+254; expires\u003dSun, 07-Dec-2025 19:38:05 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"vary": [
|
||||
"Origin",
|
||||
"X-Origin",
|
||||
|
@ -370,7 +400,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtaUjU0cW8ydnY1ayjM-NClBg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20230714.00.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xb04ccb5ee4014ed1\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23946420,23966208,23983296,23986034,23998056,24004644,24007246,24034168,24036947,24077241,24080738,24120820,24135310,24140247,24166867,24181174,24187377,24187921,24211178,24219713,24241378,24248956,24255165,24255543,24255545,24262346,24288664,24290971,24291857,24362105,24362606,24362625,24364789,24365576,24366065,24366917,24367743,24368312,24368832,24370597,24371398,24371634,24372101,24372110,24372222,24373977,24374311,24374643,24374679,24376979,24379035,24379061,24379127,24379352,24379531,24379544,24379958,24379967,24380264,24382551,24383022,24383129,24383330,24383600,24383853,24384531,24385289,24385612,24386397,24386796,24388706,24388718,24388733,24388750,24388759,24389132,24390675,24404640,24407191,24407446,24415864,24428788,24437577,24439361,24440132,24451319,24453989,24457384,24458839,24459435,24466371,24466622,24468724,24469818,24485421,24488210,24495060,24498300,24502852,24503257,24503432,24504481,24504702,24504817,24506101,24506784,24506908,24506924,24506966,24507690,24509207,24509766,24511563,24515366,24515423,24518452,24519102,24520236,24523472,24526542,24526573,24531244,24537200,24550285,24550458,24550951,24551130,24552606,24553434,24554039,24554047,24559261,24691334,24694842,24696751,24698453,24698880,24699598,24699860,24699899,39324156\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20230714\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"24211178,24506784,24526542,24498300,24385289,24428788,24368312,24507690,24552606,24362625,24007246,24371634,24466622,24036947,24388718,24255545,24385612,24698880,24502852,24379544,24290971,24453989,24379127,24262346,24255165,24383600,24520236,24550458,23986034,24523472,24372101,24506101,24550285,24506908,24140247,24380264,24120820,24388759,24382551,24376979,24495060,24526573,24457384,24379531,24386796,24407191,24554039,24440132,24368832,24367743,24255543,24374311,24459435,24077241,24519102,24364789,24379035,24389132,24696751,24553434,24004644,24187377,24503432,23998056,24241378,24372110,24366917,24379352,24699598,24371398,24509207,24383853,24504481,24388750,24458839,24515423,24511563,24439361,24559261,24080738,24135310,24166867,24691334,24374643,24388706,24550951,24415864,24384531,24554047,24383129,24374679,24468724,24488210,24699860,24469818,24379958,23966208,24503257,24248956,24383330,24509766,24551130,24698453,24362105,24370597,24187921,24518452,24537200,24531244,24372222,24504817,24390675,24373977,24362606,24386397,24506966,24288664,24451319,24383022,24504702,23804281,23946420,24407446,24699899,24515366,24466371,24404640,23983296,24437577,39324156,24034168,24219713,24485421,24291857,24366065,24379967,24506924,24181174,24388733,24694842,24379061,24365576\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIhIDB6PKTgAMVpUxBAh01GwjbMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UCTwECeGqMZee77BjdoYtI2Q\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtXTDBqYnNCaW9YOCid4c2rBjIICgJGUhICEgA%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20231208.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xf64eb8c056b59c48\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"9406121,23804281,23946420,23966208,23983296,23998056,24004644,24007246,24017848,24034168,24036948,24077241,24080738,24120820,24135310,24140247,24166867,24181174,24187377,24216872,24241378,24255543,24255545,24288664,24290971,24291857,24367580,24371778,24377598,24377910,24382552,24385728,24387949,24390675,24428788,24428941,24428945,24439361,24451319,24453989,24458839,24468724,24485421,24506515,24506784,24515423,24518452,24524098,24526515,24537200,24539025,24542367,24542452,24546075,24548627,24548629,24549786,24550458,24554164,24559327,24560416,24563006,24566293,24566687,24583802,24585907,24589492,24694842,24697067,24698452,24699899,39324156,51000012,51003636,51004018,51006176,51006181,51009781,51009900,51010235,51012165,51012291,51012659,51014091,51016856,51017346,51019626,51020570,51021953,51024416,51025415,51026715,51027870,51028271,51029412,51033399,51033577,51036511,51037540,51037819,51037893,51038399,51038805,51039199,51039493,51041497,51041809,51045885,51045888,51045969,51047579,51048239,51048489,51049006,51049131,51051343,51053690,51053957,51055917,51056263,51056270,51057501,51057534,51057746,51059322,51059573,51061018,51061427,51061926,51063327,51063643,51064283,51065651,51066749,51068528,51068752,51069269,51069319,51070192,51070203,51071181,51071411,51072197,51072748,51073315,51074183,51074391,51074661,51075805,51076209,51076264,51078467,51079353\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20231208\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"51026715,51056263,24451319,51000012,24004644,51066749,51027870,24140247,24017848,51006181,24367580,24589492,24241378,51074183,24458839,51055917,51039493,51021953,24566293,51045885,51038399,24428945,51056270,24290971,51003636,24468724,24550458,51048489,51009900,24034168,51020570,51012165,51006176,24515423,51037819,24135310,51039199,51033577,24382552,23966208,24080738,24585907,51049006,24563006,51028271,24548627,24698452,24694842,24377598,51041809,51074661,51004018,51072748,51051343,24566687,51014091,51073315,24216872,23804281,24181174,24288664,24554164,24291857,24166867,51076264,51057534,24537200,51045888,24542452,51068752,24120820,24518452,51029412,24559327,24560416,51063327,24549786,24385728,24390675,51012659,24485421,51059322,51033399,24526515,24548629,24255543,51037893,24583802,51069319,24007246,51061926,24546075,24439361,51071411,51068528,51017346,51036511,51024416,51071181,51019626,51065651,51038805,23946420,9406121,51009781,51070203,51025415,51069269,24453989,51075805,51012291,51037540,51047579,24524098,24506515,24699899,24428941,39324156,51074391,51070192,23998056,51010235,24506784,51045969,24255545,51057501,51078467,51053957,51061427,24542367,24371778,51076209,24036948,24377910,24387949,51072197,51059573,51079353,24428788,24539025,24697067,24077241,51041497,51064283,51063643,51016856,51053690,51049131,24187377,51057746,23983296,51048239,51061018\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIq_j7yMuAgwMVQ1FPBB1tmwaUMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UCTwECeGqMZee77BjdoYtI2Q\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue