Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MediaCCC] Fix regressions and improve MediaCCCLiveStreamKioskExtractor #1097

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
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;
Expand Down Expand Up @@ -112,37 +114,41 @@ public SuggestionExtractor getSuggestionExtractor() {
@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
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

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;
Expand All @@ -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";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How MediaCCC's website displays paused rooms? I don't think hardcoding - Pause at the end of a room name is a good idea for localization purposes.

} else {
return currentTalk.getString("title");
}
}

@Override
Expand Down Expand Up @@ -95,6 +104,18 @@ public String getTextualUploadDate() throws ParsingException {
@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"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ public static JsonArray getLiveStreams(final Downloader downloader,
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.
Comment on lines +86 to +88
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* <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.
* 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.
* </p>

*/
public static void resetCachedLiveStreamInfo() {
liveStreams = null;
}

/**
* Get an {@link Image} list from a given image logo URL.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,106 @@

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());

}
}
}
Original file line number Diff line number Diff line change
@@ -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>
Comment on lines +8 to +9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Clears static media.ccc.de states.
* <p>This method needs to be called in every class before running and recording mock tests.</p>
* Clears static MediaCCC states.
*
* <p>
* This method needs to be called in every class before running and recording mock tests.
* </p>

*/
public static void ensureStateless() {
MediaCCCParsingHelper.resetCachedLiveStreamInfo();
}

}
Loading