This commit is contained in:
Tobi 2024-04-11 01:41:51 +00:00 committed by GitHub
commit 8cc6359539
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 241 additions and 19 deletions

View File

@ -30,6 +30,8 @@ import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCSearch
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCStreamExtractor;
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferenceLinkHandlerFactory;
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferencesListLinkHandlerFactory;
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCLiveListLinkHandlerFactory;
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCRecentListLinkHandlerFactory;
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory;
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCStreamLinkHandlerFactory;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
@ -111,37 +113,41 @@ public class MediaCCCService extends StreamingService {
@Override
public KioskList getKioskList() throws ExtractionException {
final KioskList list = new KioskList(this);
final ListLinkHandlerFactory h = MediaCCCConferencesListLinkHandlerFactory.getInstance();
final ListLinkHandlerFactory conferenceLLHF = MediaCCCConferencesListLinkHandlerFactory
.getInstance();
final ListLinkHandlerFactory recentLLHF = MediaCCCRecentListLinkHandlerFactory
.getInstance();
final ListLinkHandlerFactory liveLLHF = MediaCCCLiveListLinkHandlerFactory.getInstance();
// add kiosks here e.g.:
try {
list.addKioskEntry(
(streamingService, url, kioskId) -> new MediaCCCConferenceKiosk(
MediaCCCService.this,
h.fromUrl(url),
conferenceLLHF.fromUrl(url),
kioskId
),
h,
conferenceLLHF,
MediaCCCConferenceKiosk.KIOSK_ID
);
list.addKioskEntry(
(streamingService, url, kioskId) -> new MediaCCCRecentKiosk(
MediaCCCService.this,
h.fromUrl(url),
recentLLHF.fromUrl(url),
kioskId
),
h,
recentLLHF,
MediaCCCRecentKiosk.KIOSK_ID
);
list.addKioskEntry(
(streamingService, url, kioskId) -> new MediaCCCLiveStreamKiosk(
MediaCCCService.this,
h.fromUrl(url),
liveLLHF.fromUrl(url),
kioskId
),
h,
liveLLHF,
MediaCCCLiveStreamKiosk.KIOSK_ID
);

View File

@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.OffsetDateTime;
import java.util.List;
import static org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper.getThumbnailsFromLiveStreamItem;
@ -19,17 +20,25 @@ public class MediaCCCLiveStreamKioskExtractor implements StreamInfoItemExtractor
private final String group;
private final JsonObject roomInfo;
@Nonnull
private final JsonObject currentTalk;
public MediaCCCLiveStreamKioskExtractor(final JsonObject conferenceInfo,
final String group,
final JsonObject roomInfo) {
this.conferenceInfo = conferenceInfo;
this.group = group;
this.roomInfo = roomInfo;
this.currentTalk = roomInfo.getObject("talks").getObject("current");
}
@Override
public String getName() throws ParsingException {
return roomInfo.getObject("talks").getObject("current").getString("title");
if (isBreak()) {
return roomInfo.getString("display") + " - Pause";
} else {
return currentTalk.getString("title");
}
}
@Override
@ -95,6 +104,18 @@ public class MediaCCCLiveStreamKioskExtractor implements StreamInfoItemExtractor
@Nullable
@Override
public DateWrapper getUploadDate() throws ParsingException {
return null;
if (isBreak()) {
return new DateWrapper(OffsetDateTime.parse(currentTalk.getString("fstart")));
} else {
return new DateWrapper(OffsetDateTime.parse(conferenceInfo.getString("startsAt")));
}
}
/**
* Whether the current "talk" is a talk or a pause.
*/
private boolean isBreak() {
return OffsetDateTime.parse(currentTalk.getString("fstart")).isBefore(OffsetDateTime.now())
|| "gap".equals(currentTalk.getString("special"));
}
}

View File

@ -82,6 +82,15 @@ public final class MediaCCCParsingHelper {
return liveStreams;
}
/**
* <p>Reset cached live stream data.</p>
* This is a temporary method which can be used to reset the cached live stream data until a
* caching policy for {@link #getLiveStreams(Downloader, Localization)} is implemented.
*/
public static void resetCachedLiveStreamInfo() {
liveStreams = null;
}
/**
* Get an {@link Image} list from a given image logo URL.
*

View File

@ -2,29 +2,106 @@ package org.schabi.newpipe.extractor.services.media_ccc;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.schabi.newpipe.downloader.DownloaderFactory;
import org.schabi.newpipe.downloader.DownloaderTestImpl;
import org.schabi.newpipe.downloader.MockOnly;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCLiveStreamKiosk;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
import static org.schabi.newpipe.extractor.services.DefaultTests.defaultTestListOfItems;
public class MediaCCCLiveStreamListExtractorTest {
private static KioskExtractor extractor;
@BeforeAll
public static void setUpClass() throws Exception {
NewPipe.init(DownloaderTestImpl.getInstance());
extractor = MediaCCC.getKioskList().getExtractorById("live", null);
extractor.fetchPage();
private static final String RESOURCE_PATH = DownloaderFactory.RESOURCE_PATH
+ "services/media.ccc.de/kiosk/live/";
private static final String LIVE_KIOSK_ID = MediaCCCLiveStreamKiosk.KIOSK_ID;
/**
* Test against the media.ccc.de livestream API endpoint
* and ensure that no exceptions are thrown.
*/
public static class LiveDataTest {
private static KioskExtractor extractor;
@BeforeAll
public static void setUpClass() throws Exception {
MediaCCCTestUtils.ensureStateless();
NewPipe.init(DownloaderTestImpl.getInstance());
extractor = MediaCCC.getKioskList().getExtractorById(LIVE_KIOSK_ID, null);
extractor.fetchPage();
}
@Test
void getConferencesListTest() throws Exception {
final ListExtractor.InfoItemsPage liveStreamPage = extractor.getInitialPage();
final List<InfoItem> items = liveStreamPage.getItems();
if (items.isEmpty()) {
// defaultTestListOfItems() fails, if items is empty.
// This can happen if there are no current live streams.
// In this case, we just check if an exception was thrown
assertTrue(liveStreamPage.getErrors().isEmpty());
} else {
defaultTestListOfItems(MediaCCC, items, liveStreamPage.getErrors());
}
}
}
@Test
public void getConferencesListTest() throws Exception {
final List<InfoItem> items = extractor.getInitialPage().getItems();
// just test if there is an exception thrown
/**
* Test conferences which are available via the API for C3voc internal testing,
* but not intended to be shown to users.
*/
@MockOnly("The live stream API returns different data depending on if and what conferences"
+ " are running. The PreparationTest tests a conference which is used "
+ "for internal testing.")
public static class PreparationTest {
private static KioskExtractor extractor;
@BeforeAll
public static void setUpClass() throws Exception {
MediaCCCTestUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "preparation"));
extractor = MediaCCC.getKioskList().getExtractorById(LIVE_KIOSK_ID, null);
extractor.fetchPage();
}
@Test
void getConferencesListTest() throws Exception {
// Testing conferences and the corresponding talks should not be extracted.
assertTrue(extractor.getInitialPage().getItems().isEmpty());
}
}
/**
* Test a running conference.
*/
@MockOnly("The live stream API returns different data depending on if and what conferences"
+ " are running. Using mocks to ensure that there are conferences & talks to extract.")
public static class LiveConferenceTest {
private static KioskExtractor extractor;
@BeforeAll
public static void setUpClass() throws Exception {
MediaCCCTestUtils.ensureStateless();
NewPipe.init(DownloaderFactory.getDownloader(RESOURCE_PATH + "running"));
extractor = MediaCCC.getKioskList().getExtractorById(LIVE_KIOSK_ID, null);
extractor.fetchPage();
}
@Test
void getConferencesListTest() throws Exception {
final ListExtractor.InfoItemsPage liveStreamPage = extractor.getInitialPage();
final List<InfoItem> items = liveStreamPage.getItems();
assertEquals(6, items.size());
defaultTestListOfItems(MediaCCC, items, liveStreamPage.getErrors());
}
}
}

View File

@ -0,0 +1,15 @@
package org.schabi.newpipe.extractor.services.media_ccc;
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper;
public final class MediaCCCTestUtils {
/**
* Clears static media.ccc.de states.
* <p>This method needs to be called in every class before running and recording mock tests.</p>
*/
public static void ensureStateless() {
MediaCCCParsingHelper.resetCachedLiveStreamInfo();
}
}