Merge pull request #813 from litetex/fix-test-2022-03

Fixed tests (+ Youtube shorts in channels)
This commit is contained in:
litetex 2022-03-26 21:09:10 +01:00 committed by GitHub
commit 5a18730845
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 869 additions and 571 deletions

View file

@ -41,16 +41,12 @@ public final class NewPipe {
}
public static void init(final Downloader d) {
downloader = d;
preferredLocalization = Localization.DEFAULT;
preferredContentCountry = ContentCountry.DEFAULT;
init(d, Localization.DEFAULT);
}
public static void init(final Downloader d, final Localization l) {
downloader = d;
preferredLocalization = l;
preferredContentCountry = l.getCountryCode().isEmpty()
? ContentCountry.DEFAULT : new ContentCountry(l.getCountryCode());
init(d, l, l.getCountryCode().isEmpty()
? ContentCountry.DEFAULT : new ContentCountry(l.getCountryCode()));
}
public static void init(final Downloader d, final Localization l, final ContentCountry c) {

View file

@ -4,6 +4,7 @@ import com.grack.nanojson.JsonArray;
import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonParser;
import com.grack.nanojson.JsonParserException;
import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.downloader.Downloader;
@ -14,10 +15,11 @@ import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.Comparator;
import javax.annotation.Nonnull;
public class MediaCCCRecentKiosk extends KioskExtractor<StreamInfoItem> {
private JsonObject doc;
@ -51,11 +53,17 @@ public class MediaCCCRecentKiosk extends KioskExtractor<StreamInfoItem> {
streamInfoItem -> streamInfoItem.getUploadDate().offsetDateTime());
comparator = comparator.reversed();
final StreamInfoItemsCollector collector
= new StreamInfoItemsCollector(getServiceId(), comparator);
for (int i = 0; i < events.size(); i++) {
collector.commit(new MediaCCCRecentKioskExtractor(events.getObject(i)));
}
final StreamInfoItemsCollector collector =
new StreamInfoItemsCollector(getServiceId(), comparator);
events.stream()
.filter(JsonObject.class::isInstance)
.map(JsonObject.class::cast)
.map(MediaCCCRecentKioskExtractor::new)
// #813 / voc/voctoweb#609 -> returns faulty data -> filter it out
.filter(extractor -> extractor.getDuration() > 0)
.forEach(collector::commit);
return new InfoItemsPage<>(collector, null);
}

View file

@ -1,16 +1,18 @@
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
import com.grack.nanojson.JsonObject;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.localization.DateWrapper;
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferenceLinkHandlerFactory;
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
import org.schabi.newpipe.extractor.stream.StreamType;
import javax.annotation.Nullable;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import javax.annotation.Nullable;
public class MediaCCCRecentKioskExtractor implements StreamInfoItemExtractor {
private final JsonObject event;
@ -45,7 +47,7 @@ public class MediaCCCRecentKioskExtractor implements StreamInfoItemExtractor {
}
@Override
public long getDuration() throws ParsingException {
public long getDuration() {
// duration and length have the same value, see
// https://github.com/voc/voctoweb/blob/master/app/views/public/shared/_event.json.jbuilder
return event.getInt("duration");

View file

@ -219,10 +219,34 @@ public final class YoutubeParsingHelper {
throw new ParsingException("Error duration string with unknown format: " + input);
}
return ((Integer.parseInt(Utils.removeNonDigitCharacters(days)) * 24
+ Integer.parseInt(Utils.removeNonDigitCharacters(hours))) * 60
+ Integer.parseInt(Utils.removeNonDigitCharacters(minutes))) * 60
+ Integer.parseInt(Utils.removeNonDigitCharacters(seconds));
return ((convertDurationToInt(days) * 24
+ convertDurationToInt(hours)) * 60
+ convertDurationToInt(minutes)) * 60
+ convertDurationToInt(seconds);
}
/**
* Tries to convert a duration string to an integer without throwing an exception.
* <br/>
* Helper method for {@link #parseDurationString(String)}.
* <br/>
* Note: This method is also used as a workaround for NewPipe#8034 (YT shorts no longer
* display any duration in channels).
*
* @param input The string to process
* @return The converted integer or 0 if the conversion failed.
*/
private static int convertDurationToInt(final String input) {
if (input == null || input.isEmpty()) {
return 0;
}
final String clearedInput = Utils.removeNonDigitCharacters(input);
try {
return Integer.parseInt(clearedInput);
} catch (final NumberFormatException ex) {
return 0;
}
}
@Nonnull

View file

@ -138,6 +138,11 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
}
}
// NewPipe#8034 - YT returns not a correct duration for "YT shorts" videos
if ("SHORTS".equalsIgnoreCase(duration)) {
return 0;
}
return YoutubeParsingHelper.parseDurationString(duration);
}

View file

@ -17,4 +17,9 @@ import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(MockOnlyCondition.class)
public @interface MockOnly {
/**
* The reason why the test is mockonly.
*/
String value();
}

View file

@ -1,17 +1,21 @@
package org.schabi.newpipe.extractor.services.media_ccc;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertGreater;
import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import java.util.stream.Stream;
public class MediaCCCRecentListExtractorTest {
private static KioskExtractor extractor;
@ -24,16 +28,23 @@ public class MediaCCCRecentListExtractorTest {
}
@Test
public void testStreamList() throws Exception {
void testStreamList() throws Exception {
final List<StreamInfoItem> items = extractor.getInitialPage().getItems();
assertEquals(100, items.size());
for (final StreamInfoItem item: items) {
assertFalse(isNullOrEmpty(item.getName()));
assertTrue(item.getDuration() > 0);
// Disabled for now, because sometimes videos are uploaded, but their release date is in the future
// assertTrue(item.getUploadDate().offsetDateTime().isBefore(OffsetDateTime.now()));
}
assertFalse(items.isEmpty(), "No items returned");
assertAll(items.stream().flatMap(this::getAllConditionsForItem));
}
private Stream<Executable> getAllConditionsForItem(final StreamInfoItem item) {
return Stream.of(
() -> assertFalse(
isNullOrEmpty(item.getName()),
"Name=[" + item.getName() + "] of " + item + " is empty or null"
),
() -> assertGreater(0,
item.getDuration(),
"Duration[=" + item.getDuration() + "] of " + item + " is <= 0"
)
);
}
}

View file

@ -28,34 +28,39 @@ public class PeertubeCommentsExtractorTest {
public static void setUp() throws Exception {
NewPipe.init(DownloaderTestImpl.getInstance());
extractor = (PeertubeCommentsExtractor) PeerTube
.getCommentsExtractor("https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d");
.getCommentsExtractor("https://framatube.org/w/kkGMgK9ZtnKfYAgnEtQxbv");
}
@Test
public void testGetComments() throws IOException, ExtractionException {
void testGetComments() throws IOException, ExtractionException {
final String comment = "I love this";
InfoItemsPage<CommentsInfoItem> comments = extractor.getInitialPage();
boolean result = findInComments(comments, "Cool.");
boolean result = findInComments(comments, comment);
while (comments.hasNextPage() && !result) {
comments = extractor.getPage(comments.getNextPage());
result = findInComments(comments, "Cool.");
result = findInComments(comments, comment);
}
assertTrue(result);
}
@Test
public void testGetCommentsFromCommentsInfo() throws IOException, ExtractionException {
CommentsInfo commentsInfo = CommentsInfo.getInfo("https://framatube.org/videos/watch/217eefeb-883d-45be-b7fc-a788ad8507d3");
void testGetCommentsFromCommentsInfo() throws IOException, ExtractionException {
final String comment = "great video";
final CommentsInfo commentsInfo =
CommentsInfo.getInfo("https://framatube.org/w/kkGMgK9ZtnKfYAgnEtQxbv");
assertEquals("Comments", commentsInfo.getName());
boolean result = findInComments(commentsInfo.getRelatedItems(), "Cool");
boolean result = findInComments(commentsInfo.getRelatedItems(), comment);
Page nextPage = commentsInfo.getNextPage();
InfoItemsPage<CommentsInfoItem> moreItems = new InfoItemsPage<>(null, nextPage, null);
while (moreItems.hasNextPage() && !result) {
moreItems = CommentsInfo.getMoreItems(PeerTube, commentsInfo, nextPage);
result = findInComments(moreItems.getItems(), "Cool");
result = findInComments(moreItems.getItems(), comment);
nextPage = moreItems.getNextPage();
}
@ -63,7 +68,7 @@ public class PeertubeCommentsExtractorTest {
}
@Test
public void testGetCommentsAllData() throws IOException, ExtractionException {
void testGetCommentsAllData() throws IOException, ExtractionException {
InfoItemsPage<CommentsInfoItem> comments = extractor.getInitialPage();
for (CommentsInfoItem c : comments.getItems()) {
assertFalse(Utils.isBlank(c.getUploaderUrl()));
@ -105,13 +110,13 @@ public class PeertubeCommentsExtractorTest {
}
@Test
public void testGetComments() throws IOException, ExtractionException {
void testGetComments() throws IOException, ExtractionException {
final InfoItemsPage<CommentsInfoItem> comments = extractor.getInitialPage();
assertTrue(comments.getErrors().isEmpty());
}
@Test
public void testGetCommentsFromCommentsInfo() throws IOException, ExtractionException {
void testGetCommentsFromCommentsInfo() throws IOException, ExtractionException {
final CommentsInfo commentsInfo = CommentsInfo.getInfo("https://framatube.org/videos/watch/217eefeb-883d-45be-b7fc-a788ad8507d3");
assertTrue(commentsInfo.getErrors().isEmpty());
}

View file

@ -7,6 +7,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubePlaylistLinkHandlerFactory;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -24,7 +25,7 @@ public class PeertubePlaylistLinkHandlerFactoryTest {
}
@Test
public void acceptUrlTest() throws ParsingException {
void acceptUrlTest() throws ParsingException {
assertTrue(linkHandler.acceptUrl("https://framatube.org/videos/watch/playlist/d8ca79f9-e4c7-4269-8183-d78ed269c909"));
assertTrue(linkHandler.acceptUrl("https://framatube.org/w/p/d8ca79f9-e4c7-4269-8183-d78ed269c909"));
assertTrue(linkHandler.acceptUrl("https://framatube.org/videos/watch/playlist/d8ca79f9-e4c7-4269-8183-d78ed269c909/videos"));
@ -35,7 +36,7 @@ public class PeertubePlaylistLinkHandlerFactoryTest {
}
@Test
public void getIdFromUrl() throws ParsingException {
void getIdFromUrl() throws ParsingException {
assertEquals("d8ca79f9-e4c7-4269-8183-d78ed269c909", linkHandler.getId("https://framatube.org/videos/watch/playlist/d8ca79f9-e4c7-4269-8183-d78ed269c909"));
assertEquals("d8ca79f9-e4c7-4269-8183-d78ed269c909", linkHandler.getId("https://framatube.org/w/p/d8ca79f9-e4c7-4269-8183-d78ed269c909"));
assertEquals("dacdc4ef-5160-4846-9b70-a655880da667", linkHandler.getId("https://framatube.org/videos/watch/playlist/dacdc4ef-5160-4846-9b70-a655880da667"));
@ -47,9 +48,9 @@ public class PeertubePlaylistLinkHandlerFactoryTest {
}
@Test
public void getUrl() throws ParsingException {
System.out.println(linkHandler.fromUrl("https://framatube.org/videos/watch/playlist/d8ca79f9-e4c7-4269-8183-d78ed269c909").getUrl());;
System.out.println(linkHandler.fromUrl("https://framatube.org/w/p/d8ca79f9-e4c7-4269-8183-d78ed269c909").getUrl());;
System.out.println(linkHandler.fromUrl("https://framatube.org/w/p/sLFbqXsw7sPR3AfvqQSBZB").getUrl());;
void getUrl() {
assertDoesNotThrow(() -> linkHandler.fromUrl("https://framatube.org/videos/watch/playlist/d8ca79f9-e4c7-4269-8183-d78ed269c909").getUrl());
assertDoesNotThrow(() -> linkHandler.fromUrl("https://framatube.org/w/p/d8ca79f9-e4c7-4269-8183-d78ed269c909").getUrl());
assertDoesNotThrow(() -> linkHandler.fromUrl("https://framatube.org/w/p/sLFbqXsw7sPR3AfvqQSBZB").getUrl());
}
}

View file

@ -86,7 +86,7 @@ public abstract class PeertubeStreamExtractorTest extends DefaultStreamExtractor
@Override public long expectedViewCountAtLeast() { return 38600; }
@Nullable @Override public String expectedUploadDate() { return "2018-10-01 10:52:46.396"; }
@Nullable @Override public String expectedTextualUploadDate() { return "2018-10-01T10:52:46.396Z"; }
@Override public long expectedLikeCountAtLeast() { return 120; }
@Override public long expectedLikeCountAtLeast() { return 50; }
@Override public long expectedDislikeCountAtLeast() { return 0; }
@Override public String expectedHost() { return "framatube.org"; }
@Override public String expectedCategory() { return "Science & Technology"; }

View file

@ -399,7 +399,8 @@ public class YoutubeChannelExtractorTest {
@Test
public void testDescription() throws Exception {
ExtractorAsserts.assertContains("small team who want to make science look beautiful", extractor.getDescription());
ExtractorAsserts.assertContains("science", extractor.getDescription());
ExtractorAsserts.assertContains("animators", extractor.getDescription());
//TODO: Description get cuts out, because the og:description is optimized and don't have all the content
//assertTrue(description, description.contains("Currently we make one animation video per month"));
}

View file

@ -1,6 +1,17 @@
package org.schabi.newpipe.extractor.services.youtube;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.YOUTUBEI_V1_URL;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getKey;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.prepareDesktopJsonBuilder;
import com.grack.nanojson.JsonWriter;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderFactory;
@ -17,15 +28,11 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
public class YoutubeMixPlaylistExtractorTest {
@ -35,8 +42,8 @@ public class YoutubeMixPlaylistExtractorTest {
private static YoutubeMixPlaylistExtractor extractor;
public static class Mix {
private static final String VIDEO_ID = "UtF6Jej8yb4";
private static final String VIDEO_TITLE = "Avicii - The Nights";
private static final String VIDEO_ID = "QqsLTNkzvaY";
private static final String VIDEO_TITLE = "Mix ";
@BeforeAll
public static void setUp() throws Exception {
@ -128,10 +135,10 @@ public class YoutubeMixPlaylistExtractorTest {
public static class MixWithIndex {
private static final String VIDEO_ID = "UtF6Jej8yb4";
private static final String VIDEO_TITLE = "Avicii - The Nights";
private static final int INDEX = 4;
private static final String VIDEO_ID_NUMBER_4 = "ebXbLfLACGM";
private static final String VIDEO_ID = "QqsLTNkzvaY";
private static final String VIDEO_TITLE = "Mix ";
private static final int INDEX = 7; // YT starts the index with 1...
private static final String VIDEO_ID_AT_INDEX = "xAUJYP8tnRE";
@BeforeAll
public static void setUp() throws Exception {
@ -140,7 +147,7 @@ public class YoutubeMixPlaylistExtractorTest {
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "mixWithIndex"));
dummyCookie.put(YoutubeMixPlaylistExtractor.COOKIE_NAME, "whatever");
extractor = (YoutubeMixPlaylistExtractor) YouTube
.getPlaylistExtractor("https://www.youtube.com/watch?v=" + VIDEO_ID_NUMBER_4
.getPlaylistExtractor("https://www.youtube.com/watch?v=" + VIDEO_ID_AT_INDEX
+ "&list=RD" + VIDEO_ID + "&index=" + INDEX);
extractor.fetchPage();
}

View file

@ -1,8 +1,12 @@
package org.schabi.newpipe.extractor.services.youtube.search;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static java.util.Collections.singletonList;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.downloader.MockOnly;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
@ -14,9 +18,6 @@ import java.net.URLEncoder;
import javax.annotation.Nullable;
import static java.util.Collections.singletonList;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
// Doesn't work with mocks. Makes request with different `dataToSend` I think
public class YoutubeMusicSearchExtractorTest {
public static class MusicSongs extends DefaultSearchExtractorTest {
@ -130,6 +131,7 @@ public class YoutubeMusicSearchExtractorTest {
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.CHANNEL; }
}
@Disabled("Currently constantly switching between \"Did you mean\" and \"Showing results for ...\" occurs")
public static class Suggestion extends DefaultSearchExtractorTest {
private static SearchExtractor extractor;
private static final String QUERY = "megaman x3";

View file

@ -1,9 +1,26 @@
package org.schabi.newpipe.extractor.services.youtube.search;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmptyErrors;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.assertNoDuplicatedItems;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.CHANNELS;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.PLAYLISTS;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.VIDEOS;
import static java.util.Collections.singletonList;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderFactory;
import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.downloader.MockOnly;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.MetaInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.search.SearchExtractor;
@ -12,7 +29,6 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.stream.Description;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import javax.annotation.Nullable;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
@ -21,13 +37,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Random;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.*;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertEmptyErrors;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.DefaultTests.assertNoDuplicatedItems;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.*;
import javax.annotation.Nullable;
public class YoutubeSearchExtractorTest {
@ -131,6 +141,7 @@ public class YoutubeSearchExtractorTest {
@Override public InfoItem.InfoType expectedInfoItemType() { return InfoItem.InfoType.STREAM; }
}
@MockOnly("Currently constantly switching between \"Did you mean\" and \"Showing results for ...\" occurs")
public static class Suggestion extends DefaultSearchExtractorTest {
private static SearchExtractor extractor;
private static final String QUERY = "newpip";

View file

@ -49,7 +49,7 @@ public class YoutubeStreamExtractorControversialTest extends DefaultStreamExtrac
@Override public StreamType expectedStreamType() { return StreamType.VIDEO_STREAM; }
@Override public String expectedUploaderName() { return "Amazing Atheist"; }
@Override public String expectedUploaderUrl() { return "https://www.youtube.com/channel/UCjNxszyFPasDdRoD9J6X-sw"; }
@Override public long expectedUploaderSubscriberCountAtLeast() { return 977_000; }
@Override public long expectedUploaderSubscriberCountAtLeast() { return 900_000; }
@Override public List<String> expectedDescriptionContains() {
return Arrays.asList("http://www.huffingtonpost.com/2010/09/09/obama-gma-interview-quran_n_710282.html",
"freedom");

View file

@ -88,7 +88,7 @@ public class YoutubeStreamExtractorRelatedMixTest extends DefaultStreamExtractor
// @formatter:on
@Test
@MockOnly // related items keep changing, and so do the mixes contained within them
@MockOnly("related items keep changing, and so do the mixes contained within them")
@Override
public void testRelatedItems() throws Exception {
super.testRelatedItems();

View file

@ -213,7 +213,7 @@
"responseMessage": "",
"responseHeaders": {
"alt-svc": [
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000,h3-T051\u003d\":443\"; ma\u003d2592000,h3-Q050\u003d\":443\"; ma\u003d2592000,h3-Q046\u003d\":443\"; ma\u003d2592000,h3-Q043\u003d\":443\"; ma\u003d2592000,quic\u003d\":443\"; ma\u003d2592000; v\u003d\"46,43\""
"h3\u003d\":443\"; ma\u003d2592000,h3-29\u003d\":443\"; ma\u003d2592000,h3-Q050\u003d\":443\"; ma\u003d2592000,h3-Q046\u003d\":443\"; ma\u003d2592000,h3-Q043\u003d\":443\"; ma\u003d2592000,quic\u003d\":443\"; ma\u003d2592000; v\u003d\"46,43\""
],
"cache-control": [
"private"
@ -222,19 +222,19 @@
"application/json; charset\u003dUTF-8"
],
"date": [
"Fri, 30 Jul 2021 17:14:25 GMT"
"Thu, 17 Mar 2022 13:52:23 GMT"
],
"expires": [
"Fri, 30 Jul 2021 17:14:25 GMT"
"Thu, 17 Mar 2022 13:52:23 GMT"
],
"p3p": [
"CP\u003d\"This is not a P3P policy! See g.co/p3phelp for more info.\""
],
"server": [
"ESF"
"scaffolding on HTTPServer2"
],
"set-cookie": [
"CONSENT\u003dPENDING+621; expires\u003dFri, 01-Jan-2038 00:00:00 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
"CONSENT\u003dPENDING+046; expires\u003dSat, 16-Mar-2024 13:52:23 GMT; path\u003d/; domain\u003d.youtube.com; Secure"
],
"vary": [
"Origin",
@ -251,7 +251,7 @@
"0"
]
},
"responseBody": "{\n \"responseContext\": {\n \"visitorData\": \"CgtIejdwdldveDJlSSjx5pCIBg%3D%3D\",\n \"serviceTrackingParams\": [\n {\n \"service\": \"CSI\",\n \"params\": [\n {\n \"key\": \"c\",\n \"value\": \"WEB\"\n },\n {\n \"key\": \"cver\",\n \"value\": \"2.20210728.00.00\"\n },\n {\n \"key\": \"yt_li\",\n \"value\": \"0\"\n },\n {\n \"key\": \"ResolveUrl_rid\",\n \"value\": \"0x26ec25b57d307359\"\n }\n ]\n },\n {\n \"service\": \"GFEEDBACK\",\n \"params\": [\n {\n \"key\": \"logged_in\",\n \"value\": \"0\"\n },\n {\n \"key\": \"e\",\n \"value\": \"23968386,23996830,24067673,24049820,23986023,24028143,24050503,1714253,24056264,24045411,23918597,24059521,24045469,24002025,23974595,23998056,24058380,24070035,24077196,24049573,23944779,23744176,24053866,24056275,24049571,24058812,23884386,23966208,23882502,24030040,23804281,24001373,23946420,23891344,24060921,24045470,24004644,24043240,24016285,24007246,24036947,23735348,24058128,24042870,24036236,24060177,24037794,23934970,24068842,23857950,23996512,24057238,23983296,24002022,23891346\"\n }\n ]\n },\n {\n \"service\": \"GUIDED_HELP\",\n \"params\": [\n {\n \"key\": \"logged_in\",\n \"value\": \"0\"\n }\n ]\n },\n {\n \"service\": \"ECATCHER\",\n \"params\": [\n {\n \"key\": \"client.version\",\n \"value\": \"2.20210728\"\n },\n {\n \"key\": \"client.name\",\n \"value\": \"WEB\"\n }\n ]\n }\n ],\n \"mainAppWebResponseContext\": {\n \"loggedOut\": true\n },\n \"webResponseContextExtensionData\": {\n \"hasDecorated\": true\n }\n },\n \"endpoint\": {\n \"clickTrackingParams\": \"IhMI1czoz6WL8gIVWRnxBR3-5A1sMghleHRlcm5hbA\u003d\u003d\",\n \"commandMetadata\": {\n \"webCommandMetadata\": {\n \"url\": \"/youtubei/v1/navigation/resolve_url\",\n \"webPageType\": \"WEB_PAGE_TYPE_CHANNEL\",\n \"rootVe\": 3611,\n \"apiUrl\": \"/youtubei/v1/browse\"\n },\n \"resolveUrlCommandMetadata\": {\n \"isVanityUrl\": true\n }\n },\n \"browseEndpoint\": {\n \"browseId\": \"UC6nSFpj9HTCZ5t-N3Rm3-HA\",\n \"params\": \"EgC4AQA%3D\"\n }\n }\n}\n",
"responseBody": "{\n \"responseContext\": {\n \"visitorData\": \"CgtuS0lURlJ0dTBubyiX-syRBg%3D%3D\",\n \"serviceTrackingParams\": [\n {\n \"service\": \"CSI\",\n \"params\": [\n {\n \"key\": \"c\",\n \"value\": \"WEB\"\n },\n {\n \"key\": \"cver\",\n \"value\": \"2.20210728.00.00\"\n },\n {\n \"key\": \"yt_li\",\n \"value\": \"0\"\n },\n {\n \"key\": \"ResolveUrl_rid\",\n \"value\": \"0x233c2bae5fb15af0\"\n }\n ]\n },\n {\n \"service\": \"GFEEDBACK\",\n \"params\": [\n {\n \"key\": \"logged_in\",\n \"value\": \"0\"\n },\n {\n \"key\": \"e\",\n \"value\": \"24123058,24152443,23943577,24145515,23934970,24007790,24167385,23998056,23986025,24036947,24138064,24180220,24180069,24177193,24180014,23966208,24138442,24140247,24158010,24179789,24164187,24176755,24077266,24007246,24165479,24135310,23918597,23946420,23804281,24004644,24077241,24161848,23983296,1714257,24080738,24002022,24141412,23744176,24148484,24165080,24181588,24166867,24045475,24175488,24002025,24082662,24154616,24181308,24166201,24110902,23882685,24027707,24053419,24144329,24062268,24108219,24085811,24120819,24106839,39321475,24045476,24001373,24174214,24175889,24180089,24034168,24169726\"\n }\n ]\n },\n {\n \"service\": \"GUIDED_HELP\",\n \"params\": [\n {\n \"key\": \"logged_in\",\n \"value\": \"0\"\n }\n ]\n },\n {\n \"service\": \"ECATCHER\",\n \"params\": [\n {\n \"key\": \"client.version\",\n \"value\": \"2.20211103\"\n },\n {\n \"key\": \"client.name\",\n \"value\": \"WEB\"\n },\n {\n \"key\": \"client.fexp\",\n \"value\": \"24123058,24152443,23943577,24145515,23934970,24007790,24167385,23998056,23986025,24036947,24138064,24180220,24180069,24177193,24180014,23966208,24138442,24140247,24158010,24179789,24164187,24176755,24077266,24007246,24165479,24135310,23918597,23946420,23804281,24004644,24077241,24161848,23983296,1714257,24080738,24002022,24141412,23744176,24148484,24165080,24181588,24166867,24045475,24175488,24002025,24082662,24154616,24181308,24166201,24110902,23882685,24027707,24053419,24144329,24062268,24108219,24085811,24120819,24106839,39321475,24045476,24001373,24174214,24175889,24180089,24034168,24169726\"\n }\n ]\n }\n ],\n \"mainAppWebResponseContext\": {\n \"loggedOut\": true\n },\n \"webResponseContextExtensionData\": {\n \"hasDecorated\": true\n }\n },\n \"endpoint\": {\n \"clickTrackingParams\": \"IhMIs_K1t6XN9gIVNOYRCB1JBgjjMghleHRlcm5hbA\u003d\u003d\",\n \"commandMetadata\": {\n \"webCommandMetadata\": {\n \"url\": \"/youtubei/v1/navigation/resolve_url\",\n \"webPageType\": \"WEB_PAGE_TYPE_CHANNEL\",\n \"rootVe\": 3611,\n \"apiUrl\": \"/youtubei/v1/browse\"\n },\n \"resolveUrlCommandMetadata\": {\n \"isVanityUrl\": true\n }\n },\n \"browseEndpoint\": {\n \"browseId\": \"UC6nSFpj9HTCZ5t-N3Rm3-HA\",\n \"params\": \"EgC4AQA%3D\"\n }\n }\n}\n",
"latestUrl": "https://www.youtube.com/youtubei/v1/navigation/resolve_url?key\u003dAIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"
}
}