Merge pull request #1127 from AudricV/yt_improvements-and-fixes

[YouTube] Make some improvements and fixes
This commit is contained in:
Audric V 2023-12-09 14:07:31 +01:00 committed by GitHub
commit 678c98f24c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
391 changed files with 25544 additions and 14511 deletions

View File

@ -152,7 +152,7 @@ public final class YoutubeParsingHelper {
* The client version for InnerTube requests with the {@code WEB} client, used as the last * The client version for InnerTube requests with the {@code WEB} client, used as the last
* fallback if the extraction of the real one failed. * fallback if the extraction of the real one failed.
*/ */
private static final String HARDCODED_CLIENT_VERSION = "2.20220809.02.00"; private static final String HARDCODED_CLIENT_VERSION = "2.20231208.01.00";
/** /**
* The InnerTube API key which should be used by YouTube's desktop website, used as a fallback * The InnerTube API key which should be used by YouTube's desktop website, used as a fallback
@ -169,7 +169,7 @@ public final class YoutubeParsingHelper {
* such as <a href="https://www.apkmirror.com/apk/google-inc/youtube/">APKMirror</a>. * such as <a href="https://www.apkmirror.com/apk/google-inc/youtube/">APKMirror</a>.
* </p> * </p>
*/ */
private static final String ANDROID_YOUTUBE_CLIENT_VERSION = "17.31.35"; private static final String ANDROID_YOUTUBE_CLIENT_VERSION = "18.48.37";
/** /**
* The InnerTube API key used by the {@code ANDROID} client. Found with the help of * The InnerTube API key used by the {@code ANDROID} client. Found with the help of
@ -187,7 +187,7 @@ public final class YoutubeParsingHelper {
* Store page of the YouTube app</a>, in the {@code Whats New} section. * Store page of the YouTube app</a>, in the {@code Whats New} section.
* </p> * </p>
*/ */
private static final String IOS_YOUTUBE_CLIENT_VERSION = "17.31.4"; private static final String IOS_YOUTUBE_CLIENT_VERSION = "18.48.3";
/** /**
* The InnerTube API key used by the {@code iOS} client. Found with the help of * The InnerTube API key used by the {@code iOS} client. Found with the help of
@ -204,7 +204,7 @@ public final class YoutubeParsingHelper {
private static String key; private static String key;
private static final String[] HARDCODED_YOUTUBE_MUSIC_KEY = private static final String[] HARDCODED_YOUTUBE_MUSIC_KEY =
{"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "1.20220808.01.00"}; {"AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30", "67", "1.20231204.01.00"};
private static String[] youtubeMusicKey; private static String[] youtubeMusicKey;
private static boolean keyAndVersionExtracted = false; private static boolean keyAndVersionExtracted = false;
@ -228,14 +228,14 @@ public final class YoutubeParsingHelper {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
/** /**
* The device machine id for the iPhone 13, used to get 60fps with the {@code iOS} client. * The device machine id for the iPhone 15, used to get 60fps with the {@code iOS} client.
* *
* <p> * <p>
* See <a href="https://gist.github.com/adamawolf/3048717">this GitHub Gist</a> for more * See <a href="https://gist.github.com/adamawolf/3048717">this GitHub Gist</a> for more
* information. * information.
* </p> * </p>
*/ */
private static final String IOS_DEVICE_MODEL = "iPhone14,5"; private static final String IOS_DEVICE_MODEL = "iPhone15,4";
private static Random numberGenerator = new Random(); private static Random numberGenerator = new Random();
@ -260,21 +260,6 @@ public final class YoutubeParsingHelper {
private static final Set<String> YOUTUBE_URLS = Set.of("youtube.com", "www.youtube.com", private static final Set<String> YOUTUBE_URLS = Set.of("youtube.com", "www.youtube.com",
"m.youtube.com", "music.youtube.com"); "m.youtube.com", "music.youtube.com");
/**
* Determines how the consent cookie (that is required for YouTube) will be generated.
*
* <p>
* {@code false} (default) will use {@code PENDING+}.
* {@code true} will use {@code YES+}.
* </p>
*
* <p>
* Setting this value to <code>true</code> is currently needed if you want to watch
* Mix Playlists in some countries (EU).
* </p>
*
* @see #generateConsentCookie()
*/
private static boolean consentAccepted = false; private static boolean consentAccepted = false;
private static boolean isGoogleURL(final String url) { private static boolean isGoogleURL(final String url) {
@ -551,12 +536,21 @@ public final class YoutubeParsingHelper {
.value("gl", "GB") .value("gl", "GB")
.value("clientName", "WEB") .value("clientName", "WEB")
.value("clientVersion", HARDCODED_CLIENT_VERSION) .value("clientVersion", HARDCODED_CLIENT_VERSION)
.value("platform", "DESKTOP")
.value("utcOffsetMinutes", 0)
.end()
.object("request")
.array("internalExperimentFlags")
.end()
.value("useSsl", true)
.end()
.object("user")
// TODO: provide a way to enable restricted mode with:
// .value("enableSafetyMode", boolean)
.value("lockedSafetyMode", false)
.end() .end()
.object("user")
.value("lockedSafetyMode", false)
.end() .end()
.value("fetchLiveState", true) .value("fetchLiveState", true)
.end()
.end().done().getBytes(StandardCharsets.UTF_8); .end().done().getBytes(StandardCharsets.UTF_8);
// @formatter:on // @formatter:on
@ -770,7 +764,7 @@ public final class YoutubeParsingHelper {
public static boolean isHardcodedYoutubeMusicKeyValid() throws IOException, public static boolean isHardcodedYoutubeMusicKeyValid() throws IOException,
ReCaptchaException { ReCaptchaException {
final String url = final String url =
"https://music.youtube.com/youtubei/v1/music/get_search_suggestions?alt=json&key=" "https://music.youtube.com/youtubei/v1/music/get_search_suggestions?key="
+ HARDCODED_YOUTUBE_MUSIC_KEY[0] + DISABLE_PRETTY_PRINT_PARAMETER; + HARDCODED_YOUTUBE_MUSIC_KEY[0] + DISABLE_PRETTY_PRINT_PARAMETER;
// @formatter:off // @formatter:off
@ -782,19 +776,18 @@ public final class YoutubeParsingHelper {
.value("clientVersion", HARDCODED_YOUTUBE_MUSIC_KEY[2]) .value("clientVersion", HARDCODED_YOUTUBE_MUSIC_KEY[2])
.value("hl", "en-GB") .value("hl", "en-GB")
.value("gl", "GB") .value("gl", "GB")
.array("experimentIds").end() .value("platform", "DESKTOP")
.value("experimentsToken", "") .value("utcOffsetMinutes", 0)
.object("locationInfo").end()
.object("musicAppInfo").end()
.end() .end()
.object("capabilities").end()
.object("request") .object("request")
.array("internalExperimentFlags").end() .array("internalExperimentFlags")
.object("sessionIndex").end() .end()
.value("useSsl", true)
.end() .end()
.object("activePlayers").end()
.object("user") .object("user")
.value("enableSafetyMode", false) // TODO: provide a way to enable restricted mode with:
// .value("enableSafetyMode", boolean)
.value("lockedSafetyMode", false)
.end() .end()
.end() .end()
.value("input", "") .value("input", "")
@ -1296,7 +1289,8 @@ public final class YoutubeParsingHelper {
.value("clientName", "WEB") .value("clientName", "WEB")
.value("clientVersion", getClientVersion()) .value("clientVersion", getClientVersion())
.value("originalUrl", "https://www.youtube.com") .value("originalUrl", "https://www.youtube.com")
.value("platform", "DESKTOP"); .value("platform", "DESKTOP")
.value("utcOffsetMinutes", 0);
if (visitorData != null) { if (visitorData != null) {
builder.value("visitorData", visitorData); builder.value("visitorData", visitorData);
@ -1309,8 +1303,8 @@ public final class YoutubeParsingHelper {
.value("useSsl", true) .value("useSsl", true)
.end() .end()
.object("user") .object("user")
// TO DO: provide a way to enable restricted mode with: // TODO: provide a way to enable restricted mode with:
// .value("enableSafetyMode", boolean) // .value("enableSafetyMode", boolean)
.value("lockedSafetyMode", false) .value("lockedSafetyMode", false)
.end() .end()
.end(); .end();
@ -1329,25 +1323,31 @@ public final class YoutubeParsingHelper {
.value("clientVersion", ANDROID_YOUTUBE_CLIENT_VERSION) .value("clientVersion", ANDROID_YOUTUBE_CLIENT_VERSION)
.value("platform", "MOBILE") .value("platform", "MOBILE")
.value("osName", "Android") .value("osName", "Android")
.value("osVersion", "12") .value("osVersion", "14")
/* /*
A valid Android SDK version is required to be sure to get a valid player A valid Android SDK version is required to be sure to get a valid player
response response
If this parameter is not provided, the player response may be replaced by If this parameter is not provided, the player response is replaced by an
the one of a 5-minute video saying the message "The following content is error saying the message "The following content is not available on this
not available on this app. Watch this content on the latest version on app. Watch this content on the latest version on YouTube" (it was
YouTube" previously a 5-minute video with this message)
See https://github.com/TeamNewPipe/NewPipe/issues/8713 See https://github.com/TeamNewPipe/NewPipe/issues/8713
The Android SDK version corresponding to the Android version used in The Android SDK version corresponding to the Android version used in
requests is sent requests is sent
*/ */
.value("androidSdkVersion", 31) .value("androidSdkVersion", 34)
.value("hl", localization.getLocalizationCode()) .value("hl", localization.getLocalizationCode())
.value("gl", contentCountry.getCountryCode()) .value("gl", contentCountry.getCountryCode())
.value("utcOffsetMinutes", 0)
.end()
.object("request")
.array("internalExperimentFlags")
.end()
.value("useSsl", true)
.end() .end()
.object("user") .object("user")
// TO DO: provide a way to enable restricted mode with: // TODO: provide a way to enable restricted mode with:
// .value("enableSafetyMode", boolean) // .value("enableSafetyMode", boolean)
.value("lockedSafetyMode", false) .value("lockedSafetyMode", false)
.end() .end()
.end(); .end();
@ -1369,17 +1369,26 @@ public final class YoutubeParsingHelper {
.value("deviceModel", IOS_DEVICE_MODEL) .value("deviceModel", IOS_DEVICE_MODEL)
.value("platform", "MOBILE") .value("platform", "MOBILE")
.value("osName", "iOS") .value("osName", "iOS")
// The value of this field seems to use the following structure: /*
// "iOS version.0.build version" The value of this field seems to use the following structure:
// The build version corresponding to the iOS version used can be found on "iOS major version.minor version.patch version.build version", where
// https://www.theiphonewiki.com/wiki/Firmware/iPhone/15.x#iPhone_13 "patch version" is equal to 0 if it isn't set
.value("osVersion", "15.6.0.19G71") The build version corresponding to the iOS version used can be found on
https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15
*/
.value("osVersion", "17.1.2.21B101")
.value("hl", localization.getLocalizationCode()) .value("hl", localization.getLocalizationCode())
.value("gl", contentCountry.getCountryCode()) .value("gl", contentCountry.getCountryCode())
.value("utcOffsetMinutes", 0)
.end()
.object("request")
.array("internalExperimentFlags")
.end()
.value("useSsl", true)
.end() .end()
.object("user") .object("user")
// TO DO: provide a way to enable restricted mode with: // TODO: provide a way to enable restricted mode with:
// .value("enableSafetyMode", boolean) // .value("enableSafetyMode", boolean)
.value("lockedSafetyMode", false) .value("lockedSafetyMode", false)
.end() .end()
.end(); .end();
@ -1401,13 +1410,19 @@ public final class YoutubeParsingHelper {
.value("platform", "TV") .value("platform", "TV")
.value("hl", localization.getLocalizationCode()) .value("hl", localization.getLocalizationCode())
.value("gl", contentCountry.getCountryCode()) .value("gl", contentCountry.getCountryCode())
.value("utcOffsetMinutes", 0)
.end() .end()
.object("thirdParty") .object("thirdParty")
.value("embedUrl", "https://www.youtube.com/watch?v=" + videoId) .value("embedUrl", "https://www.youtube.com/watch?v=" + videoId)
.end() .end()
.object("request")
.array("internalExperimentFlags")
.end()
.value("useSsl", true)
.end()
.object("user") .object("user")
// TO DO: provide a way to enable restricted mode with: // TODO: provide a way to enable restricted mode with:
// .value("enableSafetyMode", boolean) // .value("enableSafetyMode", boolean)
.value("lockedSafetyMode", false) .value("lockedSafetyMode", false)
.end() .end()
.end(); .end();
@ -1458,9 +1473,9 @@ public final class YoutubeParsingHelper {
*/ */
@Nonnull @Nonnull
public static String getAndroidUserAgent(@Nullable final Localization localization) { public static String getAndroidUserAgent(@Nullable final Localization localization) {
// Spoofing an Android 12 device with the hardcoded version of the Android app // Spoofing an Android 14 device with the hardcoded version of the Android app
return "com.google.android.youtube/" + ANDROID_YOUTUBE_CLIENT_VERSION return "com.google.android.youtube/" + ANDROID_YOUTUBE_CLIENT_VERSION
+ " (Linux; U; Android 12; " + " (Linux; U; Android 14; "
+ (localization != null ? localization : Localization.DEFAULT).getCountryCode() + (localization != null ? localization : Localization.DEFAULT).getCountryCode()
+ ") gzip"; + ") gzip";
} }
@ -1480,9 +1495,9 @@ public final class YoutubeParsingHelper {
*/ */
@Nonnull @Nonnull
public static String getIosUserAgent(@Nullable final Localization localization) { public static String getIosUserAgent(@Nullable final Localization localization) {
// Spoofing an iPhone 13 running iOS 15.6 with the hardcoded version of the iOS app // Spoofing an iPhone 15 running iOS 17.1.2 with the hardcoded version of the iOS app
return "com.google.ios.youtube/" + IOS_YOUTUBE_CLIENT_VERSION return "com.google.ios.youtube/" + IOS_YOUTUBE_CLIENT_VERSION
+ "(" + IOS_DEVICE_MODEL + "; U; CPU iOS 15_6 like Mac OS X; " + "(" + IOS_DEVICE_MODEL + "; U; CPU iOS 17_1_2 like Mac OS X; "
+ (localization != null ? localization : Localization.DEFAULT).getCountryCode() + (localization != null ? localization : Localization.DEFAULT).getCountryCode()
+ ")"; + ")";
} }
@ -1553,13 +1568,15 @@ public final class YoutubeParsingHelper {
@Nonnull @Nonnull
public static String generateConsentCookie() { public static String generateConsentCookie() {
return "CONSENT=" + (isConsentAccepted() return "SOCS=" + (isConsentAccepted()
// YES+ means that the user did submit their choices and allows tracking. // CAISAiAD means that the user configured manually cookies YouTube, regardless of
? "YES+" // the consent values
// PENDING+ means that the user did not yet submit their choices. // This value surprisingly allows to extract mixes and some YouTube Music playlists
// YT & Google should not track the user, because they did not give consent. // in the same way when a user allows all cookies
// The three digits at the end can be random, but are required. ? "CAISAiAD"
: "PENDING+" + (100 + numberGenerator.nextInt(900))); // CAE= means that the user rejected all non-necessary cookies with the "Reject
// all" button on the consent page
: "CAE=");
} }
public static String extractCookieValue(final String cookieName, public static String extractCookieValue(final String cookieName,
@ -1851,14 +1868,28 @@ public final class YoutubeParsingHelper {
} }
/** /**
* @see #consentAccepted * Determines how the consent cookie that is required for YouTube, {@code SOCS}, will be
* generated.
*
* <ul>
* <li>{@code false} (the default value) will use {@code CAE=};</li>
* <li>{@code true} will use {@code CAISAiAD}.</li>
* </ul>
*
* <p>
* Setting this value to {@code true} is needed to extract mixes and some YouTube Music
* playlists in some countries such as the EU ones.
* </p>
*/ */
public static void setConsentAccepted(final boolean accepted) { public static void setConsentAccepted(final boolean accepted) {
consentAccepted = accepted; consentAccepted = accepted;
} }
/** /**
* @see #consentAccepted * Get the value of the consent's acceptance.
*
* @see #setConsentAccepted(boolean)
* @return the consent's acceptance value
*/ */
public static boolean isConsentAccepted() { public static boolean isConsentAccepted() {
return consentAccepted; return consentAccepted;

View File

@ -448,9 +448,6 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
case "playlists": case "playlists":
addNonVideosTab.accept(ChannelTabs.PLAYLISTS); addNonVideosTab.accept(ChannelTabs.PLAYLISTS);
break; break;
case "channels":
addNonVideosTab.accept(ChannelTabs.CHANNELS);
break;
} }
} }
}); });

View File

@ -80,10 +80,9 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
return "EgdzdHJlYW1z8gYECgJ6AA%3D%3D"; return "EgdzdHJlYW1z8gYECgJ6AA%3D%3D";
case ChannelTabs.PLAYLISTS: case ChannelTabs.PLAYLISTS:
return "EglwbGF5bGlzdHPyBgQKAkIA"; return "EglwbGF5bGlzdHPyBgQKAkIA";
case ChannelTabs.CHANNELS: default:
return "EghjaGFubmVsc_IGBAoCUgA%3D"; throw new ParsingException("Unsupported channel tab: " + name);
} }
throw new ParsingException("Unsupported channel tab: " + name);
} }
@Override @Override
@ -313,9 +312,6 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
} else if (item.has("gridPlaylistRenderer")) { } else if (item.has("gridPlaylistRenderer")) {
getCommitPlaylistConsumer(collector, channelIds, getCommitPlaylistConsumer(collector, channelIds,
item.getObject("gridPlaylistRenderer")); item.getObject("gridPlaylistRenderer"));
} else if (item.has("gridChannelRenderer")) {
collector.commit(new YoutubeChannelInfoItemExtractor(
item.getObject("gridChannelRenderer")));
} else if (item.has("shelfRenderer")) { } else if (item.has("shelfRenderer")) {
return collectItem(collector, item.getObject("shelfRenderer") return collectItem(collector, item.getObject("shelfRenderer")
.getObject("content"), channelIds); .getObject("content"), channelIds);

View File

@ -54,7 +54,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
throws IOException, ExtractionException { throws IOException, ExtractionException {
final String[] youtubeMusicKeys = YoutubeParsingHelper.getYoutubeMusicKey(); final String[] youtubeMusicKeys = YoutubeParsingHelper.getYoutubeMusicKey();
final String url = "https://music.youtube.com/youtubei/v1/search?alt=json&key=" final String url = "https://music.youtube.com/youtubei/v1/search?key="
+ youtubeMusicKeys[0] + DISABLE_PRETTY_PRINT_PARAMETER; + youtubeMusicKeys[0] + DISABLE_PRETTY_PRINT_PARAMETER;
final String params; final String params;
@ -89,20 +89,18 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
.value("clientVersion", youtubeMusicKeys[2]) .value("clientVersion", youtubeMusicKeys[2])
.value("hl", "en-GB") .value("hl", "en-GB")
.value("gl", getExtractorContentCountry().getCountryCode()) .value("gl", getExtractorContentCountry().getCountryCode())
.array("experimentIds").end() .value("platform", "DESKTOP")
.value("experimentsToken", "") .value("utcOffsetMinutes", 0)
.object("locationInfo").end()
.object("musicAppInfo").end()
.end() .end()
.object("capabilities").end()
.object("request") .object("request")
.array("internalExperimentFlags").end() .array("internalExperimentFlags")
.object("sessionIndex").end() .end()
.value("useSsl", true)
.end() .end()
.object("activePlayers").end()
.object("user") .object("user")
// TO DO: provide a way to enable restricted mode with: // TODO: provide a way to enable restricted mode with:
.value("enableSafetyMode", false) // .value("enableSafetyMode", boolean)
.value("lockedSafetyMode", false)
.end() .end()
.end() .end()
.value("query", getSearchString()) .value("query", getSearchString())
@ -219,20 +217,18 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
.value("clientVersion", youtubeMusicKeys[2]) .value("clientVersion", youtubeMusicKeys[2])
.value("hl", "en-GB") .value("hl", "en-GB")
.value("gl", getExtractorContentCountry().getCountryCode()) .value("gl", getExtractorContentCountry().getCountryCode())
.array("experimentIds").end() .value("platform", "DESKTOP")
.value("experimentsToken", "")
.value("utcOffsetMinutes", 0) .value("utcOffsetMinutes", 0)
.object("locationInfo").end()
.object("musicAppInfo").end()
.end() .end()
.object("capabilities").end()
.object("request") .object("request")
.array("internalExperimentFlags").end() .array("internalExperimentFlags")
.object("sessionIndex").end() .end()
.value("useSsl", true)
.end() .end()
.object("activePlayers").end()
.object("user") .object("user")
.value("enableSafetyMode", false) // TODO: provide a way to enable restricted mode with:
// .value("enableSafetyMode", boolean)
.value("lockedSafetyMode", false)
.end() .end()
.end() .end()
.end().done().getBytes(StandardCharsets.UTF_8); .end().done().getBytes(StandardCharsets.UTF_8);
@ -310,7 +306,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
final String continuation = nextContinuationData.getString("continuation"); final String continuation = nextContinuationData.getString("continuation");
return new Page("https://music.youtube.com/youtubei/v1/search?ctoken=" + continuation return new Page("https://music.youtube.com/youtubei/v1/search?ctoken=" + continuation
+ "&continuation=" + continuation + "&alt=json" + "&key=" + "&continuation=" + continuation + "&key="
+ YoutubeParsingHelper.getYoutubeMusicKey()[0]); + YoutubeParsingHelper.getYoutubeMusicKey()[0] + DISABLE_PRETTY_PRINT_PARAMETER);
} }
} }

View File

@ -6,6 +6,10 @@ import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey; import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject; 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.YoutubeParsingHelper.prepareDesktopJsonBuilder;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.ALL;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.CHANNELS;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.PLAYLISTS;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.VIDEOS;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.getSearchParameter; import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.getSearchParameter;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
@ -32,6 +36,7 @@ import org.schabi.newpipe.extractor.utils.JsonUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.Objects;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -57,11 +62,29 @@ import javax.annotation.Nullable;
*/ */
public class YoutubeSearchExtractor extends SearchExtractor { public class YoutubeSearchExtractor extends SearchExtractor {
@Nullable
private final String searchType;
private final boolean extractVideoResults;
private final boolean extractChannelResults;
private final boolean extractPlaylistResults;
private JsonObject initialData; private JsonObject initialData;
public YoutubeSearchExtractor(final StreamingService service, public YoutubeSearchExtractor(final StreamingService service,
final SearchQueryHandler linkHandler) { final SearchQueryHandler linkHandler) {
super(service, linkHandler); super(service, linkHandler);
final List<String> contentFilters = linkHandler.getContentFilters();
searchType = isNullOrEmpty(contentFilters) ? null : contentFilters.get(0);
// Save whether we should extract video, channel and playlist results depending on the
// requested search type, as YouTube returns sometimes videos inside channel search results
// If no search type is provided or ALL filter is requested, extract everything
extractVideoResults = searchType == null || ALL.equals(searchType)
|| VIDEOS.equals(searchType);
extractChannelResults = searchType == null || ALL.equals(searchType)
|| CHANNELS.equals(searchType);
extractPlaylistResults = searchType == null || ALL.equals(searchType)
|| PLAYLISTS.equals(searchType);
} }
@Override @Override
@ -69,16 +92,7 @@ public class YoutubeSearchExtractor extends SearchExtractor {
ExtractionException { ExtractionException {
final String query = super.getSearchString(); final String query = super.getSearchString();
final Localization localization = getExtractorLocalization(); final Localization localization = getExtractorLocalization();
final String params = getSearchParameter(searchType);
// Get the search parameter of the request
final List<String> contentFilters = super.getLinkHandler().getContentFilters();
final String params;
if (!isNullOrEmpty(contentFilters)) {
final String searchType = contentFilters.get(0);
params = getSearchParameter(searchType);
} else {
params = "";
}
final JsonBuilder<JsonObject> jsonBody = prepareDesktopJsonBuilder(localization, final JsonBuilder<JsonObject> jsonBody = prepareDesktopJsonBuilder(localization,
getExtractorContentCountry()) getExtractorContentCountry())
@ -111,18 +125,17 @@ public class YoutubeSearchExtractor extends SearchExtractor {
final JsonObject didYouMeanRenderer = itemSectionRenderer.getArray("contents") final JsonObject didYouMeanRenderer = itemSectionRenderer.getArray("contents")
.getObject(0) .getObject(0)
.getObject("didYouMeanRenderer"); .getObject("didYouMeanRenderer");
final JsonObject showingResultsForRenderer = itemSectionRenderer.getArray("contents")
.getObject(0)
.getObject("showingResultsForRenderer");
if (!didYouMeanRenderer.isEmpty()) { if (!didYouMeanRenderer.isEmpty()) {
return JsonUtils.getString(didYouMeanRenderer, return JsonUtils.getString(didYouMeanRenderer,
"correctedQueryEndpoint.searchEndpoint.query"); "correctedQueryEndpoint.searchEndpoint.query");
} else if (showingResultsForRenderer != null) {
return getTextFromObject(showingResultsForRenderer.getObject("correctedQuery"));
} else {
return "";
} }
return Objects.requireNonNullElse(
getTextFromObject(itemSectionRenderer.getArray("contents")
.getObject(0)
.getObject("showingResultsForRenderer")
.getObject("correctedQuery")), "");
} }
@Override @Override
@ -211,7 +224,7 @@ public class YoutubeSearchExtractor extends SearchExtractor {
private void collectStreamsFrom(final MultiInfoItemsCollector collector, private void collectStreamsFrom(final MultiInfoItemsCollector collector,
@Nonnull final JsonArray contents) @Nonnull final JsonArray contents)
throws NothingFoundException, ParsingException { throws NothingFoundException {
final TimeAgoParser timeAgoParser = getTimeAgoParser(); final TimeAgoParser timeAgoParser = getTimeAgoParser();
for (final Object content : contents) { for (final Object content : contents) {
@ -220,13 +233,13 @@ public class YoutubeSearchExtractor extends SearchExtractor {
throw new NothingFoundException( throw new NothingFoundException(
getTextFromObject(item.getObject("backgroundPromoRenderer") getTextFromObject(item.getObject("backgroundPromoRenderer")
.getObject("bodyText"))); .getObject("bodyText")));
} else if (item.has("videoRenderer")) { } else if (extractVideoResults && item.has("videoRenderer")) {
collector.commit(new YoutubeStreamInfoItemExtractor( collector.commit(new YoutubeStreamInfoItemExtractor(
item.getObject("videoRenderer"), timeAgoParser)); item.getObject("videoRenderer"), timeAgoParser));
} else if (item.has("channelRenderer")) { } else if (extractChannelResults && item.has("channelRenderer")) {
collector.commit(new YoutubeChannelInfoItemExtractor( collector.commit(new YoutubeChannelInfoItemExtractor(
item.getObject("channelRenderer"))); item.getObject("channelRenderer")));
} else if (item.has("playlistRenderer")) { } else if (extractPlaylistResults && item.has("playlistRenderer")) {
collector.commit(new YoutubePlaylistInfoItemExtractor( collector.commit(new YoutubePlaylistInfoItemExtractor(
item.getObject("playlistRenderer"))); item.getObject("playlistRenderer")));
} }

View File

@ -388,57 +388,43 @@ public class YoutubeStreamExtractor extends StreamExtractor {
// If ratings are not allowed, there is no like count available // If ratings are not allowed, there is no like count available
if (!playerResponse.getObject("videoDetails").getBoolean("allowRatings")) { if (!playerResponse.getObject("videoDetails").getBoolean("allowRatings")) {
return -1; return -1L;
} }
String likesString = ""; final JsonArray topLevelButtons = getVideoPrimaryInfoRenderer()
.getObject("videoActions")
.getObject("menuRenderer")
.getArray("topLevelButtons");
try { try {
final JsonArray topLevelButtons = getVideoPrimaryInfoRenderer() return parseLikeCountFromLikeButtonViewModel(topLevelButtons);
.getObject("videoActions") } catch (final ParsingException ignored) {
.getObject("menuRenderer") // A segmentedLikeDislikeButtonRenderer could be returned instead of a
.getArray("topLevelButtons"); // segmentedLikeDislikeButtonViewModel, so ignore extraction errors relative to
// segmentedLikeDislikeButtonViewModel object
}
// Try first with the new video actions buttons data structure try {
JsonObject likeToggleButtonRenderer = topLevelButtons.stream() return parseLikeCountFromLikeButtonRenderer(topLevelButtons);
.filter(JsonObject.class::isInstance) } catch (final ParsingException e) {
.map(JsonObject.class::cast) throw new ParsingException("Could not get like count", e);
.map(button -> button.getObject("segmentedLikeDislikeButtonRenderer") }
.getObject("likeButton") }
.getObject("toggleButtonRenderer"))
.filter(toggleButtonRenderer -> !isNullOrEmpty(toggleButtonRenderer))
.findFirst()
.orElse(null);
// Use the old video actions buttons data structure if the new one isn't returned private static long parseLikeCountFromLikeButtonRenderer(
if (likeToggleButtonRenderer == null) { @Nonnull final JsonArray topLevelButtons) throws ParsingException {
/* String likesString = null;
In the old video actions buttons data structure, there are 3 ways to detect whether final JsonObject likeToggleButtonRenderer = topLevelButtons.stream()
a button is the like button, using its toggleButtonRenderer: .filter(JsonObject.class::isInstance)
- checking whether toggleButtonRenderer.targetId is equal to watch-like; .map(JsonObject.class::cast)
- checking whether toggleButtonRenderer.defaultIcon.iconType is equal to LIKE; .map(button -> button.getObject("segmentedLikeDislikeButtonRenderer")
- checking whether .getObject("likeButton")
toggleButtonRenderer.toggleButtonSupportedData.toggleButtonIdData.id .getObject("toggleButtonRenderer"))
is equal to TOGGLE_BUTTON_ID_TYPE_LIKE. .filter(toggleButtonRenderer -> !isNullOrEmpty(toggleButtonRenderer))
*/ .findFirst()
likeToggleButtonRenderer = topLevelButtons.stream() .orElse(null);
.filter(JsonObject.class::isInstance)
.map(JsonObject.class::cast)
.map(topLevelButton -> topLevelButton.getObject("toggleButtonRenderer"))
.filter(toggleButtonRenderer -> toggleButtonRenderer.getString("targetId")
.equalsIgnoreCase("watch-like")
|| toggleButtonRenderer.getObject("defaultIcon")
.getString("iconType")
.equalsIgnoreCase("LIKE")
|| toggleButtonRenderer.getObject("toggleButtonSupportedData")
.getObject("toggleButtonIdData")
.getString("id")
.equalsIgnoreCase("TOGGLE_BUTTON_ID_TYPE_LIKE"))
.findFirst()
.orElseThrow(() -> new ParsingException(
"The like button is missing even though ratings are enabled"));
}
if (likeToggleButtonRenderer != null) {
// Use one of the accessibility strings available (this one has the same path as the // Use one of the accessibility strings available (this one has the same path as the
// one used for comments' like count extraction) // one used for comments' like count extraction)
likesString = likeToggleButtonRenderer.getObject("accessibilityData") likesString = likeToggleButtonRenderer.getObject("accessibilityData")
@ -460,23 +446,58 @@ public class YoutubeStreamExtractor extends StreamExtractor {
.getString("label"); .getString("label");
} }
// If ratings are allowed and the likes string is null, it means that we couldn't
// extract the (real) like count from accessibility data
if (likesString == null) {
throw new ParsingException("Could not get like count from accessibility data");
}
// This check only works with English localizations! // This check only works with English localizations!
if (likesString.toLowerCase().contains("no likes")) { if (likesString != null && likesString.toLowerCase().contains("no likes")) {
return 0; return 0;
} }
}
return Integer.parseInt(Utils.removeNonDigitCharacters(likesString)); // If ratings are allowed and the likes string is null, it means that we couldn't extract
} catch (final NumberFormatException nfe) { // the full like count from accessibility data
throw new ParsingException("Could not parse \"" + likesString + "\" as an Integer", if (likesString == null) {
nfe); throw new ParsingException("Could not get like count from accessibility data");
} catch (final Exception e) { }
throw new ParsingException("Could not get like count", e);
try {
return Long.parseLong(Utils.removeNonDigitCharacters(likesString));
} catch (final NumberFormatException e) {
throw new ParsingException("Could not parse \"" + likesString + "\" as a long", e);
}
}
private static long parseLikeCountFromLikeButtonViewModel(
@Nonnull final JsonArray topLevelButtons) throws ParsingException {
// Try first with the current video actions buttons data structure
final JsonObject likeToggleButtonViewModel = topLevelButtons.stream()
.filter(JsonObject.class::isInstance)
.map(JsonObject.class::cast)
.map(button -> button.getObject("segmentedLikeDislikeButtonViewModel")
.getObject("likeButtonViewModel")
.getObject("likeButtonViewModel")
.getObject("toggleButtonViewModel")
.getObject("toggleButtonViewModel")
.getObject("defaultButtonViewModel")
.getObject("buttonViewModel"))
.filter(buttonViewModel -> !isNullOrEmpty(buttonViewModel))
.findFirst()
.orElse(null);
if (likeToggleButtonViewModel == null) {
throw new ParsingException("Could not find buttonViewModel object");
}
final String accessibilityText = likeToggleButtonViewModel.getString("accessibilityText");
if (accessibilityText == null) {
throw new ParsingException("Could not find buttonViewModel's accessibilityText string");
}
// The like count is always returned as a number in this element, even for videos with no
// likes
try {
return Long.parseLong(Utils.removeNonDigitCharacters(accessibilityText));
} catch (final NumberFormatException e) {
throw new ParsingException(
"Could not parse \"" + accessibilityText + "\" as a long", e);
} }
} }

View File

@ -31,10 +31,9 @@ public final class YoutubeChannelTabLinkHandlerFactory extends ListLinkHandlerFa
return "/streams"; return "/streams";
case ChannelTabs.PLAYLISTS: case ChannelTabs.PLAYLISTS:
return "/playlists"; return "/playlists";
case ChannelTabs.CHANNELS: default:
return "/channels"; throw new UnsupportedTabException(tab);
} }
throw new UnsupportedTabException(tab);
} }
@Override @Override
@ -66,8 +65,7 @@ public final class YoutubeChannelTabLinkHandlerFactory extends ListLinkHandlerFa
ChannelTabs.VIDEOS, ChannelTabs.VIDEOS,
ChannelTabs.SHORTS, ChannelTabs.SHORTS,
ChannelTabs.LIVESTREAMS, ChannelTabs.LIVESTREAMS,
ChannelTabs.PLAYLISTS, ChannelTabs.PLAYLISTS
ChannelTabs.CHANNELS
}; };
} }
} }

View File

@ -45,11 +45,14 @@ public final class YoutubeSearchQueryHandlerFactory extends SearchQueryHandlerFa
final String contentFilter = contentFilters.get(0); final String contentFilter = contentFilters.get(0);
switch (contentFilter) { switch (contentFilter) {
case VIDEOS: case VIDEOS:
return SEARCH_URL + encodeUrlUtf8(searchString) + "&sp=EgIQAQ%253D%253D"; return SEARCH_URL + encodeUrlUtf8(searchString)
+ "&sp=EgIQAfABAQ%253D%253D";
case CHANNELS: case CHANNELS:
return SEARCH_URL + encodeUrlUtf8(searchString) + "&sp=EgIQAg%253D%253D"; return SEARCH_URL + encodeUrlUtf8(searchString)
+ "&sp=EgIQAvABAQ%253D%253D";
case PLAYLISTS: case PLAYLISTS:
return SEARCH_URL + encodeUrlUtf8(searchString) + "&sp=EgIQAw%253D%253D"; return SEARCH_URL + encodeUrlUtf8(searchString)
+ "&sp=EgIQA_ABAQ%253D%253D";
case MUSIC_SONGS: case MUSIC_SONGS:
case MUSIC_VIDEOS: case MUSIC_VIDEOS:
case MUSIC_ALBUMS: case MUSIC_ALBUMS:
@ -59,7 +62,7 @@ public final class YoutubeSearchQueryHandlerFactory extends SearchQueryHandlerFa
} }
} }
return SEARCH_URL + encodeUrlUtf8(searchString); return SEARCH_URL + encodeUrlUtf8(searchString) + "&sp=8AEB";
} catch (final UnsupportedEncodingException e) { } catch (final UnsupportedEncodingException e) {
throw new ParsingException("Could not encode query", e); throw new ParsingException("Could not encode query", e);
} }
@ -83,24 +86,24 @@ public final class YoutubeSearchQueryHandlerFactory extends SearchQueryHandlerFa
@Nonnull @Nonnull
public static String getSearchParameter(final String contentFilter) { public static String getSearchParameter(final String contentFilter) {
if (isNullOrEmpty(contentFilter)) { if (isNullOrEmpty(contentFilter)) {
return ""; return "8AEB";
} }
switch (contentFilter) { switch (contentFilter) {
case VIDEOS: case VIDEOS:
return "EgIQAQ%3D%3D"; return "EgIQAfABAQ%3D%3D";
case CHANNELS: case CHANNELS:
return "EgIQAg%3D%3D"; return "EgIQAvABAQ%3D%3D";
case PLAYLISTS: case PLAYLISTS:
return "EgIQAw%3D%3D"; return "EgIQA_ABAQ%3D%3D";
case ALL:
case MUSIC_SONGS: case MUSIC_SONGS:
case MUSIC_VIDEOS: case MUSIC_VIDEOS:
case MUSIC_ALBUMS: case MUSIC_ALBUMS:
case MUSIC_PLAYLISTS: case MUSIC_PLAYLISTS:
case MUSIC_ARTISTS: case MUSIC_ARTISTS:
default:
return ""; return "";
default:
return "8AEB";
} }
} }
} }

View File

@ -2,11 +2,12 @@ package org.schabi.newpipe.extractor.services.youtube;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmpty; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmpty;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertNotBlank; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertNotEmpty;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertTabsContain;
import static org.schabi.newpipe.extractor.ServiceList.YouTube; import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor; import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestGetPageInNewExtractor;
@ -231,7 +232,7 @@ public class YoutubeChannelExtractorTest {
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS,
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS); ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS);
assertTrue(extractor.getTabs().stream() assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); .allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
@ -324,7 +325,7 @@ public class YoutubeChannelExtractorTest {
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.LIVESTREAMS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.LIVESTREAMS,
ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS); ChannelTabs.SHORTS, ChannelTabs.PLAYLISTS);
assertTrue(extractor.getTabs().stream() assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); .allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
@ -420,7 +421,7 @@ public class YoutubeChannelExtractorTest {
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS,
ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS); ChannelTabs.PLAYLISTS);
assertTrue(extractor.getTabs().stream() assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); .allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
@ -539,8 +540,7 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS);
ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream() assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); .allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
@ -632,8 +632,7 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS, assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS);
ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream() assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0))) .filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance)); .allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
@ -654,7 +653,7 @@ public class YoutubeChannelExtractorTest {
YoutubeTestsUtils.ensureStateless(); YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "carouselHeader")); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "carouselHeader"));
extractor = (YoutubeChannelExtractor) YouTube extractor = (YoutubeChannelExtractor) YouTube
.getChannelExtractor("https://www.youtube.com/channel/UCHF66aWLOxBW4l6VkSrS3cQ"); .getChannelExtractor("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw");
extractor.fetchPage(); extractor.fetchPage();
} }
@ -669,22 +668,22 @@ public class YoutubeChannelExtractorTest {
@Test @Test
public void testName() throws Exception { public void testName() throws Exception {
assertEquals("Coachella", extractor.getName()); assertEquals("Sports", extractor.getName());
} }
@Test @Test
public void testId() throws Exception { public void testId() throws Exception {
assertEquals("UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getId()); assertEquals("UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getId());
} }
@Test @Test
public void testUrl() throws ParsingException { public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getUrl()); assertEquals("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getUrl());
} }
@Test @Test
public void testOriginalUrl() throws ParsingException { public void testOriginalUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getOriginalUrl()); assertEquals("https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getOriginalUrl());
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -694,7 +693,7 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testDescription() throws ParsingException { public void testDescription() throws ParsingException {
assertNotBlank(extractor.getDescription()); assertNull(extractor.getDescription());
} }
@Test @Test
@ -710,12 +709,12 @@ public class YoutubeChannelExtractorTest {
@Test @Test
public void testFeedUrl() throws Exception { public void testFeedUrl() throws Exception {
assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCHF66aWLOxBW4l6VkSrS3cQ", extractor.getFeedUrl()); assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UCEgdi0XIXXZ-qJOFPf4JSKw", extractor.getFeedUrl());
} }
@Test @Test
public void testSubscriberCount() throws Exception { public void testSubscriberCount() throws Exception {
ExtractorAsserts.assertGreaterOrEqual(2_900_000, extractor.getSubscriberCount()); ExtractorAsserts.assertGreaterOrEqual(70_000_000, extractor.getSubscriberCount());
} }
@Test @Test
@ -726,18 +725,13 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testTabs() throws Exception { public void testTabs() throws Exception {
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.SHORTS, assertEmpty(extractor.getTabs());
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS, ChannelTabs.CHANNELS);
assertTrue(extractor.getTabs().stream()
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
} }
@Test @Test
@Override @Override
public void testTags() throws Exception { public void testTags() throws Exception {
assertTrue(extractor.getTags().containsAll(List.of("coachella", "music", "california", assertEmpty(extractor.getTags());
"festival", "arts")));
} }
} }
@ -881,10 +875,9 @@ public class YoutubeChannelExtractorTest {
@Test @Test
@Override @Override
public void testDescription() throws Exception { public void testDescription() throws Exception {
final String description = extractor.getDescription(); // The description changes frequently and there is no significant common word, so only
assertContains("Minecraft", description); // check if it is not empty
assertContains("game", description); assertNotEmpty(extractor.getDescription());
assertContains("Mojang", description);
} }
@Test @Test

View File

@ -68,28 +68,6 @@ class YoutubeChannelTabExtractorTest {
@Override public boolean expectedHasMoreItems() { return true; } @Override public boolean expectedHasMoreItems() { return true; }
} }
static class Channels extends DefaultListExtractorTest<ChannelTabExtractor> {
private static YoutubeChannelTabExtractor extractor;
@BeforeAll
static void setUp() throws IOException, ExtractionException {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "channels"));
extractor = (YoutubeChannelTabExtractor) YouTube.getChannelTabExtractorFromId(
"channel/UC2DjFE7Xf11URZqWBigcVOQ", ChannelTabs.CHANNELS);
extractor.fetchPage();
}
@Override public ChannelTabExtractor extractor() throws Exception { return extractor; }
@Override public StreamingService expectedService() throws Exception { return YouTube; }
@Override public String expectedName() throws Exception { return ChannelTabs.CHANNELS; }
@Override public String expectedId() throws Exception { return "UC2DjFE7Xf11URZqWBigcVOQ"; }
@Override public String expectedUrlContains() throws Exception { return "https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/channels"; }
@Override public String expectedOriginalUrlContains() throws Exception { return "https://www.youtube.com/channel/UC2DjFE7Xf11URZqWBigcVOQ/channels"; }
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.CHANNEL; }
@Override public boolean expectedHasMoreItems() { return true; }
}
static class Livestreams extends DefaultListExtractorTest<ChannelTabExtractor> { static class Livestreams extends DefaultListExtractorTest<ChannelTabExtractor> {
private static YoutubeChannelTabExtractor extractor; private static YoutubeChannelTabExtractor extractor;

View File

@ -22,7 +22,6 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeMixPlaylistExtractor; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeMixPlaylistExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem;
@ -454,7 +453,8 @@ public class YoutubeMixPlaylistExtractorTest {
.getBytes(StandardCharsets.UTF_8); .getBytes(StandardCharsets.UTF_8);
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page( final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
YOUTUBEI_V1_URL + "next?key=" + getKey(), null, null, dummyCookie, body)); YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
null, null, dummyCookie, body));
assertFalse(streams.getItems().isEmpty()); assertFalse(streams.getItems().isEmpty());
assertTrue(streams.hasNextPage()); assertTrue(streams.hasNextPage());
} }
@ -542,7 +542,8 @@ public class YoutubeMixPlaylistExtractorTest {
.getBytes(StandardCharsets.UTF_8); .getBytes(StandardCharsets.UTF_8);
final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page( final InfoItemsPage<StreamInfoItem> streams = extractor.getPage(new Page(
YOUTUBEI_V1_URL + "next?key=" + getKey(), null, null, dummyCookie, body)); YOUTUBEI_V1_URL + "next?key=" + getKey() + DISABLE_PRETTY_PRINT_PARAMETER,
null, null, dummyCookie, body));
assertFalse(streams.getItems().isEmpty()); assertFalse(streams.getItems().isEmpty());
assertTrue(streams.hasNextPage()); assertTrue(streams.hasNextPage());
} }
@ -570,7 +571,7 @@ public class YoutubeMixPlaylistExtractorTest {
} }
@Test @Test
void getStreamCount() throws ParsingException { void getStreamCount() {
assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount()); assertEquals(ListExtractor.ITEM_COUNT_INFINITE, extractor.getStreamCount());
} }

View File

@ -342,10 +342,9 @@ public class YoutubePlaylistExtractorTest {
defaultTestRelatedItems(extractor); defaultTestRelatedItems(extractor);
} }
@Disabled
@Test @Test
public void testMoreRelatedItems() throws Exception { public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor); assertFalse(extractor.getInitialPage().hasNextPage());
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////

View File

@ -15,7 +15,6 @@ import static java.util.Collections.singletonList;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderFactory; import org.schabi.newpipe.downloader.DownloaderFactory;
import org.schabi.newpipe.downloader.MockOnly;
import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.MetaInfo; import org.schabi.newpipe.extractor.MetaInfo;
@ -28,12 +27,11 @@ import org.schabi.newpipe.extractor.services.DefaultSearchExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.YoutubeTestsUtils; import org.schabi.newpipe.extractor.services.youtube.YoutubeTestsUtils;
import org.schabi.newpipe.extractor.stream.Description; import org.schabi.newpipe.extractor.stream.Description;
import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.utils.Utils;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -139,15 +137,15 @@ public class YoutubeSearchExtractorTest {
/** /**
* Test for YT's "Did you mean...". * Test for YT's "Did you mean...".
*
* <p> * <p>
* Hint: YT mostly shows "did you mean..." when you are searching in another language. * Hint: YT mostly shows "did you mean..." when you are searching in another language.
* </p> * </p>
*/ */
@MockOnly("Currently constantly switching between \"Did you mean\" and \"Showing results for ...\" occurs")
public static class Suggestion extends DefaultSearchExtractorTest { public static class Suggestion extends DefaultSearchExtractorTest {
private static SearchExtractor extractor; private static SearchExtractor extractor;
private static final String QUERY = "algorythm"; private static final String QUERY = "on board ing";
private static final String EXPECTED_SUGGESTION = "algorithm"; private static final String EXPECTED_SUGGESTION = "on boarding";
@BeforeAll @BeforeAll
public static void setUp() throws Exception { public static void setUp() throws Exception {
@ -161,8 +159,8 @@ public class YoutubeSearchExtractorTest {
@Override public StreamingService expectedService() { return YouTube; } @Override public StreamingService expectedService() { return YouTube; }
@Override public String expectedName() { return QUERY; } @Override public String expectedName() { return QUERY; }
@Override public String expectedId() { return QUERY; } @Override public String expectedId() { return QUERY; }
@Override public String expectedUrlContains() { return "youtube.com/results?search_query=" + QUERY; } @Override public String expectedUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + QUERY; } @Override public String expectedOriginalUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
@Override public String expectedSearchString() { return QUERY; } @Override public String expectedSearchString() { return QUERY; }
@Nullable @Override public String expectedSearchSuggestion() { return EXPECTED_SUGGESTION; } @Nullable @Override public String expectedSearchSuggestion() { return EXPECTED_SUGGESTION; }
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; } @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@ -396,20 +394,12 @@ public class YoutubeSearchExtractorTest {
extractor.fetchPage(); extractor.fetchPage();
} }
private String getUrlEncodedQuery() {
try {
return URLEncoder.encode(QUERY, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
@Override public SearchExtractor extractor() { return extractor; } @Override public SearchExtractor extractor() { return extractor; }
@Override public StreamingService expectedService() { return YouTube; } @Override public StreamingService expectedService() { return YouTube; }
@Override public String expectedName() { return QUERY; } @Override public String expectedName() { return QUERY; }
@Override public String expectedId() { return QUERY; } @Override public String expectedId() { return QUERY; }
@Override public String expectedUrlContains() { return "youtube.com/results?search_query=" + getUrlEncodedQuery(); } @Override public String expectedUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
@Override public String expectedOriginalUrlContains() { return "youtube.com/results?search_query=" + getUrlEncodedQuery(); } @Override public String expectedOriginalUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
@Override public String expectedSearchString() { return QUERY; } @Override public String expectedSearchString() { return QUERY; }
@Nullable @Override public String expectedSearchSuggestion() { return null; } @Nullable @Override public String expectedSearchSuggestion() { return null; }
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; } @Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
@ -424,4 +414,37 @@ public class YoutubeSearchExtractorTest {
.anyMatch(StreamInfoItem::isShortFormContent)); .anyMatch(StreamInfoItem::isShortFormContent));
} }
} }
/**
* A {@link SearchExtractor} test to check if crisis resources preventing search results to be
* returned are bypassed (searches with content filters are not tested in this test, even if
* they should work as bypasses are used with them too).
*
* <p>
* See <a href="https://support.google.com/youtube/answer/10726080?hl=en">
* https://support.google.com/youtube/answer/10726080?hl=en</a> for more info on crisis
* resources.
* </p>
*/
public static class CrisisResources extends DefaultSearchExtractorTest {
private static SearchExtractor extractor;
private static final String QUERY = "blue whale";
@BeforeAll
public static void setUp() throws Exception {
YoutubeTestsUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "crisis_resources"));
extractor = YouTube.getSearchExtractor(QUERY);
extractor.fetchPage();
}
@Override public SearchExtractor extractor() { return extractor; }
@Override public StreamingService expectedService() { return YouTube; }
@Override public String expectedName() { return QUERY; }
@Override public String expectedId() { return QUERY; }
@Override public String expectedUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
@Override public String expectedOriginalUrlContains() throws Exception { return "youtube.com/results?search_query=" + Utils.encodeUrlUtf8(QUERY); }
@Override public String expectedSearchString() { return QUERY; }
@Nullable @Override public String expectedSearchSuggestion() { return null; }
}
} }

View File

@ -14,11 +14,11 @@ public class YoutubeSearchQHTest {
@Test @Test
public void testRegularValues() throws Exception { public void testRegularValues() throws Exception {
assertEquals("https://www.youtube.com/results?search_query=asdf", YouTube.getSearchQHFactory().fromQuery("asdf").getUrl()); assertEquals("https://www.youtube.com/results?search_query=asdf&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("asdf").getUrl());
assertEquals("https://www.youtube.com/results?search_query=hans", YouTube.getSearchQHFactory().fromQuery("hans").getUrl()); assertEquals("https://www.youtube.com/results?search_query=hans&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("hans").getUrl());
assertEquals("https://www.youtube.com/results?search_query=Poifj%26jaijf", YouTube.getSearchQHFactory().fromQuery("Poifj&jaijf").getUrl()); assertEquals("https://www.youtube.com/results?search_query=Poifj%26jaijf&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("Poifj&jaijf").getUrl());
assertEquals("https://www.youtube.com/results?search_query=G%C3%BCl%C3%BCm", YouTube.getSearchQHFactory().fromQuery("Gülüm").getUrl()); assertEquals("https://www.youtube.com/results?search_query=G%C3%BCl%C3%BCm&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("Gülüm").getUrl());
assertEquals("https://www.youtube.com/results?search_query=%3Fj%24%29H%C2%A7B", YouTube.getSearchQHFactory().fromQuery("?j$)H§B").getUrl()); assertEquals("https://www.youtube.com/results?search_query=%3Fj%24%29H%C2%A7B&sp=8AEB", YouTube.getSearchQHFactory().fromQuery("?j$)H§B").getUrl());
assertEquals("https://music.youtube.com/search?q=asdf", YouTube.getSearchQHFactory().fromQuery("asdf", asList(new String[]{MUSIC_SONGS}), "").getUrl()); assertEquals("https://music.youtube.com/search?q=asdf", YouTube.getSearchQHFactory().fromQuery("asdf", asList(new String[]{MUSIC_SONGS}), "").getUrl());
assertEquals("https://music.youtube.com/search?q=hans", YouTube.getSearchQHFactory().fromQuery("hans", asList(new String[]{MUSIC_SONGS}), "").getUrl()); assertEquals("https://music.youtube.com/search?q=hans", YouTube.getSearchQHFactory().fromQuery("hans", asList(new String[]{MUSIC_SONGS}), "").getUrl());
@ -40,13 +40,13 @@ public class YoutubeSearchQHTest {
@Test @Test
public void testWithContentfilter() throws Exception { public void testWithContentfilter() throws Exception {
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAQ%253D%253D", YouTube.getSearchQHFactory() assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAfABAQ%253D%253D", YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{VIDEOS}), "").getUrl()); .fromQuery("asdf", asList(new String[]{VIDEOS}), "").getUrl());
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAg%253D%253D", YouTube.getSearchQHFactory() assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAvABAQ%253D%253D", YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{CHANNELS}), "").getUrl()); .fromQuery("asdf", asList(new String[]{CHANNELS}), "").getUrl());
assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQAw%253D%253D", YouTube.getSearchQHFactory() assertEquals("https://www.youtube.com/results?search_query=asdf&sp=EgIQA_ABAQ%253D%253D", YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{PLAYLISTS}), "").getUrl()); .fromQuery("asdf", asList(new String[]{PLAYLISTS}), "").getUrl());
assertEquals("https://www.youtube.com/results?search_query=asdf", YouTube.getSearchQHFactory() assertEquals("https://www.youtube.com/results?search_query=asdf&sp=8AEB", YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{"fjiijie"}), "").getUrl()); .fromQuery("asdf", asList(new String[]{"fjiijie"}), "").getUrl());
assertEquals("https://music.youtube.com/search?q=asdf", YouTube.getSearchQHFactory() assertEquals("https://music.youtube.com/search?q=asdf", YouTube.getSearchQHFactory()

View File

@ -48,8 +48,8 @@ public class YoutubeStreamExtractorAgeRestrictedTest extends DefaultStreamExtrac
@Override public long expectedLength() { return 10; } @Override public long expectedLength() { return 10; }
@Override public long expectedTimestamp() { return TIMESTAMP; } @Override public long expectedTimestamp() { return TIMESTAMP; }
@Override public long expectedViewCountAtLeast() { return 232_000; } @Override public long expectedViewCountAtLeast() { return 232_000; }
@Nullable @Override public String expectedUploadDate() { return "2018-03-11 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2018-03-11 19:22:08.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2018-03-11"; } @Nullable @Override public String expectedTextualUploadDate() { return "2018-03-11T12:22:08-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 3_700; } @Override public long expectedLikeCountAtLeast() { return 3_700; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public boolean expectedHasRelatedItems() { return false; } // no related videos (!) @Override public boolean expectedHasRelatedItems() { return false; } // no related videos (!)

View File

@ -52,8 +52,8 @@ public class YoutubeStreamExtractorControversialTest extends DefaultStreamExtrac
} }
@Override public long expectedLength() { return 219; } @Override public long expectedLength() { return 219; }
@Override public long expectedViewCountAtLeast() { return 285000; } @Override public long expectedViewCountAtLeast() { return 285000; }
@Nullable @Override public String expectedUploadDate() { return "2010-09-09 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2010-09-09 15:40:44.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2010-09-09"; } @Nullable @Override public String expectedTextualUploadDate() { return "2010-09-09T08:40:44-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 13300; } @Override public long expectedLikeCountAtLeast() { return 13300; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public List<String> expectedTags() { return Arrays.asList("Books", "Burning", "Jones", "Koran", "Qur'an", "Terry", "the amazing atheist"); } @Override public List<String> expectedTags() { return Arrays.asList("Books", "Burning", "Jones", "Koran", "Qur'an", "Terry", "the amazing atheist"); }

View File

@ -151,8 +151,8 @@ public class YoutubeStreamExtractorDefaultTest {
@Override public long expectedLength() { return 381; } @Override public long expectedLength() { return 381; }
@Override public long expectedTimestamp() { return TIMESTAMP; } @Override public long expectedTimestamp() { return TIMESTAMP; }
@Override public long expectedViewCountAtLeast() { return 26682500; } @Override public long expectedViewCountAtLeast() { return 26682500; }
@Nullable @Override public String expectedUploadDate() { return "2019-08-24 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2019-08-24 15:39:57.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2019-08-24"; } @Nullable @Override public String expectedTextualUploadDate() { return "2019-08-24T08:39:57-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 5212900; } @Override public long expectedLikeCountAtLeast() { return 5212900; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public int expectedStreamSegmentsCount() { return 0; } @Override public int expectedStreamSegmentsCount() { return 0; }
@ -194,8 +194,8 @@ public class YoutubeStreamExtractorDefaultTest {
} }
@Override public long expectedLength() { return 434; } @Override public long expectedLength() { return 434; }
@Override public long expectedViewCountAtLeast() { return 21229200; } @Override public long expectedViewCountAtLeast() { return 21229200; }
@Nullable @Override public String expectedUploadDate() { return "2018-06-19 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2018-06-19 19:41:34.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2018-06-19"; } @Nullable @Override public String expectedTextualUploadDate() { return "2018-06-19T12:41:34-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 340100; } @Override public long expectedLikeCountAtLeast() { return 340100; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public boolean expectedUploaderVerified() { return true; } @Override public boolean expectedUploaderVerified() { return true; }
@ -212,9 +212,8 @@ public class YoutubeStreamExtractorDefaultTest {
// @formatter:on // @formatter:on
} }
@Disabled("Test broken, video was made private")
public static class RatingsDisabledTest extends DefaultStreamExtractorTest { public static class RatingsDisabledTest extends DefaultStreamExtractorTest {
private static final String ID = "HRKu0cvrr_o"; private static final String ID = "it3OtbTxQk0";
private static final int TIMESTAMP = 17; private static final int TIMESTAMP = 17;
private static final String URL = BASE_URL + ID + "&t=" + TIMESTAMP; private static final String URL = BASE_URL + ID + "&t=" + TIMESTAMP;
private static StreamExtractor extractor; private static StreamExtractor extractor;
@ -230,22 +229,25 @@ public class YoutubeStreamExtractorDefaultTest {
// @formatter:off // @formatter:off
@Override public StreamExtractor extractor() { return extractor; } @Override public StreamExtractor extractor() { return extractor; }
@Override public StreamingService expectedService() { return YouTube; } @Override public StreamingService expectedService() { return YouTube; }
@Override public String expectedName() { return "AlphaOmegaSin Fanboy Logic: Likes/Dislikes Disabled = Point Invalid Lol wtf?"; } @Override public String expectedName() { return "Introduction to Doodle for Google 2023"; }
@Override public String expectedId() { return ID; } @Override public String expectedId() { return ID; }
@Override public String expectedUrlContains() { return BASE_URL + ID; } @Override public String expectedUrlContains() { return BASE_URL + ID; }
@Override public String expectedOriginalUrlContains() { return URL; } @Override public String expectedOriginalUrlContains() { return URL; }
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; } @Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
@Override public String expectedUploaderName() { return "YouTuber PrinceOfFALLEN"; } @Override public String expectedUploaderName() { return "GoogleDoodles"; }
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCQT2yul0lr6Ie9qNQNmw-sg"; } @Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCdq61m8s_48EhJ5OM_MCeGw"; }
@Override public List<String> expectedDescriptionContains() { return Arrays.asList("dislikes", "Alpha", "wrong"); } @Override public long expectedUploaderSubscriberCountAtLeast() { return 2270000; }
@Override public long expectedLength() { return 84; } @Override public List<String> expectedDescriptionContains() { return Arrays.asList("Doodle", "Google", "video"); }
@Override public long expectedLength() { return 145; }
@Override public long expectedTimestamp() { return TIMESTAMP; } @Override public long expectedTimestamp() { return TIMESTAMP; }
@Override public long expectedViewCountAtLeast() { return 190; } @Override public long expectedViewCountAtLeast() { return 40000; }
@Nullable @Override public String expectedUploadDate() { return "2019-01-02 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2023-01-13 21:53:57.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2019-01-02"; } @Nullable @Override public String expectedTextualUploadDate() { return "2023-01-13T13:53:57-08:00"; }
@Override public long expectedLikeCountAtLeast() { return -1; } @Override public long expectedLikeCountAtLeast() { return -1; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public String expectedLicence() { return YOUTUBE_LICENCE; }
@Override public String expectedCategory() { return "Education"; }
// @formatter:on // @formatter:on
} }
@ -281,8 +283,8 @@ public class YoutubeStreamExtractorDefaultTest {
} }
@Override public long expectedLength() { return 953; } @Override public long expectedLength() { return 953; }
@Override public long expectedViewCountAtLeast() { return 270000; } @Override public long expectedViewCountAtLeast() { return 270000; }
@Nullable @Override public String expectedUploadDate() { return "2021-03-17 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2021-03-17 19:56:59.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2021-03-17"; } @Nullable @Override public String expectedTextualUploadDate() { return "2021-03-17T12:56:59-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 2300; } @Override public long expectedLikeCountAtLeast() { return 2300; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public boolean expectedHasSubtitles() { return false; } @Override public boolean expectedHasSubtitles() { return false; }
@ -340,11 +342,10 @@ public class YoutubeStreamExtractorDefaultTest {
@Override public boolean expectedUploaderVerified() { return true; } @Override public boolean expectedUploaderVerified() { return true; }
@Override public long expectedLength() { return 1010; } @Override public long expectedLength() { return 1010; }
@Override public long expectedViewCountAtLeast() { return 815500; } @Override public long expectedViewCountAtLeast() { return 815500; }
@Nullable @Override public String expectedUploadDate() { return "2020-11-18 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2020-11-19 05:30:01.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2020-11-18"; } @Nullable @Override public String expectedTextualUploadDate() { return "2020-11-18T21:30:01-08:00"; }
@Override public long expectedLikeCountAtLeast() { return 48500; } @Override public long expectedLikeCountAtLeast() { return 48500; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public boolean expectedHasSubtitles() { return true; }
@Override public int expectedStreamSegmentsCount() { return 7; } @Override public int expectedStreamSegmentsCount() { return 7; }
@Override public String expectedLicence() { return YOUTUBE_LICENCE; } @Override public String expectedLicence() { return YOUTUBE_LICENCE; }
@Override public String expectedCategory() { return "Science & Technology"; } @Override public String expectedCategory() { return "Science & Technology"; }
@ -408,8 +409,8 @@ public class YoutubeStreamExtractorDefaultTest {
@Override public long expectedLength() { return 45; } @Override public long expectedLength() { return 45; }
@Override public long expectedTimestamp() { return TIMESTAMP; } @Override public long expectedTimestamp() { return TIMESTAMP; }
@Override public long expectedViewCountAtLeast() { return 20_000; } @Override public long expectedViewCountAtLeast() { return 20_000; }
@Nullable @Override public String expectedUploadDate() { return "2023-07-07 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2023-07-07 15:30:08.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2023-07-07"; } @Nullable @Override public String expectedTextualUploadDate() { return "2023-07-07T08:30:08-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 1000; } @Override public long expectedLikeCountAtLeast() { return 1000; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public List<MetaInfo> expectedMetaInfo() throws MalformedURLException { @Override public List<MetaInfo> expectedMetaInfo() throws MalformedURLException {
@ -453,8 +454,8 @@ public class YoutubeStreamExtractorDefaultTest {
@Override public List<String> expectedDescriptionContains() { return Arrays.asList("Makani", "prototype", "rotors"); } @Override public List<String> expectedDescriptionContains() { return Arrays.asList("Makani", "prototype", "rotors"); }
@Override public long expectedLength() { return 175; } @Override public long expectedLength() { return 175; }
@Override public long expectedViewCountAtLeast() { return 88_000; } @Override public long expectedViewCountAtLeast() { return 88_000; }
@Nullable @Override public String expectedUploadDate() { return "2017-05-16 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2017-05-16 14:50:53.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2017-05-16"; } @Nullable @Override public String expectedTextualUploadDate() { return "2017-05-16T07:50:53-07:00"; }
@Override public long expectedLikeCountAtLeast() { return -1; } @Override public long expectedLikeCountAtLeast() { return -1; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public StreamExtractor extractor() { return extractor; } @Override public StreamExtractor extractor() { return extractor; }

View File

@ -57,8 +57,8 @@ public class YoutubeStreamExtractorLivestreamTest extends DefaultStreamExtractor
@Override public long expectedLength() { return 0; } @Override public long expectedLength() { return 0; }
@Override public long expectedTimestamp() { return TIMESTAMP; } @Override public long expectedTimestamp() { return TIMESTAMP; }
@Override public long expectedViewCountAtLeast() { return 0; } @Override public long expectedViewCountAtLeast() { return 0; }
@Nullable @Override public String expectedUploadDate() { return "2022-07-12 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2022-07-12 12:12:29.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2022-07-12"; } @Nullable @Override public String expectedTextualUploadDate() { return "2022-07-12T05:12:29-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 340_000; } @Override public long expectedLikeCountAtLeast() { return 340_000; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public boolean expectedHasSubtitles() { return false; } @Override public boolean expectedHasSubtitles() { return false; }

View File

@ -4,11 +4,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertSame;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains; import static org.schabi.newpipe.extractor.ExtractorAsserts.assertContains;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertGreaterOrEqual;
import static org.schabi.newpipe.extractor.ServiceList.YouTube; import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.youtube.stream.YoutubeStreamExtractorDefaultTest.YOUTUBE_LICENCE; import static org.schabi.newpipe.extractor.services.youtube.stream.YoutubeStreamExtractorDefaultTest.YOUTUBE_LICENCE;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderFactory; import org.schabi.newpipe.downloader.DownloaderFactory;
import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.InfoItem;
@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo.PlaylistType; import org.schabi.newpipe.extractor.playlist.PlaylistInfo.PlaylistType;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
import org.schabi.newpipe.extractor.services.DefaultStreamExtractorTest; import org.schabi.newpipe.extractor.services.DefaultStreamExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.services.youtube.YoutubeTestsUtils; import org.schabi.newpipe.extractor.services.youtube.YoutubeTestsUtils;
import org.schabi.newpipe.extractor.stream.StreamExtractor; import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.extractor.stream.StreamType;
@ -30,14 +31,15 @@ import javax.annotation.Nullable;
public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractorTest { public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractorTest {
private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH + "services/youtube/extractor/stream/"; private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH + "services/youtube/extractor/stream/";
static final String ID = "K4DyBUG242c"; private static final String ID = "K4DyBUG242c";
static final String URL = YoutubeStreamExtractorDefaultTest.BASE_URL + ID; private static final String URL = YoutubeStreamExtractorDefaultTest.BASE_URL + ID;
static final String TITLE = "Cartoon - On & On (feat. Daniel Levi) [NCS Release]"; private static final String TITLE = "Cartoon - On & On (feat. Daniel Levi) | Electronic Pop | NCS - Copyright Free Music";
private static StreamExtractor extractor; private static StreamExtractor extractor;
@BeforeAll @BeforeAll
public static void setUp() throws Exception { public static void setUp() throws Exception {
YoutubeTestsUtils.ensureStateless(); YoutubeTestsUtils.ensureStateless();
YoutubeParsingHelper.setConsentAccepted(true);
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "relatedMix")); NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "relatedMix"));
extractor = YouTube.getStreamExtractor(URL); extractor = YouTube.getStreamExtractor(URL);
extractor.fetchPage(); extractor.fetchPage();
@ -60,30 +62,26 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
@Override public boolean expectedUploaderVerified() { return true; } @Override public boolean expectedUploaderVerified() { return true; }
@Override public long expectedUploaderSubscriberCountAtLeast() { return 32_000_000; } @Override public long expectedUploaderSubscriberCountAtLeast() { return 32_000_000; }
@Override public long expectedLength() { return 208; } @Override public long expectedLength() { return 208; }
@Override public long expectedTimestamp() { return 0; }
@Override public long expectedViewCountAtLeast() { return 449_000_000; } @Override public long expectedViewCountAtLeast() { return 449_000_000; }
@Nullable @Override public String expectedUploadDate() { return "2015-07-09 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2015-07-09 16:34:35.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2015-07-09"; } @Nullable @Override public String expectedTextualUploadDate() { return "2015-07-09T09:34:35-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 6_400_000; } @Override public long expectedLikeCountAtLeast() { return 6_400_000; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public boolean expectedHasSubtitles() { return true; }
@Override public int expectedStreamSegmentsCount() { return 0; } @Override public int expectedStreamSegmentsCount() { return 0; }
@Override public String expectedLicence() { return YOUTUBE_LICENCE; } @Override public String expectedLicence() { return YOUTUBE_LICENCE; }
@Override public String expectedCategory() { return "Music"; } @Override public String expectedCategory() { return "Music"; }
@Override public List<String> expectedTags() { @Override public List<String> expectedTags() {
return Arrays.asList("Cartoon", "Cartoon - On & On", "Cartoon Baboon", return Arrays.asList("Cartoon On & On (feat. Daniel Levi)", "Cartoon - On & On", "Cartoon",
"Cartoon NCS Release", "Cartoon On & On (feat. Daniel Levi)", "Cartoon best songs", "On & On", "NCS", "nocopyrightsounds", "no copyright sounds", "NCS release Cartoon",
"Copyright Free Music", "Daniel Levi", "NCS", "NCS Best Songs", "NCS Release Daniel Levi", "Daniel Levi", "NCS Release", "NCS Cartoon On & On",
"NCS Cartoon Daniel Levi", "NCS Cartoon On & On", "NCS On & On", "NCS On and On", "NCS On and On", "NCS On & On", "NCS Best Songs", "NCS Cartoon Daniel Levi",
"NCS Release", "NCS Release Daniel Levi", "NCS release Cartoon", "Official", "music", "songs", "ncs", "edm", "best music", "top music", "free music",
"On & On", "On & On NCS", "On and on", "Royalty Free Cartoon", "Royalty Free Music", "club music", "dance music", "no copyright music", "electronic music",
"electronic", "no copyright sounds", "nocopyrightsounds", "on & on lyrics", "royalty free music", "copyright free music", "gaming music", "electronic pop");
"on and on lyrics");
} }
// @formatter:on // @formatter:on
@Test @Test
@Disabled("Mixes are not available in related items anymore, see https://github.com/TeamNewPipe/NewPipeExtractor/issues/820")
@Override @Override
public void testRelatedItems() throws Exception { public void testRelatedItems() throws Exception {
super.testRelatedItems(); super.testRelatedItems();
@ -100,7 +98,7 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
final List<PlaylistInfoItem> streamMixes = playlists.stream() final List<PlaylistInfoItem> streamMixes = playlists.stream()
.filter(item -> item.getPlaylistType().equals(PlaylistType.MIX_STREAM)) .filter(item -> item.getPlaylistType().equals(PlaylistType.MIX_STREAM))
.collect(Collectors.toList()); .collect(Collectors.toList());
assertEquals(1, streamMixes.size(), "Not found exactly one stream mix in related items"); assertGreaterOrEqual(1, streamMixes.size(), "Not found one or more stream mix in related items");
final PlaylistInfoItem streamMix = streamMixes.get(0); final PlaylistInfoItem streamMix = streamMixes.get(0);
assertSame(InfoItem.InfoType.PLAYLIST, streamMix.getInfoType()); assertSame(InfoItem.InfoType.PLAYLIST, streamMix.getInfoType());
@ -109,17 +107,5 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
assertContains("list=RD" + ID, streamMix.getUrl()); assertContains("list=RD" + ID, streamMix.getUrl());
assertEquals("Mix " + TITLE, streamMix.getName()); assertEquals("Mix " + TITLE, streamMix.getName());
YoutubeTestsUtils.testImages(streamMix.getThumbnails()); YoutubeTestsUtils.testImages(streamMix.getThumbnails());
final List<PlaylistInfoItem> musicMixes = playlists.stream()
.filter(item -> item.getPlaylistType().equals(PlaylistType.MIX_MUSIC))
.collect(Collectors.toList());
assertEquals(1, musicMixes.size(), "Not found exactly one music mix in related items");
final PlaylistInfoItem musicMix = musicMixes.get(0);
assertSame(InfoItem.InfoType.PLAYLIST, musicMix.getInfoType());
assertEquals(YouTube.getServiceId(), musicMix.getServiceId());
assertContains("list=RDCLAK", musicMix.getUrl());
assertEquals("Hip Hop Essentials", musicMix.getName());
YoutubeTestsUtils.testImages(musicMix.getThumbnails());
} }
} }

View File

@ -48,8 +48,8 @@ public class YoutubeStreamExtractorUnlistedTest extends DefaultStreamExtractorTe
} }
@Override public long expectedLength() { return 2488; } @Override public long expectedLength() { return 2488; }
@Override public long expectedViewCountAtLeast() { return 1500; } @Override public long expectedViewCountAtLeast() { return 1500; }
@Nullable @Override public String expectedUploadDate() { return "2017-09-22 00:00:00.000"; } @Nullable @Override public String expectedUploadDate() { return "2017-09-22 12:15:21.000"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2017-09-22"; } @Nullable @Override public String expectedTextualUploadDate() { return "2017-09-22T05:15:21-07:00"; }
@Override public long expectedLikeCountAtLeast() { return 110; } @Override public long expectedLikeCountAtLeast() { return 110; }
@Override public long expectedDislikeCountAtLeast() { return -1; } @Override public long expectedDislikeCountAtLeast() { return -1; }
@Override public StreamExtractor.Privacy expectedPrivacy() { return UNLISTED; } @Override public StreamExtractor.Privacy expectedPrivacy() { return UNLISTED; }

View File

@ -3,10 +3,10 @@
"httpMethod": "GET", "httpMethod": "GET",
"url": "https://www.youtube.com/sw.js", "url": "https://www.youtube.com/sw.js",
"headers": { "headers": {
"Referer": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Origin": [ "Referer": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Accept-Language": [ "Accept-Language": [
@ -41,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sun, 16 Apr 2023 17:42:25 GMT" "Fri, 08 Dec 2023 19:39:00 GMT"
], ],
"expires": [ "expires": [
"Sun, 16 Apr 2023 17:42:25 GMT" "Fri, 08 Dec 2023 19:39:00 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -53,7 +53,7 @@
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\"" "CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
], ],
"permissions-policy": [ "permissions-policy": [
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*" "ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-form-factor\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
], ],
"report-to": [ "report-to": [
"{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}" "{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003deNq1o5_KNzg; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dnlRwmbCXdxA; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 20-Jul-2020 17:42:25 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+549; expires\u003dTue, 15-Apr-2025 17:42:25 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+731; expires\u003dSun, 07-Dec-2025 19:39:00 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "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

View File

@ -3,10 +3,10 @@
"httpMethod": "GET", "httpMethod": "GET",
"url": "https://www.youtube.com/sw.js", "url": "https://www.youtube.com/sw.js",
"headers": { "headers": {
"Referer": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Origin": [ "Referer": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Accept-Language": [ "Accept-Language": [
@ -41,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:07:42 GMT" "Fri, 08 Dec 2023 19:37:59 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:07:42 GMT" "Fri, 08 Dec 2023 19:37:59 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003d6HVY0O6Qgzk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003diKlrQNgJqEI; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:07:42 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+865; expires\u003dMon, 14-Jul-2025 22:07:42 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+197; expires\u003dSun, 07-Dec-2025 19:37:59 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -3,17 +3,17 @@
"httpMethod": "POST", "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?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse",
"headers": { "headers": {
"Referer": [
"https://www.youtube.com"
],
"Origin": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Referer": [
"https://www.youtube.com"
],
"Cookie": [ "Cookie": [
"CONSENT\u003dPENDING+488" "SOCS\u003dCAE\u003d"
], ],
"X-YouTube-Client-Version": [ "X-YouTube-Client-Version": [
"2.20230714.00.00" "2.20231208.01.00"
], ],
"X-YouTube-Client-Name": [ "X-YouTube-Client-Name": [
"1" "1"
@ -104,6 +104,27 @@
58, 58,
123, 123,
34, 34,
117,
116,
99,
79,
102,
102,
115,
101,
116,
77,
105,
110,
117,
116,
101,
115,
34,
58,
48,
44,
34,
104, 104,
108, 108,
34, 34,
@ -208,13 +229,13 @@
48, 48,
50, 50,
51, 51,
48,
55,
49, 49,
52, 50,
48,
56,
46, 46,
48, 48,
48, 49,
46, 46,
48, 48,
48, 48,
@ -341,11 +362,20 @@
"application/json; charset\u003dUTF-8" "application/json; charset\u003dUTF-8"
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:07:43 GMT" "Fri, 08 Dec 2023 19:37:59 GMT"
],
"expires": [
"Fri, 08 Dec 2023 19:37:59 GMT"
],
"p3p": [
"CP\u003d\"This is not a P3P policy! See g.co/p3phelp for more info.\""
], ],
"server": [ "server": [
"scaffolding on HTTPServer2" "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": [ "vary": [
"Origin", "Origin",
"X-Origin", "X-Origin",
@ -361,7 +391,7 @@
"0" "0"
] ]
}, },
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtVYTNwX0RQclVkNCivscylBg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20230714.00.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x302b0c7f330dbc2b\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"9407156,23804281,23930656,23946420,23966208,23983296,23986027,23998056,24004644,24007246,24034168,24036947,24077241,24080738,24120819,24135310,24140247,24166867,24181174,24187377,24211178,24216872,24219713,24241378,24255543,24255545,24262346,24279930,24288664,24290971,24291857,24362099,24362687,24364439,24364789,24365607,24366011,24366065,24366917,24367686,24367742,24368306,24370597,24371398,24371637,24372103,24372108,24373977,24374313,24379041,24379065,24379129,24379354,24379527,24379542,24379964,24379967,24380264,24381717,24382551,24383022,24383135,24383600,24383853,24384531,24385289,24385612,24386397,24386797,24388532,24388704,24388718,24388731,24388750,24388761,24389132,24390675,24404640,24407191,24415864,24416291,24428788,24437577,24439361,24440132,24451319,24453989,24457384,24457856,24458839,24459435,24466371,24466624,24468724,24469818,24485421,24490423,24495060,24498300,24499532,24502747,24503257,24504481,24504573,24506691,24506784,24506907,24506924,24509766,24515366,24515388,24515423,24518452,24519102,24520237,24522902,24523472,24524131,24525366,24525926,24526198,24526574,24528693,24537200,24550285,24550458,24550952,24551130,24552606,24553434,24554040,24554048,24557645,24559261,24559328,24690006,24691334,24695664,24696752,24698453,24698880,24699598,24699860,24699899,39324156\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20230714\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"24379967,24696752,9407156,24416291,24386797,24528693,24537200,24506784,24385289,23804281,23946420,24506907,24698880,24506691,24407191,24499532,24390675,24386397,24255545,24453989,24120819,24004644,24466371,24372103,24526198,24553434,24290971,24385612,23983296,24388704,24383600,24519102,24379041,24371398,24077241,24550285,24140247,24388532,24368306,24187377,24550458,24381717,24279930,24382551,24552606,24495060,24036947,24525926,23998056,24504481,24007246,24388750,24380264,24699598,24135310,24457384,24695664,24459435,24255543,24520237,24362099,24166867,24440132,24262346,24690006,24364789,24525366,24526574,24502747,24550952,24372108,24466624,24504573,24379129,24490423,24523472,24366917,24367686,24366011,24383853,24503257,24439361,24468724,24379065,23930656,24518452,24370597,24458839,24367742,24373977,24559328,24699899,24379964,24557645,24691334,24383135,24485421,24384531,24365607,24524131,24515388,24415864,24389132,24522902,24698453,24551130,24509766,24379354,24469818,24362687,24241378,24383022,24216872,24288664,24374313,24515423,24379527,24428788,24498300,24080738,24364439,24388761,24515366,24404640,24554048,24451319,24559261,24388718,24219713,24437577,23966208,24034168,24379542,39324156,24388731,24211178,24554040,24371637,24457856,24181174,24506924,23986027,24366065,24699860,24291857\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIppyt29yRgAMVwj3xBR20xA8jMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UC6nSFpj9HTCZ5t-N3Rm3-HA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}", "responseBody": "{\"responseContext\":{\"visitorData\":\"CgtVb3ZBRFhqU1NOTSiX4c2rBjIICgJGUhICEgA%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20231208.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x918e2dd007736ced\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23946420,23966208,23983296,23986028,23998056,24004644,24007246,24034168,24036948,24060815,24077241,24080738,24120819,24135310,24140247,24166867,24181174,24187377,24241378,24255543,24255545,24288664,24290971,24291857,24367579,24371778,24377598,24377910,24382552,24385728,24387949,24390675,24428788,24428941,24428945,24428949,24439361,24451319,24453989,24458839,24468724,24485421,24506515,24506784,24515423,24518452,24524098,24526515,24537200,24539025,24542367,24542452,24546075,24548627,24548629,24549786,24550458,24559327,24560416,24563005,24566293,24566687,24583802,24585907,24589493,24694842,24697069,24698452,24699899,39324156,51000012,51003636,51004018,51006176,51006181,51009781,51009900,51010235,51012165,51012291,51012659,51014091,51016856,51017346,51019626,51020570,51021953,51024416,51025415,51026715,51027696,51027870,51028271,51029412,51033399,51033577,51036511,51037540,51038399,51038805,51039200,51039493,51041497,51041809,51043774,51045888,51045969,51047579,51048489,51049006,51051343,51053689,51053957,51055917,51056262,51056268,51057501,51057534,51057746,51059323,51059572,51061018,51061427,51061926,51063327,51063643,51065651,51066749,51068528,51068752,51069269,51069319,51069593,51070193,51070203,51070731,51071181,51071412,51072197,51072748,51073039,51073316,51073892,51074183,51074391,51074661,51074821,51076265,51076445,51078467,51079353,51080181\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20231208\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"24377910,51026715,51073039,51045888,24255545,24036948,39324156,51070731,24241378,51057746,24518452,51043774,24559327,24485421,51074391,51027870,51053957,24367579,51041497,51009781,51072197,23998056,51047579,51059572,51016856,24542367,24506784,51057501,24428945,51078467,51010235,51028271,24255543,51069269,51071412,51069593,51069319,51068528,51059323,24526515,51074821,24007246,24428949,24549786,51027696,24699899,51012291,24371778,24583802,24135310,24548629,24506515,51033399,24524098,24560416,51019626,51073892,24166867,24542452,51070203,51068752,51045969,51037540,24385728,51036511,24120819,51017346,24453989,51012659,51076445,24546075,51071181,24077241,24439361,24060815,51076265,51038805,51079353,24187377,24390675,23804281,51039200,51073316,24004644,51051343,51063327,51014091,51074661,24694842,24382552,51006181,24548627,51029412,24034168,51057534,24537200,24585907,24563005,24698452,51033577,51072748,51065651,51056268,51080181,24428941,24291857,24566687,24468724,51012165,51025415,24515423,24288664,23946420,24377598,51020570,51061926,51049006,51004018,24181174,51024416,51053689,24140247,51061427,51021953,51039493,51041809,51000012,23966208,23986028,51009900,51048489,24589493,51006176,24080738,51003636,24451319,24697069,51038399,24428788,24550458,24539025,23983296,51061018,24566293,24387949,51055917,24458839,51074183,51063643,51056262,24290971,51066749,51070193\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMI4OydxsuAgwMVNFRPBB3OEgkqMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UC6nSFpj9HTCZ5t-N3Rm3-HA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse" "latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse"
} }
} }

View File

@ -41,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:08:17 GMT" "Fri, 08 Dec 2023 19:37:52 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:08:17 GMT" "Fri, 08 Dec 2023 19:37:52 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dN_LdAqhQwJo; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dZrg1hMAzzPk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:08:17 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+052; expires\u003dMon, 14-Jul-2025 22:08:17 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+514; expires\u003dSun, 07-Dec-2025 19:37:52 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -29,7 +29,7 @@
"https://www.youtube.com" "https://www.youtube.com"
], ],
"alt-svc": [ "alt-svc": [
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000,h3-Q050\u003d\":443\"; ma\u003d2592000,h3-Q046\u003d\":443\"; ma\u003d2592000,h3-Q043\u003d\":443\"; ma\u003d2592000,quic\u003d\":443\"; ma\u003d2592000; v\u003d\"46,43\"" "h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000"
], ],
"cache-control": [ "cache-control": [
"private, max-age\u003d0" "private, max-age\u003d0"
@ -37,20 +37,23 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Tue, 22 Nov 2022 10:40:04 GMT" "Fri, 08 Dec 2023 19:37:53 GMT"
], ],
"expires": [ "expires": [
"Tue, 22 Nov 2022 10:40:04 GMT" "Fri, 08 Dec 2023 19:37:53 GMT"
],
"origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
], ],
"p3p": [ "p3p": [
"CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\"" "CP\u003d\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl\u003den-GB for more info.\""
], ],
"permissions-policy": [ "permissions-policy": [
"ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*" "ch-ua-arch\u003d*, ch-ua-bitness\u003d*, ch-ua-full-version\u003d*, ch-ua-full-version-list\u003d*, ch-ua-model\u003d*, ch-ua-wow64\u003d*, ch-ua-form-factor\u003d*, ch-ua-platform\u003d*, ch-ua-platform-version\u003d*"
], ],
"report-to": [ "report-to": [
"{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}" "{\"group\":\"youtube_main\",\"max_age\":2592000,\"endpoints\":[{\"url\":\"https://csp.withgoogle.com/csp/report-to/youtube_main\"}]}"
@ -59,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003diUDF-c9d_Kc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003d5WwUdkHli5g; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dWed, 26-Feb-2020 10:40:04 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+907; expires\u003dThu, 21-Nov-2024 10:40:04 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+301; expires\u003dSun, 07-Dec-2025 19:37:53 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -3,10 +3,10 @@
"httpMethod": "GET", "httpMethod": "GET",
"url": "https://www.youtube.com/sw.js", "url": "https://www.youtube.com/sw.js",
"headers": { "headers": {
"Referer": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Origin": [ "Referer": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Accept-Language": [ "Accept-Language": [
@ -41,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:08:06 GMT" "Fri, 08 Dec 2023 19:37:54 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:08:06 GMT" "Fri, 08 Dec 2023 19:37:54 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dQz7A-y6TpO8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003d7gHwLK-eIns; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:08:06 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+310; expires\u003dMon, 14-Jul-2025 22:08:06 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+450; expires\u003dSun, 07-Dec-2025 19:37:54 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -37,14 +37,14 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:06:59 GMT" "Fri, 08 Dec 2023 19:37:55 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:06:59 GMT" "Fri, 08 Dec 2023 19:37:55 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dg_ag4hAONhk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dB5TY0jJCRl4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:06:59 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+229; expires\u003dMon, 14-Jul-2025 22:06:59 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+987; expires\u003dSun, 07-Dec-2025 19:37:55 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -3,10 +3,10 @@
"httpMethod": "GET", "httpMethod": "GET",
"url": "https://www.youtube.com/sw.js", "url": "https://www.youtube.com/sw.js",
"headers": { "headers": {
"Referer": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Origin": [ "Referer": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Accept-Language": [ "Accept-Language": [
@ -37,14 +37,14 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Tue, 08 Aug 2023 17:04:33 GMT" "Fri, 08 Dec 2023 19:37:55 GMT"
], ],
"expires": [ "expires": [
"Tue, 08 Aug 2023 17:04:33 GMT" "Fri, 08 Dec 2023 19:37:55 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dV1ZtomDP-24; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dFFmfosvsq8M; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dWed, 11-Nov-2020 17:04:33 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+547; expires\u003dThu, 07-Aug-2025 17:04:33 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+549; expires\u003dSun, 07-Dec-2025 19:37:55 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -41,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:07:17 GMT" "Fri, 08 Dec 2023 19:37:56 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:07:17 GMT" "Fri, 08 Dec 2023 19:37:56 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dk1Kj8R4lxGo; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dnZE8WYkAbSk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:07:17 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+518; expires\u003dMon, 14-Jul-2025 22:07:17 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+860; expires\u003dSun, 07-Dec-2025 19:37:56 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -37,14 +37,14 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:00:51 GMT" "Fri, 08 Dec 2023 19:38:00 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:00:51 GMT" "Fri, 08 Dec 2023 19:38:00 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dq9uvkrxFtSk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dwO2i4ilbfqc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:00:51 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+377; expires\u003dMon, 14-Jul-2025 22:00:51 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+031; expires\u003dSun, 07-Dec-2025 19:38:00 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -3,10 +3,10 @@
"httpMethod": "GET", "httpMethod": "GET",
"url": "https://www.youtube.com/sw.js", "url": "https://www.youtube.com/sw.js",
"headers": { "headers": {
"Referer": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Origin": [ "Referer": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Accept-Language": [ "Accept-Language": [
@ -37,14 +37,14 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:06:37 GMT" "Fri, 08 Dec 2023 19:37:57 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:06:37 GMT" "Fri, 08 Dec 2023 19:37:57 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dyO7EGB-OaZE; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003d45cg5Fq7qO4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:06:37 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:37:57 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+510; expires\u003dMon, 14-Jul-2025 22:06:37 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+095; expires\u003dSun, 07-Dec-2025 19:37:57 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -3,17 +3,17 @@
"httpMethod": "POST", "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?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse",
"headers": { "headers": {
"Referer": [
"https://www.youtube.com"
],
"Origin": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Referer": [
"https://www.youtube.com"
],
"Cookie": [ "Cookie": [
"CONSENT\u003dPENDING+578" "SOCS\u003dCAE\u003d"
], ],
"X-YouTube-Client-Version": [ "X-YouTube-Client-Version": [
"2.20230714.00.00" "2.20231208.01.00"
], ],
"X-YouTube-Client-Name": [ "X-YouTube-Client-Name": [
"1" "1"
@ -130,6 +130,27 @@
58, 58,
123, 123,
34, 34,
117,
116,
99,
79,
102,
102,
115,
101,
116,
77,
105,
110,
117,
116,
101,
115,
34,
58,
48,
44,
34,
104, 104,
108, 108,
34, 34,
@ -234,13 +255,13 @@
48, 48,
50, 50,
51, 51,
48,
55,
49, 49,
52, 50,
48,
56,
46, 46,
48, 48,
48, 49,
46, 46,
48, 48,
48, 48,
@ -355,7 +376,7 @@
"application/json; charset\u003dUTF-8" "application/json; charset\u003dUTF-8"
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:06:39 GMT" "Fri, 08 Dec 2023 19:37:58 GMT"
], ],
"server": [ "server": [
"scaffolding on HTTPServer2" "scaffolding on HTTPServer2"

View File

@ -41,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:07:31 GMT" "Fri, 08 Dec 2023 19:37:58 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:07:31 GMT" "Fri, 08 Dec 2023 19:37:58 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003db1xMQwJhIlw; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dnZmCsp9t2-E; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:07:31 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+426; expires\u003dMon, 14-Jul-2025 22:07:31 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+525; expires\u003dSun, 07-Dec-2025 19:37:58 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -37,14 +37,14 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sat, 15 Jul 2023 22:07:11 GMT" "Fri, 08 Dec 2023 19:37:58 GMT"
], ],
"expires": [ "expires": [
"Sat, 15 Jul 2023 22:07:11 GMT" "Fri, 08 Dec 2023 19:37:58 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dRvUxcEUa94o; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dmGbVRaILdW8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSun, 18-Oct-2020 22:07:11 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+576; expires\u003dMon, 14-Jul-2025 22:07:11 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+013; expires\u003dSun, 07-Dec-2025 19:37:58 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -34,9 +34,6 @@
"cache-control": [ "cache-control": [
"private, max-age\u003d0" "private, max-age\u003d0"
], ],
"content-security-policy-report-only": [
"require-trusted-types-for \u0027script\u0027;report-uri /cspreport"
],
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
@ -44,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sun, 06 Aug 2023 11:54:54 GMT" "Fri, 08 Dec 2023 19:38:01 GMT"
], ],
"expires": [ "expires": [
"Sun, 06 Aug 2023 11:54:54 GMT" "Fri, 08 Dec 2023 19:38:01 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -65,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dIXSPROQ-CH8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dslesUy90N9c; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 09-Nov-2020 11:54:54 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+942; expires\u003dTue, 05-Aug-2025 11:54:54 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+003; expires\u003dSun, 07-Dec-2025 19:38:01 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -37,14 +37,14 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sun, 06 Aug 2023 11:55:07 GMT" "Fri, 08 Dec 2023 19:38:01 GMT"
], ],
"expires": [ "expires": [
"Sun, 06 Aug 2023 11:55:07 GMT" "Fri, 08 Dec 2023 19:38:01 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dqCdA3bmpLFQ; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dyB7TaAiyiec; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 09-Nov-2020 11:55:07 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+717; expires\u003dTue, 05-Aug-2025 11:55:07 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+001; expires\u003dSun, 07-Dec-2025 19:38:01 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -34,9 +34,6 @@
"cache-control": [ "cache-control": [
"private, max-age\u003d0" "private, max-age\u003d0"
], ],
"content-security-policy-report-only": [
"require-trusted-types-for \u0027script\u0027;report-uri /cspreport"
],
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
@ -44,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sun, 16 Jul 2023 18:52:14 GMT" "Fri, 08 Dec 2023 19:38:02 GMT"
], ],
"expires": [ "expires": [
"Sun, 16 Jul 2023 18:52:14 GMT" "Fri, 08 Dec 2023 19:38:02 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -65,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003d9JX-39itmDs; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dsYYTQ2nPvgM; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 19-Oct-2020 18:52:14 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+644; expires\u003dTue, 15-Jul-2025 18:52:14 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+164; expires\u003dSun, 07-Dec-2025 19:38:02 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -3,10 +3,10 @@
"httpMethod": "GET", "httpMethod": "GET",
"url": "https://www.youtube.com/sw.js", "url": "https://www.youtube.com/sw.js",
"headers": { "headers": {
"Referer": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Origin": [ "Referer": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Accept-Language": [ "Accept-Language": [
@ -37,14 +37,14 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sun, 16 Jul 2023 18:52:40 GMT" "Fri, 08 Dec 2023 19:38:03 GMT"
], ],
"expires": [ "expires": [
"Sun, 16 Jul 2023 18:52:40 GMT" "Fri, 08 Dec 2023 19:38:03 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dq_DT7lNw0D4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dnA0Qd2uyByw; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 19-Oct-2020 18:52:40 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "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+204; expires\u003dTue, 15-Jul-2025 18:52:40 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+819; expires\u003dSun, 07-Dec-2025 19:38:03 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -3,10 +3,10 @@
"httpMethod": "GET", "httpMethod": "GET",
"url": "https://www.youtube.com/sw.js", "url": "https://www.youtube.com/sw.js",
"headers": { "headers": {
"Referer": [ "Origin": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Origin": [ "Referer": [
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Accept-Language": [ "Accept-Language": [
@ -37,14 +37,14 @@
"content-type": [ "content-type": [
"text/javascript; charset\u003dutf-8" "text/javascript; charset\u003dutf-8"
], ],
"cross-origin-opener-policy-report-only": [ "cross-origin-opener-policy": [
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Tue, 18 Jul 2023 23:55:38 GMT" "Fri, 08 Dec 2023 19:38:04 GMT"
], ],
"expires": [ "expires": [
"Tue, 18 Jul 2023 23:55:38 GMT" "Fri, 08 Dec 2023 19:38:04 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dFes-x1Jw3Yk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dXVJaGz18ttE; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dWed, 21-Oct-2020 23:55:38 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:04 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+486; expires\u003dThu, 17-Jul-2025 23:55:38 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+916; expires\u003dSun, 07-Dec-2025 19:38:04 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -41,10 +41,10 @@
"same-origin; report-to\u003d\"youtube_main\"" "same-origin; report-to\u003d\"youtube_main\""
], ],
"date": [ "date": [
"Sun, 16 Jul 2023 18:51:54 GMT" "Fri, 08 Dec 2023 19:38:05 GMT"
], ],
"expires": [ "expires": [
"Sun, 16 Jul 2023 18:51:54 GMT" "Fri, 08 Dec 2023 19:38:05 GMT"
], ],
"origin-trial": [ "origin-trial": [
"AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9" "AvC9UlR6RDk2crliDsFl66RWLnTbHrDbp+DiY6AYz/PNQ4G4tdUTjrHYr2sghbkhGQAVxb7jaPTHpEVBz0uzQwkAAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTcxOTUzMjc5OSwiaXNTdWJkb21haW4iOnRydWV9"
@ -62,9 +62,9 @@
"ESF" "ESF"
], ],
"set-cookie": [ "set-cookie": [
"YSC\u003dgnERa_YMa0w; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "YSC\u003dO2iOuaMhLuc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 19-Oct-2020 18:51:54 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone", "VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dSat, 13-Mar-2021 19:38:05 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
"CONSENT\u003dPENDING+072; expires\u003dTue, 15-Jul-2025 18:51:54 GMT; path\u003d/; domain\u003d.youtube.com; Secure" "CONSENT\u003dPENDING+851; expires\u003dSun, 07-Dec-2025 19:38:05 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
], ],
"strict-transport-security": [ "strict-transport-security": [
"max-age\u003d31536000" "max-age\u003d31536000"

View File

@ -10,10 +10,10 @@
"https://www.youtube.com" "https://www.youtube.com"
], ],
"Cookie": [ "Cookie": [
"CONSENT\u003dPENDING+488" "SOCS\u003dCAE\u003d"
], ],
"X-YouTube-Client-Version": [ "X-YouTube-Client-Version": [
"2.20230714.00.00" "2.20231208.01.00"
], ],
"X-YouTube-Client-Name": [ "X-YouTube-Client-Name": [
"1" "1"
@ -104,6 +104,27 @@
58, 58,
123, 123,
34, 34,
117,
116,
99,
79,
102,
102,
115,
101,
116,
77,
105,
110,
117,
116,
101,
115,
34,
58,
48,
44,
34,
104, 104,
108, 108,
34, 34,
@ -208,13 +229,13 @@
48, 48,
50, 50,
51, 51,
48,
55,
49, 49,
52, 50,
48,
56,
46, 46,
48, 48,
48, 49,
46, 46,
48, 48,
48, 48,
@ -350,11 +371,20 @@
"application/json; charset\u003dUTF-8" "application/json; charset\u003dUTF-8"
], ],
"date": [ "date": [
"Sun, 16 Jul 2023 18:51:56 GMT" "Fri, 08 Dec 2023 19:38:05 GMT"
],
"expires": [
"Fri, 08 Dec 2023 19:38:05 GMT"
],
"p3p": [
"CP\u003d\"This is not a P3P policy! See g.co/p3phelp for more info.\""
], ],
"server": [ "server": [
"scaffolding on HTTPServer2" "scaffolding on HTTPServer2"
], ],
"set-cookie": [
"CONSENT\u003dPENDING+254; expires\u003dSun, 07-Dec-2025 19:38:05 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
],
"vary": [ "vary": [
"Origin", "Origin",
"X-Origin", "X-Origin",
@ -370,7 +400,7 @@
"0" "0"
] ]
}, },
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtaUjU0cW8ydnY1ayjM-NClBg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20230714.00.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xb04ccb5ee4014ed1\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23946420,23966208,23983296,23986034,23998056,24004644,24007246,24034168,24036947,24077241,24080738,24120820,24135310,24140247,24166867,24181174,24187377,24187921,24211178,24219713,24241378,24248956,24255165,24255543,24255545,24262346,24288664,24290971,24291857,24362105,24362606,24362625,24364789,24365576,24366065,24366917,24367743,24368312,24368832,24370597,24371398,24371634,24372101,24372110,24372222,24373977,24374311,24374643,24374679,24376979,24379035,24379061,24379127,24379352,24379531,24379544,24379958,24379967,24380264,24382551,24383022,24383129,24383330,24383600,24383853,24384531,24385289,24385612,24386397,24386796,24388706,24388718,24388733,24388750,24388759,24389132,24390675,24404640,24407191,24407446,24415864,24428788,24437577,24439361,24440132,24451319,24453989,24457384,24458839,24459435,24466371,24466622,24468724,24469818,24485421,24488210,24495060,24498300,24502852,24503257,24503432,24504481,24504702,24504817,24506101,24506784,24506908,24506924,24506966,24507690,24509207,24509766,24511563,24515366,24515423,24518452,24519102,24520236,24523472,24526542,24526573,24531244,24537200,24550285,24550458,24550951,24551130,24552606,24553434,24554039,24554047,24559261,24691334,24694842,24696751,24698453,24698880,24699598,24699860,24699899,39324156\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20230714\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"24211178,24506784,24526542,24498300,24385289,24428788,24368312,24507690,24552606,24362625,24007246,24371634,24466622,24036947,24388718,24255545,24385612,24698880,24502852,24379544,24290971,24453989,24379127,24262346,24255165,24383600,24520236,24550458,23986034,24523472,24372101,24506101,24550285,24506908,24140247,24380264,24120820,24388759,24382551,24376979,24495060,24526573,24457384,24379531,24386796,24407191,24554039,24440132,24368832,24367743,24255543,24374311,24459435,24077241,24519102,24364789,24379035,24389132,24696751,24553434,24004644,24187377,24503432,23998056,24241378,24372110,24366917,24379352,24699598,24371398,24509207,24383853,24504481,24388750,24458839,24515423,24511563,24439361,24559261,24080738,24135310,24166867,24691334,24374643,24388706,24550951,24415864,24384531,24554047,24383129,24374679,24468724,24488210,24699860,24469818,24379958,23966208,24503257,24248956,24383330,24509766,24551130,24698453,24362105,24370597,24187921,24518452,24537200,24531244,24372222,24504817,24390675,24373977,24362606,24386397,24506966,24288664,24451319,24383022,24504702,23804281,23946420,24407446,24699899,24515366,24466371,24404640,23983296,24437577,39324156,24034168,24219713,24485421,24291857,24366065,24379967,24506924,24181174,24388733,24694842,24379061,24365576\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIhIDB6PKTgAMVpUxBAh01GwjbMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UCTwECeGqMZee77BjdoYtI2Q\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}", "responseBody": "{\"responseContext\":{\"visitorData\":\"CgtXTDBqYnNCaW9YOCid4c2rBjIICgJGUhICEgA%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20231208.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xf64eb8c056b59c48\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"9406121,23804281,23946420,23966208,23983296,23998056,24004644,24007246,24017848,24034168,24036948,24077241,24080738,24120820,24135310,24140247,24166867,24181174,24187377,24216872,24241378,24255543,24255545,24288664,24290971,24291857,24367580,24371778,24377598,24377910,24382552,24385728,24387949,24390675,24428788,24428941,24428945,24439361,24451319,24453989,24458839,24468724,24485421,24506515,24506784,24515423,24518452,24524098,24526515,24537200,24539025,24542367,24542452,24546075,24548627,24548629,24549786,24550458,24554164,24559327,24560416,24563006,24566293,24566687,24583802,24585907,24589492,24694842,24697067,24698452,24699899,39324156,51000012,51003636,51004018,51006176,51006181,51009781,51009900,51010235,51012165,51012291,51012659,51014091,51016856,51017346,51019626,51020570,51021953,51024416,51025415,51026715,51027870,51028271,51029412,51033399,51033577,51036511,51037540,51037819,51037893,51038399,51038805,51039199,51039493,51041497,51041809,51045885,51045888,51045969,51047579,51048239,51048489,51049006,51049131,51051343,51053690,51053957,51055917,51056263,51056270,51057501,51057534,51057746,51059322,51059573,51061018,51061427,51061926,51063327,51063643,51064283,51065651,51066749,51068528,51068752,51069269,51069319,51070192,51070203,51071181,51071411,51072197,51072748,51073315,51074183,51074391,51074661,51075805,51076209,51076264,51078467,51079353\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20231208\"},{\"key\":\"client.name\",\"value\":\"WEB\"},{\"key\":\"client.fexp\",\"value\":\"51026715,51056263,24451319,51000012,24004644,51066749,51027870,24140247,24017848,51006181,24367580,24589492,24241378,51074183,24458839,51055917,51039493,51021953,24566293,51045885,51038399,24428945,51056270,24290971,51003636,24468724,24550458,51048489,51009900,24034168,51020570,51012165,51006176,24515423,51037819,24135310,51039199,51033577,24382552,23966208,24080738,24585907,51049006,24563006,51028271,24548627,24698452,24694842,24377598,51041809,51074661,51004018,51072748,51051343,24566687,51014091,51073315,24216872,23804281,24181174,24288664,24554164,24291857,24166867,51076264,51057534,24537200,51045888,24542452,51068752,24120820,24518452,51029412,24559327,24560416,51063327,24549786,24385728,24390675,51012659,24485421,51059322,51033399,24526515,24548629,24255543,51037893,24583802,51069319,24007246,51061926,24546075,24439361,51071411,51068528,51017346,51036511,51024416,51071181,51019626,51065651,51038805,23946420,9406121,51009781,51070203,51025415,51069269,24453989,51075805,51012291,51037540,51047579,24524098,24506515,24699899,24428941,39324156,51074391,51070192,23998056,51010235,24506784,51045969,24255545,51057501,51078467,51053957,51061427,24542367,24371778,51076209,24036948,24377910,24387949,51072197,51059573,51079353,24428788,24539025,24697067,24077241,51041497,51064283,51063643,51016856,51053690,51049131,24187377,51057746,23983296,51048239,51061018\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIq_j7yMuAgwMVQ1FPBB1tmwaUMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UCTwECeGqMZee77BjdoYtI2Q\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse" "latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8\u0026prettyPrint\u003dfalse"
} }
} }

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