Compare commits
41 Commits
Author | SHA1 | Date |
---|---|---|
|
8e92227b2e | |
|
eebcc46255 | |
|
9fb03f6c87 | |
|
e4a1a6ecd8 | |
|
727e791602 | |
|
d635d4db2a | |
|
ea1a1d1375 | |
|
c00d0a7028 | |
|
d3d5f2b3f0 | |
|
0de224124b | |
|
183563cc9e | |
|
f52d2269fc | |
|
667c867ad8 | |
|
169098432b | |
|
06b2c8e2aa | |
|
c343e31ed2 | |
|
1f26c12098 | |
|
6af22e3e45 | |
|
8a3350f79d | |
|
542867ff4d | |
|
abba78cf9d | |
|
534bbc90cf | |
|
f169885dbc | |
|
18c9f1fd38 | |
|
fb81eaab82 | |
|
5431069588 | |
|
743a4000b8 | |
|
69ff271be1 | |
|
eb30316a36 | |
|
42c1afaf87 | |
|
596bce294d | |
|
f9ffdd91d5 | |
|
34f28fc1f0 | |
|
f926fbcf35 | |
|
36cc17c789 | |
|
6e3a4a6d9d | |
|
70d6a06bf2 | |
|
1278517492 | |
|
bcacfc53c5 | |
|
6963385176 | |
|
5f1ba8cf7d |
|
@ -0,0 +1,93 @@
|
|||
name: Bug report
|
||||
description: Create a bug report to help us improve
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for helping to make the NewPipe Extractor better by reporting a bug. :hugs:
|
||||
|
||||
Please fill in as much information as possible about your bug so that we don't have to play "information ping-pong" and can help you immediately.
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: "Checklist"
|
||||
options:
|
||||
- label: "I am able to reproduce the bug with the latest version given here: [CLICK THIS LINK](https://github.com/TeamNewPipe/NewPipeExtractor/releases/latest)."
|
||||
required: true
|
||||
- label: "I am aware that this issue is being opened for the NewPipe Extractor, NOT the [app](https://github.com/TeamNewPipe/NewPipe), and my bug report will be dismissed otherwise."
|
||||
required: true
|
||||
- label: "I made sure that there are *no existing issues* - [open](https://github.com/TeamNewPipe/NewPipeExtractor/issues) or [closed](https://github.com/TeamNewPipe/NewPipeExtractor/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to."
|
||||
required: true
|
||||
- label: "I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise."
|
||||
required: true
|
||||
- label: "This issue contains only one bug."
|
||||
required: true
|
||||
- label: "I have read and understood the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md)."
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: extractor-version
|
||||
attributes:
|
||||
label: Affected version
|
||||
description: "In which NewPipe Extractor version did you encounter the bug?"
|
||||
placeholder: "x.xx.x"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: steps-to-reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce the bug
|
||||
description: |
|
||||
What did you do for the bug to show up?
|
||||
|
||||
If you can't cause the bug to show up again reliably (and hence don't have a proper set of steps to give us), please still try to give as many details as possible on how you think you encountered the bug.
|
||||
placeholder: |
|
||||
1. Init NewPipe with 'NewPipe.init(...)'
|
||||
2. Create a StreamExtractor for xyz: 'StreamExtractor e = YouTube.getStreamExtractor(xyz.com)'
|
||||
3. Get the description 'e.getDescription()'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: |
|
||||
Tell us what you expect to happen.
|
||||
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: Actual behavior
|
||||
description: |
|
||||
Tell us what happens with the steps given above.
|
||||
|
||||
- type: textarea
|
||||
id: screen-media
|
||||
attributes:
|
||||
label: Screenshots/Screen recordings
|
||||
description: |
|
||||
A picture or video is worth a thousand words.
|
||||
|
||||
If applicable, add screenshots or a screen recording to help explain your problem.
|
||||
GitHub supports uploading them directly in the text box.
|
||||
If your file is too big for Github to accept, try to compress it (ZIP-file) or feel free to paste a link to an image/video hoster here instead.
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs
|
||||
description: |
|
||||
If your bug includes a log you think we need to see, paste it here.
|
||||
|
||||
- type: textarea
|
||||
id: additional-information
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: |
|
||||
Any other information you'd like to include, for instance that
|
||||
* your cat disabled your network connection
|
||||
* ...
|
|
@ -0,0 +1,8 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Matrix
|
||||
url: https://matrix.to/#/#newpipe:matrix.newpipe-ev.de
|
||||
about: Chat with us via Matrix for quick Q/A
|
||||
- name: 💬 IRC
|
||||
url: https://web.libera.chat/#newpipe
|
||||
about: Chat with us via IRC for quick Q/A
|
|
@ -0,0 +1,50 @@
|
|||
name: Feature request
|
||||
description: Suggest an idea for this project
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for helping to make the NewPipe Extractor better by suggesting a feature. :hugs:
|
||||
|
||||
Your ideas are highly welcome! The Extractor is made for you, the downstream developers, after all.
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: "Checklist"
|
||||
options:
|
||||
- label: "I am aware that this issue is being opened for the NewPipe Extractor, NOT the [app](https://github.com/TeamNewPipe/NewPipe), and my feature request will be dismissed otherwise."
|
||||
required: true
|
||||
- label: "I made sure that there are *no existing issues* - [open](https://github.com/TeamNewPipe/NewPipeExtractor/issues) or [closed](https://github.com/TeamNewPipe/NewPipeExtractor/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to."
|
||||
required: true
|
||||
- label: "I have taken the time to fill in all the required details. I understand that the feature request will be dismissed otherwise."
|
||||
required: true
|
||||
- label: "This issue contains only one feature request."
|
||||
required: true
|
||||
- label: "I have read and understood the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/dev/.github/CONTRIBUTING.md)."
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature description
|
||||
description: |
|
||||
Explain how you want the Extractor's behavior to change to suit your needs.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: why-is-the-feature-requested
|
||||
attributes:
|
||||
label: Why do you want this feature?
|
||||
description: |
|
||||
Describe any problem or limitation you come across while using the Extractor which would be solved by this feature.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional-information
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Any other information you'd like to include, for instance sketches, mockups, pictures of cats, etc.
|
|
@ -1,6 +1,6 @@
|
|||
# NewPipe Extractor
|
||||
|
||||
[](https://github.com/TeamNewPipe/NewPipeExtractor/actions/workflows/ci.yml) [](https://jitpack.io/#TeamNewPipe/NewPipeExtractor) [JDoc](https://teamnewpipe.github.io/NewPipeExtractor/javadoc/) • [Documentation](https://teamnewpipe.github.io/documentation/)
|
||||
[](https://github.com/TeamNewPipe/NewPipeExtractor/actions/workflows/ci.yml) [](https://jitpack.io/#teamnewpipe/NewPipeExtractor) [JDoc](https://teamnewpipe.github.io/NewPipeExtractor/javadoc/) • [Documentation](https://teamnewpipe.github.io/documentation/)
|
||||
|
||||
NewPipe Extractor is a library for extracting things from streaming sites. It is a core component of [NewPipe](https://github.com/TeamNewPipe/NewPipe), but could be used independently.
|
||||
|
||||
|
@ -11,7 +11,7 @@ NewPipe Extractor is available at JitPack's Maven repo.
|
|||
If you're using Gradle, you could add NewPipe Extractor as a dependency with the following steps:
|
||||
|
||||
1. Add `maven { url 'https://jitpack.io' }` to the `repositories` in your `build.gradle`.
|
||||
2. Add `implementation 'com.github.TeamNewPipe:NewPipeExtractor:INSERT_VERSION_HERE'` to the `dependencies` in your `build.gradle`. Replace `INSERT_VERSION_HERE` with the [latest release](https://github.com/TeamNewPipe/NewPipeExtractor/releases/latest).
|
||||
2. Add `implementation 'com.github.teamnewpipe:NewPipeExtractor:INSERT_VERSION_HERE'` to the `dependencies` in your `build.gradle`. Replace `INSERT_VERSION_HERE` with the [latest release](https://github.com/TeamNewPipe/NewPipeExtractor/releases/latest).
|
||||
3. If you are using tools to minimize your project, make sure to keep the files below, by e.g. adding the following lines to your proguard file:
|
||||
```
|
||||
## Rules for NewPipeExtractor
|
||||
|
@ -30,7 +30,7 @@ To test changes quickly you can build the library locally. A good approach would
|
|||
```groovy
|
||||
includeBuild('../NewPipeExtractor') {
|
||||
dependencySubstitution {
|
||||
substitute module('com.github.TeamNewPipe:NewPipeExtractor') with project(':extractor')
|
||||
substitute module('com.github.teamnewpipe:NewPipeExtractor') with project(':extractor')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -40,7 +40,7 @@ Another approach would be to use the local Maven repository, here's a gist of ho
|
|||
1. Add `mavenLocal()` in your project `repositories` list (usually as the first entry to give priority above the others).
|
||||
2. It's _recommended_ that you change the `version` of this library (e.g. `LOCAL_SNAPSHOT`).
|
||||
3. Run gradle's `ìnstall` task to deploy this library to your local repository (using the wrapper, present in the root of this project: `./gradlew install`)
|
||||
4. Change the dependency version used in your project to match the one you chose in step 2 (`implementation 'com.github.TeamNewPipe:NewPipeExtractor:LOCAL_SNAPSHOT'`)
|
||||
4. Change the dependency version used in your project to match the one you chose in step 2 (`implementation 'com.github.teamnewpipe:NewPipeExtractor:LOCAL_SNAPSHOT'`)
|
||||
|
||||
> Tip for Android Studio users: After you make changes and run the `install` task, use the menu option `File → "Sync with File System"` to refresh the library in your project.
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ allprojects {
|
|||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
|
||||
version 'v0.24.2'
|
||||
version 'v0.24.3'
|
||||
group 'com.github.TeamNewPipe'
|
||||
|
||||
repositories {
|
||||
|
@ -29,7 +29,7 @@ allprojects {
|
|||
ext {
|
||||
nanojsonVersion = "1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"
|
||||
spotbugsVersion = "4.8.6"
|
||||
junitVersion = "5.10.3"
|
||||
junitVersion = "5.11.3"
|
||||
checkstyleVersion = "10.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
|||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
|
||||
import org.schabi.newpipe.extractor.utils.Parser;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
@ -14,6 +15,7 @@ public final class PeertubeChannelLinkHandlerFactory extends ListLinkHandlerFact
|
|||
private static final PeertubeChannelLinkHandlerFactory INSTANCE
|
||||
= new PeertubeChannelLinkHandlerFactory();
|
||||
private static final String ID_PATTERN = "((accounts|a)|(video-channels|c))/([^/?&#]*)";
|
||||
private static final String ID_URL_PATTERN = "/((accounts|a)|(video-channels|c))/([^/?&#]*)";
|
||||
public static final String API_ENDPOINT = "/api/v1/";
|
||||
|
||||
private PeertubeChannelLinkHandlerFactory() {
|
||||
|
@ -25,7 +27,7 @@ public final class PeertubeChannelLinkHandlerFactory extends ListLinkHandlerFact
|
|||
|
||||
@Override
|
||||
public String getId(final String url) throws ParsingException, UnsupportedOperationException {
|
||||
return fixId(Parser.matchGroup(ID_PATTERN, url, 0));
|
||||
return fixId(Parser.matchGroup(ID_URL_PATTERN, url, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,12 +76,13 @@ public final class PeertubeChannelLinkHandlerFactory extends ListLinkHandlerFact
|
|||
* @param id the id to fix
|
||||
* @return the fixed id
|
||||
*/
|
||||
private String fixId(final String id) {
|
||||
if (id.startsWith("a/")) {
|
||||
return "accounts" + id.substring(1);
|
||||
} else if (id.startsWith("c/")) {
|
||||
return "video-channels" + id.substring(1);
|
||||
private String fixId(@Nonnull final String id) {
|
||||
final String cleanedId = id.startsWith("/") ? id.substring(1) : id;
|
||||
if (cleanedId.startsWith("a/")) {
|
||||
return "accounts" + cleanedId.substring(1);
|
||||
} else if (cleanedId.startsWith("c/")) {
|
||||
return "video-channels" + cleanedId.substring(1);
|
||||
}
|
||||
return id;
|
||||
return cleanedId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,14 @@ import org.schabi.newpipe.extractor.localization.Localization;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.defaultAlertsCheck;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getJsonPostResponse;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.hasArtistOrVerifiedIconBadgeAttachment;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
|
@ -233,7 +235,7 @@ public final class YoutubeChannelHelper {
|
|||
* properties.
|
||||
* </p>
|
||||
*/
|
||||
public static final class ChannelHeader {
|
||||
public static final class ChannelHeader implements Serializable {
|
||||
|
||||
/**
|
||||
* Types of supported YouTube channel headers.
|
||||
|
@ -294,27 +296,27 @@ public final class YoutubeChannelHelper {
|
|||
*/
|
||||
public final HeaderType headerType;
|
||||
|
||||
private ChannelHeader(@Nonnull final JsonObject json, final HeaderType headerType) {
|
||||
public ChannelHeader(@Nonnull final JsonObject json, final HeaderType headerType) {
|
||||
this.json = json;
|
||||
this.headerType = headerType;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a channel header as an {@link Optional} it if exists.
|
||||
* Get a channel header it if exists.
|
||||
*
|
||||
* @param channelResponse a full channel JSON response
|
||||
* @return an {@link Optional} containing a {@link ChannelHeader} or an empty {@link Optional}
|
||||
* if no supported header has been found
|
||||
* @return a {@link ChannelHeader} or {@code null} if no supported header has been found
|
||||
*/
|
||||
@Nonnull
|
||||
public static Optional<ChannelHeader> getChannelHeader(
|
||||
@Nullable
|
||||
public static ChannelHeader getChannelHeader(
|
||||
@Nonnull final JsonObject channelResponse) {
|
||||
final JsonObject header = channelResponse.getObject(HEADER);
|
||||
|
||||
if (header.has(C4_TABBED_HEADER_RENDERER)) {
|
||||
return Optional.of(header.getObject(C4_TABBED_HEADER_RENDERER))
|
||||
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.C4_TABBED));
|
||||
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.C4_TABBED))
|
||||
.orElse(null);
|
||||
} else if (header.has(CAROUSEL_HEADER_RENDERER)) {
|
||||
return header.getObject(CAROUSEL_HEADER_RENDERER)
|
||||
.getArray(CONTENTS)
|
||||
|
@ -324,17 +326,20 @@ public final class YoutubeChannelHelper {
|
|||
.filter(item -> item.has(TOPIC_CHANNEL_DETAILS_RENDERER))
|
||||
.findFirst()
|
||||
.map(item -> item.getObject(TOPIC_CHANNEL_DETAILS_RENDERER))
|
||||
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.CAROUSEL));
|
||||
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.CAROUSEL))
|
||||
.orElse(null);
|
||||
} else if (header.has("pageHeaderRenderer")) {
|
||||
return Optional.of(header.getObject("pageHeaderRenderer"))
|
||||
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.PAGE));
|
||||
.map(json -> new ChannelHeader(json, ChannelHeader.HeaderType.PAGE))
|
||||
.orElse(null);
|
||||
} else if (header.has("interactiveTabbedHeaderRenderer")) {
|
||||
return Optional.of(header.getObject("interactiveTabbedHeaderRenderer"))
|
||||
.map(json -> new ChannelHeader(json,
|
||||
ChannelHeader.HeaderType.INTERACTIVE_TABBED));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
ChannelHeader.HeaderType.INTERACTIVE_TABBED))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -359,27 +364,11 @@ public final class YoutubeChannelHelper {
|
|||
final JsonObject pageHeaderViewModel = channelHeader.json.getObject(CONTENT)
|
||||
.getObject(PAGE_HEADER_VIEW_MODEL);
|
||||
|
||||
final boolean hasCircleOrMusicIcon = pageHeaderViewModel.getObject(TITLE)
|
||||
.getObject("dynamicTextViewModel")
|
||||
.getObject("text")
|
||||
.getArray("attachmentRuns")
|
||||
.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.anyMatch(attachmentRun -> attachmentRun.getObject("element")
|
||||
.getObject("type")
|
||||
.getObject("imageType")
|
||||
.getObject("image")
|
||||
.getArray("sources")
|
||||
.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.anyMatch(source -> {
|
||||
final String imageName = source.getObject("clientResource")
|
||||
.getString("imageName");
|
||||
return "CHECK_CIRCLE_FILLED".equals(imageName)
|
||||
|| "MUSIC_FILLED".equals(imageName);
|
||||
}));
|
||||
final boolean hasCircleOrMusicIcon = hasArtistOrVerifiedIconBadgeAttachment(
|
||||
pageHeaderViewModel.getObject(TITLE)
|
||||
.getObject("dynamicTextViewModel")
|
||||
.getObject("text")
|
||||
.getArray("attachmentRuns"));
|
||||
if (!hasCircleOrMusicIcon && pageHeaderViewModel.getObject("image")
|
||||
.has("contentPreviewImageViewModel")) {
|
||||
// If a pageHeaderRenderer has no object in which a check verified may be
|
||||
|
@ -418,7 +407,7 @@ public final class YoutubeChannelHelper {
|
|||
* If the ID cannot still be get, the fallback channel ID, if provided, will be used.
|
||||
* </p>
|
||||
*
|
||||
* @param header the channel header
|
||||
* @param channelHeader the channel header
|
||||
* @param fallbackChannelId the fallback channel ID, which can be null
|
||||
* @return the ID of the channel
|
||||
* @throws ParsingException if the channel ID cannot be got from the channel header, the
|
||||
|
@ -426,12 +415,10 @@ public final class YoutubeChannelHelper {
|
|||
*/
|
||||
@Nonnull
|
||||
public static String getChannelId(
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
@Nonnull final Optional<ChannelHeader> header,
|
||||
@Nullable final ChannelHeader channelHeader,
|
||||
@Nonnull final JsonObject jsonResponse,
|
||||
@Nullable final String fallbackChannelId) throws ParsingException {
|
||||
if (header.isPresent()) {
|
||||
final ChannelHeader channelHeader = header.get();
|
||||
if (channelHeader != null) {
|
||||
switch (channelHeader.headerType) {
|
||||
case C4_TABBED:
|
||||
final String channelId = channelHeader.json.getObject(HEADER)
|
||||
|
@ -486,10 +473,9 @@ public final class YoutubeChannelHelper {
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
public static String getChannelName(@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
@Nonnull final Optional<ChannelHeader> channelHeader,
|
||||
@Nonnull final JsonObject jsonResponse,
|
||||
@Nullable final JsonObject channelAgeGateRenderer)
|
||||
public static String getChannelName(@Nullable final ChannelHeader channelHeader,
|
||||
@Nullable final JsonObject channelAgeGateRenderer,
|
||||
@Nonnull final JsonObject jsonResponse)
|
||||
throws ParsingException {
|
||||
if (channelAgeGateRenderer != null) {
|
||||
final String title = channelAgeGateRenderer.getString("channelTitle");
|
||||
|
@ -506,7 +492,8 @@ public final class YoutubeChannelHelper {
|
|||
return metadataRendererTitle;
|
||||
}
|
||||
|
||||
return channelHeader.map(header -> {
|
||||
return Optional.ofNullable(channelHeader)
|
||||
.map(header -> {
|
||||
final JsonObject channelJson = header.json;
|
||||
switch (header.headerType) {
|
||||
case PAGE:
|
||||
|
|
|
@ -1584,6 +1584,29 @@ public final class YoutubeParsingHelper {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasArtistOrVerifiedIconBadgeAttachment(
|
||||
@Nonnull final JsonArray attachmentRuns) {
|
||||
return attachmentRuns.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.anyMatch(attachmentRun -> attachmentRun.getObject("element")
|
||||
.getObject("type")
|
||||
.getObject("imageType")
|
||||
.getObject("image")
|
||||
.getArray("sources")
|
||||
.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.anyMatch(source -> {
|
||||
final String imageName = source.getObject("clientResource")
|
||||
.getString("imageName");
|
||||
return "CHECK_CIRCLE_FILLED".equals(imageName)
|
||||
|| "AUDIO_BADGE".equals(imageName)
|
||||
|| "MUSIC_FILLED".equals(imageName);
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a content playback nonce (also called {@code cpn}), sent by YouTube clients in
|
||||
* playback requests (and also for some clients, in the player request body).
|
||||
|
@ -1720,9 +1743,12 @@ public final class YoutubeParsingHelper {
|
|||
case "original":
|
||||
return AudioTrackType.ORIGINAL;
|
||||
case "dubbed":
|
||||
case "dubbed-auto":
|
||||
return AudioTrackType.DUBBED;
|
||||
case "descriptive":
|
||||
return AudioTrackType.DESCRIPTIVE;
|
||||
case "secondary":
|
||||
return AudioTrackType.SECONDARY;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ final class YoutubeThrottlingParameterUtils {
|
|||
|
||||
private static final String SINGLE_CHAR_VARIABLE_REGEX = "[a-zA-Z0-9$_]";
|
||||
|
||||
private static final String FUNCTION_NAME_REGEX = SINGLE_CHAR_VARIABLE_REGEX + "+";
|
||||
private static final String MULTIPLE_CHARS_REGEX = SINGLE_CHAR_VARIABLE_REGEX + "+";
|
||||
|
||||
private static final String ARRAY_ACCESS_REGEX = "\\[(\\d+)]";
|
||||
|
||||
|
@ -30,31 +30,54 @@ final class YoutubeThrottlingParameterUtils {
|
|||
private static final Pattern[] DEOBFUSCATION_FUNCTION_NAME_REGEXES = {
|
||||
|
||||
/*
|
||||
* The first regex matches the following text, where we want rDa and the array index
|
||||
* The first regex matches the following text, where we want Wma and the array index
|
||||
* accessed:
|
||||
*
|
||||
* a.D&&(b="nn"[+a.D],WL(a),c=a.j[b]||null)&&(c=SDa[0](c),a.set(b,c),SDa.length||Wma("")
|
||||
*/
|
||||
Pattern.compile(SINGLE_CHAR_VARIABLE_REGEX + "=\"nn\"\\[\\+" + MULTIPLE_CHARS_REGEX
|
||||
+ "\\." + MULTIPLE_CHARS_REGEX + "]," + MULTIPLE_CHARS_REGEX + "\\("
|
||||
+ MULTIPLE_CHARS_REGEX + "\\)," + MULTIPLE_CHARS_REGEX + "="
|
||||
+ MULTIPLE_CHARS_REGEX + "\\." + MULTIPLE_CHARS_REGEX + "\\["
|
||||
+ MULTIPLE_CHARS_REGEX + "]\\|\\|null\\).+\\|\\|(" + MULTIPLE_CHARS_REGEX
|
||||
+ ")\\(\"\"\\)"),
|
||||
|
||||
/*
|
||||
* The second regex matches the following text, where we want SDa and the array index
|
||||
* accessed:
|
||||
*
|
||||
* a.D&&(b="nn"[+a.D],WL(a),c=a.j[b]||null)&&(c=SDa[0](c),a.set(b,c),SDa.length||Wma("")
|
||||
*/
|
||||
Pattern.compile(SINGLE_CHAR_VARIABLE_REGEX + "=\"nn\"\\[\\+" + MULTIPLE_CHARS_REGEX
|
||||
+ "\\." + MULTIPLE_CHARS_REGEX + "]," + MULTIPLE_CHARS_REGEX + "\\("
|
||||
+ MULTIPLE_CHARS_REGEX + "\\)," + MULTIPLE_CHARS_REGEX + "="
|
||||
+ MULTIPLE_CHARS_REGEX + "\\." + MULTIPLE_CHARS_REGEX + "\\["
|
||||
+ MULTIPLE_CHARS_REGEX + "]\\|\\|null\\)&&\\(" + MULTIPLE_CHARS_REGEX + "=("
|
||||
+ MULTIPLE_CHARS_REGEX + ")" + ARRAY_ACCESS_REGEX),
|
||||
|
||||
/*
|
||||
* The third regex matches the following text, where we want rma:
|
||||
*
|
||||
* a.D&&(b="nn"[+a.D],c=a.get(b))&&(c=rDa[0](c),a.set(b,c),rDa.length||rma("")
|
||||
*/
|
||||
Pattern.compile(SINGLE_CHAR_VARIABLE_REGEX + "=\"nn\"\\[\\+" + MULTIPLE_CHARS_REGEX
|
||||
+ "\\." + MULTIPLE_CHARS_REGEX + "]," + MULTIPLE_CHARS_REGEX + "="
|
||||
+ MULTIPLE_CHARS_REGEX + "\\.get\\(" + MULTIPLE_CHARS_REGEX + "\\)\\).+\\|\\|("
|
||||
+ MULTIPLE_CHARS_REGEX + ")\\(\"\"\\)"),
|
||||
|
||||
/*
|
||||
* The fourth regex matches the following text, where we want rDa and the array index
|
||||
* accessed:
|
||||
*
|
||||
* a.D&&(b="nn"[+a.D],c=a.get(b))&&(c=rDa[0](c),a.set(b,c),rDa.length||rma("")
|
||||
*/
|
||||
Pattern.compile(SINGLE_CHAR_VARIABLE_REGEX + "+=\"nn\"\\[\\+"
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "+\\." + SINGLE_CHAR_VARIABLE_REGEX + "+],"
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "+=" + SINGLE_CHAR_VARIABLE_REGEX
|
||||
+ "+\\.get\\(" + SINGLE_CHAR_VARIABLE_REGEX + "+\\)\\)&&\\("
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "+=(" + SINGLE_CHAR_VARIABLE_REGEX
|
||||
+ "+)\\[(\\d+)]"),
|
||||
Pattern.compile(SINGLE_CHAR_VARIABLE_REGEX + "=\"nn\"\\[\\+" + MULTIPLE_CHARS_REGEX
|
||||
+ "\\." + MULTIPLE_CHARS_REGEX + "]," + MULTIPLE_CHARS_REGEX + "="
|
||||
+ MULTIPLE_CHARS_REGEX + "\\.get\\(" + MULTIPLE_CHARS_REGEX + "\\)\\)&&\\("
|
||||
+ MULTIPLE_CHARS_REGEX + "=(" + MULTIPLE_CHARS_REGEX + ")\\[(\\d+)]"),
|
||||
|
||||
/*
|
||||
* The second regex matches the following text, where we want rma:
|
||||
*
|
||||
* a.D&&(b="nn"[+a.D],c=a.get(b))&&(c=rDa[0](c),a.set(b,c),rDa.length||rma("")
|
||||
*/
|
||||
Pattern.compile(SINGLE_CHAR_VARIABLE_REGEX + "+=\"nn\"\\[\\+"
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "+\\." + SINGLE_CHAR_VARIABLE_REGEX + "+],"
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "+=" + SINGLE_CHAR_VARIABLE_REGEX + "+\\.get\\("
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "+\\)\\).+\\|\\|(" + SINGLE_CHAR_VARIABLE_REGEX
|
||||
+ "+)\\(\"\"\\)"),
|
||||
|
||||
/*
|
||||
* The third regex matches the following text, where we want BDa and the array index
|
||||
* The fifth regex matches the following text, where we want BDa and the array index
|
||||
* accessed:
|
||||
*
|
||||
* (b=String.fromCharCode(110),c=a.get(b))&&(c=BDa[0](c)
|
||||
|
@ -62,17 +85,17 @@ final class YoutubeThrottlingParameterUtils {
|
|||
Pattern.compile("\\(" + SINGLE_CHAR_VARIABLE_REGEX + "=String\\.fromCharCode\\(110\\),"
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "=" + SINGLE_CHAR_VARIABLE_REGEX + "\\.get\\("
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "\\)\\)" + "&&\\(" + SINGLE_CHAR_VARIABLE_REGEX
|
||||
+ "=(" + FUNCTION_NAME_REGEX + ")" + "(?:" + ARRAY_ACCESS_REGEX + ")?\\("
|
||||
+ "=(" + MULTIPLE_CHARS_REGEX + ")" + "(?:" + ARRAY_ACCESS_REGEX + ")?\\("
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "\\)"),
|
||||
|
||||
/*
|
||||
* The fourth regex matches the following text, where we want Yva and the array index
|
||||
* The sixth regex matches the following text, where we want Yva and the array index
|
||||
* accessed:
|
||||
*
|
||||
* .get("n"))&&(b=Yva[0](b)
|
||||
*/
|
||||
Pattern.compile("\\.get\\(\"n\"\\)\\)&&\\(" + SINGLE_CHAR_VARIABLE_REGEX
|
||||
+ "=(" + FUNCTION_NAME_REGEX + ")(?:" + ARRAY_ACCESS_REGEX + ")?\\("
|
||||
+ "=(" + MULTIPLE_CHARS_REGEX + ")(?:" + ARRAY_ACCESS_REGEX + ")?\\("
|
||||
+ SINGLE_CHAR_VARIABLE_REGEX + "\\)")
|
||||
};
|
||||
// CHECKSTYLE:ON
|
||||
|
|
|
@ -325,6 +325,8 @@ public final class YoutubeDashManifestCreatorsUtils {
|
|||
case DESCRIPTIVE:
|
||||
return "description";
|
||||
default:
|
||||
// Secondary track types do not seem to have a dedicated role in the DASH
|
||||
// specification, so use alternate for them
|
||||
return "alternate";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
|
||||
private JsonObject jsonResponse;
|
||||
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
private Optional<ChannelHeader> channelHeader;
|
||||
@Nullable
|
||||
private ChannelHeader channelHeader;
|
||||
|
||||
private String channelId;
|
||||
|
||||
|
@ -132,7 +132,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
public String getName() throws ParsingException {
|
||||
assertPageFetched();
|
||||
return YoutubeChannelHelper.getChannelName(
|
||||
channelHeader, jsonResponse, channelAgeGateRenderer);
|
||||
channelHeader, channelAgeGateRenderer, jsonResponse);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -146,40 +146,40 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
.orElseThrow(() -> new ParsingException("Could not get avatars"));
|
||||
}
|
||||
|
||||
return channelHeader.map(header -> {
|
||||
switch (header.headerType) {
|
||||
case PAGE:
|
||||
final JsonObject imageObj = header.json.getObject(CONTENT)
|
||||
.getObject(PAGE_HEADER_VIEW_MODEL)
|
||||
.getObject(IMAGE);
|
||||
return Optional.ofNullable(channelHeader)
|
||||
.map(header -> {
|
||||
switch (header.headerType) {
|
||||
case PAGE:
|
||||
final JsonObject imageObj = header.json.getObject(CONTENT)
|
||||
.getObject(PAGE_HEADER_VIEW_MODEL)
|
||||
.getObject(IMAGE);
|
||||
|
||||
if (imageObj.has(CONTENT_PREVIEW_IMAGE_VIEW_MODEL)) {
|
||||
return imageObj.getObject(CONTENT_PREVIEW_IMAGE_VIEW_MODEL)
|
||||
.getObject(IMAGE)
|
||||
.getArray(SOURCES);
|
||||
if (imageObj.has(CONTENT_PREVIEW_IMAGE_VIEW_MODEL)) {
|
||||
return imageObj.getObject(CONTENT_PREVIEW_IMAGE_VIEW_MODEL)
|
||||
.getObject(IMAGE)
|
||||
.getArray(SOURCES);
|
||||
}
|
||||
|
||||
if (imageObj.has("decoratedAvatarViewModel")) {
|
||||
return imageObj.getObject("decoratedAvatarViewModel")
|
||||
.getObject(AVATAR)
|
||||
.getObject("avatarViewModel")
|
||||
.getObject(IMAGE)
|
||||
.getArray(SOURCES);
|
||||
}
|
||||
|
||||
// Return an empty avatar array as a fallback
|
||||
return new JsonArray();
|
||||
case INTERACTIVE_TABBED:
|
||||
return header.json.getObject("boxArt")
|
||||
.getArray(THUMBNAILS);
|
||||
case C4_TABBED:
|
||||
case CAROUSEL:
|
||||
default:
|
||||
return header.json.getObject(AVATAR)
|
||||
.getArray(THUMBNAILS);
|
||||
}
|
||||
|
||||
if (imageObj.has("decoratedAvatarViewModel")) {
|
||||
return imageObj.getObject("decoratedAvatarViewModel")
|
||||
.getObject(AVATAR)
|
||||
.getObject("avatarViewModel")
|
||||
.getObject(IMAGE)
|
||||
.getArray(SOURCES);
|
||||
}
|
||||
|
||||
// Return an empty avatar array as a fallback
|
||||
return new JsonArray();
|
||||
case INTERACTIVE_TABBED:
|
||||
return header.json.getObject("boxArt")
|
||||
.getArray(THUMBNAILS);
|
||||
|
||||
case C4_TABBED:
|
||||
case CAROUSEL:
|
||||
default:
|
||||
return header.json.getObject(AVATAR)
|
||||
.getArray(THUMBNAILS);
|
||||
}
|
||||
})
|
||||
})
|
||||
.map(YoutubeParsingHelper::getImagesFromThumbnailsArray)
|
||||
.orElseThrow(() -> new ParsingException("Could not get avatars"));
|
||||
}
|
||||
|
@ -192,7 +192,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
return List.of();
|
||||
}
|
||||
|
||||
return channelHeader.map(header -> {
|
||||
return Optional.ofNullable(channelHeader)
|
||||
.map(header -> {
|
||||
if (header.headerType == HeaderType.PAGE) {
|
||||
final JsonObject pageHeaderViewModel = header.json.getObject(CONTENT)
|
||||
.getObject(PAGE_HEADER_VIEW_MODEL);
|
||||
|
@ -235,16 +236,14 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
return UNKNOWN_SUBSCRIBER_COUNT;
|
||||
}
|
||||
|
||||
if (channelHeader.isPresent()) {
|
||||
final ChannelHeader header = channelHeader.get();
|
||||
|
||||
if (header.headerType == HeaderType.INTERACTIVE_TABBED) {
|
||||
if (channelHeader != null) {
|
||||
if (channelHeader.headerType == HeaderType.INTERACTIVE_TABBED) {
|
||||
// No subscriber count is available on interactiveTabbedHeaderRenderer header
|
||||
return UNKNOWN_SUBSCRIBER_COUNT;
|
||||
}
|
||||
|
||||
final JsonObject headerJson = header.json;
|
||||
if (header.headerType == HeaderType.PAGE) {
|
||||
final JsonObject headerJson = channelHeader.json;
|
||||
if (channelHeader.headerType == HeaderType.PAGE) {
|
||||
return getSubscriberCountFromPageChannelHeader(headerJson);
|
||||
}
|
||||
|
||||
|
@ -321,19 +320,17 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
}
|
||||
|
||||
try {
|
||||
if (channelHeader.isPresent()) {
|
||||
final ChannelHeader header = channelHeader.get();
|
||||
if (header.headerType == HeaderType.INTERACTIVE_TABBED) {
|
||||
/*
|
||||
In an interactiveTabbedHeaderRenderer, the real description, is only available
|
||||
in its header
|
||||
The other one returned in non-About tabs accessible in the
|
||||
microformatDataRenderer object of the response may be completely different
|
||||
The description extracted is incomplete and the original one can be only
|
||||
accessed from the About tab
|
||||
*/
|
||||
return getTextFromObject(header.json.getObject("description"));
|
||||
}
|
||||
if (channelHeader != null
|
||||
&& channelHeader.headerType == HeaderType.INTERACTIVE_TABBED) {
|
||||
/*
|
||||
In an interactiveTabbedHeaderRenderer, the real description, is only available
|
||||
in its header
|
||||
The other one returned in non-About tabs accessible in the
|
||||
microformatDataRenderer object of the response may be completely different
|
||||
The description extracted is incomplete and the original one can be only
|
||||
accessed from the About tab
|
||||
*/
|
||||
return getTextFromObject(channelHeader.json.getObject("description"));
|
||||
}
|
||||
|
||||
return jsonResponse.getObject(METADATA)
|
||||
|
@ -368,8 +365,12 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
return false;
|
||||
}
|
||||
|
||||
return YoutubeChannelHelper.isChannelVerified(channelHeader.orElseThrow(() ->
|
||||
new ParsingException("Could not get verified status")));
|
||||
if (channelHeader == null) {
|
||||
throw new ParsingException(
|
||||
"Could not get channel verified status, no channel header has been extracted");
|
||||
}
|
||||
|
||||
return YoutubeChannelHelper.isChannelVerified(channelHeader);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -421,6 +422,19 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
|
||||
final String urlSuffix = urlParts[urlParts.length - 1];
|
||||
|
||||
/*
|
||||
Make a copy of the channelHeader member to avoid keeping a reference to
|
||||
this YoutubeChannelExtractor instance which would prevent serialization of
|
||||
the ReadyChannelTabListLinkHandler instance created above
|
||||
*/
|
||||
final ChannelHeader channelHeaderCopy;
|
||||
if (channelHeader == null) {
|
||||
channelHeaderCopy = null;
|
||||
} else {
|
||||
channelHeaderCopy = new ChannelHeader(channelHeader.json,
|
||||
channelHeader.headerType);
|
||||
}
|
||||
|
||||
switch (urlSuffix) {
|
||||
case "videos":
|
||||
// Since the Videos tab has already its contents fetched, make
|
||||
|
@ -431,9 +445,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
|||
channelId,
|
||||
ChannelTabs.VIDEOS,
|
||||
(service, linkHandler) -> new VideosTabExtractor(
|
||||
service, linkHandler, tabRenderer, channelHeader,
|
||||
name, id, url)));
|
||||
|
||||
service, linkHandler, tabRenderer,
|
||||
channelHeaderCopy, name, id, url)));
|
||||
break;
|
||||
case "shorts":
|
||||
addNonVideosTab.accept(ChannelTabs.SHORTS);
|
||||
|
|
|
@ -42,30 +42,15 @@ import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
|||
*/
|
||||
public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
||||
|
||||
/**
|
||||
* Whether the visitor data extracted from the initial channel response is required to be used
|
||||
* for continuations.
|
||||
*
|
||||
* <p>
|
||||
* A valid {@code visitorData} is required to get continuations of shorts in channels.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It should be not used when it is not needed, in order to reduce YouTube's tracking.
|
||||
* </p>
|
||||
*/
|
||||
private final boolean useVisitorData;
|
||||
@Nullable
|
||||
protected YoutubeChannelHelper.ChannelHeader channelHeader;
|
||||
|
||||
private JsonObject jsonResponse;
|
||||
private String channelId;
|
||||
@Nullable
|
||||
private String visitorData;
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
protected Optional<YoutubeChannelHelper.ChannelHeader> channelHeader;
|
||||
|
||||
public YoutubeChannelTabExtractor(final StreamingService service,
|
||||
final ListLinkHandler linkHandler) {
|
||||
super(service, linkHandler);
|
||||
useVisitorData = getName().equals(ChannelTabs.SHORTS);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -100,9 +85,6 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
jsonResponse = data.jsonResponse;
|
||||
channelHeader = YoutubeChannelHelper.getChannelHeader(jsonResponse);
|
||||
channelId = data.channelId;
|
||||
if (useVisitorData) {
|
||||
visitorData = jsonResponse.getObject("responseContext").getString("visitorData");
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -123,9 +105,9 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
}
|
||||
|
||||
protected String getChannelName() throws ParsingException {
|
||||
return YoutubeChannelHelper.getChannelName(
|
||||
channelHeader, jsonResponse,
|
||||
YoutubeChannelHelper.getChannelAgeGateRenderer(jsonResponse));
|
||||
return YoutubeChannelHelper.getChannelName(channelHeader,
|
||||
YoutubeChannelHelper.getChannelAgeGateRenderer(jsonResponse),
|
||||
jsonResponse);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -159,11 +141,14 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
}
|
||||
}
|
||||
|
||||
final VerifiedStatus verifiedStatus = channelHeader.flatMap(header ->
|
||||
YoutubeChannelHelper.isChannelVerified(header)
|
||||
? Optional.of(VerifiedStatus.VERIFIED)
|
||||
: Optional.of(VerifiedStatus.UNVERIFIED))
|
||||
.orElse(VerifiedStatus.UNKNOWN);
|
||||
final VerifiedStatus verifiedStatus;
|
||||
if (channelHeader == null) {
|
||||
verifiedStatus = VerifiedStatus.UNKNOWN;
|
||||
} else {
|
||||
verifiedStatus = YoutubeChannelHelper.isChannelVerified(channelHeader)
|
||||
? VerifiedStatus.VERIFIED
|
||||
: VerifiedStatus.UNVERIFIED;
|
||||
}
|
||||
|
||||
// If a channel tab is fetched, the next page requires channel ID and name, as channel
|
||||
// streams don't have their channel specified.
|
||||
|
@ -176,10 +161,8 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
channelName, channelUrl)
|
||||
.orElse(null);
|
||||
|
||||
final Page nextPage = getNextPageFrom(continuation,
|
||||
useVisitorData && !isNullOrEmpty(visitorData)
|
||||
? List.of(channelName, channelUrl, verifiedStatus.toString(), visitorData)
|
||||
: List.of(channelName, channelUrl, verifiedStatus.toString()));
|
||||
final Page nextPage = getNextPageFrom(
|
||||
continuation, List.of(channelName, channelUrl, verifiedStatus.toString()));
|
||||
|
||||
return new InfoItemsPage<>(collector, nextPage);
|
||||
}
|
||||
|
@ -299,6 +282,9 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
} else if (richItem.has("reelItemRenderer")) {
|
||||
commitReel(collector, richItem.getObject("reelItemRenderer"),
|
||||
channelVerifiedStatus, channelName, channelUrl);
|
||||
} else if (richItem.has("shortsLockupViewModel")) {
|
||||
commitShortsLockup(collector, richItem.getObject("shortsLockupViewModel"),
|
||||
channelVerifiedStatus, channelName, channelUrl);
|
||||
} else if (richItem.has("playlistRenderer")) {
|
||||
commitPlaylist(collector, richItem.getObject("playlistRenderer"),
|
||||
channelVerifiedStatus, channelName, channelUrl);
|
||||
|
@ -325,6 +311,12 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
} else if (item.has("expandedShelfContentsRenderer")) {
|
||||
return collectItemsFrom(collector, item.getObject("expandedShelfContentsRenderer")
|
||||
.getArray("items"), channelVerifiedStatus, channelName, channelUrl);
|
||||
} else if (item.has("lockupViewModel")) {
|
||||
final JsonObject lockupViewModel = item.getObject("lockupViewModel");
|
||||
if ("LOCKUP_CONTENT_TYPE_PLAYLIST".equals(lockupViewModel.getString("contentType"))) {
|
||||
commitPlaylistLockup(collector, lockupViewModel, channelVerifiedStatus,
|
||||
channelName, channelUrl);
|
||||
}
|
||||
} else if (item.has("continuationItemRenderer")) {
|
||||
return Optional.ofNullable(item.getObject("continuationItemRenderer"));
|
||||
}
|
||||
|
@ -356,6 +348,61 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
});
|
||||
}
|
||||
|
||||
private static void commitShortsLockup(@Nonnull final MultiInfoItemsCollector collector,
|
||||
@Nonnull final JsonObject shortsLockupViewModel,
|
||||
@Nonnull final VerifiedStatus channelVerifiedStatus,
|
||||
@Nullable final String channelName,
|
||||
@Nullable final String channelUrl) {
|
||||
collector.commit(
|
||||
new YoutubeShortsLockupInfoItemExtractor(shortsLockupViewModel) {
|
||||
@Override
|
||||
public String getUploaderName() throws ParsingException {
|
||||
return isNullOrEmpty(channelName) ? super.getUploaderName() : channelName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUploaderUrl() throws ParsingException {
|
||||
return isNullOrEmpty(channelUrl) ? super.getUploaderName() : channelUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUploaderVerified() {
|
||||
return channelVerifiedStatus == VerifiedStatus.VERIFIED;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void commitPlaylistLockup(@Nonnull final MultiInfoItemsCollector collector,
|
||||
@Nonnull final JsonObject playlistLockupViewModel,
|
||||
@Nonnull final VerifiedStatus channelVerifiedStatus,
|
||||
@Nullable final String channelName,
|
||||
@Nullable final String channelUrl) {
|
||||
collector.commit(
|
||||
new YoutubeMixOrPlaylistLockupInfoItemExtractor(playlistLockupViewModel) {
|
||||
@Override
|
||||
public String getUploaderName() throws ParsingException {
|
||||
return isNullOrEmpty(channelName) ? super.getUploaderName() : channelName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUploaderUrl() throws ParsingException {
|
||||
return isNullOrEmpty(channelUrl) ? super.getUploaderName() : channelUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUploaderVerified() throws ParsingException {
|
||||
switch (channelVerifiedStatus) {
|
||||
case VERIFIED:
|
||||
return true;
|
||||
case UNVERIFIED:
|
||||
return false;
|
||||
default:
|
||||
return super.isUploaderVerified();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void commitVideo(@Nonnull final MultiInfoItemsCollector collector,
|
||||
@Nonnull final TimeAgoParser timeAgoParser,
|
||||
@Nonnull final JsonObject jsonObject,
|
||||
|
@ -434,8 +481,7 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
.getString("token");
|
||||
|
||||
final byte[] body = JsonWriter.string(prepareDesktopJsonBuilder(getExtractorLocalization(),
|
||||
getExtractorContentCountry(),
|
||||
useVisitorData && channelIds.size() >= 3 ? channelIds.get(2) : null)
|
||||
getExtractorContentCountry())
|
||||
.value("continuation", continuation)
|
||||
.done())
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
@ -457,8 +503,7 @@ public class YoutubeChannelTabExtractor extends ChannelTabExtractor {
|
|||
VideosTabExtractor(final StreamingService service,
|
||||
final ListLinkHandler linkHandler,
|
||||
final JsonObject tabRenderer,
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
final Optional<YoutubeChannelHelper.ChannelHeader> channelHeader,
|
||||
@Nullable final YoutubeChannelHelper.ChannelHeader channelHeader,
|
||||
final String channelName,
|
||||
final String channelId,
|
||||
final String channelUrl) {
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
package org.schabi.newpipe.extractor.services.youtube.extractors;
|
||||
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import org.schabi.newpipe.extractor.Image;
|
||||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor;
|
||||
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubePlaylistLinkHandlerFactory;
|
||||
import org.schabi.newpipe.extractor.utils.Utils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.extractPlaylistTypeFromPlaylistId;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getImagesFromThumbnailsArray;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getUrlFromNavigationEndpoint;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.hasArtistOrVerifiedIconBadgeAttachment;
|
||||
|
||||
public class YoutubeMixOrPlaylistLockupInfoItemExtractor implements PlaylistInfoItemExtractor {
|
||||
|
||||
@Nonnull
|
||||
private final JsonObject lockupViewModel;
|
||||
@Nonnull
|
||||
private final JsonObject thumbnailViewModel;
|
||||
@Nonnull
|
||||
private final JsonObject lockupMetadataViewModel;
|
||||
@Nonnull
|
||||
private final JsonObject firstMetadataRow;
|
||||
@Nonnull
|
||||
private PlaylistInfo.PlaylistType playlistType;
|
||||
|
||||
public YoutubeMixOrPlaylistLockupInfoItemExtractor(@Nonnull final JsonObject lockupViewModel) {
|
||||
this.lockupViewModel = lockupViewModel;
|
||||
this.thumbnailViewModel = lockupViewModel.getObject("contentImage")
|
||||
.getObject("collectionThumbnailViewModel")
|
||||
.getObject("primaryThumbnail")
|
||||
.getObject("thumbnailViewModel");
|
||||
this.lockupMetadataViewModel = lockupViewModel.getObject("metadata")
|
||||
.getObject("lockupMetadataViewModel");
|
||||
/*
|
||||
The metadata rows are structured in the following way:
|
||||
1st part: uploader info, playlist type, playlist updated date
|
||||
2nd part: space row
|
||||
3rd element: first video
|
||||
4th (not always returned for playlists with less than 2 items?): second video
|
||||
5th element (always returned, but at a different index for playlists with less than 2
|
||||
items?): Show full playlist
|
||||
|
||||
The first metadata row has the following structure:
|
||||
1st array element: uploader info
|
||||
2nd element: playlist type (course, playlist, podcast)
|
||||
3rd element (not always returned): playlist updated date
|
||||
*/
|
||||
this.firstMetadataRow = lockupMetadataViewModel.getObject("metadata")
|
||||
.getObject("contentMetadataViewModel")
|
||||
.getArray("metadataRows")
|
||||
.getObject(0);
|
||||
|
||||
try {
|
||||
this.playlistType = extractPlaylistTypeFromPlaylistId(getPlaylistId());
|
||||
} catch (final ParsingException e) {
|
||||
// If we cannot extract the playlist type, fall back to the normal one
|
||||
this.playlistType = PlaylistInfo.PlaylistType.NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUploaderName() throws ParsingException {
|
||||
return firstMetadataRow.getArray("metadataParts")
|
||||
.getObject(0)
|
||||
.getObject("text")
|
||||
.getString("content");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUploaderUrl() throws ParsingException {
|
||||
if (playlistType != PlaylistInfo.PlaylistType.NORMAL) {
|
||||
// If the playlist is a mix, there is no uploader as they are auto-generated
|
||||
return null;
|
||||
}
|
||||
|
||||
return getUrlFromNavigationEndpoint(
|
||||
firstMetadataRow.getArray("metadataParts")
|
||||
.getObject(0)
|
||||
.getObject("text")
|
||||
.getArray("commandRuns")
|
||||
.getObject(0)
|
||||
.getObject("onTap")
|
||||
.getObject("innertubeCommand"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUploaderVerified() throws ParsingException {
|
||||
if (playlistType != PlaylistInfo.PlaylistType.NORMAL) {
|
||||
// If the playlist is a mix, there is no uploader as they are auto-generated
|
||||
return false;
|
||||
}
|
||||
|
||||
return hasArtistOrVerifiedIconBadgeAttachment(
|
||||
firstMetadataRow.getArray("metadataParts")
|
||||
.getObject(0)
|
||||
.getObject("text")
|
||||
.getArray("attachmentRuns"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStreamCount() throws ParsingException {
|
||||
if (playlistType != PlaylistInfo.PlaylistType.NORMAL) {
|
||||
// If the playlist is a mix, we are not able to get its stream count
|
||||
return ListExtractor.ITEM_COUNT_INFINITE;
|
||||
}
|
||||
|
||||
try {
|
||||
return Long.parseLong(Utils.removeNonDigitCharacters(
|
||||
thumbnailViewModel.getArray("overlays")
|
||||
.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.filter(overlay -> overlay.has("thumbnailOverlayBadgeViewModel"))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new ParsingException(
|
||||
"Could not get thumbnailOverlayBadgeViewModel"))
|
||||
.getObject("thumbnailOverlayBadgeViewModel")
|
||||
.getArray("thumbnailBadges")
|
||||
.stream()
|
||||
.filter(JsonObject.class::isInstance)
|
||||
.map(JsonObject.class::cast)
|
||||
.filter(badge -> badge.has("thumbnailBadgeViewModel"))
|
||||
.findFirst()
|
||||
.orElseThrow(() ->
|
||||
new ParsingException("Could not get thumbnailBadgeViewModel"))
|
||||
.getObject("thumbnailBadgeViewModel")
|
||||
.getString("text")));
|
||||
} catch (final Exception e) {
|
||||
throw new ParsingException("Could not get playlist stream count", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() throws ParsingException {
|
||||
return lockupMetadataViewModel.getObject("title")
|
||||
.getString("content");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() throws ParsingException {
|
||||
// If the playlist item is a mix, we cannot return just its playlist ID as mix playlists
|
||||
// are not viewable in playlist pages
|
||||
// Use directly getUrlFromNavigationEndpoint in this case, which returns the watch URL with
|
||||
// the mix playlist
|
||||
if (playlistType == PlaylistInfo.PlaylistType.NORMAL) {
|
||||
try {
|
||||
return YoutubePlaylistLinkHandlerFactory.getInstance().getUrl(getPlaylistId());
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return getUrlFromNavigationEndpoint(lockupViewModel.getObject("rendererContext")
|
||||
.getObject("commandContext")
|
||||
.getObject("onTap")
|
||||
.getObject("innertubeCommand"));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<Image> getThumbnails() throws ParsingException {
|
||||
return getImagesFromThumbnailsArray(thumbnailViewModel.getObject("image")
|
||||
.getArray("sources"));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public PlaylistInfo.PlaylistType getPlaylistType() throws ParsingException {
|
||||
return playlistType;
|
||||
}
|
||||
|
||||
private String getPlaylistId() throws ParsingException {
|
||||
String id = lockupViewModel.getString("contentId");
|
||||
if (Utils.isNullOrEmpty(id)) {
|
||||
id = lockupViewModel.getObject("rendererContext")
|
||||
.getObject("commandContext")
|
||||
.getObject("watchEndpoint")
|
||||
.getString("playlistId");
|
||||
}
|
||||
|
||||
if (Utils.isNullOrEmpty(id)) {
|
||||
throw new ParsingException("Could not get playlist ID");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -20,13 +20,19 @@ import javax.annotation.Nonnull;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A {@link StreamInfoItemExtractor} for YouTube's {@code reelItemRenderers}.
|
||||
* A {@link StreamInfoItemExtractor} for YouTube's {@code reelItemRenderer}s.
|
||||
*
|
||||
* <p>
|
||||
* {@code reelItemRenderers} are returned on YouTube for their short-form contents on almost every
|
||||
* {@code reelItemRenderer}s were returned on YouTube for their short-form contents on almost every
|
||||
* place and every major client. They provide a limited amount of information and do not provide
|
||||
* the exact view count, any uploader info (name, URL, avatar, verified status) and the upload date.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* At the time this documentation has been updated, they are being replaced by
|
||||
* {@code shortsLockupViewModel}s. See {@link YoutubeShortsLockupInfoItemExtractor} for an
|
||||
* extractor for this new UI data type.
|
||||
* </p>
|
||||
*/
|
||||
public class YoutubeReelInfoItemExtractor implements StreamInfoItemExtractor {
|
||||
|
||||
|
|
|
@ -245,6 +245,13 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
|||
} else if (item.has("showRenderer")) {
|
||||
collector.commit(new YoutubeShowRendererInfoItemExtractor(
|
||||
item.getObject("showRenderer")));
|
||||
} else if (item.has("lockupViewModel")) {
|
||||
final JsonObject lockupViewModel = item.getObject("lockupViewModel");
|
||||
if ("LOCKUP_CONTENT_TYPE_PLAYLIST".equals(
|
||||
lockupViewModel.getString("contentType"))) {
|
||||
collector.commit(
|
||||
new YoutubeMixOrPlaylistLockupInfoItemExtractor(lockupViewModel));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
package org.schabi.newpipe.extractor.services.youtube.extractors;
|
||||
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import org.schabi.newpipe.extractor.Image;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.extractor.utils.Utils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getImagesFromThumbnailsArray;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
/**
|
||||
* A {@link StreamInfoItemExtractor} for YouTube's {@code shortsLockupViewModel}s.
|
||||
*
|
||||
* <p>
|
||||
* {@code shortsLockupViewModel}s are returned on YouTube for their short-form contents on almost
|
||||
* every place and every major client. They provide a limited amount of information and do not
|
||||
* provide the exact view count, any uploader info (name, URL, avatar, verified status) and the
|
||||
* upload date.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* At the time this documentation has been written, this data UI type is not fully used (rolled
|
||||
* out), so {@code reelItemRenderer}s are also returned. See {@link YoutubeReelInfoItemExtractor}
|
||||
* for an extractor for this UI data type.
|
||||
* </p>
|
||||
*/
|
||||
public class YoutubeShortsLockupInfoItemExtractor implements StreamInfoItemExtractor {
|
||||
|
||||
@Nonnull
|
||||
private final JsonObject shortsLockupViewModel;
|
||||
|
||||
public YoutubeShortsLockupInfoItemExtractor(@Nonnull final JsonObject shortsLockupViewModel) {
|
||||
this.shortsLockupViewModel = shortsLockupViewModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() throws ParsingException {
|
||||
return shortsLockupViewModel.getObject("overlayMetadata")
|
||||
.getObject("primaryText")
|
||||
.getString("content");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() throws ParsingException {
|
||||
String videoId = shortsLockupViewModel.getObject("onTap")
|
||||
.getObject("innertubeCommand")
|
||||
.getObject("reelWatchEndpoint")
|
||||
.getString("videoId");
|
||||
|
||||
if (isNullOrEmpty(videoId)) {
|
||||
videoId = shortsLockupViewModel.getObject("inlinePlayerData")
|
||||
.getObject("onVisible")
|
||||
.getObject("innertubeCommand")
|
||||
.getObject("watchEndpoint")
|
||||
.getString("videoId");
|
||||
}
|
||||
|
||||
if (isNullOrEmpty(videoId)) {
|
||||
throw new ParsingException("Could not get video ID");
|
||||
}
|
||||
|
||||
try {
|
||||
return YoutubeStreamLinkHandlerFactory.getInstance().getUrl(videoId);
|
||||
} catch (final Exception e) {
|
||||
throw new ParsingException("Could not get URL", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<Image> getThumbnails() throws ParsingException {
|
||||
return getImagesFromThumbnailsArray(shortsLockupViewModel.getObject("thumbnail")
|
||||
.getArray("sources"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamType getStreamType() throws ParsingException {
|
||||
return StreamType.VIDEO_STREAM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getViewCount() throws ParsingException {
|
||||
final String viewCountText = shortsLockupViewModel.getObject("overlayMetadata")
|
||||
.getObject("secondaryText")
|
||||
.getString("content");
|
||||
if (!isNullOrEmpty(viewCountText)) {
|
||||
// This approach is language dependent
|
||||
if (viewCountText.toLowerCase().contains("no views")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Utils.mixedNumberWordToLong(viewCountText);
|
||||
}
|
||||
|
||||
throw new ParsingException("Could not get short view count");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShortFormContent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// All the following properties cannot be obtained from shortsLockupViewModels
|
||||
|
||||
@Override
|
||||
public boolean isAd() throws ParsingException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDuration() throws ParsingException {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUploaderName() throws ParsingException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUploaderUrl() throws ParsingException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUploaderVerified() throws ParsingException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getTextualUploadDate() throws ParsingException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DateWrapper getUploadDate() throws ParsingException {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -726,6 +726,13 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||
} else if (result.has("compactPlaylistRenderer")) {
|
||||
return new YoutubeMixOrPlaylistInfoItemExtractor(
|
||||
result.getObject("compactPlaylistRenderer"));
|
||||
} else if (result.has("lockupViewModel")) {
|
||||
final JsonObject lockupViewModel = result.getObject("lockupViewModel");
|
||||
if ("LOCKUP_CONTENT_TYPE_PLAYLIST".equals(
|
||||
lockupViewModel.getString("contentType"))) {
|
||||
return new YoutubeMixOrPlaylistLockupInfoItemExtractor(
|
||||
lockupViewModel);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})
|
||||
|
@ -1377,6 +1384,20 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
|||
return itagInfo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Should return a list of Frameset object that contains preview of stream frames
|
||||
*
|
||||
* <p><b>Warning:</b> When using this method be aware
|
||||
* that the YouTube API very rarely returns framesets,
|
||||
* that are slightly too small e.g. framesPerPageX = 5, frameWidth = 160, but the url contains
|
||||
* a storyboard that is only 795 pixels wide (5*160 > 795). You will need to handle this
|
||||
* "manually" to avoid errors.</p>
|
||||
*
|
||||
* @see <a href="https://github.com/TeamNewPipe/NewPipe/pull/11596">
|
||||
* TeamNewPipe/NewPipe#11596</a>
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<Frameset> getFrames() throws ExtractionException {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package org.schabi.newpipe.extractor.stream;
|
||||
|
||||
/**
|
||||
* An enum representing the track type of an {@link AudioStream} extracted by a {@link
|
||||
* An enum representing the track type of {@link AudioStream}s extracted by a {@link
|
||||
* StreamExtractor}.
|
||||
*/
|
||||
public enum AudioTrackType {
|
||||
|
||||
/**
|
||||
* An original audio track of the video.
|
||||
* An original audio track of a video.
|
||||
*/
|
||||
ORIGINAL,
|
||||
|
||||
|
@ -20,6 +21,7 @@ public enum AudioTrackType {
|
|||
|
||||
/**
|
||||
* A descriptive audio track.
|
||||
*
|
||||
* <p>
|
||||
* A descriptive audio track is an audio track in which descriptions of visual elements of
|
||||
* a video are added to the original audio, with the goal to make a video more accessible to
|
||||
|
@ -29,5 +31,15 @@ public enum AudioTrackType {
|
|||
* @see <a href="https://en.wikipedia.org/wiki/Audio_description">
|
||||
* https://en.wikipedia.org/wiki/Audio_description</a>
|
||||
*/
|
||||
DESCRIPTIVE
|
||||
DESCRIPTIVE,
|
||||
|
||||
/**
|
||||
* A secondary audio track.
|
||||
*
|
||||
* <p>
|
||||
* A secondary audio track can be an alternate audio track from the original language of a
|
||||
* video or an alternate language.
|
||||
* </p>
|
||||
*/
|
||||
SECONDARY
|
||||
}
|
||||
|
|
|
@ -18,8 +18,11 @@ import okhttp3.RequestBody;
|
|||
import okhttp3.ResponseBody;
|
||||
|
||||
public final class DownloaderTestImpl extends Downloader {
|
||||
/**
|
||||
* Should be the latest Firefox ESR version.
|
||||
*/
|
||||
private static final String USER_AGENT
|
||||
= "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0";
|
||||
= "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0";
|
||||
private static DownloaderTestImpl instance;
|
||||
private final OkHttpClient client;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
@ -37,17 +38,31 @@ import javax.annotation.Nonnull;
|
|||
*/
|
||||
class RecordingDownloader extends Downloader {
|
||||
|
||||
public final static String FILE_NAME_PREFIX = "generated_mock_";
|
||||
public static final String FILE_NAME_PREFIX = "generated_mock_";
|
||||
|
||||
// From https://stackoverflow.com/a/15875500/13516981
|
||||
private final static String IP_V4_PATTERN =
|
||||
private static final String IP_V4_PATTERN =
|
||||
"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
|
||||
|
||||
private int index = 0;
|
||||
private final String path;
|
||||
|
||||
// try to prevent ReCaptchaExceptions / rate limits by tracking and throttling the requests
|
||||
/**
|
||||
* Creates the folder described by {@code stringPath} if it does not exists.
|
||||
* The maximum number of requests per 20 seconds which are executed
|
||||
* by the {@link RecordingDownloader}.
|
||||
* 20 seconds is used as upper bound because the rate limit can be triggered within 30 seconds
|
||||
* and hitting the rate limit should be prevented because it comes with a bigger delay.
|
||||
* The values can be adjusted when executing the downloader and running into problems.
|
||||
* <p>TODO: Allow adjusting the value by setting a param in the gradle command</p>
|
||||
*/
|
||||
private static final int MAX_REQUESTS_PER_20_SECONDS = 30;
|
||||
private static final long[] requestTimes = new long[MAX_REQUESTS_PER_20_SECONDS];
|
||||
private static int requestTimesCursor = -1;
|
||||
private static final Random throttleRandom = new Random();
|
||||
|
||||
/**
|
||||
* Creates the folder described by {@code stringPath} if it does not exist.
|
||||
* Deletes existing files starting with {@link RecordingDownloader#FILE_NAME_PREFIX}.
|
||||
* @param stringPath Path to the folder where the json files will be saved to.
|
||||
*/
|
||||
|
@ -69,6 +84,48 @@ class RecordingDownloader extends Downloader {
|
|||
@Override
|
||||
public Response execute(@Nonnull final Request request) throws IOException,
|
||||
ReCaptchaException {
|
||||
|
||||
// Delay the execution if the max number of requests per minute is reached
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
// the cursor points to the latest request time and the next position is the oldest one
|
||||
final int oldestRequestTimeCursor = (requestTimesCursor + 1) % requestTimes.length;
|
||||
final long oldestRequestTime = requestTimes[oldestRequestTimeCursor];
|
||||
if (oldestRequestTime + 20_000 >= currentTime) {
|
||||
try {
|
||||
// sleep at least until the oldest request is 20s old, but not more than 20s
|
||||
final int minSleepTime = (int) (currentTime - oldestRequestTime);
|
||||
Thread.sleep(minSleepTime + throttleRandom.nextInt(20_000 - minSleepTime));
|
||||
} catch (InterruptedException e) {
|
||||
// handle the exception gracefully because it's not critical for the test
|
||||
System.err.println("Error while throttling the RecordingDownloader.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
requestTimesCursor = oldestRequestTimeCursor; // the oldest value needs to be overridden
|
||||
requestTimes[requestTimesCursor] = System.currentTimeMillis();
|
||||
|
||||
// Handle ReCaptchaExceptions by retrying the request once after a while
|
||||
try {
|
||||
return executeRequest(request);
|
||||
} catch (ReCaptchaException e) {
|
||||
try {
|
||||
// sleep for 35-60 seconds to circumvent the rate limit
|
||||
System.out.println("Throttling the RecordingDownloader to handle a ReCaptcha."
|
||||
+ " Sleeping for 35-60 seconds.");
|
||||
Thread.sleep(35_000 + throttleRandom.nextInt(25_000));
|
||||
} catch (InterruptedException ie) {
|
||||
// handle the exception gracefully because it's not critical for the test
|
||||
System.err.println("Error while throttling the RecordingDownloader.");
|
||||
ie.printStackTrace();
|
||||
e.printStackTrace();
|
||||
}
|
||||
return executeRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Response executeRequest(@Nonnull final Request request) throws IOException,
|
||||
ReCaptchaException {
|
||||
final Downloader downloader = DownloaderTestImpl.getInstance();
|
||||
Response response = downloader.execute(request);
|
||||
String cleanedResponseBody = response.responseBody().replaceAll(IP_V4_PATTERN, "127.0.0.1");
|
||||
|
|
|
@ -234,4 +234,111 @@ public class PeertubeChannelExtractorTest {
|
|||
assertTrue(extractor.getTags().isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
public static class DocumentaryChannel implements BaseChannelExtractorTest {
|
||||
// https://github.com/TeamNewPipe/NewPipe/issues/11369
|
||||
|
||||
private static PeertubeChannelExtractor extractor;
|
||||
|
||||
@BeforeAll
|
||||
public static void setUp() throws Exception {
|
||||
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||
// setting instance might break test when running in parallel
|
||||
PeerTube.setInstance(new PeertubeInstance("https://kolektiva.media", "kolektiva.media"));
|
||||
extractor = (PeertubeChannelExtractor) PeerTube
|
||||
.getChannelExtractor("https://kolektiva.media/video-channels/documentary_channel");
|
||||
extractor.fetchPage();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Extractor
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Test
|
||||
public void testServiceId() {
|
||||
assertEquals(PeerTube.getServiceId(), extractor.getServiceId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testName() throws ParsingException {
|
||||
assertEquals("Documentary Channel", extractor.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testId() throws ParsingException {
|
||||
assertEquals("video-channels/documentary_channel", extractor.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUrl() throws ParsingException {
|
||||
assertEquals("https://kolektiva.media/video-channels/documentary_channel", extractor.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOriginalUrl() throws ParsingException {
|
||||
assertEquals("https://kolektiva.media/video-channels/documentary_channel", extractor.getOriginalUrl());
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// ChannelExtractor
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Test
|
||||
public void testDescription() {
|
||||
assertNotNull(extractor.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParentChannelName() throws ParsingException {
|
||||
assertEquals("consumedmind", extractor.getParentChannelName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParentChannelUrl() throws ParsingException {
|
||||
assertEquals("https://kolektiva.media/accounts/consumedmind", extractor.getParentChannelUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParentChannelAvatars() {
|
||||
defaultTestImageCollection(extractor.getParentChannelAvatars());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAvatars() {
|
||||
defaultTestImageCollection(extractor.getAvatars());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBanners() throws ParsingException {
|
||||
assertGreaterOrEqual(1, extractor.getBanners().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeedUrl() throws ParsingException {
|
||||
assertEquals("https://kolektiva.media/feeds/videos.xml?videoChannelId=2994", extractor.getFeedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriberCount() {
|
||||
assertGreaterOrEqual(25, extractor.getSubscriberCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testVerified() throws Exception {
|
||||
assertFalse(extractor.isVerified());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testTags() throws Exception {
|
||||
assertTrue(extractor.getTags().isEmpty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public class PeertubeChannelLinkHandlerFactoryTest {
|
|||
assertTrue(linkHandler.acceptUrl("https://peertube.stream/video-channels/kranti_channel@videos.squat.net/videos"));
|
||||
assertTrue(linkHandler.acceptUrl("https://peertube.stream/c/kranti_channel@videos.squat.net/videos"));
|
||||
assertTrue(linkHandler.acceptUrl("https://peertube.stream/api/v1/video-channels/7682d9f2-07be-4622-862e-93ec812e2ffa"));
|
||||
assertTrue(linkHandler.acceptUrl("https://kolektiva.media/video-channels/documentary_channel"));
|
||||
|
||||
assertDoNotAcceptNonURLs(linkHandler);
|
||||
}
|
||||
|
@ -60,6 +61,16 @@ public class PeertubeChannelLinkHandlerFactoryTest {
|
|||
linkHandler.fromUrl("https://peertube.stream/c/kranti_channel@videos.squat.net/video-playlists").getId());
|
||||
assertEquals("video-channels/kranti_channel@videos.squat.net",
|
||||
linkHandler.fromUrl("https://peertube.stream/api/v1/video-channels/kranti_channel@videos.squat.net").getId());
|
||||
|
||||
// instance URL ending with an "a": https://kolektiva.media
|
||||
assertEquals("video-channels/documentary_channel",
|
||||
linkHandler.fromUrl("https://kolektiva.media/video-channels/documentary_channel/videos").getId());
|
||||
assertEquals("video-channels/documentary_channel",
|
||||
linkHandler.fromUrl("https://kolektiva.media/c/documentary_channel/videos").getId());
|
||||
assertEquals("video-channels/documentary_channel",
|
||||
linkHandler.fromUrl("https://kolektiva.media/c/documentary_channel/video-playlists").getId());
|
||||
assertEquals("video-channels/documentary_channel",
|
||||
linkHandler.fromUrl("https://kolektiva.media/api/v1/video-channels/documentary_channel").getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -49,7 +49,7 @@ public class SoundcloudStreamExtractorTest {
|
|||
|
||||
@Override public StreamExtractor extractor() { return extractor; }
|
||||
@Override public StreamingService expectedService() { return SoundCloud; }
|
||||
@Override public String expectedName() { return "Jess Glynne & Jax Jones - One Touch"; }
|
||||
@Override public String expectedName() { return "One Touch"; }
|
||||
@Override public String expectedId() { return "621612588"; }
|
||||
@Override public String expectedUrlContains() { return UPLOADER + "/" + ID; }
|
||||
@Override public String expectedOriginalUrlContains() { return URL; }
|
||||
|
|
|
@ -232,8 +232,7 @@ public class YoutubeChannelExtractorTest {
|
|||
@Test
|
||||
@Override
|
||||
public void testTabs() throws Exception {
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS,
|
||||
ChannelTabs.LIVESTREAMS, ChannelTabs.PLAYLISTS);
|
||||
assertTabsContain(extractor.getTabs(), ChannelTabs.VIDEOS, ChannelTabs.PLAYLISTS);
|
||||
assertTrue(extractor.getTabs().stream()
|
||||
.filter(it -> ChannelTabs.VIDEOS.equals(it.getContentFilters().get(0)))
|
||||
.allMatch(ReadyChannelTabListLinkHandler.class::isInstance));
|
||||
|
|
|
@ -40,7 +40,7 @@ public class YoutubeStreamExtractorLivestreamTest extends DefaultStreamExtractor
|
|||
|
||||
@Override public StreamExtractor extractor() { return extractor; }
|
||||
@Override public StreamingService expectedService() { return YouTube; }
|
||||
@Override public String expectedName() { return "lofi hip hop radio \uD83D\uDCDA - beats to relax/study to"; }
|
||||
@Override public String expectedName() { return "lofi hip hop radio \uD83D\uDCDA beats to relax/study to"; }
|
||||
@Override public String expectedId() { return ID; }
|
||||
@Override public String expectedUrlContains() { return YoutubeStreamExtractorDefaultTest.BASE_URL + ID; }
|
||||
@Override public String expectedOriginalUrlContains() { return URL; }
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 18:09:57 GMT"
|
||||
"Sun, 10 Nov 2024 17:54:30 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 18:09:57 GMT"
|
||||
"Sun, 10 Nov 2024 17:54:30 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dAc2NF4wLV18; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 18:09:57 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003da4d0v1pvpMk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:54:30 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:47:54 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:59 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:47:54 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:59 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dQ-hpT9jfKtU; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:47:54 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dj9_R69devYo; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:47:59 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13,7 +13,7 @@
|
|||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240718.01.00"
|
||||
"2.20241107.11.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -229,12 +229,12 @@
|
|||
48,
|
||||
50,
|
||||
52,
|
||||
49,
|
||||
49,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
|
@ -362,7 +362,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:47:56 GMT"
|
||||
"Sun, 10 Nov 2024 17:48:19 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
@ -382,7 +382,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtzVEVQR1dURHphWSjMquW0BjIiCgJGUhIcEhgSFgsMDg8QERITFBUWFxgZGhscHR4fICEgGA%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240718.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xd625b21ac0ea5a53\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23703445,23804281,23946420,23966208,23986028,23998056,24004644,24077241,24166867,24181174,24241378,24290971,24439361,24453989,24456089,24468724,24499533,24542367,24548627,24548629,24550458,24566687,24690004,24699899,39325854,39326848,39326916,51009781,51010235,51016856,51017346,51020570,51025415,51030101,51037346,51037353,51041512,51050361,51053689,51057848,51057851,51060353,51063643,51064835,51072748,51091058,51091331,51095478,51098297,51098299,51102410,51105630,51111738,51113658,51113661,51115184,51116067,51117319,51118932,51121939,51124104,51133103,51139379,51141472,51148688,51148974,51148983,51149607,51150450,51152050,51157411,51157430,51157432,51157838,51158470,51158514,51160545,51162170,51163635,51165467,51165568,51169117,51170249,51172670,51172684,51172691,51172700,51172707,51172716,51172723,51172728,51173021,51173508,51175606,51176511,51178310,51178333,51178340,51178357,51178706,51178982,51182275,51183508,51183909,51184022,51184990,51186528,51186670,51189826,51190059,51190075,51190078,51190085,51190198,51190213,51190220,51190229,51190652,51193591,51194137,51195231,51196476,51196769,51197569,51197687,51197694,51197697,51197708,51199193,51200251,51200256,51200295,51200298,51200568,51201350,51201363,51201372,51201381,51201428,51201435,51201444,51201451,51201814,51203141,51203200,51204329,51204587,51204938,51207174,51207191,51207196,51207209,51209172,51210770,51211461,51212464,51212553,51212567,51213807,51217504,51219800,51221011,51221152,51222152,51222695,51223962,51224134,51224747,51224922,51225437,51226344,51227408,51227772,51227881,51227902,51228202,51228349,51228351,51228695,51228771,51228776,51228787,51228796,51228805,51228814,51229628,51230124,51230423,51230478,51230492,51232125,51232143,51232230,51233332,51235147,51237540,51238400,51238514,51238569,51238736,51240880,51240888,51241028,51241600\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240718\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIusK-7pKxhwMVBDPxBR08yQnhMghleHRlcm5hbJoBAA\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\":\"Cgt2SjhfUUx2UnFmayjj48O5BjIKCgJERRIEEgAgRQ%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20241107.11.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x3a41c164850da49a\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"9406121,23804281,23880829,23880835,23966208,23986021,24004644,24077241,24166867,24181174,24241378,24299873,24439361,24445497,24453989,24459436,24542367,24547317,24548629,24566687,24699899,39325854,39326986,51009781,51010235,51017346,51020570,51025415,51030101,51037344,51037351,51050361,51053689,51057844,51057851,51063643,51064835,51072748,51091058,51095478,51098299,51101169,51111738,51115184,51117319,51124104,51129210,51133103,51134507,51141472,51144925,51151423,51152050,51156055,51157411,51157841,51158514,51160545,51165467,51169118,51176511,51178310,51178331,51178344,51178355,51178982,51182851,51183909,51184990,51194137,51195231,51204329,51213773,51217504,51221150,51222382,51222973,51223961,51226709,51227037,51227778,51228350,51230241,51230478,51231220,51231814,51237842,51239093,51241028,51242448,51243940,51248255,51248734,51249749,51251836,51255676,51255680,51255743,51256074,51256084,51257900,51257911,51257916,51258066,51259133,51260456,51263449,51265335,51265364,51265369,51266454,51272458,51273608,51274583,51275782,51276557,51276565,51281227,51282069,51282086,51282792,51283950,51284503,51285052,51285417,51285717,51287196,51287500,51289926,51289935,51289938,51289952,51289961,51289970,51290043,51291889,51294322,51295132,51295578,51296439,51298019,51298020,51299154,51299710,51299724,51299977,51299999,51300010,51300176,51300241,51300699,51302492,51302680,51303667,51303669,51303789,51304004,51304155,51305839,51306259,51307502,51308045,51308060,51308871,51309313,51310323,51311031,51311034,51311505,51311520,51312150,51312688,51313149,51313767,51314158,51314669,51314681,51314692,51314699,51314710,51314727,51315041,51315914,51315919,51315926,51315935,51315940,51315949,51315956,51315963,51315968,51315979,51316415,51316749,51317749,51318845,51320778,51323366,51325576,51326208,51326527,51326641,51326762,51326932,51327144,51327165,51327178,51327614,51327636,51328144,51329146,51329227,51329392,51329506,51330194,51330660,51331481,51331500,51331522,51331531,51331538,51331547,51331554,51331561,51332896,51333739,51333878,51335364,51335570,51335973,51336632,51337186,51337349,51337702,51338495,51338524,51339163,51339747,51340618,51341226,51341729,51342093,51342576,51342845,51343110,51343368,51344672,51344926,51345126,51345228\"},{\"key\":\"visitor_data\",\"value\":\"Cgt2SjhfUUx2UnFmayjj48O5BjIKCgJERRIEEgAgRQ%3D%3D\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20241107\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIxIjKt6nSiQMVJEF6BR10IyrwMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UC6nSFpj9HTCZ5t-N3Rm3-HA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:49:35 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:56 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:49:35 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:56 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dZHHPT-DrXJQ; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:49:35 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dHEqrYtop-08; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:46:56 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:48:47 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:57 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:48:47 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:57 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003d9_8OVS-ITHc; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:48:47 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dw-_Feucl-TI; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:46:57 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3,17 +3,17 @@
|
|||
"httpMethod": "POST",
|
||||
"url": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Cookie": [
|
||||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240718.01.00"
|
||||
"2.20241107.11.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -229,12 +229,12 @@
|
|||
48,
|
||||
50,
|
||||
52,
|
||||
49,
|
||||
49,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
|
@ -374,7 +374,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:48:48 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:57 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
@ -394,7 +394,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtiVTZPVEtWdkUtayiAq-W0BjIiCgJGUhIcEhgSFgsMDg8QERITFBUWFxgZGhscHR4fICEgMg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240718.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xe140936d506561d9\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23946420,23966208,23986015,23998056,24004644,24077241,24108448,24166867,24181174,24241378,24290971,24439361,24453989,24456089,24468724,24542367,24543669,24548627,24548629,24550458,24566687,24699899,39325854,39326848,39326916,51009781,51010235,51016856,51017346,51020570,51025415,51030101,51037342,51037349,51041512,51050361,51053689,51057846,51057851,51060353,51063643,51064835,51072748,51087998,51091058,51091331,51095478,51098297,51098299,51102409,51111738,51113656,51113663,51115184,51116067,51118932,51124104,51126280,51131738,51133103,51139379,51141472,51144926,51148688,51148978,51148985,51149422,51149607,51150448,51152050,51153490,51157411,51157430,51157432,51157838,51157895,51158470,51158514,51160545,51160817,51162170,51163641,51165467,51165568,51170247,51172670,51172686,51172691,51172702,51172705,51172716,51172721,51172730,51173021,51175606,51176511,51177817,51178310,51178331,51178348,51178355,51178706,51178982,51182275,51183910,51184022,51184990,51186528,51186669,51186752,51189826,51190059,51190073,51190082,51190085,51190200,51190209,51190216,51190231,51190652,51195231,51196476,51196769,51197685,51197694,51197697,51197704,51199193,51199719,51200184,51200249,51200260,51200295,51200300,51200568,51201352,51201367,51201372,51201383,51201426,51201437,51201442,51201447,51201814,51203200,51204329,51204585,51207178,51207187,51207200,51207215,51211461,51212466,51212545,51212551,51212567,51213714,51213807,51213887,51217504,51219800,51221011,51221152,51222759,51222972,51223961,51224134,51224655,51224747,51224921,51225437,51226344,51226709,51227410,51227776,51227880,51227902,51228202,51228349,51228352,51228695,51228769,51228774,51228785,51228800,51228809,51228818,51229233,51230123,51230477,51230492,51231813,51232109,51232143,51236268,51237540,51237884,51238568,51238737,51240880,51240890,51241028,51241658,51241862\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240718\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMImfCdh5OxhwMVgEtPBB1-bw1fMghleHRlcm5hbJoBAA\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\":\"UCEOXxzW2vU0P-0THehuIIeg\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtZNC1HTkNITGlOYyiR48O5BjIKCgJERRIEEgAgRg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20241107.11.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x89e1c78312cedec5\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23966208,23986027,24004644,24077241,24108448,24166867,24181174,24186125,24241378,24299875,24439361,24453989,24459436,24502053,24542367,24547316,24548629,24566687,24699899,39325854,39326986,51009781,51010235,51017346,51020570,51025415,51030101,51037346,51037351,51043774,51050361,51053689,51057848,51057851,51063643,51064835,51072748,51091058,51095478,51098299,51111738,51115184,51117319,51119595,51124104,51129210,51133103,51134507,51141472,51152050,51157411,51157841,51158514,51160545,51165467,51169118,51176511,51178316,51178335,51178342,51178351,51178982,51182850,51183910,51184990,51195231,51204329,51213773,51217504,51221152,51222382,51222973,51223961,51225391,51227037,51227772,51228350,51230241,51230478,51231814,51237842,51239093,51241028,51242448,51243940,51248255,51248734,51251836,51255676,51255680,51255743,51256074,51256084,51257563,51257904,51257911,51257914,51258066,51258612,51263448,51265335,51265362,51265367,51266454,51272458,51273608,51274583,51275785,51276557,51276565,51277311,51281227,51282071,51282082,51282792,51285052,51285419,51285717,51287196,51287500,51289922,51289935,51289938,51289952,51289963,51289972,51291319,51292055,51294322,51294589,51294590,51295132,51295578,51296439,51298019,51298021,51299626,51299710,51299724,51299977,51300005,51300018,51300176,51300241,51300699,51302492,51302680,51303667,51303669,51303789,51304155,51305032,51305494,51305691,51305839,51306259,51306545,51307502,51308045,51308060,51309313,51310323,51310742,51311025,51311038,51311147,51311505,51312144,51312688,51312880,51313149,51313767,51314158,51314679,51314694,51314701,51314710,51314729,51315041,51315910,51315921,51315926,51315931,51315940,51315945,51315954,51315959,51315972,51315977,51316747,51317748,51318844,51321167,51322670,51323366,51325576,51326208,51326233,51326527,51326641,51326767,51326932,51327144,51327163,51327178,51327636,51328144,51328948,51329227,51329505,51330194,51330662,51331198,51331487,51331502,51331518,51331535,51331538,51331547,51331552,51331563,51331691,51332896,51333739,51333878,51335646,51337187,51337350,51337854,51338523,51339163,51339517,51339747,51340616,51341226,51341757,51342093,51342468,51342740,51343110,51343368,51344663,51344727,51345228\"},{\"key\":\"visitor_data\",\"value\":\"CgtZNC1HTkNITGlOYyiR48O5BjIKCgJERRIEEgAgRg%3D%3D\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20241107\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIuqqokKnSiQMVcWh6BR08NAEDMghleHRlcm5hbA\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\":\"UCEOXxzW2vU0P-0THehuIIeg\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027;report-uri /cspreport"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:49:19 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:57 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:49:19 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:57 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dauHnMsX2TkQ; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:49:19 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dDum5dtfP5VQ; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:46:57 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:47:35 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:59 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:47:35 GMT"
|
||||
"Sun, 10 Nov 2024 17:46:59 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003doTOG10oOeIY; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:47:35 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003deZhZw_X0aHw; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:46:59 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13,7 +13,7 @@
|
|||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240718.01.00"
|
||||
"2.20241107.11.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -229,12 +229,12 @@
|
|||
48,
|
||||
50,
|
||||
52,
|
||||
49,
|
||||
49,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
|
@ -358,7 +358,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:47:36 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:05 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
@ -378,7 +378,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"Cgt2Rm1wQklIYlhmVSi4quW0BjIiCgJGUhIcEhgSFgsMDg8QERITFBUWFxgZGhscHR4fICEgUQ%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240718.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x5b4ab0a81ff46292\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"9479112,23804281,23946420,23966208,23986033,23998056,24004644,24077241,24135942,24166867,24181174,24241378,24290971,24299873,24425061,24439361,24453989,24456089,24468724,24542367,24548627,24548629,24550458,24566687,24699899,39325854,39326848,39326916,51009781,51010235,51016856,51017346,51020570,51025415,51030103,51037342,51037353,51041512,51043554,51043998,51050361,51053689,51057844,51057851,51057863,51060353,51063643,51064835,51072748,51091058,51091331,51095478,51098297,51098299,51101170,51102409,51105628,51111738,51113658,51113661,51115184,51116067,51117318,51118932,51120721,51124104,51133103,51139379,51141472,51148037,51148688,51148978,51148981,51149607,51152050,51157411,51157430,51157432,51157838,51158470,51158514,51160545,51162170,51163637,51165467,51165568,51170247,51172670,51172686,51172693,51172700,51172709,51172712,51172719,51172726,51175606,51176511,51177818,51178297,51178310,51178344,51178357,51178705,51178982,51181298,51182274,51183506,51183910,51184022,51184990,51186528,51187251,51189826,51190059,51190071,51190080,51190089,51190202,51190213,51190218,51190229,51190652,51191448,51195231,51196769,51197687,51197692,51197701,51197708,51199193,51200253,51200260,51200293,51200298,51200568,51201350,51201365,51201370,51201383,51201426,51201433,51201442,51201449,51201814,51203112,51204329,51204587,51207182,51207189,51207204,51207207,51211461,51212084,51212458,51212466,51212551,51212569,51213807,51217236,51217504,51219800,51219963,51221011,51221152,51222972,51223961,51224747,51224921,51225437,51226344,51227637,51227774,51227881,51228202,51228350,51228352,51228695,51228771,51228778,51228781,51228800,51228807,51228812,51230122,51230477,51230492,51231131,51231220,51232109,51232143,51232189,51232710,51234853,51235174,51235462,51237540,51237841,51238399,51238569,51238736,51240880,51240886,51241028,51241636,51241644,51242269\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240718\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMI3bWR5ZKxhwMVDEFPBB2x_wAnMghleHRlcm5hbJoBAA\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\":\"UCYJ61XIK64sp6ZFFS8sctxw\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtiSkxMTlQ1NjlwOCiZ48O5BjIKCgJERRIEEgAgHQ%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20241107.11.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x969100737f7caf2d\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23966208,23986025,24004644,24077241,24166867,24181174,24241378,24420425,24439361,24453989,24542367,24543669,24547317,24548629,24566687,24699899,39325854,39326986,51009781,51010235,51017346,51020570,51025415,51043774,51050361,51053689,51063643,51064835,51072748,51091058,51095478,51098299,51107205,51111738,51115184,51117319,51124104,51129210,51133103,51135270,51141472,51144926,51152050,51157411,51157841,51158514,51160545,51165467,51169118,51176511,51178982,51179884,51182851,51183910,51184990,51195231,51204329,51213773,51217504,51222382,51222973,51223962,51227037,51227291,51228350,51230241,51230478,51230877,51231814,51237842,51239093,51241028,51242448,51243940,51248255,51248734,51249751,51251836,51255676,51255680,51255743,51256074,51256084,51257939,51258066,51263449,51266454,51272458,51273608,51274583,51275782,51276557,51276565,51277535,51281227,51282792,51285052,51285717,51287196,51287500,51287509,51287510,51289938,51294322,51295132,51296439,51298019,51298021,51299627,51299710,51299724,51300176,51300241,51300699,51302492,51302680,51303667,51303669,51303789,51304155,51305032,51305839,51306259,51306416,51307502,51308045,51308060,51309313,51310323,51311505,51312688,51313149,51313767,51314158,51315041,51315245,51316749,51317749,51318845,51320400,51323366,51325523,51325576,51326207,51326641,51326703,51326932,51327636,51328144,51329227,51329506,51330194,51332896,51333739,51333878,51335973,51336056,51337186,51337350,51338524,51339163,51339747,51342093,51343110,51343368,51344412,51344725,51344926\"},{\"key\":\"visitor_data\",\"value\":\"CgtiSkxMTlQ1NjlwOCiZ48O5BjIKCgJERRIEEgAgHQ%3D%3D\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20241107\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIrZColKnSiQMVD3R6BR3zPDaMMghleHRlcm5hbA\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\":\"UCYJ61XIK64sp6ZFFS8sctxw\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:49:51 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:23 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:49:51 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:23 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dc9wErMbEWpQ; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:49:51 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dTDPINDDje70; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:47:23 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027;report-uri /cspreport"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:48:26 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:23 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:48:26 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:23 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dCZ8xidUhzf4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:48:26 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dCwHorxLAtLA; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:47:23 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:50:19 GMT"
|
||||
"Sun, 10 Nov 2024 17:48:20 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:50:19 GMT"
|
||||
"Sun, 10 Nov 2024 17:48:20 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003d_U6D2v9w8QE; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:50:19 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dwLNTGYmBqa4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:48:20 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13,7 +13,7 @@
|
|||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240718.01.00"
|
||||
"2.20241107.11.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -229,12 +229,12 @@
|
|||
48,
|
||||
50,
|
||||
52,
|
||||
49,
|
||||
49,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
|
@ -363,7 +363,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:50:21 GMT"
|
||||
"Sun, 10 Nov 2024 17:48:20 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
@ -383,7 +383,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"Cgt2UFRzSmhuM0J2SSjdq-W0BjIiCgJGUhIcEhgSFgsMDg8QERITFBUWFxgZGhscHR4fICEgVw%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240718.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x93cf961e95e44789\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23946420,23966208,23998056,24004644,24017848,24077241,24108447,24166867,24181174,24241378,24290971,24439361,24453989,24456089,24468724,24499533,24534951,24542367,24548627,24548629,24550458,24566687,24699899,39325854,39326848,39326916,51009781,51010235,51016856,51017346,51020570,51025415,51041512,51043555,51050361,51053689,51060353,51063643,51064835,51072748,51091058,51091331,51095478,51098297,51098299,51101170,51102410,51111738,51115184,51116067,51118932,51119595,51124104,51133103,51139379,51141472,51146015,51148688,51149607,51152050,51155997,51157411,51157430,51157432,51157838,51158470,51158514,51160545,51162170,51165467,51165568,51170249,51175606,51176511,51178705,51178982,51183909,51184022,51184990,51185141,51186528,51189826,51190652,51195231,51196180,51196769,51197711,51199193,51200569,51201814,51204329,51204585,51210036,51211461,51213715,51213807,51217504,51219800,51221011,51223961,51224135,51224747,51224921,51225437,51226344,51227881,51228202,51228350,51228352,51228695,51230477,51230492,51232143,51232684,51235463,51236950,51237540,51238568,51238736,51239209,51239303,51241029\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240718\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIzZ65s5OxhwMVE0RPBB33uQzmMghleHRlcm5hbJoBAA\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\":\"UCeY0bbntWzzVIaj2z3QigXg\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"Cgt3YnlVWl9pM05IOCjk48O5BjIKCgJERRIEEgAgTw%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20241107.11.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x6a6e1d1954f31f83\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23966208,23986015,24000320,24004644,24077241,24166867,24181174,24186125,24216873,24241378,24367823,24425063,24439361,24453989,24499534,24542367,24547317,24548629,24566687,24699899,39325854,39326986,51009781,51010235,51017346,51020570,51025415,51030103,51037346,51037349,51050361,51053689,51057846,51057853,51063643,51064835,51072748,51091058,51095478,51098299,51111738,51115184,51117319,51124104,51129210,51133103,51141472,51144925,51152050,51156055,51157411,51157838,51158514,51160545,51165467,51169118,51176511,51178320,51178327,51178346,51178351,51178982,51179884,51182850,51183910,51184990,51195231,51204329,51213773,51217504,51221152,51222382,51222973,51223962,51227037,51227778,51228350,51230241,51230478,51231814,51237842,51239093,51241028,51242448,51243940,51248255,51248734,51249751,51251836,51255676,51255680,51255743,51256074,51256084,51257900,51257907,51257916,51258066,51263449,51265345,51265358,51265367,51266454,51269139,51272458,51273608,51274583,51275782,51276557,51276565,51281227,51282073,51282088,51282792,51285052,51285419,51285717,51287196,51287500,51287509,51287510,51289484,51289922,51289933,51289938,51289956,51289965,51289970,51290045,51291810,51294322,51294906,51295132,51295578,51296439,51297232,51298019,51298021,51299710,51299724,51299973,51300005,51300018,51300176,51300241,51300699,51302492,51302680,51303666,51303667,51303670,51303789,51304155,51305496,51305839,51306259,51306417,51306559,51306871,51307502,51308045,51308060,51309313,51310323,51310742,51311025,51311036,51311505,51312144,51312688,51313110,51313149,51313767,51314158,51314685,51314696,51314705,51314718,51314727,51315041,51315914,51315919,51315928,51315931,51315942,51315945,51315959,51315972,51315977,51316415,51316749,51316846,51317749,51318243,51318844,51322163,51323366,51323555,51325576,51326207,51326281,51326641,51326652,51326760,51326932,51327122,51327144,51327167,51327182,51327636,51328144,51329227,51329506,51330194,51330316,51330398,51330475,51330662,51331197,51331483,51331504,51331520,51331529,51331538,51331547,51331556,51331563,51332896,51333739,51333879,51335366,51335646,51336660,51337186,51337350,51338524,51339162,51339163,51339747,51341226,51342093,51342575,51342741,51342847,51343109,51343244,51343368,51343866,51344672\"},{\"key\":\"visitor_data\",\"value\":\"Cgt3YnlVWl9pM05IOCjk48O5BjIKCgJERRIEEgAgTw%3D%3D\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20241107\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIrbDwt6nSiQMVeVp6BR1kviADMghleHRlcm5hbA\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\":\"UCeY0bbntWzzVIaj2z3QigXg\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:45:17 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:25 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:45:17 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:25 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dmt8ojN0j5ss; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:45:17 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003ds2PN637_j94; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:47:25 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,17 +3,17 @@
|
|||
"httpMethod": "POST",
|
||||
"url": "https://www.youtube.com/youtubei/v1/browse?prettyPrint\u003dfalse",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Cookie": [
|
||||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240718.01.00"
|
||||
"2.20241107.11.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -255,12 +255,12 @@
|
|||
48,
|
||||
50,
|
||||
52,
|
||||
49,
|
||||
49,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
|
@ -376,7 +376,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:45:19 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:45 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:49:01 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:45 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:49:01 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:45 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dqO-eHy3Kz4k; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:49:01 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dECiwETXt944; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:47:45 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:46:52 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:46 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:46:52 GMT"
|
||||
"Sun, 10 Nov 2024 17:47:46 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dCPnrnhg5fno; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:46:52 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dMXNUBrLOj0I; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:47:46 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:52:03 GMT"
|
||||
"Sun, 10 Nov 2024 17:48:21 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:52:03 GMT"
|
||||
"Sun, 10 Nov 2024 17:48:21 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dCy4aX6DBam4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:52:03 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003d4hCTcf7rUXA; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:48:21 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:51:50 GMT"
|
||||
"Sun, 10 Nov 2024 17:48:58 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:51:50 GMT"
|
||||
"Sun, 10 Nov 2024 17:48:58 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dgoEUVn3I_Gk; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:51:50 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dXTJBIfCZjcU; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:48:58 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -3,10 +3,10 @@
|
|||
"httpMethod": "GET",
|
||||
"url": "https://www.youtube.com/sw.js",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Accept-Language": [
|
||||
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:51:38 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:00 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:51:38 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:00 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003djgnm7tfpqYw; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:51:38 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dENzmdII1fQw; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:49:00 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3,17 +3,17 @@
|
|||
"httpMethod": "POST",
|
||||
"url": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse",
|
||||
"headers": {
|
||||
"Referer": [
|
||||
"Origin": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Origin": [
|
||||
"Referer": [
|
||||
"https://www.youtube.com"
|
||||
],
|
||||
"Cookie": [
|
||||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240718.01.00"
|
||||
"2.20241107.11.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -229,12 +229,12 @@
|
|||
48,
|
||||
50,
|
||||
52,
|
||||
49,
|
||||
49,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
|
@ -361,7 +361,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:51:39 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:00 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
@ -381,7 +381,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"Cgs5WUtfRXZBTXNKWSirrOW0BjIiCgJGUhIcEhgSFgsMDg8QERITFBUWFxgZGhscHR4fICEgEA%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240718.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xb264e2e3ad7e95b4\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"9407155,23804281,23946420,23966208,23998056,24004644,24007613,24077241,24108447,24166867,24173288,24181174,24241378,24266634,24290971,24378828,24439361,24453989,24456089,24468724,24499534,24542367,24548627,24548629,24550458,24566687,24697011,24699899,39325854,39326848,39326916,51009781,51010235,51016856,51017346,51020570,51025415,51030101,51037342,51037351,51041512,51050361,51053689,51057842,51057857,51060353,51063643,51064835,51072748,51076858,51091058,51091331,51095478,51098297,51098299,51102410,51111738,51113656,51113663,51115184,51116067,51117318,51118932,51124104,51133103,51139379,51141472,51148688,51148976,51148983,51149607,51152050,51157411,51157430,51157432,51157838,51158470,51158514,51159332,51160545,51162170,51163639,51165467,51165568,51169118,51170248,51172672,51172684,51172695,51172702,51172705,51172712,51172719,51172728,51175606,51176511,51177818,51178318,51178327,51178344,51178351,51178705,51178982,51182274,51183506,51183910,51184022,51184990,51186528,51189826,51190059,51190071,51190080,51190085,51190198,51190211,51190220,51190231,51190652,51191461,51195231,51196181,51196769,51197687,51197694,51197697,51197704,51199193,51200253,51200260,51200291,51200302,51200569,51201350,51201365,51201372,51201383,51201428,51201435,51201442,51201449,51201542,51201814,51202231,51202419,51204329,51204586,51207176,51207187,51207196,51207213,51207302,51211461,51212464,51212555,51212567,51213807,51217504,51218321,51219800,51220610,51221011,51221152,51223962,51224433,51224747,51224922,51225437,51226344,51226707,51227774,51227881,51228202,51228350,51228352,51228695,51228769,51228776,51228781,51228800,51228803,51228812,51229177,51230477,51230492,51231081,51232143,51232191,51232677,51235078,51236658,51237540,51238399,51238568,51238736,51239331,51240880,51240886,51241029\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240718\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIupvy2JOxhwMVIj3xBR24uQwtMghleHRlcm5hbJoBAA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UCq19-LqvG35A-30oyAiPiqA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtwN252WUt4bnBCOCiM5MO5BjIKCgJERRIEEgAgKg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20241107.11.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xd104e5d714f830d7\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23966208,23986028,24004644,24077241,24166867,24181174,24186125,24241378,24439361,24453989,24542367,24547316,24548629,24566687,24699899,39325854,39326986,51009781,51010235,51017346,51020570,51025415,51050361,51053689,51063643,51064835,51072748,51091058,51095478,51098299,51111738,51115184,51117319,51119595,51124104,51129210,51133103,51141472,51152050,51157411,51157841,51158514,51160545,51165467,51169118,51176511,51178982,51182851,51183910,51184990,51194136,51195231,51204329,51213773,51217504,51222382,51222973,51223962,51227037,51228350,51228849,51230241,51230478,51231814,51237842,51239093,51241028,51242448,51243940,51248255,51248734,51249749,51251836,51255676,51255680,51255743,51256074,51256084,51258066,51263449,51264008,51266454,51272458,51273608,51274583,51275785,51276557,51276565,51281227,51282792,51285052,51285717,51287196,51287500,51289938,51292055,51294322,51294583,51294584,51295132,51296439,51298019,51298020,51299154,51299710,51299724,51300176,51300241,51300699,51302492,51302680,51303667,51303670,51303789,51304155,51305031,51305558,51305839,51306256,51306870,51307502,51308045,51308060,51308708,51309313,51310323,51310742,51311147,51311505,51312688,51313149,51313767,51314158,51315041,51316438,51316747,51317748,51318844,51319711,51320778,51323366,51325576,51326207,51326641,51326932,51327616,51327636,51328144,51329227,51329505,51330194,51331675,51332896,51333670,51333739,51333879,51335365,51337186,51337349,51337774,51338524,51339163,51339518,51339747,51341342,51342093,51342468,51343109,51343244,51343368,51343866,51344927\"},{\"key\":\"visitor_data\",\"value\":\"CgtwN252WUt4bnBCOCiM5MO5BjIKCgJERRIEEgAgKg%3D%3D\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20241107\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMI0c70yqnSiQMV9SEGAB3RCT0gMghleHRlcm5hbA\u003d\u003d\",\"commandMetadata\":{\"webCommandMetadata\":{\"url\":\"/youtubei/v1/navigation/resolve_url\",\"webPageType\":\"WEB_PAGE_TYPE_CHANNEL\",\"rootVe\":3611,\"apiUrl\":\"/youtubei/v1/browse\"},\"resolveUrlCommandMetadata\":{\"isVanityUrl\":true}},\"browseEndpoint\":{\"browseId\":\"UCq19-LqvG35A-30oyAiPiqA\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:51:17 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:00 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:51:17 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:00 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dB7ZQVZteI6U; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:51:17 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dKCR7WRhwlzM; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:49:00 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13,7 +13,7 @@
|
|||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240718.01.00"
|
||||
"2.20241107.11.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -229,12 +229,12 @@
|
|||
48,
|
||||
50,
|
||||
52,
|
||||
49,
|
||||
49,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
|
@ -365,7 +365,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:51:18 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:05 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
@ -385,7 +385,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtiT1B0Rk1tQkhLVSiWrOW0BjIiCgJGUhIcEhgSFgsMDg8QERITFBUWFxgZGhscHR4fICEgQA%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240718.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xacf065d4845918b6\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23885487,23946420,23966208,23986017,23998056,24004644,24077241,24166867,24181174,24241378,24290971,24439361,24453989,24456089,24468724,24499534,24542367,24543669,24548627,24548629,24550458,24566687,24699899,39325854,39326848,39326916,51009781,51010235,51016856,51017346,51020570,51025415,51030103,51037344,51037351,51041512,51043774,51050361,51053689,51057848,51057855,51060353,51063643,51064835,51072748,51091058,51091331,51095478,51098297,51098299,51102409,51111738,51113658,51113663,51114642,51115184,51116067,51117319,51118932,51124104,51129247,51133103,51134506,51139379,51141472,51144925,51148688,51148978,51148985,51149306,51149607,51152050,51153492,51157411,51157430,51157432,51157838,51158470,51158514,51160545,51162170,51163639,51165467,51165568,51170247,51172670,51172688,51172691,51172698,51172709,51172712,51172721,51172726,51173020,51175606,51175619,51176511,51178316,51178327,51178340,51178351,51178705,51178982,51182275,51183909,51184022,51184990,51186528,51187250,51189826,51190061,51190073,51190082,51190085,51190198,51190211,51190216,51190229,51190652,51194136,51195231,51196180,51196769,51197687,51197690,51197701,51197706,51199193,51200051,51200249,51200260,51200291,51200298,51200568,51201350,51201365,51201372,51201381,51201430,51201435,51201440,51201451,51201814,51202232,51204329,51204586,51207174,51207187,51207196,51207209,51208329,51209973,51211461,51212466,51212551,51212569,51213807,51216379,51217504,51217767,51218324,51219800,51220670,51221011,51221146,51223962,51224747,51224922,51225437,51226344,51227395,51227776,51227881,51228202,51228349,51228351,51228695,51228765,51228778,51228783,51228796,51228809,51228816,51230124,51230478,51230492,51231220,51232143,51235371,51235463,51237540,51238569,51238736,51239329,51240878,51240888,51241028,51241192,51241212,51241813,51243005,51243941\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240718\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIpef8zpOxhwMVcFBPBB32mQPCMghleHRlcm5hbJoBAA\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\":\"UCR-DXc1voovS8nhAvccRZhg\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtsLVc4aXJYQTRpbyiR5MO5BjIKCgJERRIEEgAgFg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20241107.11.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0x3b0f84f256641642\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23966208,23986016,24004644,24077241,24166867,24181174,24241378,24439361,24453989,24542367,24547316,24548629,24566687,24699899,39325854,39326986,51009781,51010235,51017346,51020570,51025415,51030103,51037346,51037351,51043774,51050361,51053689,51057848,51057851,51063643,51064835,51072748,51091058,51095478,51098299,51111738,51115184,51117319,51124104,51129210,51133103,51141472,51144926,51151423,51152050,51157411,51157841,51158514,51160545,51165467,51169118,51176511,51178316,51178337,51178348,51178353,51178982,51182851,51183909,51184990,51195231,51199253,51204329,51213773,51213887,51217504,51219963,51221152,51222382,51222973,51223961,51227037,51227774,51228350,51230241,51230478,51231814,51237842,51239093,51241028,51242448,51243940,51248255,51248734,51249749,51251836,51255676,51255680,51255743,51256074,51256084,51257895,51257900,51257911,51257918,51258066,51263449,51265339,51265362,51265375,51266454,51268346,51272458,51273608,51274583,51275782,51276557,51276565,51281227,51282075,51282080,51282792,51285052,51285417,51285717,51287196,51287500,51289483,51289924,51289933,51289938,51289956,51289961,51289970,51290204,51291888,51292054,51294322,51295132,51295576,51296439,51298019,51298021,51299519,51299710,51299724,51299979,51299999,51300008,51300176,51300241,51300699,51302492,51302680,51303667,51303669,51303789,51304155,51304660,51304730,51305311,51305839,51306256,51306543,51306559,51307502,51308045,51308060,51308709,51309314,51310323,51310742,51311027,51311036,51311505,51312146,51312688,51312881,51313149,51313767,51314158,51314683,51314696,51314701,51314714,51314729,51315041,51315910,51315921,51315928,51315935,51315942,51315949,51315956,51315963,51315968,51315975,51316174,51316416,51317749,51318074,51318243,51318844,51323366,51325522,51325576,51326207,51326286,51326641,51326932,51327138,51327169,51327182,51327636,51328144,51328902,51329144,51329227,51329506,51329696,51330194,51331487,51331500,51331520,51331531,51331542,51331549,51331556,51331559,51332858,51332896,51333543,51333739,51333878,51336665,51337187,51337349,51337456,51337855,51338470,51338524,51339163,51339747,51340611,51341228,51341729,51342090,51342093,51342298,51342446,51342575,51343109,51343243,51343368,51344663,51344672,51345230\"},{\"key\":\"visitor_data\",\"value\":\"CgtsLVc4aXJYQTRpbyiR5MO5BjIKCgJERRIEEgAgFg%3D%3D\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20241107\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIm56wzanSiQMVoF96BR37ESIDMghleHRlcm5hbA\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\":\"UCR-DXc1voovS8nhAvccRZhg\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:51:07 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:34 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Thu, 18 Jul 2024 17:51:07 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:34 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dw9VR4AUigv4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dFri, 22-Oct-2021 17:51:07 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003dciZmI0rA5B8; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:49:34 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13,7 +13,7 @@
|
|||
"SOCS\u003dCAE\u003d"
|
||||
],
|
||||
"X-YouTube-Client-Version": [
|
||||
"2.20240718.01.00"
|
||||
"2.20241107.11.00"
|
||||
],
|
||||
"X-YouTube-Client-Name": [
|
||||
"1"
|
||||
|
@ -229,12 +229,12 @@
|
|||
48,
|
||||
50,
|
||||
52,
|
||||
49,
|
||||
49,
|
||||
48,
|
||||
55,
|
||||
49,
|
||||
56,
|
||||
46,
|
||||
48,
|
||||
49,
|
||||
49,
|
||||
46,
|
||||
48,
|
||||
|
@ -359,7 +359,7 @@
|
|||
"application/json; charset\u003dUTF-8"
|
||||
],
|
||||
"date": [
|
||||
"Thu, 18 Jul 2024 17:51:08 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:34 GMT"
|
||||
],
|
||||
"server": [
|
||||
"scaffolding on HTTPServer2"
|
||||
|
@ -379,7 +379,7 @@
|
|||
"0"
|
||||
]
|
||||
},
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgstcFYyWThEelA2VSiMrOW0BjIiCgJGUhIcEhgSFgsMDg8QERITFBUWFxgZGhscHR4fICEgMg%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20240718.01.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xd3d3538277ffc4e2\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"23804281,23946420,23966208,23986021,23998056,24004644,24077241,24166867,24181174,24241378,24290971,24367823,24439361,24453989,24456089,24457854,24468724,24542367,24548627,24548629,24550458,24566687,24699899,39325854,39326848,39326916,51009781,51010235,51016856,51017346,51020570,51025415,51030103,51037346,51037353,51041512,51050361,51053689,51057842,51057851,51060353,51063643,51064835,51072748,51087997,51091058,51091331,51095478,51098297,51098299,51102409,51111738,51113656,51113663,51115184,51116067,51118932,51124104,51133103,51139379,51141472,51144925,51148688,51148974,51148981,51149607,51152050,51157411,51157430,51157432,51157838,51158470,51158514,51160545,51162170,51163637,51165467,51165568,51169117,51170247,51172670,51172686,51172691,51172702,51172709,51172716,51172723,51172726,51172920,51175606,51176511,51177817,51178320,51178331,51178346,51178351,51178706,51178982,51182275,51183506,51183910,51184022,51184990,51186528,51189826,51190059,51190075,51190078,51190087,51190200,51190209,51190216,51190227,51190652,51195231,51196769,51197685,51197692,51197701,51197704,51199193,51200251,51200256,51200291,51200302,51200569,51201352,51201363,51201370,51201385,51201428,51201435,51201440,51201449,51201814,51203145,51203200,51204329,51204585,51207176,51207187,51207202,51207207,51209049,51211461,51211864,51212464,51212546,51212553,51212567,51213807,51217504,51218324,51219800,51221011,51221150,51222382,51223962,51224747,51224921,51225437,51226344,51226683,51227776,51227880,51227903,51228202,51228349,51228351,51228695,51228765,51228776,51228781,51228796,51228809,51228818,51230123,51230478,51230492,51230886,51231083,51232143,51232189,51232678,51236254,51237540,51238070,51238569,51238736,51239404,51240133,51240878,51240888,51241028,51241645\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20240718\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIyqKHypOxhwMV6YKxAx1bewjjMghleHRlcm5hbJoBAA\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\":\"UC2DjFE7Xf11URZqWBigcVOQ\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"responseBody": "{\"responseContext\":{\"visitorData\":\"CgtBdGJnQm9rRFhmWSiu5MO5BjIKCgJERRIEEgAgHw%3D%3D\",\"serviceTrackingParams\":[{\"service\":\"CSI\",\"params\":[{\"key\":\"c\",\"value\":\"WEB\"},{\"key\":\"cver\",\"value\":\"2.20241107.11.00\"},{\"key\":\"yt_li\",\"value\":\"0\"},{\"key\":\"ResolveUrl_rid\",\"value\":\"0xd9fdd210611c51cf\"}]},{\"service\":\"GFEEDBACK\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"},{\"key\":\"e\",\"value\":\"9453586,9453587,23804281,23966208,23986016,24004644,24077241,24108447,24166867,24181174,24241378,24439361,24453989,24534952,24542367,24543669,24547316,24548629,24566687,24699899,39325854,39326986,51009781,51010235,51017346,51020570,51025415,51050361,51053689,51063643,51064835,51072748,51091058,51095478,51098299,51101170,51111738,51115184,51117319,51124104,51129210,51133103,51141472,51152050,51157411,51157838,51158514,51160545,51165467,51169118,51176511,51177818,51178982,51182850,51183909,51184990,51195231,51204329,51213773,51217504,51222382,51222973,51223962,51224489,51227037,51228350,51230241,51230478,51231814,51237842,51239093,51239210,51241028,51242448,51243940,51248255,51248734,51251836,51255676,51255680,51255743,51256074,51256084,51258066,51263449,51266454,51272458,51273608,51274583,51275785,51276557,51276565,51281227,51282792,51285052,51285717,51287196,51287500,51289938,51294322,51295132,51296439,51297233,51298019,51298021,51299710,51299724,51300176,51300241,51300699,51302492,51302680,51303665,51303667,51303670,51303789,51304155,51305839,51306259,51307502,51308045,51308060,51309313,51310323,51310742,51311146,51311505,51312688,51313149,51313767,51314158,51315041,51317749,51317787,51318845,51321590,51323366,51325576,51326207,51326282,51326641,51326932,51327636,51328144,51329227,51329505,51330194,51332896,51333739,51333879,51335734,51336160,51337187,51337349,51338440,51338524,51339163,51339518,51339522,51339747,51342093,51343110,51343244,51343368\"},{\"key\":\"visitor_data\",\"value\":\"CgtBdGJnQm9rRFhmWSiu5MO5BjIKCgJERRIEEgAgHw%3D%3D\"}]},{\"service\":\"GUIDED_HELP\",\"params\":[{\"key\":\"logged_in\",\"value\":\"0\"}]},{\"service\":\"ECATCHER\",\"params\":[{\"key\":\"client.version\",\"value\":\"2.20241107\"},{\"key\":\"client.name\",\"value\":\"WEB\"}]}],\"mainAppWebResponseContext\":{\"loggedOut\":true},\"webResponseContextExtensionData\":{\"hasDecorated\":true}},\"endpoint\":{\"clickTrackingParams\":\"IhMIq8CL26nSiQMVkkN6BR0DNTMRMghleHRlcm5hbA\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\":\"UC2DjFE7Xf11URZqWBigcVOQ\",\"params\":\"EgC4AQCSAwDyBgQKAjIA\"}}}",
|
||||
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?prettyPrint\u003dfalse"
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -34,6 +34,9 @@
|
|||
"cache-control": [
|
||||
"private, max-age\u003d0"
|
||||
],
|
||||
"content-security-policy": [
|
||||
"require-trusted-types-for \u0027script\u0027;report-uri /cspreport"
|
||||
],
|
||||
"content-type": [
|
||||
"text/javascript; charset\u003dutf-8"
|
||||
],
|
||||
|
@ -41,10 +44,10 @@
|
|||
"same-origin; report-to\u003d\"youtube_main\""
|
||||
],
|
||||
"date": [
|
||||
"Wed, 24 Jul 2024 17:37:25 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:34 GMT"
|
||||
],
|
||||
"expires": [
|
||||
"Wed, 24 Jul 2024 17:37:25 GMT"
|
||||
"Sun, 10 Nov 2024 17:49:34 GMT"
|
||||
],
|
||||
"origin-trial": [
|
||||
"AmhMBR6zCLzDDxpW+HfpP67BqwIknWnyMOXOQGfzYswFmJe+fgaI6XZgAzcxOrzNtP7hEDsOo1jdjFnVr2IdxQ4AAAB4eyJvcmlnaW4iOiJodHRwczovL3lvdXR1YmUuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJWaWV3WFJlcXVlc3RlZFdpdGhEZXByZWNhdGlvbiIsImV4cGlyeSI6MTc1ODA2NzE5OSwiaXNTdWJkb21haW4iOnRydWV9"
|
||||
|
@ -62,8 +65,8 @@
|
|||
"ESF"
|
||||
],
|
||||
"set-cookie": [
|
||||
"YSC\u003dQqImeZ_ECz4; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dThu, 28-Oct-2021 17:37:25 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
"YSC\u003d9-fGwlPnwcs; Domain\u003d.youtube.com; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone",
|
||||
"VISITOR_INFO1_LIVE\u003d; Domain\u003d.youtube.com; Expires\u003dMon, 14-Feb-2022 17:49:34 GMT; Path\u003d/; Secure; HttpOnly; SameSite\u003dnone"
|
||||
],
|
||||
"strict-transport-security": [
|
||||
"max-age\u003d31536000"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue