mirror of
https://github.com/TeamNewPipe/NewPipeExtractor.git
synced 2024-12-14 22:30:33 +05:30
Merge pull request #500 from TeamNewPipe/media.ccc.de_live
[media.ccc.de] live stream kiosk
This commit is contained in:
commit
1259521d53
@ -45,11 +45,11 @@ public abstract class KioskExtractor<T extends InfoItem> extends ListExtractor<T
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id should be the name of the kiosk, tho Id is used for identifing it in the frontend,
|
* Id should be the name of the kiosk, tho Id is used for identifying it in the frontend,
|
||||||
* so id should be kept in english.
|
* so id should be kept in english.
|
||||||
* In order to get the name of the kiosk in the desired language we have to
|
* In order to get the name of the kiosk in the desired language we have to
|
||||||
* crawl if from the website.
|
* crawl if from the website.
|
||||||
* @return the tranlsated version of id
|
* @return the translated version of id
|
||||||
* @throws ParsingException
|
* @throws ParsingException
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -14,14 +14,8 @@ import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
|||||||
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory;
|
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
|
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
|
||||||
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCConferenceExtractor;
|
import org.schabi.newpipe.extractor.services.media_ccc.extractors.*;
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCConferenceKiosk;
|
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.*;
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCSearchExtractor;
|
|
||||||
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.MediaCCCSearchQueryHandlerFactory;
|
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCStreamLinkHandlerFactory;
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||||
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
|
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
|
||||||
import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
|
import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
|
||||||
@ -62,6 +56,9 @@ public class MediaCCCService extends StreamingService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamExtractor getStreamExtractor(final LinkHandler linkHandler) {
|
public StreamExtractor getStreamExtractor(final LinkHandler linkHandler) {
|
||||||
|
if (MediaCCCParsingHelper.isLiveStreamId(linkHandler.getId())) {
|
||||||
|
return new MediaCCCLiveStreamExtractor(this, linkHandler);
|
||||||
|
}
|
||||||
return new MediaCCCStreamExtractor(this, linkHandler);
|
return new MediaCCCStreamExtractor(this, linkHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +92,28 @@ public class MediaCCCService extends StreamingService {
|
|||||||
new MediaCCCConferencesListLinkHandlerFactory().fromUrl(url), kioskId);
|
new MediaCCCConferencesListLinkHandlerFactory().fromUrl(url), kioskId);
|
||||||
}
|
}
|
||||||
}, new MediaCCCConferencesListLinkHandlerFactory(), "conferences");
|
}, new MediaCCCConferencesListLinkHandlerFactory(), "conferences");
|
||||||
list.setDefaultKiosk("conferences");
|
|
||||||
|
list.addKioskEntry(new KioskList.KioskExtractorFactory() {
|
||||||
|
@Override
|
||||||
|
public KioskExtractor createNewKiosk(final StreamingService streamingService,
|
||||||
|
final String url, final String kioskId)
|
||||||
|
throws ExtractionException {
|
||||||
|
return new MediaCCCRecentKiosk(MediaCCCService.this,
|
||||||
|
new MediaCCCRecentListLinkHandlerFactory().fromUrl(url), kioskId);
|
||||||
|
}
|
||||||
|
}, new MediaCCCRecentListLinkHandlerFactory(), "recent");
|
||||||
|
|
||||||
|
list.addKioskEntry(new KioskList.KioskExtractorFactory() {
|
||||||
|
@Override
|
||||||
|
public KioskExtractor createNewKiosk(final StreamingService streamingService,
|
||||||
|
final String url, final String kioskId)
|
||||||
|
throws ExtractionException {
|
||||||
|
return new MediaCCCLiveStreamKiosk(MediaCCCService.this,
|
||||||
|
new MediaCCCLiveListLinkHandlerFactory().fromUrl(url), kioskId);
|
||||||
|
}
|
||||||
|
}, new MediaCCCLiveListLinkHandlerFactory(), "live");
|
||||||
|
|
||||||
|
list.setDefaultKiosk("recent");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ExtractionException(e);
|
throw new ExtractionException(e);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,300 @@
|
|||||||
|
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
|
||||||
|
|
||||||
|
import com.grack.nanojson.JsonArray;
|
||||||
|
import com.grack.nanojson.JsonObject;
|
||||||
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
|
import org.schabi.newpipe.extractor.MetaInfo;
|
||||||
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
|
||||||
|
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||||
|
import org.schabi.newpipe.extractor.stream.*;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class MediaCCCLiveStreamExtractor extends StreamExtractor {
|
||||||
|
private JsonArray doc = null;
|
||||||
|
private JsonObject conference = null;
|
||||||
|
private String group = "";
|
||||||
|
private JsonObject room = null;
|
||||||
|
|
||||||
|
public MediaCCCLiveStreamExtractor(StreamingService service, LinkHandler linkHandler) {
|
||||||
|
super(service, linkHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
||||||
|
doc = MediaCCCParsingHelper.getLiveStreams(downloader, getExtractorLocalization());
|
||||||
|
// find correct room
|
||||||
|
for (int c = 0; c < doc.size(); c++) {
|
||||||
|
final JsonObject conference = doc.getObject(c);
|
||||||
|
final JsonArray groups = conference.getArray("groups");
|
||||||
|
for (int g = 0; g < groups.size(); g++) {
|
||||||
|
final String group = groups.getObject(g).getString("group");
|
||||||
|
final JsonArray rooms = groups.getObject(g).getArray("rooms");
|
||||||
|
for (int r = 0; r < rooms.size(); r++) {
|
||||||
|
final JsonObject room = rooms.getObject(r);
|
||||||
|
if (getId().equals(conference.getString("slug") + "/" + room.getString("slug"))) {
|
||||||
|
this.conference = conference;
|
||||||
|
this.group = group;
|
||||||
|
this.room = room;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ExtractionException("Could not find room matching id: '" + getId() + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getName() throws ParsingException {
|
||||||
|
return room.getString("display");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getTextualUploadDate() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public DateWrapper getUploadDate() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getThumbnailUrl() throws ParsingException {
|
||||||
|
return room.getString("thumb");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public Description getDescription() throws ParsingException {
|
||||||
|
return new Description(conference.getString("description") + " - " + group, Description.PLAIN_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAgeLimit() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLength() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTimeStamp() throws ParsingException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getViewCount() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLikeCount() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDislikeCount() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUploaderUrl() throws ParsingException {
|
||||||
|
return "https://streaming.media.ccc.de/" + conference.getString("slug");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUploaderName() throws ParsingException {
|
||||||
|
return conference.getString("conference");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getUploaderAvatarUrl() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getSubChannelUrl() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getSubChannelName() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getSubChannelAvatarUrl() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getDashMpdUrl() throws ParsingException {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getHlsUrl() {
|
||||||
|
// TODO: There are multiple HLS streams.
|
||||||
|
// Make getHlsUrl() and getDashMpdUrl() return lists of VideoStreams, so the user can choose a resolution.
|
||||||
|
for (int s = 0; s < room.getArray("streams").size(); s++) {
|
||||||
|
final JsonObject stream = room.getArray("streams").getObject(s);
|
||||||
|
if (stream.getString("type").equals("video")) {
|
||||||
|
final String resolution = stream.getArray("videoSize").getInt(0) + "x"
|
||||||
|
+ stream.getArray("videoSize").getInt(1);
|
||||||
|
if (stream.has("hls")) {
|
||||||
|
return stream.getObject("urls").getObject("hls").getString("url");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AudioStream> getAudioStreams() throws IOException, ExtractionException {
|
||||||
|
final List<AudioStream> audioStreams = new ArrayList<>();
|
||||||
|
for (int s = 0; s < room.getArray("streams").size(); s++) {
|
||||||
|
final JsonObject stream = room.getArray("streams").getObject(s);
|
||||||
|
if (stream.getString("type").equals("audio")) {
|
||||||
|
for (final String type :stream.getObject("urls").keySet()) {
|
||||||
|
final JsonObject url = stream.getObject("urls").getObject(type);
|
||||||
|
audioStreams.add(new AudioStream(url.getString("url"), MediaFormat.getFromSuffix(type), -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return audioStreams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<VideoStream> getVideoStreams() throws IOException, ExtractionException {
|
||||||
|
final List<VideoStream> videoStreams = new ArrayList<>();
|
||||||
|
for (int s = 0; s < room.getArray("streams").size(); s++) {
|
||||||
|
final JsonObject stream = room.getArray("streams").getObject(s);
|
||||||
|
if (stream.getString("type").equals("video")) {
|
||||||
|
final String resolution = stream.getArray("videoSize").getInt(0) + "x"
|
||||||
|
+ stream.getArray("videoSize").getInt(1);
|
||||||
|
for (final String type :stream.getObject("urls").keySet()) {
|
||||||
|
if (!type.equals("hls")) {
|
||||||
|
final JsonObject url = stream.getObject("urls").getObject(type);
|
||||||
|
videoStreams.add(new VideoStream(
|
||||||
|
url.getString("url"),
|
||||||
|
MediaFormat.getFromSuffix(type),
|
||||||
|
resolution));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return videoStreams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<VideoStream> getVideoOnlyStreams() throws IOException, ExtractionException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<SubtitlesStream> getSubtitlesDefault(){
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<SubtitlesStream> getSubtitles(MediaFormat format) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamType getStreamType() throws ParsingException {
|
||||||
|
return StreamType.LIVE_STREAM; // TODO: video and audio only streams are both available
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public StreamInfoItemsCollector getRelatedStreams() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getHost() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getPrivacy() {
|
||||||
|
return "Public";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getCategory() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getLicence() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Locale getLanguageInfo() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<String> getTags() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getSupportInfo() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<StreamSegment> getStreamSegments() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public List<MetaInfo> getMetaInfo() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class MediaCCCLiveStreamKiosk extends KioskExtractor<StreamInfoItem> {
|
||||||
|
public JsonArray doc;
|
||||||
|
|
||||||
|
public MediaCCCLiveStreamKiosk(StreamingService streamingService, ListLinkHandler linkHandler, String kioskId) {
|
||||||
|
super(streamingService, linkHandler, kioskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
||||||
|
doc = MediaCCCParsingHelper.getLiveStreams(downloader, getExtractorLocalization());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public InfoItemsPage<StreamInfoItem> getInitialPage() throws IOException, ExtractionException {
|
||||||
|
StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
|
||||||
|
for (int c = 0; c < doc.size(); c++) {
|
||||||
|
final JsonObject conference = doc.getObject(c);
|
||||||
|
final JsonArray groups = conference.getArray("groups");
|
||||||
|
for (int g = 0; g < groups.size(); g++) {
|
||||||
|
final String group = groups.getObject(g).getString("group");
|
||||||
|
final JsonArray rooms = groups.getObject(g).getArray("rooms");
|
||||||
|
for (int r = 0; r < rooms.size(); r++) {
|
||||||
|
final JsonObject room = rooms.getObject(r);
|
||||||
|
collector.commit(new MediaCCCLiveStreamKioskExtractor(conference, group, room));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return new InfoItemsPage<>(collector, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InfoItemsPage<StreamInfoItem> getPage(Page page) throws IOException, ExtractionException {
|
||||||
|
return InfoItemsPage.emptyPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getName() throws ParsingException {
|
||||||
|
return "live";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
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.stream.StreamInfoItemExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class MediaCCCLiveStreamKioskExtractor implements StreamInfoItemExtractor {
|
||||||
|
|
||||||
|
private final JsonObject conferenceInfo;
|
||||||
|
private final String group;
|
||||||
|
private final JsonObject roomInfo;
|
||||||
|
|
||||||
|
public MediaCCCLiveStreamKioskExtractor(final JsonObject conferenceInfo, final String group,
|
||||||
|
final JsonObject roomInfo) {
|
||||||
|
this.conferenceInfo = conferenceInfo;
|
||||||
|
this.group = group;
|
||||||
|
this.roomInfo = roomInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() throws ParsingException {
|
||||||
|
return roomInfo.getString("schedulename");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() throws ParsingException {
|
||||||
|
return roomInfo.getString("link");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getThumbnailUrl() throws ParsingException {
|
||||||
|
return roomInfo.getString("thumb");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamType getStreamType() throws ParsingException {
|
||||||
|
boolean isVideo = false;
|
||||||
|
for (Object stream : roomInfo.getArray("streams")) {
|
||||||
|
if ("video".equals(((JsonObject) stream).getString("type"))) {
|
||||||
|
isVideo = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isVideo ? StreamType.LIVE_STREAM : StreamType.AUDIO_LIVE_STREAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAd() throws ParsingException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDuration() throws ParsingException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getViewCount() throws ParsingException {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUploaderName() throws ParsingException {
|
||||||
|
return conferenceInfo.getString("conference");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUploaderUrl() throws ParsingException {
|
||||||
|
return "https://media.ccc.de/c/" + conferenceInfo.getString("slug");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getTextualUploadDate() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public DateWrapper getUploadDate() throws ParsingException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,23 @@
|
|||||||
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
|
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
|
||||||
|
|
||||||
|
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.downloader.Downloader;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||||
|
import org.schabi.newpipe.extractor.localization.Localization;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class MediaCCCParsingHelper {
|
public final class MediaCCCParsingHelper {
|
||||||
|
private static JsonArray liveStreams = null;
|
||||||
|
|
||||||
private MediaCCCParsingHelper() { }
|
private MediaCCCParsingHelper() { }
|
||||||
|
|
||||||
public static OffsetDateTime parseDateFrom(final String textualUploadDate) throws ParsingException {
|
public static OffsetDateTime parseDateFrom(final String textualUploadDate) throws ParsingException {
|
||||||
@ -15,4 +27,24 @@ public final class MediaCCCParsingHelper {
|
|||||||
throw new ParsingException("Could not parse date: \"" + textualUploadDate + "\"", e);
|
throw new ParsingException("Could not parse date: \"" + textualUploadDate + "\"", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isLiveStreamId(final String url) {
|
||||||
|
final String pattern = "\\w+/\\w+";
|
||||||
|
return Pattern.matches(pattern, url); // {conference_slug}/{room_slug}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonArray getLiveStreams(final Downloader downloader, final Localization localization) throws ExtractionException {
|
||||||
|
if (liveStreams == null) {
|
||||||
|
try {
|
||||||
|
final String site = downloader.get("https://streaming.media.ccc.de/streams/v2.json",
|
||||||
|
localization).responseBody();
|
||||||
|
liveStreams = JsonParser.array().from(site);
|
||||||
|
} catch (IOException | ReCaptchaException e) {
|
||||||
|
throw new ExtractionException("Could not get live stream JSON.", e);
|
||||||
|
} catch (JsonParserException e) {
|
||||||
|
throw new ExtractionException("Could not parse JSON.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return liveStreams;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class MediaCCCRecentKiosk extends KioskExtractor<StreamInfoItem> {
|
||||||
|
|
||||||
|
private JsonObject doc;
|
||||||
|
|
||||||
|
public MediaCCCRecentKiosk(StreamingService streamingService, ListLinkHandler linkHandler, String kioskId) {
|
||||||
|
super(streamingService, linkHandler, kioskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
||||||
|
final String site = downloader.get("https://api.media.ccc.de/public/events/recent",
|
||||||
|
getExtractorLocalization()).responseBody();
|
||||||
|
try {
|
||||||
|
doc = JsonParser.object().from(site);
|
||||||
|
} catch (JsonParserException jpe) {
|
||||||
|
throw new ExtractionException("Could not parse json.", jpe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public InfoItemsPage<StreamInfoItem> getInitialPage() throws IOException, ExtractionException {
|
||||||
|
final JsonArray events = doc.getArray("events");
|
||||||
|
StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
|
||||||
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
collector.commit(new MediaCCCRecentKioskExtractor(events.getObject(i)));
|
||||||
|
}
|
||||||
|
return new InfoItemsPage<>(collector, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InfoItemsPage<StreamInfoItem> getPage(Page page) throws IOException, ExtractionException {
|
||||||
|
return InfoItemsPage.emptyPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String getName() throws ParsingException {
|
||||||
|
return "recent";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
public class MediaCCCRecentKioskExtractor implements StreamInfoItemExtractor {
|
||||||
|
|
||||||
|
private final JsonObject event;
|
||||||
|
|
||||||
|
public MediaCCCRecentKioskExtractor(final JsonObject event) {
|
||||||
|
this.event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() throws ParsingException {
|
||||||
|
return event.getString("title");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() throws ParsingException {
|
||||||
|
return event.getString("frontend_link");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getThumbnailUrl() throws ParsingException {
|
||||||
|
return event.getString("thumb_url");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamType getStreamType() throws ParsingException {
|
||||||
|
return StreamType.VIDEO_STREAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAd() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDuration() throws ParsingException {
|
||||||
|
return event.getInt("duration");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getViewCount() throws ParsingException {
|
||||||
|
return event.getInt("view_count");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUploaderName() throws ParsingException {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUploaderUrl() throws ParsingException {
|
||||||
|
return new MediaCCCConferenceLinkHandlerFactory()
|
||||||
|
.fromUrl(event.getString("conference_url")) // API URL
|
||||||
|
.getUrl(); // web URL
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getTextualUploadDate() throws ParsingException {
|
||||||
|
return event.getString("date");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public DateWrapper getUploadDate() throws ParsingException {
|
||||||
|
final ZonedDateTime zonedDateTime = ZonedDateTime.parse(event.getString("date"),
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSzzzz"));
|
||||||
|
return new DateWrapper(zonedDateTime.toOffsetDateTime(), false);
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@ import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
|
|||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
|
||||||
public class MediaCCCConferenceInfoItemExtractor implements ChannelInfoItemExtractor {
|
public class MediaCCCConferenceInfoItemExtractor implements ChannelInfoItemExtractor {
|
||||||
private JsonObject conference;
|
private final JsonObject conference;
|
||||||
|
|
||||||
public MediaCCCConferenceInfoItemExtractor(final JsonObject conference) {
|
public MediaCCCConferenceInfoItemExtractor(final JsonObject conference) {
|
||||||
this.conference = conference;
|
this.conference = conference;
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.schabi.newpipe.extractor.services.media_ccc.linkHandler;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class MediaCCCLiveListLinkHandlerFactory extends ListLinkHandlerFactory {
|
||||||
|
private static final String streamPattern = "^(?:https?://)?media\\.ccc\\.de/live$";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId(String url) throws ParsingException {
|
||||||
|
return "live";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onAcceptUrl(String url) throws ParsingException {
|
||||||
|
return Pattern.matches(streamPattern, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl(String id, List<String> contentFilter, String sortFilter) throws ParsingException {
|
||||||
|
// FIXME: wrong URL; should be https://streaming.media.ccc.de/{conference_slug}/{room_slug}
|
||||||
|
return "https://media.ccc.de/live";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.schabi.newpipe.extractor.services.media_ccc.linkHandler;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.utils.Parser;
|
||||||
|
|
||||||
|
public class MediaCCCLiveStreamLinkHandlerFactory extends LinkHandlerFactory {
|
||||||
|
public static final String VIDEO_API_ENDPOINT = "https://api.media.ccc.de/public/events/";
|
||||||
|
private static final String VIDEO_PATH = "https://streaming.media.ccc.de/v/";
|
||||||
|
private static final String ID_PATTERN = "(?:(?:(?:api\\.)?media\\.ccc\\.de/public/events/)|(?:media\\.ccc\\.de/v/))([^/?&#]*)";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId(final String url) throws ParsingException {
|
||||||
|
return Parser.matchGroup1(ID_PATTERN, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl(final String id) throws ParsingException {
|
||||||
|
return VIDEO_PATH + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onAcceptUrl(final String url) {
|
||||||
|
try {
|
||||||
|
return getId(url) != null;
|
||||||
|
} catch (ParsingException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package org.schabi.newpipe.extractor.services.media_ccc.linkHandler;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class MediaCCCRecentListLinkHandlerFactory extends ListLinkHandlerFactory {
|
||||||
|
private static final String pattern = "^(https?://)?media\\.ccc\\.de/recent/?$";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId(String url) {
|
||||||
|
return "recent";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onAcceptUrl(String url) {
|
||||||
|
return Pattern.matches(pattern, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl(String id, List<String> contentFilter, String sortFilter) {
|
||||||
|
return "https://media.ccc.de/recent";
|
||||||
|
}
|
||||||
|
}
|
@ -2,20 +2,36 @@ package org.schabi.newpipe.extractor.services.media_ccc.linkHandler;
|
|||||||
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
|
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCParsingHelper;
|
||||||
import org.schabi.newpipe.extractor.utils.Parser;
|
import org.schabi.newpipe.extractor.utils.Parser;
|
||||||
|
|
||||||
public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory {
|
public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory {
|
||||||
public static final String VIDEO_API_ENDPOINT = "https://api.media.ccc.de/public/events/";
|
public static final String VIDEO_API_ENDPOINT = "https://api.media.ccc.de/public/events/";
|
||||||
private static final String VIDEO_PATH = "https://media.ccc.de/v/";
|
private static final String VIDEO_PATH = "https://media.ccc.de/v/";
|
||||||
private static final String ID_PATTERN = "(?:(?:(?:api\\.)?media\\.ccc\\.de/public/events/)|(?:media\\.ccc\\.de/v/))([^/?&#]*)";
|
private static final String RECORDING_ID_PATTERN = "(?:(?:(?:api\\.)?media\\.ccc\\.de/public/events/)|(?:media\\.ccc\\.de/v/))([^/?&#]*)";
|
||||||
|
private static final String LIVE_STREAM_API_ENDPOINT = "https://streaming.media.ccc.de/streams/v2.json";
|
||||||
|
private static final String LIVE_STREAM_PATH = "https://streaming.media.ccc.de/";
|
||||||
|
private static final String LIVE_STREAM_ID_PATTERN = "streaming\\.media\\.ccc\\.de\\/(\\w+\\/\\w+)";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId(final String url) throws ParsingException {
|
public String getId(final String url) throws ParsingException {
|
||||||
return Parser.matchGroup1(ID_PATTERN, url);
|
String streamId = null;
|
||||||
|
try {
|
||||||
|
streamId = Parser.matchGroup1(LIVE_STREAM_ID_PATTERN, url);
|
||||||
|
} catch (Parser.RegexException ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
if (streamId == null) {
|
||||||
|
return Parser.matchGroup1(RECORDING_ID_PATTERN, url);
|
||||||
|
}
|
||||||
|
return streamId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl(final String id) throws ParsingException {
|
public String getUrl(final String id) throws ParsingException {
|
||||||
|
if (MediaCCCParsingHelper.isLiveStreamId(id)) {
|
||||||
|
return LIVE_STREAM_PATH + id;
|
||||||
|
}
|
||||||
return VIDEO_PATH + id;
|
return VIDEO_PATH + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class MediaCCCConferenceListExtractorTest {
|
|||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUpClass() throws Exception {
|
public static void setUpClass() throws Exception {
|
||||||
NewPipe.init(DownloaderTestImpl.getInstance());
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
extractor = MediaCCC.getKioskList().getDefaultKioskExtractor();
|
extractor = MediaCCC.getKioskList().getExtractorById("conferences", null);
|
||||||
extractor.fetchPage();
|
extractor.fetchPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package org.schabi.newpipe.extractor.services.media_ccc;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.schabi.newpipe.DownloaderTestImpl;
|
||||||
|
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 java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
|
||||||
|
|
||||||
|
public class MediaCCCLiveStreamListExtractorTest {
|
||||||
|
private static KioskExtractor extractor;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpClass() throws Exception {
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
extractor = MediaCCC.getKioskList().getExtractorById("live", null);
|
||||||
|
extractor.fetchPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConferencesListTest() throws Exception {
|
||||||
|
final List<InfoItem> a = extractor.getInitialPage().getItems();
|
||||||
|
assertTrue(a.size() > 2);
|
||||||
|
for (int i = 0; i < a.size(); i++) {
|
||||||
|
final InfoItem b = a.get(i);
|
||||||
|
assertNotNull(a.get(i).getName());
|
||||||
|
assertTrue(a.get(i).getName().length() >= 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package org.schabi.newpipe.extractor.services.media_ccc;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.schabi.newpipe.DownloaderTestImpl;
|
||||||
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
|
||||||
|
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||||
|
|
||||||
|
public class MediaCCCRecentListExtractorTest {
|
||||||
|
private static KioskExtractor extractor;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpClass() throws Exception {
|
||||||
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
extractor = MediaCCC.getKioskList().getExtractorById("recent", null);
|
||||||
|
extractor.fetchPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public 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);
|
||||||
|
assertTrue(isNullOrEmpty(item.getUploaderName())); // we do not get the uploader name
|
||||||
|
assertTrue(item.getUploadDate().offsetDateTime().isBefore(OffsetDateTime.now()));
|
||||||
|
assertTrue(item.getUploadDate().offsetDateTime().isAfter(OffsetDateTime.now().minusYears(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user