kopia lustrzana https://github.com/TeamNewPipe/NewPipeExtractor
Porównaj commity
17 Commity
c2a4250d2a
...
9f0255fd6e
Autor | SHA1 | Data |
---|---|---|
Kavin | 9f0255fd6e | |
Tobi | ec3e8378c6 | |
TobiGr | 8d2a7a5281 | |
TobiGr | 7c29dbc965 | |
Stypox | fbe9e6223a | |
Stypox | 4e9e7cb29c | |
Stypox | 9d0dd36034 | |
Stypox | d4e6d22e64 | |
AudricV | 74bf000473 | |
AudricV | f9792cf3a9 | |
AudricV | f40fc0aa4f | |
AudricV | 2a3c6f80d2 | |
AudricV | 657b4377aa | |
AudricV | 7bf50bf1cb | |
AudricV | 27dc1b1f50 | |
AudricV | e380bb4bc3 | |
Kavin | b204560b3d |
|
@ -38,6 +38,8 @@
|
|||
<module name="LineLength">
|
||||
<property name="max" value="100"/>
|
||||
<property name="fileExtensions" value="java"/>
|
||||
<!-- Also allow links in javadocs to be longer (the default would just cover imports) -->
|
||||
<property name="ignorePattern" value="^((package|import) .*)|( *\* (@see )?<a href ?\= ?".*">)$"/>
|
||||
</module>
|
||||
|
||||
<!-- Checks for whitespace -->
|
||||
|
|
|
@ -51,7 +51,7 @@ public enum MediaFormat {
|
|||
WEBMA_OPUS(0x200, "WebM Opus", "webm", "audio/webm"),
|
||||
AIFF (0x600, "AIFF", "aiff", "audio/aiff"),
|
||||
/**
|
||||
* Same as {@link MediaFormat.AIFF}, just with the shorter suffix/file extension
|
||||
* Same as {@link MediaFormat#AIFF}, just with the shorter suffix/file extension
|
||||
*/
|
||||
AIF (0x600, "AIFF", "aif", "audio/aiff"),
|
||||
WAV (0x700, "WAV", "wav", "audio/wav"),
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.List;
|
|||
* return ((ReadyChannelTabListLinkHandler) linkHandler).getChannelTabExtractor(this);
|
||||
* }
|
||||
* </pre>
|
||||
* </p>
|
||||
*/
|
||||
public class ReadyChannelTabListLinkHandler extends ListLinkHandler {
|
||||
|
||||
|
|
|
@ -111,8 +111,7 @@ public final class BandcampExtractorHelper {
|
|||
|
||||
/**
|
||||
* Fetch artist details from mobile endpoint.
|
||||
* <a href="https://notabug.org/fynngodau/bandcampDirect/wiki/
|
||||
* rewindBandcamp+%E2%80%93+Fetching+artist+details">
|
||||
* <a href="https://notabug.org/fynngodau/bandcampDirect/wiki/rewindBandcamp+%E2%80%93+Fetching+artist+details">
|
||||
* More technical info.</a>
|
||||
*/
|
||||
public static JsonObject getArtistDetails(final String id) throws ParsingException {
|
||||
|
|
|
@ -81,6 +81,10 @@ public class ItagItem implements Serializable {
|
|||
new ItagItem(400, VIDEO_ONLY, MPEG_4, "1440p"),
|
||||
new ItagItem(266, VIDEO_ONLY, MPEG_4, "2160p"),
|
||||
new ItagItem(401, VIDEO_ONLY, MPEG_4, "2160p"),
|
||||
new ItagItem(402, VIDEO_ONLY, MPEG_4, "4320p"), // can be 4320p60 as well
|
||||
new ItagItem(571, VIDEO_ONLY, MPEG_4, "4320p"),
|
||||
// can be 4320p60 HDR as well (1La4QzGeaaQ)
|
||||
new ItagItem(402, VIDEO_ONLY, MPEG_4, "4320p60", 60),
|
||||
|
||||
new ItagItem(278, VIDEO_ONLY, WEBM, "144p"),
|
||||
new ItagItem(242, VIDEO_ONLY, WEBM, "240p"),
|
||||
|
@ -91,28 +95,19 @@ public class ItagItem implements Serializable {
|
|||
new ItagItem(247, VIDEO_ONLY, WEBM, "720p"),
|
||||
new ItagItem(248, VIDEO_ONLY, WEBM, "1080p"),
|
||||
new ItagItem(271, VIDEO_ONLY, WEBM, "1440p"),
|
||||
// #272 is either 3840x2160 (e.g. RtoitU2A-3E) or 7680x4320 (sLprVF6d7Ug)
|
||||
new ItagItem(272, VIDEO_ONLY, WEBM, "2160p"),
|
||||
new ItagItem(302, VIDEO_ONLY, WEBM, "720p60", 60),
|
||||
new ItagItem(303, VIDEO_ONLY, WEBM, "1080p60", 60),
|
||||
new ItagItem(308, VIDEO_ONLY, WEBM, "1440p60", 60),
|
||||
new ItagItem(313, VIDEO_ONLY, WEBM, "2160p"),
|
||||
new ItagItem(315, VIDEO_ONLY, WEBM, "2160p60", 60)
|
||||
new ItagItem(315, VIDEO_ONLY, WEBM, "2160p60", 60),
|
||||
new ItagItem(272, VIDEO_ONLY, WEBM, "4320p60", 60)
|
||||
};
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public static boolean isSupported(final int itag) {
|
||||
for (final ItagItem item : ITAG_LIST) {
|
||||
if (itag == item.id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Nonnull
|
||||
public static ItagItem getItag(final int itagId) throws ParsingException {
|
||||
for (final ItagItem item : ITAG_LIST) {
|
||||
|
@ -123,6 +118,65 @@ public class ItagItem implements Serializable {
|
|||
throw new ParsingException("itag " + itagId + " is not supported");
|
||||
}
|
||||
|
||||
public static ItagItem getItag(final int itagId, final int averageBitrate,
|
||||
final int fps, final String qualityLabel, final String mimeType)
|
||||
throws ParsingException {
|
||||
|
||||
final String[] split = mimeType.split(";")[0].split("/");
|
||||
final String streamType = split[0];
|
||||
final String fileType = split[1];
|
||||
final String codec = mimeType.split("\"")[1];
|
||||
|
||||
MediaFormat format = null;
|
||||
ItagType itagType = null;
|
||||
|
||||
if (codec.contains(",")) { // muxed streams have both an audio and video codec
|
||||
itagType = VIDEO;
|
||||
} else {
|
||||
if (streamType.equals("video")) {
|
||||
itagType = VIDEO_ONLY;
|
||||
}
|
||||
if (streamType.equals("audio")) {
|
||||
itagType = AUDIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (itagType == VIDEO) {
|
||||
if (fileType.equals("mp4")) {
|
||||
format = MPEG_4;
|
||||
}
|
||||
if (fileType.equals("3gpp")) {
|
||||
format = v3GPP;
|
||||
}
|
||||
}
|
||||
|
||||
if (itagType == VIDEO_ONLY) {
|
||||
if (fileType.equals("mp4")) {
|
||||
format = MPEG_4;
|
||||
}
|
||||
if (fileType.equals("webm")) {
|
||||
format = WEBM;
|
||||
}
|
||||
}
|
||||
|
||||
if (itagType == AUDIO) {
|
||||
if (fileType.equals("mp4") && (codec.startsWith("m4a") || codec.startsWith("mp4a"))) {
|
||||
format = M4A;
|
||||
}
|
||||
if (fileType.startsWith("webm") && codec.equals("opus")) {
|
||||
format = WEBMA_OPUS;
|
||||
}
|
||||
}
|
||||
|
||||
if (itagType == null || format == null) {
|
||||
throw new ParsingException("Unknown mimeType: " + mimeType);
|
||||
}
|
||||
|
||||
return itagType == AUDIO
|
||||
? new ItagItem(itagId, itagType, format, Math.round(averageBitrate / 1024f))
|
||||
: new ItagItem(itagId, itagType, format, qualityLabel, fps);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Static constants
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
|
@ -170,16 +170,34 @@ public final class YoutubeMetaInfoHelper {
|
|||
|
||||
// usually an encouragement like "We are with you"
|
||||
final String title = getTextFromObjectOrThrow(r.getObject("title"), "title");
|
||||
|
||||
// usually a phone number
|
||||
final String action = getTextFromObjectOrThrow(r.getObject("actionText"), "action");
|
||||
final String action; // this variable is expected to start with "\n"
|
||||
if (r.has("actionText")) {
|
||||
action = "\n" + getTextFromObjectOrThrow(r.getObject("actionText"), "action");
|
||||
} else if (r.has("contacts")) {
|
||||
final JsonArray contacts = r.getArray("contacts");
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
// Loop over contacts item from the first contact to the last one
|
||||
for (int i = 0; i < contacts.size(); i++) {
|
||||
stringBuilder.append("\n");
|
||||
stringBuilder.append(getTextFromObjectOrThrow(contacts.getObject(i)
|
||||
.getObject("actionText"), "contacts.actionText"));
|
||||
}
|
||||
action = stringBuilder.toString();
|
||||
} else {
|
||||
action = "";
|
||||
}
|
||||
|
||||
// usually details about the phone number
|
||||
final String details = getTextFromObjectOrThrow(r.getObject("detailsText"), "details");
|
||||
|
||||
// usually the name of an association
|
||||
final String urlText = getTextFromObjectOrThrow(r.getObject("navigationText"),
|
||||
"urlText");
|
||||
|
||||
metaInfo.setTitle(title);
|
||||
metaInfo.setContent(new Description(details + "\n" + action, Description.PLAIN_TEXT));
|
||||
metaInfo.setContent(new Description(details + action, Description.PLAIN_TEXT));
|
||||
metaInfo.addUrlText(urlText);
|
||||
|
||||
// usually the webpage of the association
|
||||
|
|
|
@ -100,17 +100,17 @@ public final class YoutubeParsingHelper {
|
|||
* sizes.
|
||||
*
|
||||
* <p>
|
||||
* Sent in query parameters of the requests, <b>after</b> the API key.
|
||||
* Sent in query parameters of the requests.
|
||||
* </p>
|
||||
**/
|
||||
public static final String DISABLE_PRETTY_PRINT_PARAMETER = "&prettyPrint=false";
|
||||
public static final String DISABLE_PRETTY_PRINT_PARAMETER = "prettyPrint=false";
|
||||
|
||||
/**
|
||||
* A parameter sent by official clients named {@code contentPlaybackNonce}.
|
||||
*
|
||||
* <p>
|
||||
* It is sent by official clients on videoplayback requests, and by all clients (except the
|
||||
* {@code WEB} one to the player requests.
|
||||
* It is sent by official clients on videoplayback requests and InnerTube player requests in
|
||||
* most cases.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
|
@ -144,17 +144,16 @@ public final class YoutubeParsingHelper {
|
|||
*/
|
||||
public static final String RACY_CHECK_OK = "racyCheckOk";
|
||||
|
||||
/**
|
||||
* The hardcoded client ID used for InnerTube requests with the {@code WEB} client.
|
||||
*/
|
||||
private static final String WEB_CLIENT_ID = "1";
|
||||
|
||||
/**
|
||||
* 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.20231208.01.00";
|
||||
|
||||
/**
|
||||
* The InnerTube API key which should be used by YouTube's desktop website, used as a fallback
|
||||
* if the extraction of the real one failed.
|
||||
*/
|
||||
private static final String HARDCODED_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
|
||||
private static final String HARDCODED_CLIENT_VERSION = "2.20240410.01.00";
|
||||
|
||||
/**
|
||||
* The hardcoded client version of the Android app used for InnerTube requests with this
|
||||
|
@ -165,17 +164,10 @@ 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 = "18.48.37";
|
||||
private static final String ANDROID_YOUTUBE_CLIENT_VERSION = "19.13.36";
|
||||
|
||||
/**
|
||||
* The InnerTube API key used by the {@code ANDROID} client. Found with the help of
|
||||
* reverse-engineering app network requests.
|
||||
*/
|
||||
private static final String ANDROID_YOUTUBE_KEY = "AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w";
|
||||
|
||||
/**
|
||||
* The hardcoded client version of the iOS app used for InnerTube requests with this
|
||||
* client.
|
||||
* The hardcoded client version of the iOS app used for InnerTube requests with this client.
|
||||
*
|
||||
* <p>
|
||||
* It can be extracted by getting the latest release version of the app on
|
||||
|
@ -183,42 +175,39 @@ 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 = "18.48.3";
|
||||
|
||||
/**
|
||||
* The InnerTube API key used by the {@code iOS} client. Found with the help of
|
||||
* reverse-engineering app network requests.
|
||||
*/
|
||||
private static final String IOS_YOUTUBE_KEY = "AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc";
|
||||
private static final String IOS_YOUTUBE_CLIENT_VERSION = "19.14.3";
|
||||
|
||||
/**
|
||||
* The hardcoded client version used for InnerTube requests with the TV HTML5 embed client.
|
||||
*/
|
||||
private static final String TVHTML5_SIMPLY_EMBED_CLIENT_VERSION = "2.0";
|
||||
|
||||
/**
|
||||
* The hardcoded client ID used for InnerTube requests with the YouTube Music desktop client.
|
||||
*/
|
||||
private static final String YOUTUBE_MUSIC_CLIENT_ID = "67";
|
||||
|
||||
/**
|
||||
* The hardcoded client version used for InnerTube requests with the YouTube Music desktop
|
||||
* client.
|
||||
*/
|
||||
private static final String HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION = "1.20240403.01.00";
|
||||
|
||||
private static String clientVersion;
|
||||
private static String key;
|
||||
|
||||
private static final String[] HARDCODED_YOUTUBE_MUSIC_KEY =
|
||||
{"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "1.20231204.01.00"};
|
||||
private static String[] youtubeMusicKey;
|
||||
private static String youtubeMusicClientVersion;
|
||||
|
||||
private static boolean keyAndVersionExtracted = false;
|
||||
private static boolean clientVersionExtracted = false;
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
private static Optional<Boolean> hardcodedClientVersionAndKeyValid = Optional.empty();
|
||||
private static Optional<Boolean> hardcodedClientVersionValid = Optional.empty();
|
||||
|
||||
private static final String[] INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES =
|
||||
{"INNERTUBE_CONTEXT_CLIENT_VERSION\":\"([0-9\\.]+?)\"",
|
||||
"innertube_context_client_version\":\"([0-9\\.]+?)\"",
|
||||
"client.version=([0-9\\.]+)"};
|
||||
private static final String[] INNERTUBE_API_KEY_REGEXES =
|
||||
{"INNERTUBE_API_KEY\":\"([0-9a-zA-Z_-]+?)\"",
|
||||
"innertubeApiKey\":\"([0-9a-zA-Z_-]+?)\""};
|
||||
private static final String[] INITIAL_DATA_REGEXES =
|
||||
{"window\\[\"ytInitialData\"\\]\\s*=\\s*(\\{.*?\\});",
|
||||
"var\\s*ytInitialData\\s*=\\s*(\\{.*?\\});"};
|
||||
private static final String INNERTUBE_CLIENT_NAME_REGEX =
|
||||
"INNERTUBE_CONTEXT_CLIENT_NAME\":([0-9]+?),";
|
||||
|
||||
private static final String CONTENT_PLAYBACK_NONCE_ALPHABET =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
@ -233,6 +222,30 @@ public final class YoutubeParsingHelper {
|
|||
*/
|
||||
private static final String IOS_DEVICE_MODEL = "iPhone15,4";
|
||||
|
||||
/**
|
||||
* Spoofing an iPhone 15 running iOS 17.4.1 with the hardcoded version of the iOS app. To be
|
||||
* used for the {@code "osVersion"} field in JSON POST requests.
|
||||
* <p>
|
||||
* 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
|
||||
* <a href="https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15">
|
||||
* https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15</a>
|
||||
* </p>
|
||||
*
|
||||
* @see #IOS_USER_AGENT_VERSION
|
||||
*/
|
||||
private static final String IOS_OS_VERSION = "17.4.1.21E237";
|
||||
|
||||
/**
|
||||
* Spoofing an iPhone 15 running iOS 17.4.1 with the hardcoded version of the iOS app. To be
|
||||
* used in the user agent for requests.
|
||||
*
|
||||
* @see #IOS_OS_VERSION
|
||||
*/
|
||||
private static final String IOS_USER_AGENT_VERSION = "17_4_1";
|
||||
|
||||
private static Random numberGenerator = new Random();
|
||||
|
||||
private static final String FEED_BASE_CHANNEL_ID =
|
||||
|
@ -518,10 +531,10 @@ public final class YoutubeParsingHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean areHardcodedClientVersionAndKeyValid()
|
||||
public static boolean isHardcodedClientVersionValid()
|
||||
throws IOException, ExtractionException {
|
||||
if (hardcodedClientVersionAndKeyValid.isPresent()) {
|
||||
return hardcodedClientVersionAndKeyValid.get();
|
||||
if (hardcodedClientVersionValid.isPresent()) {
|
||||
return hardcodedClientVersionValid.get();
|
||||
}
|
||||
// @formatter:off
|
||||
final byte[] body = JsonWriter.string()
|
||||
|
@ -550,25 +563,25 @@ public final class YoutubeParsingHelper {
|
|||
.end().done().getBytes(StandardCharsets.UTF_8);
|
||||
// @formatter:on
|
||||
|
||||
final var headers = getClientHeaders("1", HARDCODED_CLIENT_VERSION);
|
||||
final var headers = getClientHeaders(WEB_CLIENT_ID, HARDCODED_CLIENT_VERSION);
|
||||
|
||||
// This endpoint is fetched by the YouTube website to get the items of its main menu and is
|
||||
// pretty lightweight (around 30kB)
|
||||
final Response response = getDownloader().postWithContentTypeJson(
|
||||
YOUTUBEI_V1_URL + "guide?key=" + HARDCODED_KEY + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
YOUTUBEI_V1_URL + "guide?" + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
headers, body);
|
||||
final String responseBody = response.responseBody();
|
||||
final int responseCode = response.responseCode();
|
||||
|
||||
hardcodedClientVersionAndKeyValid = Optional.of(responseBody.length() > 5000
|
||||
hardcodedClientVersionValid = Optional.of(responseBody.length() > 5000
|
||||
&& responseCode == 200); // Ensure to have a valid response
|
||||
return hardcodedClientVersionAndKeyValid.get();
|
||||
return hardcodedClientVersionValid.get();
|
||||
}
|
||||
|
||||
|
||||
private static void extractClientVersionAndKeyFromSwJs()
|
||||
private static void extractClientVersionFromSwJs()
|
||||
throws IOException, ExtractionException {
|
||||
if (keyAndVersionExtracted) {
|
||||
if (clientVersionExtracted) {
|
||||
return;
|
||||
}
|
||||
final String url = "https://www.youtube.com/sw.js";
|
||||
|
@ -577,18 +590,17 @@ public final class YoutubeParsingHelper {
|
|||
try {
|
||||
clientVersion = getStringResultFromRegexArray(response,
|
||||
INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES, 1);
|
||||
key = getStringResultFromRegexArray(response, INNERTUBE_API_KEY_REGEXES, 1);
|
||||
} catch (final Parser.RegexException e) {
|
||||
throw new ParsingException("Could not extract YouTube WEB InnerTube client version "
|
||||
+ "and API key from sw.js", e);
|
||||
+ "from sw.js", e);
|
||||
}
|
||||
keyAndVersionExtracted = true;
|
||||
clientVersionExtracted = true;
|
||||
}
|
||||
|
||||
private static void extractClientVersionAndKeyFromHtmlSearchResultsPage()
|
||||
private static void extractClientVersionFromHtmlSearchResultsPage()
|
||||
throws IOException, ExtractionException {
|
||||
// Don't extract the client version and the InnerTube key if it has been already extracted
|
||||
if (keyAndVersionExtracted) {
|
||||
// Don't extract the InnerTube client version if it has been already extracted
|
||||
if (clientVersionExtracted) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -622,18 +634,6 @@ public final class YoutubeParsingHelper {
|
|||
serviceTrackingParamsStream, "ECATCHER", "client.version");
|
||||
}
|
||||
|
||||
try {
|
||||
key = getStringResultFromRegexArray(html, INNERTUBE_API_KEY_REGEXES, 1);
|
||||
} catch (final Parser.RegexException ignored) {
|
||||
}
|
||||
|
||||
if (isNullOrEmpty(key)) {
|
||||
throw new ParsingException(
|
||||
// CHECKSTYLE:OFF
|
||||
"Could not extract YouTube WEB InnerTube API key from HTML search results page");
|
||||
// CHECKSTYLE:ON
|
||||
}
|
||||
|
||||
if (clientVersion == null) {
|
||||
throw new ParsingException(
|
||||
// CHECKSTYLE:OFF
|
||||
|
@ -641,7 +641,7 @@ public final class YoutubeParsingHelper {
|
|||
// CHECKSTYLE:ON
|
||||
}
|
||||
|
||||
keyAndVersionExtracted = true;
|
||||
clientVersionExtracted = true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -676,17 +676,17 @@ public final class YoutubeParsingHelper {
|
|||
// JavaScript service worker, then from HTML search results page as a fallback, to prevent
|
||||
// fingerprinting based on the client version used
|
||||
try {
|
||||
extractClientVersionAndKeyFromSwJs();
|
||||
extractClientVersionFromSwJs();
|
||||
} catch (final Exception e) {
|
||||
extractClientVersionAndKeyFromHtmlSearchResultsPage();
|
||||
extractClientVersionFromHtmlSearchResultsPage();
|
||||
}
|
||||
|
||||
if (keyAndVersionExtracted) {
|
||||
if (clientVersionExtracted) {
|
||||
return clientVersion;
|
||||
}
|
||||
|
||||
// Fallback to the hardcoded one if it is valid
|
||||
if (areHardcodedClientVersionAndKeyValid()) {
|
||||
if (isHardcodedClientVersionValid()) {
|
||||
clientVersion = HARDCODED_CLIENT_VERSION;
|
||||
return clientVersion;
|
||||
}
|
||||
|
@ -694,39 +694,6 @@ public final class YoutubeParsingHelper {
|
|||
throw new ExtractionException("Could not get YouTube WEB client version");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the internal API key used by YouTube website on InnerTube requests.
|
||||
*/
|
||||
public static String getKey() throws IOException, ExtractionException {
|
||||
if (!isNullOrEmpty(key)) {
|
||||
return key;
|
||||
}
|
||||
|
||||
// Always extract the key used by the website, by trying first to extract it from the
|
||||
// JavaScript service worker, then from HTML search results page as a fallback, to prevent
|
||||
// fingerprinting based on the key and/or invalid key issues
|
||||
try {
|
||||
extractClientVersionAndKeyFromSwJs();
|
||||
} catch (final Exception e) {
|
||||
extractClientVersionAndKeyFromHtmlSearchResultsPage();
|
||||
}
|
||||
|
||||
if (keyAndVersionExtracted) {
|
||||
return key;
|
||||
}
|
||||
|
||||
// Fallback to the hardcoded one if it's valid
|
||||
if (areHardcodedClientVersionAndKeyValid()) {
|
||||
key = HARDCODED_KEY;
|
||||
return key;
|
||||
}
|
||||
|
||||
// The ANDROID API key is also valid with the WEB client so return it if we couldn't
|
||||
// extract the WEB API key. This can be used as a way to fingerprint the extractor in this
|
||||
// case
|
||||
return ANDROID_YOUTUBE_KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* <b>Only used in tests.</b>
|
||||
|
@ -742,10 +709,9 @@ public final class YoutubeParsingHelper {
|
|||
* tests with mocks will fail, because the mock is missing.
|
||||
* </p>
|
||||
*/
|
||||
public static void resetClientVersionAndKey() {
|
||||
public static void resetClientVersion() {
|
||||
clientVersion = null;
|
||||
key = null;
|
||||
keyAndVersionExtracted = false;
|
||||
clientVersionExtracted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -757,11 +723,11 @@ public final class YoutubeParsingHelper {
|
|||
numberGenerator = random;
|
||||
}
|
||||
|
||||
public static boolean isHardcodedYoutubeMusicKeyValid() throws IOException,
|
||||
public static boolean isHardcodedYoutubeMusicClientVersionValid() throws IOException,
|
||||
ReCaptchaException {
|
||||
final String url =
|
||||
"https://music.youtube.com/youtubei/v1/music/get_search_suggestions?key="
|
||||
+ HARDCODED_YOUTUBE_MUSIC_KEY[0] + DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
"https://music.youtube.com/youtubei/v1/music/get_search_suggestions?"
|
||||
+ DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
|
||||
// @formatter:off
|
||||
final byte[] json = JsonWriter.string()
|
||||
|
@ -769,7 +735,7 @@ public final class YoutubeParsingHelper {
|
|||
.object("context")
|
||||
.object("client")
|
||||
.value("clientName", "WEB_REMIX")
|
||||
.value("clientVersion", HARDCODED_YOUTUBE_MUSIC_KEY[2])
|
||||
.value("clientVersion", HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION)
|
||||
.value("hl", "en-GB")
|
||||
.value("gl", "GB")
|
||||
.value("platform", "DESKTOP")
|
||||
|
@ -791,48 +757,40 @@ public final class YoutubeParsingHelper {
|
|||
// @formatter:on
|
||||
|
||||
final var headers = new HashMap<>(getOriginReferrerHeaders(YOUTUBE_MUSIC_URL));
|
||||
headers.putAll(getClientHeaders(HARDCODED_YOUTUBE_MUSIC_KEY[1],
|
||||
HARDCODED_YOUTUBE_MUSIC_KEY[2]));
|
||||
headers.putAll(getClientHeaders(YOUTUBE_MUSIC_CLIENT_ID,
|
||||
HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION));
|
||||
|
||||
final Response response = getDownloader().postWithContentTypeJson(url, headers, json);
|
||||
// Ensure to have a valid response
|
||||
return response.responseBody().length() > 500 && response.responseCode() == 200;
|
||||
}
|
||||
|
||||
public static String[] getYoutubeMusicKey()
|
||||
public static String getYoutubeMusicClientVersion()
|
||||
throws IOException, ReCaptchaException, Parser.RegexException {
|
||||
if (youtubeMusicKey != null && youtubeMusicKey.length == 3) {
|
||||
return youtubeMusicKey;
|
||||
if (!isNullOrEmpty(youtubeMusicClientVersion)) {
|
||||
return youtubeMusicClientVersion;
|
||||
}
|
||||
if (isHardcodedYoutubeMusicKeyValid()) {
|
||||
youtubeMusicKey = HARDCODED_YOUTUBE_MUSIC_KEY;
|
||||
return youtubeMusicKey;
|
||||
if (isHardcodedYoutubeMusicClientVersionValid()) {
|
||||
youtubeMusicClientVersion = HARDCODED_YOUTUBE_MUSIC_CLIENT_VERSION;
|
||||
return youtubeMusicClientVersion;
|
||||
}
|
||||
|
||||
String musicClientVersion;
|
||||
String musicKey;
|
||||
String musicClientName;
|
||||
|
||||
try {
|
||||
final String url = "https://music.youtube.com/sw.js";
|
||||
final var headers = getOriginReferrerHeaders(YOUTUBE_MUSIC_URL);
|
||||
final String response = getDownloader().get(url, headers).responseBody();
|
||||
musicClientVersion = getStringResultFromRegexArray(response,
|
||||
|
||||
youtubeMusicClientVersion = getStringResultFromRegexArray(response,
|
||||
INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES, 1);
|
||||
musicKey = getStringResultFromRegexArray(response, INNERTUBE_API_KEY_REGEXES, 1);
|
||||
musicClientName = Parser.matchGroup1(INNERTUBE_CLIENT_NAME_REGEX, response);
|
||||
} catch (final Exception e) {
|
||||
final String url = "https://music.youtube.com/?ucbcb=1";
|
||||
final String html = getDownloader().get(url, getCookieHeader()).responseBody();
|
||||
|
||||
musicKey = getStringResultFromRegexArray(html, INNERTUBE_API_KEY_REGEXES, 1);
|
||||
musicClientVersion = getStringResultFromRegexArray(html,
|
||||
youtubeMusicClientVersion = getStringResultFromRegexArray(html,
|
||||
INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES, 1);
|
||||
musicClientName = Parser.matchGroup1(INNERTUBE_CLIENT_NAME_REGEX, html);
|
||||
}
|
||||
|
||||
youtubeMusicKey = new String[] {musicKey, musicClientName, musicClientVersion};
|
||||
return youtubeMusicKey;
|
||||
return youtubeMusicClientVersion;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -1150,8 +1108,8 @@ public final class YoutubeParsingHelper {
|
|||
final var headers = getYouTubeHeaders();
|
||||
|
||||
return JsonUtils.toJsonObject(getValidJsonResponseBody(
|
||||
getDownloader().postWithContentTypeJson(YOUTUBEI_V1_URL + endpoint + "?key="
|
||||
+ getKey() + DISABLE_PRETTY_PRINT_PARAMETER, headers, body, localization)));
|
||||
getDownloader().postWithContentTypeJson(YOUTUBEI_V1_URL + endpoint + "?"
|
||||
+ DISABLE_PRETTY_PRINT_PARAMETER, headers, body, localization)));
|
||||
}
|
||||
|
||||
public static JsonObject getJsonAndroidPostResponse(
|
||||
|
@ -1160,7 +1118,7 @@ public final class YoutubeParsingHelper {
|
|||
@Nonnull final Localization localization,
|
||||
@Nullable final String endPartOfUrlRequest) throws IOException, ExtractionException {
|
||||
return getMobilePostResponse(endpoint, body, localization,
|
||||
getAndroidUserAgent(localization), ANDROID_YOUTUBE_KEY, endPartOfUrlRequest);
|
||||
getAndroidUserAgent(localization), endPartOfUrlRequest);
|
||||
}
|
||||
|
||||
public static JsonObject getJsonIosPostResponse(
|
||||
|
@ -1169,7 +1127,7 @@ public final class YoutubeParsingHelper {
|
|||
@Nonnull final Localization localization,
|
||||
@Nullable final String endPartOfUrlRequest) throws IOException, ExtractionException {
|
||||
return getMobilePostResponse(endpoint, body, localization, getIosUserAgent(localization),
|
||||
IOS_YOUTUBE_KEY, endPartOfUrlRequest);
|
||||
endPartOfUrlRequest);
|
||||
}
|
||||
|
||||
private static JsonObject getMobilePostResponse(
|
||||
|
@ -1177,12 +1135,11 @@ public final class YoutubeParsingHelper {
|
|||
final byte[] body,
|
||||
@Nonnull final Localization localization,
|
||||
@Nonnull final String userAgent,
|
||||
@Nonnull final String innerTubeApiKey,
|
||||
@Nullable final String endPartOfUrlRequest) throws IOException, ExtractionException {
|
||||
final var headers = Map.of("User-Agent", List.of(userAgent),
|
||||
"X-Goog-Api-Format-Version", List.of("2"));
|
||||
|
||||
final String baseEndpointUrl = YOUTUBEI_V1_GAPIS_URL + endpoint + "?key=" + innerTubeApiKey
|
||||
final String baseEndpointUrl = YOUTUBEI_V1_GAPIS_URL + endpoint + "?"
|
||||
+ DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
|
||||
return JsonUtils.toJsonObject(getValidJsonResponseBody(
|
||||
|
@ -1295,14 +1252,7 @@ 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 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("osVersion", IOS_OS_VERSION)
|
||||
.value("hl", localization.getLocalizationCode())
|
||||
.value("gl", contentCountry.getCountryCode())
|
||||
.value("utcOffsetMinutes", 0)
|
||||
|
@ -1421,9 +1371,10 @@ public final class YoutubeParsingHelper {
|
|||
*/
|
||||
@Nonnull
|
||||
public static String getIosUserAgent(@Nullable final Localization localization) {
|
||||
// Spoofing an iPhone 15 running iOS 17.1.2 with the hardcoded version of the iOS app
|
||||
// Spoofing an iPhone 15 running iOS 17.4.1 with the hardcoded version of the iOS app
|
||||
return "com.google.ios.youtube/" + IOS_YOUTUBE_CLIENT_VERSION
|
||||
+ "(" + IOS_DEVICE_MODEL + "; U; CPU iOS 17_1_2 like Mac OS X; "
|
||||
+ "(" + IOS_DEVICE_MODEL + "; U; CPU iOS "
|
||||
+ IOS_USER_AGENT_VERSION + " like Mac OS X; "
|
||||
+ (localization != null ? localization : Localization.DEFAULT).getCountryCode()
|
||||
+ ")";
|
||||
}
|
||||
|
@ -1434,7 +1385,8 @@ public final class YoutubeParsingHelper {
|
|||
@Nonnull
|
||||
public static Map<String, List<String>> getYoutubeMusicHeaders() {
|
||||
final var headers = new HashMap<>(getOriginReferrerHeaders(YOUTUBE_MUSIC_URL));
|
||||
headers.putAll(getClientHeaders(youtubeMusicKey[1], youtubeMusicKey[2]));
|
||||
headers.putAll(getClientHeaders(YOUTUBE_MUSIC_CLIENT_ID,
|
||||
youtubeMusicClientVersion));
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
@ -1456,7 +1408,7 @@ public final class YoutubeParsingHelper {
|
|||
public static Map<String, List<String>> getClientInfoHeaders()
|
||||
throws ExtractionException, IOException {
|
||||
final var headers = new HashMap<>(getOriginReferrerHeaders("https://www.youtube.com"));
|
||||
headers.putAll(getClientHeaders("1", getClientVersion()));
|
||||
headers.putAll(getClientHeaders(WEB_CLIENT_ID, getClientVersion()));
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
/**
|
||||
* Generate a {@link Document} with common manifest creator elements added to it.
|
||||
*
|
||||
* <p>
|
||||
* <br>
|
||||
* Those are:
|
||||
* <ul>
|
||||
* <li>{@code MPD} (using {@link #generateDocumentAndMpdElement(long)});</li>
|
||||
|
@ -132,7 +132,7 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
* <li>and, for audio streams, {@code AudioChannelConfiguration} (using
|
||||
* {@link #generateAudioChannelConfigurationElement(Document, ItagItem)}).</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param itagItem the {@link ItagItem} associated to the stream, which must not be null
|
||||
* @param streamDuration the duration of the stream, in milliseconds
|
||||
|
@ -494,7 +494,6 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
* This method is only used when generating DASH manifests from OTF and post-live-DVR streams.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It will produce a {@code <SegmentTemplate>} element with the following attributes:
|
||||
* <ul>
|
||||
* <li>{@code startNumber}, which takes the value {@code 0} for post-live-DVR streams and
|
||||
|
@ -505,7 +504,6 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
* <li>{@code initialization} (only for OTF streams), which is the base URL of the stream
|
||||
* on which is appended {@link #SQ_0}.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The {@code <Representation>} element needs to be generated before this element with
|
||||
|
@ -578,8 +576,8 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
|
||||
/**
|
||||
* Get the "initialization" {@link Response response} of a stream.
|
||||
*
|
||||
* <p>This method fetches, for OTF streams and for post-live-DVR streams:
|
||||
* <br>
|
||||
* This method fetches, for OTF streams and for post-live-DVR streams:
|
||||
* <ul>
|
||||
* <li>the base URL of the stream, to which are appended {@link #SQ_0} and
|
||||
* {@link #RN_0} parameters, with a {@code GET} request for streaming URLs from HTML5
|
||||
|
@ -588,7 +586,6 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
* <li>for streaming URLs from HTML5 clients, the {@link #ALR_YES} param is also added.
|
||||
* </li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @param baseStreamingUrl the base URL of the stream, which must not be null
|
||||
* @param itagItem the {@link ItagItem} of stream, which must not be null
|
||||
|
|
|
@ -53,38 +53,37 @@ public final class YoutubeOtfDashManifestCreator {
|
|||
* livestreams which have just been re-encoded as normal videos.
|
||||
* </p>
|
||||
*
|
||||
* <p>This method needs:
|
||||
* <ul>
|
||||
* <li>the base URL of the stream (which, if you try to access to it, returns HTTP
|
||||
* status code 404 after redirects, and if the URL is valid);</li>
|
||||
* <li>an {@link ItagItem}, which needs to contain the following information:
|
||||
* <ul>
|
||||
* <li>its type (see {@link ItagItem.ItagType}), to identify if the content is
|
||||
* an audio or a video stream;</li>
|
||||
* <li>its bitrate;</li>
|
||||
* <li>its mime type;</li>
|
||||
* <li>its codec(s);</li>
|
||||
* <li>for an audio stream: its audio channels;</li>
|
||||
* <li>for a video stream: its width and height.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>the duration of the video, which will be used if the duration could not be
|
||||
* parsed from the first sequence of the stream.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* This method needs:
|
||||
* <ul>
|
||||
* <li>the base URL of the stream (which, if you try to access to it, returns HTTP
|
||||
* status code 404 after redirects, and if the URL is valid);</li>
|
||||
* <li>an {@link ItagItem}, which needs to contain the following information:
|
||||
* <ul>
|
||||
* <li>its type (see {@link ItagItem.ItagType}), to identify if the content is
|
||||
* an audio or a video stream;</li>
|
||||
* <li>its bitrate;</li>
|
||||
* <li>its mime type;</li>
|
||||
* <li>its codec(s);</li>
|
||||
* <li>for an audio stream: its audio channels;</li>
|
||||
* <li>for a video stream: its width and height.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>the duration of the video, which will be used if the duration could not be
|
||||
* parsed from the first sequence of the stream.</li>
|
||||
* </ul>
|
||||
*
|
||||
* In order to generate the DASH manifest, this method will:
|
||||
* <ul>
|
||||
* <li>request the first sequence of the stream (the base URL on which the first
|
||||
* sequence parameter is appended (see {@link YoutubeDashManifestCreatorsUtils#SQ_0}))
|
||||
* with a {@code POST} or {@code GET} request (depending of the client on which the
|
||||
* streaming URL comes from is a mobile one ({@code POST}) or not ({@code GET}));</li>
|
||||
* <li>follow its redirection(s), if any;</li>
|
||||
* <li>save the last URL, remove the first sequence parameter;</li>
|
||||
* <li>use the information provided in the {@link ItagItem} to generate all
|
||||
* elements of the DASH manifest.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>In order to generate the DASH manifest, this method will:
|
||||
* <ul>
|
||||
* <li>request the first sequence of the stream (the base URL on which the first
|
||||
* sequence parameter is appended (see {@link YoutubeDashManifestCreatorsUtils#SQ_0}))
|
||||
* with a {@code POST} or {@code GET} request (depending of the client on which the
|
||||
* streaming URL comes from is a mobile one ({@code POST}) or not ({@code GET}));</li>
|
||||
* <li>follow its redirection(s), if any;</li>
|
||||
* <li>save the last URL, remove the first sequence parameter;</li>
|
||||
* <li>use the information provided in the {@link ItagItem} to generate all
|
||||
* elements of the DASH manifest.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If the duration cannot be extracted, the {@code durationSecondsFallback} value will be used
|
||||
|
|
|
@ -56,25 +56,25 @@ public final class YoutubePostLiveStreamDvrDashManifestCreator {
|
|||
* the time)
|
||||
* </p>
|
||||
*
|
||||
* <p>This method needs:
|
||||
* <ul>
|
||||
* <li>the base URL of the stream (which, if you try to access to it, returns HTTP
|
||||
* status code 404 after redirects, and if the URL is valid);</li>
|
||||
* <li>an {@link ItagItem}, which needs to contain the following information:
|
||||
* <ul>
|
||||
* <li>its type (see {@link ItagItem.ItagType}), to identify if the content is
|
||||
* an audio or a video stream;</li>
|
||||
* <li>its bitrate;</li>
|
||||
* <li>its mime type;</li>
|
||||
* <li>its codec(s);</li>
|
||||
* <li>for an audio stream: its audio channels;</li>
|
||||
* <li>for a video stream: its width and height.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>the duration of the video, which will be used if the duration could not be
|
||||
* parsed from the first sequence of the stream.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* This method needs:
|
||||
* <ul>
|
||||
* <li>the base URL of the stream (which, if you try to access to it, returns HTTP
|
||||
* status code 404 after redirects, and if the URL is valid);</li>
|
||||
* <li>an {@link ItagItem}, which needs to contain the following information:
|
||||
* <ul>
|
||||
* <li>its type (see {@link ItagItem.ItagType}), to identify if the content is
|
||||
* an audio or a video stream;</li>
|
||||
* <li>its bitrate;</li>
|
||||
* <li>its mime type;</li>
|
||||
* <li>its codec(s);</li>
|
||||
* <li>for an audio stream: its audio channels;</li>
|
||||
* <li>for a video stream: its width and height.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>the duration of the video, which will be used if the duration could not be
|
||||
* parsed from the first sequence of the stream.</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <p>In order to generate the DASH manifest, this method will:
|
||||
* <ul>
|
||||
|
|
|
@ -47,26 +47,25 @@ public final class YoutubeProgressiveDashManifestCreator {
|
|||
* YouTube partner, and on videos with a large number of views.
|
||||
* </p>
|
||||
*
|
||||
* <p>This method needs:
|
||||
* <ul>
|
||||
* <li>the base URL of the stream (which, if you try to access to it, returns the whole
|
||||
* stream, after redirects, and if the URL is valid);</li>
|
||||
* <li>an {@link ItagItem}, which needs to contain the following information:
|
||||
* <ul>
|
||||
* <li>its type (see {@link ItagItem.ItagType}), to identify if the content is
|
||||
* an audio or a video stream;</li>
|
||||
* <li>its bitrate;</li>
|
||||
* <li>its mime type;</li>
|
||||
* <li>its codec(s);</li>
|
||||
* <li>for an audio stream: its audio channels;</li>
|
||||
* <li>for a video stream: its width and height.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>the duration of the video (parameter {@code durationSecondsFallback}), which
|
||||
* will be used as the stream duration if the duration could not be parsed from the
|
||||
* {@link ItagItem}.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* This method needs:
|
||||
* <ul>
|
||||
* <li>the base URL of the stream (which, if you try to access to it, returns the whole
|
||||
* stream, after redirects, and if the URL is valid);</li>
|
||||
* <li>an {@link ItagItem}, which needs to contain the following information:
|
||||
* <ul>
|
||||
* <li>its type (see {@link ItagItem.ItagType}), to identify if the content is
|
||||
* an audio or a video stream;</li>
|
||||
* <li>its bitrate;</li>
|
||||
* <li>its mime type;</li>
|
||||
* <li>its codec(s);</li>
|
||||
* <li>for an audio stream: its audio channels;</li>
|
||||
* <li>for a video stream: its width and height.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li>the duration of the video (parameter {@code durationSecondsFallback}), which
|
||||
* will be used as the stream duration if the duration could not be parsed from the
|
||||
* {@link ItagItem}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param progressiveStreamingBaseUrl the base URL of the progressive stream, which must not be
|
||||
* null
|
||||
|
|
|
@ -8,15 +8,13 @@ import java.io.Serializable;
|
|||
/**
|
||||
* Class to build easier {@link org.schabi.newpipe.extractor.stream.Stream}s for
|
||||
* {@link YoutubeStreamExtractor}.
|
||||
*
|
||||
* <p>
|
||||
* <br>
|
||||
* It stores, per stream:
|
||||
* <ul>
|
||||
* <li>its content (the URL/the base URL of streams);</li>
|
||||
* <li>whether its content is the URL the content itself or the base URL;</li>
|
||||
* <li>its associated {@link ItagItem}.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
final class ItagInfo implements Serializable {
|
||||
@Nonnull
|
||||
|
|
|
@ -29,7 +29,6 @@ import static org.schabi.newpipe.extractor.services.youtube.YoutubeChannelHelper
|
|||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.YOUTUBEI_V1_URL;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
|
||||
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.utils.Utils.isNullOrEmpty;
|
||||
|
@ -422,8 +421,8 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
.done())
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return new Page(YOUTUBEI_V1_URL + "browse?key=" + getKey()
|
||||
+ DISABLE_PRETTY_PRINT_PARAMETER, null, channelIds, null, body);
|
||||
return new Page(YOUTUBEI_V1_URL + "browse?" + DISABLE_PRETTY_PRINT_PARAMETER, null,
|
||||
channelIds, null, body);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,7 +4,6 @@ import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper
|
|||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.YOUTUBEI_V1_URL;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.extractCookieValue;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.extractPlaylistTypeFromPlaylistId;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getValidJsonResponseBody;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getYouTubeHeaders;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
|
||||
|
@ -103,8 +102,8 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
|
|||
final var headers = getYouTubeHeaders();
|
||||
|
||||
final Response response = getDownloader().postWithContentTypeJson(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
headers, body, localization);
|
||||
YOUTUBEI_V1_URL + "next?" + DISABLE_PRETTY_PRINT_PARAMETER, headers, body,
|
||||
localization);
|
||||
|
||||
initialData = JsonUtils.toJsonObject(getValidJsonResponseBody(response));
|
||||
playlistData = initialData
|
||||
|
@ -225,7 +224,8 @@ public class YoutubeMixPlaylistExtractor extends PlaylistExtractor {
|
|||
.done())
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return new Page(YOUTUBEI_V1_URL + "next?key=" + getKey(), null, null, cookies, body);
|
||||
return new Page(YOUTUBEI_V1_URL + "next?" + DISABLE_PRETTY_PRINT_PARAMETER, null, null,
|
||||
cookies, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
|
|||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getValidJsonResponseBody;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getYoutubeMusicClientVersion;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getYoutubeMusicHeaders;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_ALBUMS;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_ARTISTS;
|
||||
|
@ -25,10 +26,8 @@ import org.schabi.newpipe.extractor.StreamingService;
|
|||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
||||
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
|
||||
import org.schabi.newpipe.extractor.utils.JsonUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -52,10 +51,8 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||
@Override
|
||||
public void onFetchPage(@Nonnull final Downloader downloader)
|
||||
throws IOException, ExtractionException {
|
||||
final String[] youtubeMusicKeys = YoutubeParsingHelper.getYoutubeMusicKey();
|
||||
|
||||
final String url = "https://music.youtube.com/youtubei/v1/search?key="
|
||||
+ youtubeMusicKeys[0] + DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
final String url = "https://music.youtube.com/youtubei/v1/search?"
|
||||
+ DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
|
||||
final String params;
|
||||
|
||||
|
@ -86,7 +83,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||
.object("context")
|
||||
.object("client")
|
||||
.value("clientName", "WEB_REMIX")
|
||||
.value("clientVersion", youtubeMusicKeys[2])
|
||||
.value("clientVersion", getYoutubeMusicClientVersion())
|
||||
.value("hl", "en-GB")
|
||||
.value("gl", getExtractorContentCountry().getCountryCode())
|
||||
.value("platform", "DESKTOP")
|
||||
|
@ -206,15 +203,13 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||
|
||||
final MultiInfoItemsCollector collector = new MultiInfoItemsCollector(getServiceId());
|
||||
|
||||
final String[] youtubeMusicKeys = YoutubeParsingHelper.getYoutubeMusicKey();
|
||||
|
||||
// @formatter:off
|
||||
final byte[] json = JsonWriter.string()
|
||||
.object()
|
||||
.object("context")
|
||||
.object("client")
|
||||
.value("clientName", "WEB_REMIX")
|
||||
.value("clientVersion", youtubeMusicKeys[2])
|
||||
.value("clientVersion", getYoutubeMusicClientVersion())
|
||||
.value("hl", "en-GB")
|
||||
.value("gl", getExtractorContentCountry().getCountryCode())
|
||||
.value("platform", "DESKTOP")
|
||||
|
@ -295,8 +290,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private Page getNextPageFrom(final JsonArray continuations)
|
||||
throws IOException, ParsingException, ReCaptchaException {
|
||||
private Page getNextPageFrom(final JsonArray continuations) {
|
||||
if (isNullOrEmpty(continuations)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -306,7 +300,6 @@ 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 + "&key="
|
||||
+ YoutubeParsingHelper.getYoutubeMusicKey()[0] + DISABLE_PRETTY_PRINT_PARAMETER);
|
||||
+ "&continuation=" + continuation + "&" + DISABLE_PRETTY_PRINT_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper
|
|||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.YOUTUBEI_V1_URL;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.extractPlaylistTypeFromPlaylistUrl;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
|
||||
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.getImagesFromThumbnailsArray;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getUrlFromNavigationEndpoint;
|
||||
|
@ -387,8 +386,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
|
|||
.done())
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return new Page(YOUTUBEI_V1_URL + "browse?key=" + getKey()
|
||||
+ DISABLE_PRETTY_PRINT_PARAMETER, body);
|
||||
return new Page(YOUTUBEI_V1_URL + "browse?" + DISABLE_PRETTY_PRINT_PARAMETER, body);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
|
|||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.YOUTUBEI_V1_URL;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
|
||||
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;
|
||||
|
@ -247,8 +246,7 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private Page getNextPageFrom(final JsonObject continuationItemRenderer) throws IOException,
|
||||
ExtractionException {
|
||||
private Page getNextPageFrom(final JsonObject continuationItemRenderer) {
|
||||
if (isNullOrEmpty(continuationItemRenderer)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -257,8 +255,7 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
|||
.getObject("continuationCommand")
|
||||
.getString("token");
|
||||
|
||||
final String url = YOUTUBEI_V1_URL + "search?key=" + getKey()
|
||||
+ DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
final String url = YOUTUBEI_V1_URL + "search?" + DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
|
||||
return new Page(url, token);
|
||||
}
|
||||
|
|
|
@ -965,7 +965,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||
.value(RACY_CHECK_OK, true)
|
||||
// Workaround getting streaming URLs which return 403 HTTP response code by
|
||||
// using some parameters for Android client requests
|
||||
.value("params", "CgIQBg")
|
||||
.value("params", "CgIIAQ%3D%3D")
|
||||
.done())
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
|
@ -1297,9 +1297,18 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||
return streamingData.getArray(streamingDataKey).stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.filter(formatData -> !formatData.getString("mimeType", "")
|
||||
.startsWith("text"))
|
||||
.map(formatData -> {
|
||||
try {
|
||||
final ItagItem itagItem = ItagItem.getItag(formatData.getInt("itag"));
|
||||
final int itag = formatData.getInt("itag");
|
||||
final int averageBitrate = formatData.getInt("averageBitrate");
|
||||
final int fps = formatData.getInt("fps");
|
||||
final String qualityLabel = formatData.getString("qualityLabel");
|
||||
final String mimeType = formatData.getString("mimeType");
|
||||
|
||||
final ItagItem itagItem = ItagItem.
|
||||
getItag(itag, averageBitrate, fps, qualityLabel, mimeType);
|
||||
if (itagItem.itagType == itagTypeWanted) {
|
||||
return buildAndAddItagInfoToList(videoId, formatData, itagItem,
|
||||
itagItem.itagType, contentPlaybackNonce);
|
||||
|
|
|
@ -34,8 +34,8 @@ public enum DeliveryMethod {
|
|||
/**
|
||||
* Used for {@link Stream}s served using the SmoothStreaming adaptive streaming method.
|
||||
*
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Adaptive_bitrate_streaming
|
||||
* #Microsoft_Smooth_Streaming_(MSS)">Wikipedia's page about adaptive bitrate streaming,
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Adaptive_bitrate_streaming#Microsoft_Smooth_Streaming_(MSS)">
|
||||
* Wikipedia's page about adaptive bitrate streaming,
|
||||
* section <i>Microsoft Smooth Streaming (MSS)</i></a> for more information about the
|
||||
* SmoothStreaming delivery method
|
||||
*/
|
||||
|
|
|
@ -171,8 +171,17 @@ public class ExtractorAsserts {
|
|||
public static void assertTabsContain(@Nonnull final List<ListLinkHandler> tabs,
|
||||
@Nonnull final String... expectedTabs) {
|
||||
final Set<String> tabSet = tabs.stream()
|
||||
.map(linkHandler -> linkHandler.getContentFilters().get(0))
|
||||
.map(linkHandler -> {
|
||||
assertEquals(1, linkHandler.getContentFilters().size(),
|
||||
"Unexpected content filters for channel tab: "
|
||||
+ linkHandler.getContentFilters());
|
||||
return linkHandler.getContentFilters().get(0);
|
||||
})
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
|
||||
assertEquals(expectedTabs.length, tabSet.size(),
|
||||
"Different amount of tabs returned:\nExpected: "
|
||||
+ Arrays.toString(expectedTabs) + "\nActual: " + tabSet);
|
||||
Arrays.stream(expectedTabs)
|
||||
.forEach(expectedTab -> assertTrue(tabSet.contains(expectedTab),
|
||||
"Missing " + expectedTab + " tab (got " + tabSet + ")"));
|
||||
|
|
|
@ -85,7 +85,7 @@ public abstract class PeertubeStreamExtractorTest extends DefaultStreamExtractor
|
|||
@Override public long expectedViewCountAtLeast() { return 38600; }
|
||||
@Nullable @Override public String expectedUploadDate() { return "2018-10-01 10:52:46.396"; }
|
||||
@Nullable @Override public String expectedTextualUploadDate() { return "2018-10-01T10:52:46.396Z"; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 20; }
|
||||
@Override public long expectedLikeCountAtLeast() { return 19; }
|
||||
@Override public long expectedDislikeCountAtLeast() { return 0; }
|
||||
@Override public String expectedHost() { return "framatube.org"; }
|
||||
@Override public String expectedCategory() { return "Science & Technology"; }
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.schabi.newpipe.extractor.channel.tabs.ChannelTabs;
|
|||
import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
||||
import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler;
|
||||
import org.schabi.newpipe.extractor.services.BaseChannelExtractorTest;
|
||||
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeChannelExtractor;
|
||||
|
@ -540,7 +541,8 @@ public class YoutubeChannelExtractorTest {
|
|||
@Test
|
||||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS);
|
||||
assertTabsContain(extractor.getTabs(),
|
||||
ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS, ChannelTabs.SHORTS);
|
||||
assertTrue(extractor.getTabs().stream()
|
||||
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
|
||||
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
|
||||
|
@ -916,8 +918,10 @@ public class YoutubeChannelExtractorTest {
|
|||
@Test
|
||||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
// Gaming topic channels tabs are not yet supported, so an empty list should be returned
|
||||
assertTrue(extractor.getTabs().isEmpty());
|
||||
// Gaming topic channels tabs are not yet supported
|
||||
// However, a Shorts tab like on other channel types is returned, so it is supported
|
||||
// Check that it is returned
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.SHORTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -8,7 +8,6 @@ import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.Creati
|
|||
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.YoutubeOtfDashManifestCreator;
|
||||
import org.schabi.newpipe.extractor.services.youtube.dashmanifestcreators.YoutubeProgressiveDashManifestCreator;
|
||||
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream.AudioTrackType;
|
||||
import org.schabi.newpipe.extractor.stream.DeliveryMethod;
|
||||
import org.schabi.newpipe.extractor.stream.Stream;
|
||||
import org.w3c.dom.Document;
|
||||
|
@ -89,7 +88,7 @@ class YoutubeDashManifestCreatorsTest {
|
|||
|
||||
@BeforeAll
|
||||
public static void setUp() throws Exception {
|
||||
YoutubeParsingHelper.resetClientVersionAndKey();
|
||||
YoutubeParsingHelper.resetClientVersion();
|
||||
YoutubeParsingHelper.setNumberGenerator(new Random(1));
|
||||
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.DISABLE_PRETTY_PRINT_PARAMETER;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.YOUTUBEI_V1_URL;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
|
||||
|
||||
import com.grack.nanojson.JsonWriter;
|
||||
|
@ -91,7 +90,7 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
YOUTUBEI_V1_URL + "next?" + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
null, null, dummyCookie, body));
|
||||
assertFalse(streams.getItems().isEmpty());
|
||||
assertTrue(streams.hasNextPage());
|
||||
|
@ -180,7 +179,7 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
YOUTUBEI_V1_URL + "next?" + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
null, null, dummyCookie, body));
|
||||
assertFalse(streams.getItems().isEmpty());
|
||||
assertTrue(streams.hasNextPage());
|
||||
|
@ -268,7 +267,7 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
YOUTUBEI_V1_URL + "next?" + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
null, null, dummyCookie, body));
|
||||
assertFalse(streams.getItems().isEmpty());
|
||||
assertTrue(streams.hasNextPage());
|
||||
|
@ -386,7 +385,7 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
YOUTUBEI_V1_URL + "next?" + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
null, null, dummyCookie, body));
|
||||
assertFalse(streams.getItems().isEmpty());
|
||||
assertTrue(streams.hasNextPage());
|
||||
|
@ -453,7 +452,7 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
YOUTUBEI_V1_URL + "next?" + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
null, null, dummyCookie, body));
|
||||
assertFalse(streams.getItems().isEmpty());
|
||||
assertTrue(streams.hasNextPage());
|
||||
|
@ -542,7 +541,7 @@ public class YoutubeMixPlaylistExtractorTest {
|
|||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
|
||||
YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
YOUTUBEI_V1_URL + "next?" + DISABLE_PRETTY_PRINT_PARAMETER,
|
||||
null, null, dummyCookie, body));
|
||||
assertFalse(streams.getItems().isEmpty());
|
||||
assertTrue(streams.hasNextPage());
|
||||
|
|
|
@ -25,15 +25,15 @@ public class YoutubeParsingHelperTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void testAreHardcodedClientVersionAndKeyValid() throws IOException, ExtractionException {
|
||||
assertTrue(YoutubeParsingHelper.areHardcodedClientVersionAndKeyValid(),
|
||||
"Hardcoded client version and key are not valid anymore");
|
||||
void testIsHardcodedClientVersionValid() throws IOException, ExtractionException {
|
||||
assertTrue(YoutubeParsingHelper.isHardcodedClientVersionValid(),
|
||||
"Hardcoded client version is not valid anymore");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAreHardcodedYoutubeMusicKeysValid() throws IOException, ExtractionException {
|
||||
assertTrue(YoutubeParsingHelper.isHardcodedYoutubeMusicKeyValid(),
|
||||
"Hardcoded YouTube Music keys are not valid anymore");
|
||||
void testIsHardcodedYoutubeMusicClientVersionValid() throws IOException, ExtractionException {
|
||||
assertTrue(YoutubeParsingHelper.isHardcodedYoutubeMusicClientVersionValid(),
|
||||
"Hardcoded YouTube Music client version is not valid anymore");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -26,7 +26,7 @@ public final class YoutubeTestsUtils {
|
|||
*/
|
||||
public static void ensureStateless() {
|
||||
YoutubeParsingHelper.setConsentAccepted(false);
|
||||
YoutubeParsingHelper.resetClientVersionAndKey();
|
||||
YoutubeParsingHelper.resetClientVersion();
|
||||
YoutubeParsingHelper.setNumberGenerator(new Random(1));
|
||||
YoutubeJavaScriptPlayerManager.clearAllCaches();
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
|
||||
@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 long expectedUploaderSubscriberCountAtLeast() { return 2200000; }
|
||||
@Override public List<String> expectedDescriptionContains() { return Arrays.asList("Doodle", "Google", "video"); }
|
||||
@Override public long expectedLength() { return 145; }
|
||||
@Override public long expectedTimestamp() { return TIMESTAMP; }
|
||||
|
@ -321,7 +321,7 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
@BeforeAll
|
||||
public static void setUp() throws Exception {
|
||||
YoutubeTestsUtils.ensureStateless();
|
||||
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "streamSegmentsMaiLab"));
|
||||
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "streamSegmentsMaithinkX"));
|
||||
extractor = YouTube.getStreamExtractor(URL);
|
||||
extractor.fetchPage();
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ public class YoutubeStreamExtractorDefaultTest {
|
|||
@Override public String expectedOriginalUrlContains() { return URL; }
|
||||
|
||||
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
|
||||
@Override public String expectedUploaderName() { return "maiLab"; }
|
||||
@Override public String expectedUploaderName() { return "MAITHINK X"; }
|
||||
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCyHDQ5C6z1NDmJ4g6SerW8g"; }
|
||||
@Override public long expectedUploaderSubscriberCountAtLeast() { return 1_400_000; }
|
||||
@Override public List<String> expectedDescriptionContains() {return Arrays.asList("Vitamin", "2:44", "Was ist Vitamin D?");}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
|
|||
private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH + "services/youtube/extractor/stream/";
|
||||
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 final String TITLE = "Cartoon, Jéja - On & On (feat. Daniel Levi) | Electronic Pop | NCS - Copyright Free Music";
|
||||
private static StreamExtractor extractor;
|
||||
|
||||
@BeforeAll
|
||||
|
@ -71,13 +71,13 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
|
|||
@Override public String expectedLicence() { return YOUTUBE_LICENCE; }
|
||||
@Override public String expectedCategory() { return "Music"; }
|
||||
@Override public List<String> expectedTags() {
|
||||
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");
|
||||
return Arrays.asList("Cartoon", "Cartoon - On & On", "Cartoon On & On (feat. Daniel Levi)",
|
||||
"Daniel Levi", "NCS Best Songs", "NCS Cartoon Daniel Levi", "NCS Cartoon On & On",
|
||||
"NCS On & On", "NCS On and On", "NCS Release Daniel Levi", "NCS release Cartoon",
|
||||
"On & On", "best music", "club music", "copyright free music", "dance music", "edm",
|
||||
"electronic music", "electronic pop", "free music", "gaming music", "music", "ncs",
|
||||
"no copyright music", "no copyright sounds", "nocopyrightsounds",
|
||||
"royalty free music", "songs", "top music");
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:39:00 GMT"
|
||||
"Wed, 10 Apr 2024 17:32:05 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:39:00 GMT"
|
||||
"Wed, 10 Apr 2024 17:32:05 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003drP1g96D6iSY; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:32:05 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:59 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:16 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:59 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:16 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dR5CBjvYjQSM; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:16 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
"request": {
|
||||
"httpMethod": "POST",
|
||||
"url": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse",
|
||||
"url": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse",
|
||||
"headers": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Cookie": [
|
||||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20231208.01.00"
|
||||
"2.20240410.01.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -228,11 +228,11 @@
|
|||
50,
|
||||
48,
|
||||
50,
|
||||
51,
|
||||
49,
|
||||
50,
|
||||
52,
|
||||
48,
|
||||
52,
|
||||
49,
|
||||
48,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
|
@ -362,20 +362,11 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"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.\""
|
||||
"Wed, 10 Apr 2024 17:31:16 GMT"
|
||||
],
|
||||
"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",
|
||||
|
@ -391,7 +382,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"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"
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtnNEJUcEpIazMtbyjkmduwBjIOCgJGUhIIEgQSAgsMIGc%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240410.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xca7be53690c60dbf\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23776346,23804281,23946420,23966208,23983296,23986016,23998056,24004644,24036948,24077241,24080738,24120819,24135310,24166867,24181174,24187377,24241378,24290971,24377598,24439361,24451319,24453989,24468724,24506784,24515388,24515423,24524098,24524562,24525811,24542367,24548627,24548629,24550458,24560416,24566687,24697069,24699899,39325854,39325978,51003636,51006181,51009781,51010235,51012659,51016856,51017346,51019626,51020570,51025415,51026715,51027870,51030101,51033399,51033765,51037344,51037353,51038805,51039200,51043774,51048489,51050361,51053689,51056364,51057501,51057846,51057853,51059573,51060353,51063643,51064835,51069269,51072748,51074183,51079239,51080343,51089175,51089441,51089956,51091331,51091810,51091897,51092661,51094173,51094195,51094202,51094207,51095478,51096577,51096646,51098297,51098299,51100401,51101454,51103044,51103858,51105630,51105690,51105868,51106995,51107336,51108006,51109078,51109704,51111738,51113658,51113663,51115184,51116067,51117319,51118932,51119507,51119509,51119511,51120529,51120721,51123073,51124104,51124304,51124405,51124478,51127560,51128585,51129210,51129216,51129218,51129220,51129222,51129224,51129395,51131429,51132393,51133103,51135346,51135656,51136218,51136785,51136924,51139379,51140749,51140806,51141539,51141798,51142840,51142842,51142886,51142889,51144925,51145052,51145216,51145258,51145749,51146567,51146962,51147554,51147789,51147897,51148750,51148974,51148983,51149504,51151572,51152043,51152050,51152207,51152530,51153775,51154012,51155674,51156055,51156581,51157410,51157729,51157841,51158470,51158513,51159916,51160594\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240410\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIivSxv5a4hQMVaivxBR1E3QYaMghleHRlcm5hbJoBAA\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?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:52 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:11 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:52 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:11 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dFBJkWNhWCv0; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:11 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:53 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:11 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:53 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:11 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dVQZ7dBDq_80; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:11 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:54 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:12 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:54 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:12 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dRUU709V770o; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:12 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:55 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:12 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:55 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:12 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dVFl0_DSlGaw; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:12 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:55 GMT"
|
||||
"Wed, 10 Apr 2024 17:30:55 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:55 GMT"
|
||||
"Wed, 10 Apr 2024 17:30:55 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dZwoT5Z7xpsc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:30:55 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:56 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:13 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:56 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:13 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dLS28t4xIaN8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:13 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:38:00 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:16 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:38:00 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:16 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dwSKoU71ODdc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:16 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Wed, 20 Mar 2024 13:58:42 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:14 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Wed, 20 Mar 2024 13:58:42 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:14 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dLzBi9veM9G4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 24-Jun-2021 13:58:42 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dWd13sWd3cpk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:14 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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
|
@ -1,19 +1,19 @@
|
|||
{
|
||||
"request": {
|
||||
"httpMethod": "POST",
|
||||
"url": "https://www.youtube.com/youtubei/v1/browse?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse",
|
||||
"url": "https://www.youtube.com/youtubei/v1/browse?prettyPrint\u003dfalse",
|
||||
"headers": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Cookie": [
|
||||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240313.05.00"
|
||||
"2.20240410.01.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -256,12 +256,12 @@
|
|||
50,
|
||||
52,
|
||||
48,
|
||||
51,
|
||||
52,
|
||||
49,
|
||||
51,
|
||||
48,
|
||||
46,
|
||||
48,
|
||||
53,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
48,
|
||||
|
@ -376,7 +376,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Wed, 20 Mar 2024 13:58:43 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:15 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
@ -397,6 +397,6 @@
|
|||
]
|
||||
},
|
||||
"responseBody": "{\n \"error\": {\n \"code\": 400,\n \"message\": \"Request contains an invalid argument.\",\n \"errors\": [\n {\n \"message\": \"Request contains an invalid argument.\",\n \"domain\": \"global\",\n \"reason\": \"badRequest\"\n }\n ],\n \"status\": \"INVALID_ARGUMENT\"\n }\n}\n",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/browse?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse"
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/browse?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:15 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:15 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dTN_tYcQa7Ro; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:15 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:15 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:37:58 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:15 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dLEBE5JO8Blk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:15 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:38:01 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:18 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:38:01 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:18 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003ddxRIN7KwkLY; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:18 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:38:01 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:18 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:38:01 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:18 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dgkaI3HruKqg; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:18 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Sat, 30 Dec 2023 13:43:25 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:19 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 30 Dec 2023 13:43:25 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:19 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dpk4qlD0k7qs; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 04-Apr-2021 13:43:25 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"CONSENT\u003dPENDING+551; expires\u003dMon, 29-Dec-2025 13:43:25 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
"YSC\u003dC2Eot0opIMA; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:19 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"request": {
|
||||
"httpMethod": "POST",
|
||||
"url": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse",
|
||||
"url": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
|
@ -13,7 +13,7 @@
|
|||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20231219.04.00"
|
||||
"2.20240410.01.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -228,14 +228,14 @@
|
|||
50,
|
||||
48,
|
||||
50,
|
||||
51,
|
||||
49,
|
||||
50,
|
||||
49,
|
||||
57,
|
||||
46,
|
||||
52,
|
||||
48,
|
||||
52,
|
||||
49,
|
||||
48,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
48,
|
||||
|
@ -361,20 +361,11 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Sat, 30 Dec 2023 13:43:25 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Sat, 30 Dec 2023 13:43:25 GMT"
|
||||
],
|
||||
"p3p": [
|
||||
"CP\u003d\"This is not a P3P policy! See g.co/p3phelp for more info.\""
|
||||
"Wed, 10 Apr 2024 17:31:19 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
],
|
||||
"set-cookie": [
|
||||
"CONSENT\u003dPENDING+476; expires\u003dMon, 29-Dec-2025 13:43:25 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
|
||||
],
|
||||
"vary": [
|
||||
"Origin",
|
||||
"X-Origin",
|
||||
|
@ -390,7 +381,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgszSmVQc192a2J6TSj9vMCsBjIKCgJOTxIEEgAgMQ%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20231219.04.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x26bcd15632ab68f4\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23880831,23880837,23946420,23966208,23983296,23986019,23998056,24004644,24007246,24034168,24036948,24077241,24080738,24120820,24135310,24140247,24166867,24181174,24187377,24241378,24255543,24255545,24288664,24290971,24367579,24377598,24377909,24382552,24385728,24387949,24390675,24428788,24428941,24428945,24439361,24451319,24453989,24458839,24459435,24468724,24485421,24506515,24506784,24515423,24518452,24524098,24526646,24526770,24526783,24526790,24526797,24526806,24526811,24526827,24528552,24528557,24528575,24528584,24528644,24528649,24528657,24528666,24531244,24537200,24539025,24542367,24542452,24543669,24546059,24546075,24548627,24548629,24549786,24550458,24559328,24560416,24561210,24561384,24566687,24589493,24694842,24697069,24698453,24699899,51003636,51004018,51006181,51009781,51009900,51010235,51012165,51012291,51012659,51014091,51016856,51017346,51019626,51020570,51021953,51025415,51026715,51027870,51028271,51029412,51030101,51032409,51033399,51033577,51035289,51036511,51037044,51037342,51037353,51037540,51037819,51037893,51038399,51038805,51039200,51039493,51041280,51041331,51041497,51042259,51043775,51043942,51045885,51045889,51045969,51047539,51048240,51048279,51049006,51050361,51053689,51055135,51056262,51056268,51057451,51057501,51057534,51057746,51057809,51057822,51057846,51057857,51059269,51059543,51059573,51059972,51060895,51061001,51061018,51062131,51063131,51063138,51063151,51063160,51063551,51063643,51064593,51065651,51065706,51069269,51070203,51070732,51072748,51074183,51074391,51074609,51074662,51074717,51074739,51075839,51076209,51077150,51078193,51078481,51078868,51079299,51079353,51080182,51080510,51080715,51082236,51082367,51083014,51083232,51083651,51083748,51084269,51084277,51084288,51084695,51086857,51088826,51090887\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20231219\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"51076209,24550458,24007246,51084695,51082236,51041331,24120820,51033399,51012659,51090887,24548629,51080510,51042259,24135310,51041497,24255543,51028271,51037893,51010235,24528644,24166867,51045969,24528666,24367579,51043775,23880837,24526811,24524098,51078481,24382552,51084277,51041280,51014091,24459435,51020570,24526797,24526646,51057534,51057857,51009781,24526790,24566687,24526783,51083651,51045889,24468724,51065651,51063551,24528552,24377598,51056268,23998056,51061001,24518452,24439361,51036511,51056262,51084269,24559328,51038805,24458839,24542367,51033577,51078193,24699899,51057822,23986019,24548627,51048240,51070203,51027870,24526827,51077150,51072748,51039200,24506515,51074662,24546075,51063151,24485421,24549786,51059972,51037044,24526806,51037540,51057809,51079299,51078868,24526770,24698453,51037353,24528575,51088826,24542452,24241378,51069269,51083232,51035289,51060895,51074609,51065706,24531244,51053689,51074717,24377909,24451319,24561210,51057846,24428788,24515423,24181174,51055135,24539025,24080738,51063160,51030101,51039493,51080715,51061018,24288664,51062131,51050361,51057746,24034168,51012165,51009900,51086857,51016856,51059269,51084288,51063131,24561384,51021953,51037819,24546059,51059543,51074739,24428945,24528584,51083748,24528649,51057451,51080182,51057501,23966208,51075839,24694842,51004018,51063138,24543669,51006181,24428941,51074183,24506784,51049006,51045885,51047539,51017346,51082367,24537200,51083014,24589493,51012291,51048279,23804281,51064593,23946420,24390675,24255545,23880831,51003636,24528657,51025415,51074391,24453989,23983296,24387949,51043942,51070732,24187377,51059573,51029412,24004644,51032409,24290971,24560416,51079353,51063643,24077241,51038399,24697069,24140247,24528557,51019626,51037342,24385728,51026715,24036948\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIvI34qaW3gwMVQaD0Bx2BFwuHMghleHRlcm5hbA\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\":\"UCq19-LqvG35A-30oyAiPiqA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse"
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgswZjJkMXhLSllOdyjnmduwBjIOCgJGUhIIEgQSAgsMIDY%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240410.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xee917970428b3686\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23946420,23966208,23983296,23986016,23998056,24004644,24036947,24077241,24080738,24120819,24135310,24166867,24181174,24186126,24187377,24241378,24290971,24377598,24439361,24451319,24453989,24468724,24506784,24515423,24524098,24524562,24534951,24542367,24548627,24548629,24550458,24560416,24566687,24697068,24699899,39325854,39325978,51003636,51006181,51009781,51010235,51012659,51016856,51017346,51019626,51020570,51025415,51026715,51027870,51033399,51033765,51038805,51039200,51048489,51049132,51050361,51053689,51057501,51059571,51060353,51063643,51064835,51069269,51072748,51074183,51079239,51080343,51089441,51089956,51091331,51092661,51095478,51096576,51096646,51098297,51098299,51100401,51101454,51103858,51105868,51106995,51107658,51108006,51109077,51111738,51112865,51115184,51116067,51118932,51119507,51119510,51119511,51124104,51128585,51129209,51129216,51129218,51129220,51129222,51129224,51129395,51132393,51133103,51135346,51136218,51136785,51138503,51139379,51140749,51140806,51142840,51142842,51145052,51145216,51145749,51146568,51146949,51146962,51147556,51147789,51147897,51148750,51152043,51152050,51152207,51152333,51152530,51153775,51154012,51155662,51155998,51156581,51157411,51157515,51157838,51158470,51158535,51159917,51160401\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240410\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIxoXuwJa4hQMVsUFPBB2kBAyQMghleHRlcm5hbJoBAA\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\":\"UCq19-LqvG35A-30oyAiPiqA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:38:02 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:20 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:38:02 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:20 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dHQQy08rv4_Y; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:20 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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": {
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -41,10 +41,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Fri, 08 Dec 2023 19:38:03 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:20 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Fri, 08 Dec 2023 19:38:03 GMT"
|
||||
"Wed, 10 Apr 2024 17:31:20 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,9 +62,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"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"
|
||||
"YSC\u003dwTHgOqPWWAQ; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 15-Jul-2021 17:31:20 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"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
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue