Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
e7b046db9d
38 changed files with 426 additions and 529 deletions
|
@ -1,7 +1,7 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':timeago-parser')
|
implementation project(':timeago-parser')
|
||||||
|
|
||||||
implementation 'com.github.wb9688:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
||||||
implementation 'org.jsoup:jsoup:1.9.2'
|
implementation 'org.jsoup:jsoup:1.9.2'
|
||||||
implementation 'org.mozilla:rhino:1.7.7.1'
|
implementation 'org.mozilla:rhino:1.7.7.1'
|
||||||
implementation 'com.github.spotbugs:spotbugs-annotations:3.1.0'
|
implementation 'com.github.spotbugs:spotbugs-annotations:3.1.0'
|
||||||
|
|
|
@ -6,7 +6,12 @@ import org.schabi.newpipe.extractor.comments.CommentsExtractor;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
|
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
|
||||||
import org.schabi.newpipe.extractor.kiosk.KioskList;
|
import org.schabi.newpipe.extractor.kiosk.KioskList;
|
||||||
import org.schabi.newpipe.extractor.linkhandler.*;
|
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
|
||||||
|
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
||||||
|
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.MediaCCCConferenceExtractor;
|
||||||
|
@ -21,19 +26,17 @@ 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;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO;
|
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.AUDIO;
|
||||||
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO;
|
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.VIDEO;
|
||||||
|
|
||||||
public class MediaCCCService extends StreamingService {
|
public class MediaCCCService extends StreamingService {
|
||||||
public MediaCCCService(int id) {
|
public MediaCCCService(final int id) {
|
||||||
super(id, "MediaCCC", asList(AUDIO, VIDEO));
|
super(id, "MediaCCC", asList(AUDIO, VIDEO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SearchExtractor getSearchExtractor(SearchQueryHandler query) {
|
public SearchExtractor getSearchExtractor(final SearchQueryHandler query) {
|
||||||
return new MediaCCCSearchExtractor(this, query);
|
return new MediaCCCSearchExtractor(this, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,17 +61,17 @@ public class MediaCCCService extends StreamingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamExtractor getStreamExtractor(LinkHandler linkHandler) {
|
public StreamExtractor getStreamExtractor(final LinkHandler linkHandler) {
|
||||||
return new MediaCCCStreamExtractor(this, linkHandler);
|
return new MediaCCCStreamExtractor(this, linkHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) {
|
public ChannelExtractor getChannelExtractor(final ListLinkHandler linkHandler) {
|
||||||
return new MediaCCCConferenceExtractor(this, linkHandler);
|
return new MediaCCCConferenceExtractor(this, linkHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) {
|
public PlaylistExtractor getPlaylistExtractor(final ListLinkHandler linkHandler) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +88,9 @@ public class MediaCCCService extends StreamingService {
|
||||||
try {
|
try {
|
||||||
list.addKioskEntry(new KioskList.KioskExtractorFactory() {
|
list.addKioskEntry(new KioskList.KioskExtractorFactory() {
|
||||||
@Override
|
@Override
|
||||||
public KioskExtractor createNewKiosk(StreamingService streamingService,
|
public KioskExtractor createNewKiosk(final StreamingService streamingService,
|
||||||
String url,
|
final String url, final String kioskId)
|
||||||
String kioskId) throws ExtractionException, IOException {
|
throws ExtractionException {
|
||||||
return new MediaCCCConferenceKiosk(MediaCCCService.this,
|
return new MediaCCCConferenceKiosk(MediaCCCService.this,
|
||||||
new MediaCCCConferencesListLinkHandlerFactory().fromUrl(url), kioskId);
|
new MediaCCCConferencesListLinkHandlerFactory().fromUrl(url), kioskId);
|
||||||
}
|
}
|
||||||
|
@ -111,8 +114,7 @@ public class MediaCCCService extends StreamingService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommentsExtractor getCommentsExtractor(ListLinkHandler linkHandler)
|
public CommentsExtractor getCommentsExtractor(final ListLinkHandler linkHandler) {
|
||||||
throws ExtractionException {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
import com.grack.nanojson.JsonParserException;
|
import com.grack.nanojson.JsonParserException;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
|
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
|
@ -14,45 +15,46 @@ import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.Medi
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class MediaCCCConferenceExtractor extends ChannelExtractor {
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class MediaCCCConferenceExtractor extends ChannelExtractor {
|
||||||
private JsonObject conferenceData;
|
private JsonObject conferenceData;
|
||||||
|
|
||||||
public MediaCCCConferenceExtractor(StreamingService service, ListLinkHandler linkHandler) {
|
public MediaCCCConferenceExtractor(final StreamingService service,
|
||||||
|
final ListLinkHandler linkHandler) {
|
||||||
super(service, linkHandler);
|
super(service, linkHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAvatarUrl() throws ParsingException {
|
public String getAvatarUrl() {
|
||||||
return conferenceData.getString("logo_url");
|
return conferenceData.getString("logo_url");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBannerUrl() throws ParsingException {
|
public String getBannerUrl() {
|
||||||
return conferenceData.getString("logo_url");
|
return conferenceData.getString("logo_url");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFeedUrl() throws ParsingException {
|
public String getFeedUrl() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubscriberCount() throws ParsingException {
|
public long getSubscriberCount() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() throws ParsingException {
|
public String getDescription() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public InfoItemsPage<StreamInfoItem> getInitialPage() throws IOException, ExtractionException {
|
public InfoItemsPage<StreamInfoItem> getInitialPage() {
|
||||||
StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
|
StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
|
||||||
JsonArray events = conferenceData.getArray("events");
|
JsonArray events = conferenceData.getArray("events");
|
||||||
for (int i = 0; i < events.size(); i++) {
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
@ -62,17 +64,18 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNextPageUrl() throws IOException, ExtractionException {
|
public String getNextPageUrl() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InfoItemsPage<StreamInfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
|
public InfoItemsPage<StreamInfoItem> getPage(final String pageUrl) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
public void onFetchPage(@Nonnull final Downloader downloader)
|
||||||
|
throws IOException, ExtractionException {
|
||||||
try {
|
try {
|
||||||
conferenceData = JsonParser.object().from(downloader.get(getUrl()).responseBody());
|
conferenceData = JsonParser.object().from(downloader.get(getUrl()).responseBody());
|
||||||
} catch (JsonParserException jpe) {
|
} catch (JsonParserException jpe) {
|
||||||
|
@ -88,7 +91,7 @@ public class MediaCCCConferenceExtractor extends ChannelExtractor {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getOriginalUrl() throws ParsingException {
|
public String getOriginalUrl() {
|
||||||
return "https://media.ccc.de/c/" + conferenceData.getString("acronym");
|
return "https://media.ccc.de/c/" + conferenceData.getString("acronym");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
import com.grack.nanojson.JsonParserException;
|
import com.grack.nanojson.JsonParserException;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItemsCollector;
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItemsCollector;
|
||||||
|
@ -14,22 +15,22 @@ import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
|
||||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.MediaCCCConferenceInfoItemExtractor;
|
import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.MediaCCCConferenceInfoItemExtractor;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class MediaCCCConferenceKiosk extends KioskExtractor<ChannelInfoItem> {
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class MediaCCCConferenceKiosk extends KioskExtractor<ChannelInfoItem> {
|
||||||
private JsonObject doc;
|
private JsonObject doc;
|
||||||
|
|
||||||
public MediaCCCConferenceKiosk(StreamingService streamingService,
|
public MediaCCCConferenceKiosk(final StreamingService streamingService,
|
||||||
ListLinkHandler linkHandler,
|
final ListLinkHandler linkHandler,
|
||||||
String kioskId) {
|
final String kioskId) {
|
||||||
super(streamingService, linkHandler, kioskId);
|
super(streamingService, linkHandler, kioskId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public InfoItemsPage<ChannelInfoItem> getInitialPage() throws IOException, ExtractionException {
|
public InfoItemsPage<ChannelInfoItem> getInitialPage() {
|
||||||
JsonArray conferences = doc.getArray("conferences");
|
JsonArray conferences = doc.getArray("conferences");
|
||||||
ChannelInfoItemsCollector collector = new ChannelInfoItemsCollector(getServiceId());
|
ChannelInfoItemsCollector collector = new ChannelInfoItemsCollector(getServiceId());
|
||||||
for (int i = 0; i < conferences.size(); i++) {
|
for (int i = 0; i < conferences.size(); i++) {
|
||||||
|
@ -40,18 +41,20 @@ public class MediaCCCConferenceKiosk extends KioskExtractor<ChannelInfoItem> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNextPageUrl() throws IOException, ExtractionException {
|
public String getNextPageUrl() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InfoItemsPage<ChannelInfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
|
public InfoItemsPage<ChannelInfoItem> getPage(final String pageUrl) {
|
||||||
return InfoItemsPage.emptyPage();
|
return InfoItemsPage.emptyPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
public void onFetchPage(@Nonnull final Downloader downloader)
|
||||||
String site = downloader.get(getLinkHandler().getUrl(), getExtractorLocalization()).responseBody();
|
throws IOException, ExtractionException {
|
||||||
|
final String site = downloader.get(getLinkHandler().getUrl(), getExtractorLocalization())
|
||||||
|
.responseBody();
|
||||||
try {
|
try {
|
||||||
doc = JsonParser.object().from(site);
|
doc = JsonParser.object().from(site);
|
||||||
} catch (JsonParserException jpe) {
|
} catch (JsonParserException jpe) {
|
||||||
|
|
|
@ -7,11 +7,10 @@ import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
public class MediaCCCParsingHelper {
|
public final class MediaCCCParsingHelper {
|
||||||
private MediaCCCParsingHelper() {
|
private MediaCCCParsingHelper() { }
|
||||||
}
|
|
||||||
|
|
||||||
public static Calendar parseDateFrom(String textualUploadDate) throws ParsingException {
|
public static Calendar parseDateFrom(final String textualUploadDate) throws ParsingException {
|
||||||
Date date;
|
Date date;
|
||||||
try {
|
try {
|
||||||
date = new SimpleDateFormat("yyyy-MM-dd").parse(textualUploadDate);
|
date = new SimpleDateFormat("yyyy-MM-dd").parse(textualUploadDate);
|
||||||
|
|
|
@ -4,31 +4,34 @@ import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
import com.grack.nanojson.JsonParserException;
|
import com.grack.nanojson.JsonParserException;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.InfoItem;
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
|
||||||
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
|
||||||
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
|
||||||
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.MediaCCCStreamInfoItemExtractor;
|
import org.schabi.newpipe.extractor.services.media_ccc.extractors.infoItems.MediaCCCStreamInfoItemExtractor;
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferencesListLinkHandlerFactory;
|
import org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCConferencesListLinkHandlerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.*;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.ALL;
|
||||||
|
import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.CONFERENCES;
|
||||||
|
import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.EVENTS;
|
||||||
|
|
||||||
public class MediaCCCSearchExtractor extends SearchExtractor {
|
public class MediaCCCSearchExtractor extends SearchExtractor {
|
||||||
|
|
||||||
private JsonObject doc;
|
private JsonObject doc;
|
||||||
private MediaCCCConferenceKiosk conferenceKiosk;
|
private MediaCCCConferenceKiosk conferenceKiosk;
|
||||||
|
|
||||||
public MediaCCCSearchExtractor(StreamingService service, SearchQueryHandler linkHandler) {
|
public MediaCCCSearchExtractor(final StreamingService service,
|
||||||
|
final SearchQueryHandler linkHandler) {
|
||||||
super(service, linkHandler);
|
super(service, linkHandler);
|
||||||
try {
|
try {
|
||||||
conferenceKiosk = new MediaCCCConferenceKiosk(service,
|
conferenceKiosk = new MediaCCCConferenceKiosk(service,
|
||||||
|
@ -40,13 +43,13 @@ public class MediaCCCSearchExtractor extends SearchExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSearchSuggestion() throws ParsingException {
|
public String getSearchSuggestion() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public InfoItemsPage<InfoItem> getInitialPage() throws IOException, ExtractionException {
|
public InfoItemsPage<InfoItem> getInitialPage() {
|
||||||
final InfoItemsSearchCollector searchItems = new InfoItemsSearchCollector(getServiceId());
|
final InfoItemsSearchCollector searchItems = new InfoItemsSearchCollector(getServiceId());
|
||||||
|
|
||||||
if (getLinkHandler().getContentFilters().contains(CONFERENCES)
|
if (getLinkHandler().getContentFilters().contains(CONFERENCES)
|
||||||
|
@ -70,17 +73,18 @@ public class MediaCCCSearchExtractor extends SearchExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNextPageUrl() throws IOException, ExtractionException {
|
public String getNextPageUrl() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InfoItemsPage<InfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
|
public InfoItemsPage<InfoItem> getPage(final String pageUrl) {
|
||||||
return InfoItemsPage.emptyPage();
|
return InfoItemsPage.emptyPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
public void onFetchPage(@Nonnull final Downloader downloader)
|
||||||
|
throws IOException, ExtractionException {
|
||||||
if (getLinkHandler().getContentFilters().contains(EVENTS)
|
if (getLinkHandler().getContentFilters().contains(EVENTS)
|
||||||
|| getLinkHandler().getContentFilters().contains(ALL)
|
|| getLinkHandler().getContentFilters().contains(ALL)
|
||||||
|| getLinkHandler().getContentFilters().isEmpty()) {
|
|| getLinkHandler().getContentFilters().isEmpty()) {
|
||||||
|
@ -95,44 +99,45 @@ public class MediaCCCSearchExtractor extends SearchExtractor {
|
||||||
}
|
}
|
||||||
if (getLinkHandler().getContentFilters().contains(CONFERENCES)
|
if (getLinkHandler().getContentFilters().contains(CONFERENCES)
|
||||||
|| getLinkHandler().getContentFilters().contains(ALL)
|
|| getLinkHandler().getContentFilters().contains(ALL)
|
||||||
|| getLinkHandler().getContentFilters().isEmpty())
|
|| getLinkHandler().getContentFilters().isEmpty()) {
|
||||||
conferenceKiosk.fetchPage();
|
conferenceKiosk.fetchPage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void searchConferences(String searchString,
|
private void searchConferences(final String searchString,
|
||||||
List<ChannelInfoItem> channelItems,
|
final List<ChannelInfoItem> channelItems,
|
||||||
InfoItemsSearchCollector collector) {
|
final InfoItemsSearchCollector collector) {
|
||||||
for (final ChannelInfoItem item : channelItems) {
|
for (final ChannelInfoItem item : channelItems) {
|
||||||
if (item.getName().toUpperCase().contains(
|
if (item.getName().toUpperCase().contains(
|
||||||
searchString.toUpperCase())) {
|
searchString.toUpperCase())) {
|
||||||
collector.commit(new ChannelInfoItemExtractor() {
|
collector.commit(new ChannelInfoItemExtractor() {
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() throws ParsingException {
|
public String getDescription() {
|
||||||
return item.getDescription();
|
return item.getDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubscriberCount() throws ParsingException {
|
public long getSubscriberCount() {
|
||||||
return item.getSubscriberCount();
|
return item.getSubscriberCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getStreamCount() throws ParsingException {
|
public long getStreamCount() {
|
||||||
return item.getStreamCount();
|
return item.getStreamCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() throws ParsingException {
|
public String getName() {
|
||||||
return item.getName();
|
return item.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl() throws ParsingException {
|
public String getUrl() {
|
||||||
return item.getUrl();
|
return item.getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getThumbnailUrl() throws ParsingException {
|
public String getThumbnailUrl() {
|
||||||
return item.getThumbnailUrl();
|
return item.getThumbnailUrl();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
import com.grack.nanojson.JsonParserException;
|
import com.grack.nanojson.JsonParserException;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.MediaFormat;
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
|
@ -11,27 +12,34 @@ 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.linkhandler.LinkHandler;
|
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
|
||||||
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||||
import org.schabi.newpipe.extractor.stream.*;
|
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||||
|
import org.schabi.newpipe.extractor.stream.Description;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamExtractor;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||||
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class MediaCCCStreamExtractor extends StreamExtractor {
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class MediaCCCStreamExtractor extends StreamExtractor {
|
||||||
private JsonObject data;
|
private JsonObject data;
|
||||||
private JsonObject conferenceData;
|
private JsonObject conferenceData;
|
||||||
|
|
||||||
public MediaCCCStreamExtractor(StreamingService service, LinkHandler linkHandler) {
|
public MediaCCCStreamExtractor(final StreamingService service, final LinkHandler linkHandler) {
|
||||||
super(service, linkHandler);
|
super(service, linkHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getTextualUploadDate() throws ParsingException {
|
public String getTextualUploadDate() {
|
||||||
return data.getString("release_date");
|
return data.getString("release_date");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,79 +51,79 @@ public class MediaCCCStreamExtractor extends StreamExtractor {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getThumbnailUrl() throws ParsingException {
|
public String getThumbnailUrl() {
|
||||||
return data.getString("thumb_url");
|
return data.getString("thumb_url");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Description getDescription() throws ParsingException {
|
public Description getDescription() {
|
||||||
return new Description(data.getString("description"), Description.PLAIN_TEXT);
|
return new Description(data.getString("description"), Description.PLAIN_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAgeLimit() throws ParsingException {
|
public int getAgeLimit() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLength() throws ParsingException {
|
public long getLength() {
|
||||||
return data.getInt("length");
|
return data.getInt("length");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTimeStamp() throws ParsingException {
|
public long getTimeStamp() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getViewCount() throws ParsingException {
|
public long getViewCount() {
|
||||||
return data.getInt("view_count");
|
return data.getInt("view_count");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLikeCount() throws ParsingException {
|
public long getLikeCount() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDislikeCount() throws ParsingException {
|
public long getDislikeCount() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderUrl() throws ParsingException {
|
public String getUploaderUrl() {
|
||||||
return data.getString("conference_url");
|
return data.getString("conference_url");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderName() throws ParsingException {
|
public String getUploaderName() {
|
||||||
return data.getString("conference_url")
|
return data.getString("conference_url")
|
||||||
.replace("https://api.media.ccc.de/public/conferences/", "");
|
.replaceFirst("https://(api\\.)?media\\.ccc\\.de/public/conferences/", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderAvatarUrl() throws ParsingException {
|
public String getUploaderAvatarUrl() {
|
||||||
return conferenceData.getString("logo_url");
|
return conferenceData.getString("logo_url");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getDashMpdUrl() throws ParsingException {
|
public String getDashMpdUrl() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getHlsUrl() throws ParsingException {
|
public String getHlsUrl() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AudioStream> getAudioStreams() throws IOException, ExtractionException {
|
public List<AudioStream> getAudioStreams() throws ExtractionException {
|
||||||
final JsonArray recordings = data.getArray("recordings");
|
final JsonArray recordings = data.getArray("recordings");
|
||||||
final List<AudioStream> audioStreams = new ArrayList<>();
|
final List<AudioStream> audioStreams = new ArrayList<>();
|
||||||
for (int i = 0; i < recordings.size(); i++) {
|
for (int i = 0; i < recordings.size(); i++) {
|
||||||
|
@ -134,14 +142,15 @@ public class MediaCCCStreamExtractor extends StreamExtractor {
|
||||||
throw new ExtractionException("Unknown media format: " + mimeType);
|
throw new ExtractionException("Unknown media format: " + mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
audioStreams.add(new AudioStream(recording.getString("recording_url"), mediaFormat, -1));
|
audioStreams.add(new AudioStream(recording.getString("recording_url"),
|
||||||
|
mediaFormat, -1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return audioStreams;
|
return audioStreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<VideoStream> getVideoStreams() throws IOException, ExtractionException {
|
public List<VideoStream> getVideoStreams() throws ExtractionException {
|
||||||
final JsonArray recordings = data.getArray("recordings");
|
final JsonArray recordings = data.getArray("recordings");
|
||||||
final List<VideoStream> videoStreams = new ArrayList<>();
|
final List<VideoStream> videoStreams = new ArrayList<>();
|
||||||
for (int i = 0; i < recordings.size(); i++) {
|
for (int i = 0; i < recordings.size(); i++) {
|
||||||
|
@ -167,34 +176,34 @@ public class MediaCCCStreamExtractor extends StreamExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<VideoStream> getVideoOnlyStreams() throws IOException, ExtractionException {
|
public List<VideoStream> getVideoOnlyStreams() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public List<SubtitlesStream> getSubtitlesDefault() throws IOException, ExtractionException {
|
public List<SubtitlesStream> getSubtitlesDefault() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public List<SubtitlesStream> getSubtitles(final MediaFormat format) throws IOException, ExtractionException {
|
public List<SubtitlesStream> getSubtitles(final MediaFormat format) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamType getStreamType() throws ParsingException {
|
public StreamType getStreamType() {
|
||||||
return StreamType.VIDEO_STREAM;
|
return StreamType.VIDEO_STREAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamInfoItem getNextStream() throws IOException, ExtractionException {
|
public StreamInfoItem getNextStream() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamInfoItemsCollector getRelatedStreams() throws IOException, ExtractionException {
|
public StreamInfoItemsCollector getRelatedStreams() {
|
||||||
return new StreamInfoItemsCollector(getServiceId());
|
return new StreamInfoItemsCollector(getServiceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,14 +213,16 @@ public class MediaCCCStreamExtractor extends StreamExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
public void onFetchPage(@Nonnull final Downloader downloader)
|
||||||
|
throws IOException, ExtractionException {
|
||||||
try {
|
try {
|
||||||
data = JsonParser.object().from(
|
data = JsonParser.object().from(
|
||||||
downloader.get(getLinkHandler().getUrl()).responseBody());
|
downloader.get(getLinkHandler().getUrl()).responseBody());
|
||||||
conferenceData = JsonParser.object()
|
conferenceData = JsonParser.object()
|
||||||
.from(downloader.get(getUploaderUrl()).responseBody());
|
.from(downloader.get(getUploaderUrl()).responseBody());
|
||||||
} catch (JsonParserException jpe) {
|
} catch (JsonParserException jpe) {
|
||||||
throw new ExtractionException("Could not parse json returned by url: " + getLinkHandler().getUrl(), jpe);
|
throw new ExtractionException("Could not parse json returned by url: "
|
||||||
|
+ getLinkHandler().getUrl(), jpe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,44 +234,44 @@ public class MediaCCCStreamExtractor extends StreamExtractor {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getOriginalUrl() throws ParsingException {
|
public String getOriginalUrl() {
|
||||||
return data.getString("frontend_link");
|
return data.getString("frontend_link");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHost() throws ParsingException {
|
public String getHost() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPrivacy() throws ParsingException {
|
public String getPrivacy() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCategory() throws ParsingException {
|
public String getCategory() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLicence() throws ParsingException {
|
public String getLicence() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Locale getLanguageInfo() throws ParsingException {
|
public Locale getLanguageInfo() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public List<String> getTags() throws ParsingException {
|
public List<String> getTags() {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getSupportInfo() throws ParsingException {
|
public String getSupportInfo() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package org.schabi.newpipe.extractor.services.media_ccc.extractors;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
|
||||||
import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MediaCCCSuggestionExtractor extends SuggestionExtractor {
|
|
||||||
|
|
||||||
public MediaCCCSuggestionExtractor(StreamingService service) {
|
|
||||||
super(service);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> suggestionList(String query) throws IOException, ExtractionException {
|
|
||||||
return new ArrayList<>(0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,25 +5,24 @@ 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;
|
||||||
|
|
||||||
JsonObject conference;
|
public MediaCCCConferenceInfoItemExtractor(final JsonObject conference) {
|
||||||
|
|
||||||
public MediaCCCConferenceInfoItemExtractor(JsonObject conference) {
|
|
||||||
this.conference = conference;
|
this.conference = conference;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() throws ParsingException {
|
public String getDescription() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubscriberCount() throws ParsingException {
|
public long getSubscriberCount() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getStreamCount() throws ParsingException {
|
public long getStreamCount() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ public class MediaCCCConferenceInfoItemExtractor implements ChannelInfoItemExtra
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getThumbnailUrl() throws ParsingException {
|
public String getThumbnailUrl() {
|
||||||
return conference.getString("logo_url");
|
return conference.getString("logo_url");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,47 +10,46 @@ import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
|
private JsonObject event;
|
||||||
|
|
||||||
JsonObject event;
|
public MediaCCCStreamInfoItemExtractor(final JsonObject event) {
|
||||||
|
|
||||||
public MediaCCCStreamInfoItemExtractor(JsonObject event) {
|
|
||||||
this.event = event;
|
this.event = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamType getStreamType() throws ParsingException {
|
public StreamType getStreamType() {
|
||||||
return StreamType.VIDEO_STREAM;
|
return StreamType.VIDEO_STREAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAd() throws ParsingException {
|
public boolean isAd() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() throws ParsingException {
|
public long getDuration() {
|
||||||
return event.getInt("length");
|
return event.getInt("length");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getViewCount() throws ParsingException {
|
public long getViewCount() {
|
||||||
return event.getInt("view_count");
|
return event.getInt("view_count");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderName() throws ParsingException {
|
public String getUploaderName() {
|
||||||
return event.getString("conference_url")
|
return event.getString("conference_url")
|
||||||
.replace("https://api.media.ccc.de/public/conferences/", "");
|
.replaceFirst("https://(api\\.)?media\\.ccc\\.de/public/conferences/", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderUrl() throws ParsingException {
|
public String getUploaderUrl() {
|
||||||
return event.getString("conference_url");
|
return event.getString("conference_url");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public String getTextualUploadDate() throws ParsingException {
|
public String getTextualUploadDate() {
|
||||||
return event.getString("release_date");
|
return event.getString("release_date");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +66,12 @@ public class MediaCCCStreamInfoItemExtractor implements StreamInfoItemExtractor
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl() throws ParsingException {
|
public String getUrl() throws ParsingException {
|
||||||
return "https://api.media.ccc.de/public/events/" +
|
return "https://media.ccc.de/public/events/"
|
||||||
event.getString("guid");
|
+ event.getString("guid");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getThumbnailUrl() throws ParsingException {
|
public String getThumbnailUrl() {
|
||||||
return event.getString("thumb_url");
|
return event.getString("thumb_url");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,17 @@ import org.schabi.newpipe.extractor.utils.Parser;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MediaCCCConferenceLinkHandlerFactory extends ListLinkHandlerFactory {
|
public class MediaCCCConferenceLinkHandlerFactory extends ListLinkHandlerFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl(String id, List<String> contentFilter, String sortFilter) throws ParsingException {
|
public String getUrl(final String id, final List<String> contentFilter, final String sortFilter)
|
||||||
return "https://api.media.ccc.de/public/conferences/" + id;
|
throws ParsingException {
|
||||||
|
return "https://media.ccc.de/public/conferences/" + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId(String url) throws ParsingException {
|
public String getId(final String url) throws ParsingException {
|
||||||
if (url.startsWith("https://api.media.ccc.de/public/conferences/")) {
|
if (url.startsWith("https://media.ccc.de/public/conferences/")
|
||||||
return url.replace("https://api.media.ccc.de/public/conferences/", "");
|
|| url.startsWith("https://api.media.ccc.de/public/conferences/")) {
|
||||||
|
return url.replaceFirst("https://(api\\.)?media\\.ccc\\.de/public/conferences/", "");
|
||||||
} else if (url.startsWith("https://media.ccc.de/c/")) {
|
} else if (url.startsWith("https://media.ccc.de/c/")) {
|
||||||
return Parser.matchGroup1("https://media.ccc.de/c/([^?#]*)", url);
|
return Parser.matchGroup1("https://media.ccc.de/c/([^?#]*)", url);
|
||||||
} else if (url.startsWith("https://media.ccc.de/b/")) {
|
} else if (url.startsWith("https://media.ccc.de/b/")) {
|
||||||
|
@ -26,7 +27,7 @@ public class MediaCCCConferenceLinkHandlerFactory extends ListLinkHandlerFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onAcceptUrl(String url) throws ParsingException {
|
public boolean onAcceptUrl(final String url) {
|
||||||
try {
|
try {
|
||||||
getId(url);
|
getId(url);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -7,18 +7,20 @@ import java.util.List;
|
||||||
|
|
||||||
public class MediaCCCConferencesListLinkHandlerFactory extends ListLinkHandlerFactory {
|
public class MediaCCCConferencesListLinkHandlerFactory extends ListLinkHandlerFactory {
|
||||||
@Override
|
@Override
|
||||||
public String getId(String url) throws ParsingException {
|
public String getId(final String url) throws ParsingException {
|
||||||
return "conferences";
|
return "conferences";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl(String id, List<String> contentFilter, String sortFilter) throws ParsingException {
|
public String getUrl(final String id, final List<String> contentFilter,
|
||||||
return "https://api.media.ccc.de/public/conferences";
|
final String sortFilter) throws ParsingException {
|
||||||
|
return "https://media.ccc.de/public/conferences";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onAcceptUrl(String url) throws ParsingException {
|
public boolean onAcceptUrl(final String url) {
|
||||||
return url.equals("https://media.ccc.de/b/conferences")
|
return url.equals("https://media.ccc.de/b/conferences")
|
||||||
|
|| url.equals("https://media.ccc.de/public/conferences")
|
||||||
|| url.equals("https://api.media.ccc.de/public/conferences");
|
|| url.equals("https://api.media.ccc.de/public/conferences");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.net.URLEncoder;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MediaCCCSearchQueryHandlerFactory extends SearchQueryHandlerFactory {
|
public class MediaCCCSearchQueryHandlerFactory extends SearchQueryHandlerFactory {
|
||||||
|
|
||||||
public static final String ALL = "all";
|
public static final String ALL = "all";
|
||||||
public static final String CONFERENCES = "conferences";
|
public static final String CONFERENCES = "conferences";
|
||||||
public static final String EVENTS = "events";
|
public static final String EVENTS = "events";
|
||||||
|
@ -28,11 +27,13 @@ public class MediaCCCSearchQueryHandlerFactory extends SearchQueryHandlerFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl(String querry, List<String> contentFilter, String sortFilter) throws ParsingException {
|
public String getUrl(final String query, final List<String> contentFilter,
|
||||||
|
final String sortFilter) throws ParsingException {
|
||||||
try {
|
try {
|
||||||
return "https://api.media.ccc.de/public/events/search?q=" + URLEncoder.encode(querry, "UTF-8");
|
return "https://media.ccc.de/public/events/search?q="
|
||||||
|
+ URLEncoder.encode(query, "UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
throw new ParsingException("Could not create search string with querry: " + querry, e);
|
throw new ParsingException("Could not create search string with querry: " + query, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.schabi.newpipe.extractor.services.media_ccc.linkHandler;
|
package org.schabi.newpipe.extractor.services.media_ccc.linkHandler;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
|
|
||||||
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.utils.Utils;
|
import org.schabi.newpipe.extractor.utils.Utils;
|
||||||
|
@ -9,11 +8,15 @@ import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory {
|
public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId(String urlString) throws ParsingException {
|
public String getId(final String urlString) throws ParsingException {
|
||||||
if (urlString.startsWith("https://api.media.ccc.de/public/events/") &&
|
if (urlString.startsWith("https://media.ccc.de/public/events/")
|
||||||
!urlString.contains("?q=")) {
|
&& !urlString.contains("?q=")) {
|
||||||
|
return urlString.substring(35); //remove …/public/events part
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlString.startsWith("https://api.media.ccc.de/public/events/")
|
||||||
|
&& !urlString.contains("?q=")) {
|
||||||
return urlString.substring(39); //remove api…/public/events part
|
return urlString.substring(39); //remove api…/public/events part
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,12 +41,12 @@ public class MediaCCCStreamLinkHandlerFactory extends LinkHandlerFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUrl(String id) throws ParsingException {
|
public String getUrl(final String id) throws ParsingException {
|
||||||
return "https://api.media.ccc.de/public/events/" + id;
|
return "https://media.ccc.de/public/events/" + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onAcceptUrl(String url) throws ParsingException {
|
public boolean onAcceptUrl(final String url) {
|
||||||
try {
|
try {
|
||||||
getId(url);
|
getId(url);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -109,7 +109,7 @@ public class PeertubeAccountExtractor extends ChannelExtractor {
|
||||||
public InfoItemsPage<StreamInfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
|
public InfoItemsPage<StreamInfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
|
||||||
Response response = getDownloader().get(pageUrl);
|
Response response = getDownloader().get(pageUrl);
|
||||||
JsonObject json = null;
|
JsonObject json = null;
|
||||||
if (null != response && !StringUtil.isBlank(response.responseBody())) {
|
if (response != null && !StringUtil.isBlank(response.responseBody())) {
|
||||||
try {
|
try {
|
||||||
json = JsonParser.object().from(response.responseBody());
|
json = JsonParser.object().from(response.responseBody());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -169,7 +169,7 @@ public class PeertubeAccountExtractor extends ChannelExtractor {
|
||||||
try {
|
try {
|
||||||
json = JsonParser.object().from(responseBody);
|
json = JsonParser.object().from(responseBody);
|
||||||
} catch (JsonParserException e) {
|
} catch (JsonParserException e) {
|
||||||
throw new ExtractionException("Unable to extract peertube channel data", e);
|
throw new ExtractionException("Unable to extract PeerTube channel data", e);
|
||||||
}
|
}
|
||||||
if (json == null) throw new ExtractionException("Unable to extract PeerTube channel data");
|
if (json == null) throw new ExtractionException("Unable to extract PeerTube channel data");
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ public class PeertubeStreamExtractor extends StreamExtractor {
|
||||||
assertPageFetched();
|
assertPageFetched();
|
||||||
List<VideoStream> videoStreams = new ArrayList<>();
|
List<VideoStream> videoStreams = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
JsonArray streams = json.getArray("files", new JsonArray());
|
JsonArray streams = json.getArray("files");
|
||||||
for (Object s : streams) {
|
for (Object s : streams) {
|
||||||
if (!(s instanceof JsonObject)) continue;
|
if (!(s instanceof JsonObject)) continue;
|
||||||
JsonObject stream = (JsonObject) s;
|
JsonObject stream = (JsonObject) s;
|
||||||
|
|
|
@ -16,6 +16,8 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public class SoundcloudChannelExtractor extends ChannelExtractor {
|
public class SoundcloudChannelExtractor extends ChannelExtractor {
|
||||||
private String userId;
|
private String userId;
|
||||||
|
@ -62,10 +64,7 @@ public class SoundcloudChannelExtractor extends ChannelExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBannerUrl() {
|
public String getBannerUrl() {
|
||||||
return user.getObject("visuals", new JsonObject())
|
return user.getObject("visuals").getArray("visuals").getObject(0).getString("visual_url");
|
||||||
.getArray("visuals", new JsonArray())
|
|
||||||
.getObject(0, new JsonObject())
|
|
||||||
.getString("visual_url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,7 +79,7 @@ public class SoundcloudChannelExtractor extends ChannelExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return user.getString("description", "");
|
return user.getString("description", EMPTY_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.schabi.newpipe.extractor.services.soundcloud;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
|
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
|
||||||
|
|
||||||
public class SoundcloudChannelInfoItemExtractor implements ChannelInfoItemExtractor {
|
public class SoundcloudChannelInfoItemExtractor implements ChannelInfoItemExtractor {
|
||||||
|
@ -24,7 +25,7 @@ public class SoundcloudChannelInfoItemExtractor implements ChannelInfoItemExtrac
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getThumbnailUrl() {
|
public String getThumbnailUrl() {
|
||||||
String avatarUrl = itemObject.getString("avatar_url", "");
|
String avatarUrl = itemObject.getString("avatar_url", EMPTY_STRING);
|
||||||
String avatarUrlBetterResolution = avatarUrl.replace("large.jpg", "crop.jpg");
|
String avatarUrlBetterResolution = avatarUrl.replace("large.jpg", "crop.jpg");
|
||||||
return avatarUrlBetterResolution;
|
return avatarUrlBetterResolution;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +42,6 @@ public class SoundcloudChannelInfoItemExtractor implements ChannelInfoItemExtrac
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return itemObject.getString("description", "");
|
return itemObject.getString("description", EMPTY_STRING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.util.*;
|
||||||
|
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
|
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
|
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
|
||||||
|
|
||||||
public class SoundcloudParsingHelper {
|
public class SoundcloudParsingHelper {
|
||||||
|
@ -256,17 +257,17 @@ public class SoundcloudParsingHelper {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
static String getUploaderUrl(JsonObject object) {
|
static String getUploaderUrl(JsonObject object) {
|
||||||
String url = object.getObject("user").getString("permalink_url", "");
|
String url = object.getObject("user").getString("permalink_url", EMPTY_STRING);
|
||||||
return replaceHttpWithHttps(url);
|
return replaceHttpWithHttps(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
static String getAvatarUrl(JsonObject object) {
|
static String getAvatarUrl(JsonObject object) {
|
||||||
String url = object.getObject("user", new JsonObject()).getString("avatar_url", "");
|
String url = object.getObject("user").getString("avatar_url", EMPTY_STRING);
|
||||||
return replaceHttpWithHttps(url);
|
return replaceHttpWithHttps(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUploaderName(JsonObject object) {
|
public static String getUploaderName(JsonObject object) {
|
||||||
return object.getObject("user").getString("username", "");
|
return object.getObject("user").getString("username", EMPTY_STRING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.grack.nanojson.JsonObject;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor;
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
|
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
|
||||||
|
|
||||||
public class SoundcloudPlaylistInfoItemExtractor implements PlaylistInfoItemExtractor {
|
public class SoundcloudPlaylistInfoItemExtractor implements PlaylistInfoItemExtractor {
|
||||||
|
@ -31,7 +32,7 @@ public class SoundcloudPlaylistInfoItemExtractor implements PlaylistInfoItemExtr
|
||||||
public String getThumbnailUrl() throws ParsingException {
|
public String getThumbnailUrl() throws ParsingException {
|
||||||
// Over-engineering at its finest
|
// Over-engineering at its finest
|
||||||
if (itemObject.isString(ARTWORK_URL_KEY)) {
|
if (itemObject.isString(ARTWORK_URL_KEY)) {
|
||||||
final String artworkUrl = itemObject.getString(ARTWORK_URL_KEY, "");
|
final String artworkUrl = itemObject.getString(ARTWORK_URL_KEY, EMPTY_STRING);
|
||||||
if (!artworkUrl.isEmpty()) {
|
if (!artworkUrl.isEmpty()) {
|
||||||
String artworkUrlBetterResolution = artworkUrl.replace("large.jpg", "crop.jpg");
|
String artworkUrlBetterResolution = artworkUrl.replace("large.jpg", "crop.jpg");
|
||||||
return artworkUrlBetterResolution;
|
return artworkUrlBetterResolution;
|
||||||
|
@ -45,7 +46,7 @@ public class SoundcloudPlaylistInfoItemExtractor implements PlaylistInfoItemExtr
|
||||||
|
|
||||||
// First look for track artwork url
|
// First look for track artwork url
|
||||||
if (trackObject.isString(ARTWORK_URL_KEY)) {
|
if (trackObject.isString(ARTWORK_URL_KEY)) {
|
||||||
String artworkUrl = trackObject.getString(ARTWORK_URL_KEY, "");
|
String artworkUrl = trackObject.getString(ARTWORK_URL_KEY, EMPTY_STRING);
|
||||||
if (!artworkUrl.isEmpty()) {
|
if (!artworkUrl.isEmpty()) {
|
||||||
String artworkUrlBetterResolution = artworkUrl.replace("large.jpg", "crop.jpg");
|
String artworkUrlBetterResolution = artworkUrl.replace("large.jpg", "crop.jpg");
|
||||||
return artworkUrlBetterResolution;
|
return artworkUrlBetterResolution;
|
||||||
|
@ -53,8 +54,8 @@ public class SoundcloudPlaylistInfoItemExtractor implements PlaylistInfoItemExtr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then look for track creator avatar url
|
// Then look for track creator avatar url
|
||||||
final JsonObject creator = trackObject.getObject(USER_KEY, new JsonObject());
|
final JsonObject creator = trackObject.getObject(USER_KEY);
|
||||||
final String creatorAvatar = creator.getString(AVATAR_URL_KEY, "");
|
final String creatorAvatar = creator.getString(AVATAR_URL_KEY, EMPTY_STRING);
|
||||||
if (!creatorAvatar.isEmpty()) return creatorAvatar;
|
if (!creatorAvatar.isEmpty()) return creatorAvatar;
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
|
@ -63,7 +64,7 @@ public class SoundcloudPlaylistInfoItemExtractor implements PlaylistInfoItemExtr
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Last resort, use user avatar url. If still not found, then throw exception.
|
// Last resort, use user avatar url. If still not found, then throw exception.
|
||||||
return itemObject.getObject(USER_KEY).getString(AVATAR_URL_KEY, "");
|
return itemObject.getObject(USER_KEY).getString(AVATAR_URL_KEY, EMPTY_STRING);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ParsingException("Failed to extract playlist thumbnail url", e);
|
throw new ParsingException("Failed to extract playlist thumbnail url", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.ITEMS_PER_PAGE;
|
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.ITEMS_PER_PAGE;
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
|
|
||||||
public class SoundcloudSearchExtractor extends SearchExtractor {
|
public class SoundcloudSearchExtractor extends SearchExtractor {
|
||||||
|
|
||||||
|
@ -84,7 +85,7 @@ public class SoundcloudSearchExtractor extends SearchExtractor {
|
||||||
if (!(result instanceof JsonObject)) continue;
|
if (!(result instanceof JsonObject)) continue;
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
JsonObject searchResult = (JsonObject) result;
|
JsonObject searchResult = (JsonObject) result;
|
||||||
String kind = searchResult.getString("kind", "");
|
String kind = searchResult.getString("kind", EMPTY_STRING);
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case "user":
|
case "user":
|
||||||
collector.commit(new SoundcloudChannelInfoItemExtractor(searchResult));
|
collector.commit(new SoundcloudChannelInfoItemExtractor(searchResult));
|
||||||
|
|
|
@ -34,6 +34,8 @@ import java.util.Locale;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
|
|
||||||
public class SoundcloudStreamExtractor extends StreamExtractor {
|
public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||||
private JsonObject track;
|
private JsonObject track;
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||||
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
|
||||||
track = SoundcloudParsingHelper.resolveFor(downloader, getOriginalUrl());
|
track = SoundcloudParsingHelper.resolveFor(downloader, getOriginalUrl());
|
||||||
|
|
||||||
String policy = track.getString("policy", "");
|
String policy = track.getString("policy", EMPTY_STRING);
|
||||||
if (!policy.equals("ALLOW") && !policy.equals("MONETIZE")) {
|
if (!policy.equals("ALLOW") && !policy.equals("MONETIZE")) {
|
||||||
throw new ContentNotAvailableException("Content not available: policy " + policy);
|
throw new ContentNotAvailableException("Content not available: policy " + policy);
|
||||||
}
|
}
|
||||||
|
@ -78,9 +80,9 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getThumbnailUrl() {
|
public String getThumbnailUrl() {
|
||||||
String artworkUrl = track.getString("artwork_url", "");
|
String artworkUrl = track.getString("artwork_url", EMPTY_STRING);
|
||||||
if (artworkUrl.isEmpty()) {
|
if (artworkUrl.isEmpty()) {
|
||||||
artworkUrl = track.getObject("user").getString("avatar_url", "");
|
artworkUrl = track.getObject("user").getString("avatar_url", EMPTY_STRING);
|
||||||
}
|
}
|
||||||
String artworkUrlBetterResolution = artworkUrl.replace("large.jpg", "crop.jpg");
|
String artworkUrlBetterResolution = artworkUrl.replace("large.jpg", "crop.jpg");
|
||||||
return artworkUrlBetterResolution;
|
return artworkUrlBetterResolution;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.schabi.newpipe.extractor.localization.DateWrapper;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
|
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
|
||||||
|
|
||||||
public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
|
@ -62,7 +63,7 @@ public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtracto
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getThumbnailUrl() {
|
public String getThumbnailUrl() {
|
||||||
String artworkUrl = itemObject.getString("artwork_url", "");
|
String artworkUrl = itemObject.getString("artwork_url", EMPTY_STRING);
|
||||||
if (artworkUrl.isEmpty()) {
|
if (artworkUrl.isEmpty()) {
|
||||||
artworkUrl = itemObject.getObject("user").getString("avatar_url");
|
artworkUrl = itemObject.getObject("user").getString("avatar_url");
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,22 +72,16 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
||||||
while (level < 3) {
|
while (level < 3) {
|
||||||
final JsonArray jsonResponse = getJsonResponse(url, getExtractorLocalization());
|
final JsonArray jsonResponse = getJsonResponse(url, getExtractorLocalization());
|
||||||
|
|
||||||
final JsonObject endpoint = jsonResponse.getObject(1, EMPTY_OBJECT)
|
final JsonObject endpoint = jsonResponse.getObject(1).getObject("response")
|
||||||
.getObject("response", EMPTY_OBJECT).getArray("onResponseReceivedActions", EMPTY_ARRAY)
|
.getArray("onResponseReceivedActions").getObject(0).getObject("navigateAction")
|
||||||
.getObject(0, EMPTY_OBJECT).getObject("navigateAction", EMPTY_OBJECT)
|
.getObject("endpoint");
|
||||||
.getObject("endpoint", EMPTY_OBJECT);
|
|
||||||
|
|
||||||
final String webPageType = endpoint
|
final String webPageType = endpoint.getObject("commandMetadata").getObject("webCommandMetadata")
|
||||||
.getObject("commandMetadata", EMPTY_OBJECT)
|
|
||||||
.getObject("webCommandMetadata", EMPTY_OBJECT)
|
|
||||||
.getString("webPageType", EMPTY_STRING);
|
.getString("webPageType", EMPTY_STRING);
|
||||||
|
|
||||||
final String browseId = endpoint
|
final String browseId = endpoint.getObject("browseEndpoint").getString("browseId", EMPTY_STRING);
|
||||||
.getObject("browseEndpoint", EMPTY_OBJECT)
|
|
||||||
.getString("browseId", EMPTY_STRING);
|
|
||||||
|
|
||||||
if (webPageType.equalsIgnoreCase("WEB_PAGE_TYPE_BROWSE") && !browseId.isEmpty()) {
|
if (webPageType.equalsIgnoreCase("WEB_PAGE_TYPE_BROWSE") && !browseId.isEmpty()) {
|
||||||
|
|
||||||
if (!browseId.startsWith("UC")) {
|
if (!browseId.startsWith("UC")) {
|
||||||
throw new ExtractionException("Redirected id is not pointing to a channel");
|
throw new ExtractionException("Redirected id is not pointing to a channel");
|
||||||
}
|
}
|
||||||
|
@ -131,10 +125,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getId() throws ParsingException {
|
public String getId() throws ParsingException {
|
||||||
final String channelId = initialData
|
final String channelId = initialData.getObject("header").getObject("c4TabbedHeaderRenderer")
|
||||||
.getObject("header", EMPTY_OBJECT)
|
.getString("channelId", EMPTY_STRING);
|
||||||
.getObject("c4TabbedHeaderRenderer", EMPTY_OBJECT)
|
|
||||||
.getString("channelId", EMPTY_STRING);
|
|
||||||
|
|
||||||
if (!channelId.isEmpty()) {
|
if (!channelId.isEmpty()) {
|
||||||
return channelId;
|
return channelId;
|
||||||
|
@ -170,11 +162,9 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
||||||
@Override
|
@Override
|
||||||
public String getBannerUrl() throws ParsingException {
|
public String getBannerUrl() throws ParsingException {
|
||||||
try {
|
try {
|
||||||
String url = null;
|
String url = initialData.getObject("header").getObject("c4TabbedHeaderRenderer").getObject("banner")
|
||||||
try {
|
|
||||||
url = initialData.getObject("header").getObject("c4TabbedHeaderRenderer").getObject("banner")
|
|
||||||
.getArray("thumbnails").getObject(0).getString("url");
|
.getArray("thumbnails").getObject(0).getString("url");
|
||||||
} catch (Exception ignored) {}
|
|
||||||
if (url == null || url.contains("s.ytimg.com") || url.contains("default_banner")) {
|
if (url == null || url.contains("s.ytimg.com") || url.contains("default_banner")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -196,19 +186,19 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSubscriberCount() throws ParsingException {
|
public long getSubscriberCount() throws ParsingException {
|
||||||
final JsonObject subscriberInfo = initialData.getObject("header").getObject("c4TabbedHeaderRenderer").getObject("subscriberCountText");
|
final JsonObject c4TabbedHeaderRenderer = initialData.getObject("header").getObject("c4TabbedHeaderRenderer");
|
||||||
if (subscriberInfo != null) {
|
if (c4TabbedHeaderRenderer.has("subscriberCountText")) {
|
||||||
try {
|
try {
|
||||||
return Utils.mixedNumberWordToLong(getTextFromObject(subscriberInfo));
|
return Utils.mixedNumberWordToLong(getTextFromObject(c4TabbedHeaderRenderer.getObject("subscriberCountText")));
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new ParsingException("Could not get subscriber count", e);
|
throw new ParsingException("Could not get subscriber count", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If there's no subscribe button, the channel has the subscriber count disabled
|
// If there's no subscribe button, the channel has the subscriber count disabled
|
||||||
if (initialData.getObject("header").getObject("c4TabbedHeaderRenderer").getObject("subscribeButton") == null) {
|
if (c4TabbedHeaderRenderer.has("subscribeButton")) {
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,7 +250,9 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
||||||
|
|
||||||
|
|
||||||
private String getNextPageUrlFrom(JsonArray continuations) {
|
private String getNextPageUrlFrom(JsonArray continuations) {
|
||||||
if (continuations == null) return "";
|
if (continuations == null || continuations.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject nextContinuationData = continuations.getObject(0).getObject("nextContinuationData");
|
JsonObject nextContinuationData = continuations.getObject(0).getObject("nextContinuationData");
|
||||||
String continuation = nextContinuationData.getString("continuation");
|
String continuation = nextContinuationData.getString("continuation");
|
||||||
|
@ -277,7 +269,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
||||||
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
||||||
|
|
||||||
for (Object video : videos) {
|
for (Object video : videos) {
|
||||||
if (((JsonObject) video).getObject("gridVideoRenderer") != null) {
|
if (((JsonObject) video).has("gridVideoRenderer")) {
|
||||||
collector.commit(new YoutubeStreamInfoItemExtractor(
|
collector.commit(new YoutubeStreamInfoItemExtractor(
|
||||||
((JsonObject) video).getObject("gridVideoRenderer"), timeAgoParser) {
|
((JsonObject) video).getObject("gridVideoRenderer"), timeAgoParser) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -302,8 +294,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
||||||
JsonObject videoTab = null;
|
JsonObject videoTab = null;
|
||||||
|
|
||||||
for (Object tab : tabs) {
|
for (Object tab : tabs) {
|
||||||
if (((JsonObject) tab).getObject("tabRenderer") != null) {
|
if (((JsonObject) tab).has("tabRenderer")) {
|
||||||
if (((JsonObject) tab).getObject("tabRenderer").getString("title").equals("Videos")) {
|
if (((JsonObject) tab).getObject("tabRenderer").getString("title", EMPTY_STRING).equals("Videos")) {
|
||||||
videoTab = ((JsonObject) tab).getObject("tabRenderer");
|
videoTab = ((JsonObject) tab).getObject("tabRenderer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -314,13 +306,12 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
|
||||||
throw new ContentNotSupportedException("This channel has no Videos tab");
|
throw new ContentNotSupportedException("This channel has no Videos tab");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (getTextFromObject(videoTab.getObject("content").getObject("sectionListRenderer")
|
||||||
if (getTextFromObject(videoTab.getObject("content").getObject("sectionListRenderer")
|
.getArray("contents").getObject(0).getObject("itemSectionRenderer")
|
||||||
.getArray("contents").getObject(0).getObject("itemSectionRenderer")
|
.getArray("contents").getObject(0).getObject("messageRenderer")
|
||||||
.getArray("contents").getObject(0).getObject("messageRenderer")
|
.getObject("text")).equals("This channel has no videos.")) {
|
||||||
.getObject("text")).equals("This channel has no videos."))
|
return null;
|
||||||
return null;
|
}
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
this.videoTab = videoTab;
|
this.videoTab = videoTab;
|
||||||
return videoTab;
|
return videoTab;
|
||||||
|
|
|
@ -70,14 +70,12 @@ public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor
|
||||||
@Override
|
@Override
|
||||||
public long getSubscriberCount() throws ParsingException {
|
public long getSubscriberCount() throws ParsingException {
|
||||||
try {
|
try {
|
||||||
final JsonObject subscriberCountObject = channelInfoItem.getObject("subscriberCountText");
|
if (!channelInfoItem.has("subscriberCountText")) {
|
||||||
|
|
||||||
if (subscriberCountObject == null) {
|
|
||||||
// Subscription count is not available for this channel item.
|
// Subscription count is not available for this channel item.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Utils.mixedNumberWordToLong(getTextFromObject(subscriberCountObject));
|
return Utils.mixedNumberWordToLong(getTextFromObject(channelInfoItem.getObject("subscriberCountText")));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ParsingException("Could not get subscriber count", e);
|
throw new ParsingException("Could not get subscriber count", e);
|
||||||
}
|
}
|
||||||
|
@ -86,14 +84,13 @@ public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor
|
||||||
@Override
|
@Override
|
||||||
public long getStreamCount() throws ParsingException {
|
public long getStreamCount() throws ParsingException {
|
||||||
try {
|
try {
|
||||||
final JsonObject videoCountObject = channelInfoItem.getObject("videoCountText");
|
if (!channelInfoItem.has("videoCountText")) {
|
||||||
|
|
||||||
if (videoCountObject == null) {
|
|
||||||
// Video count is not available, channel probably has no public uploads.
|
// Video count is not available, channel probably has no public uploads.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Long.parseLong(Utils.removeNonDigitCharacters(getTextFromObject(videoCountObject)));
|
return Long.parseLong(Utils.removeNonDigitCharacters(getTextFromObject(
|
||||||
|
channelInfoItem.getObject("videoCountText"))));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ParsingException("Could not get stream count", e);
|
throw new ParsingException("Could not get stream count", e);
|
||||||
}
|
}
|
||||||
|
@ -102,14 +99,12 @@ public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() throws ParsingException {
|
public String getDescription() throws ParsingException {
|
||||||
try {
|
try {
|
||||||
final JsonObject descriptionObject = channelInfoItem.getObject("descriptionSnippet");
|
if (!channelInfoItem.has("descriptionSnippet")) {
|
||||||
|
|
||||||
if (descriptionObject == null) {
|
|
||||||
// Channel have no description.
|
// Channel have no description.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getTextFromObject(descriptionObject);
|
return getTextFromObject(channelInfoItem.getObject("descriptionSnippet"));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ParsingException("Could not get description", e);
|
throw new ParsingException("Could not get description", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
import com.grack.nanojson.JsonParserException;
|
import com.grack.nanojson.JsonParserException;
|
||||||
import com.grack.nanojson.JsonWriter;
|
import com.grack.nanojson.JsonWriter;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.InfoItem;
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
|
@ -20,23 +19,23 @@ import org.schabi.newpipe.extractor.search.SearchExtractor;
|
||||||
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper;
|
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper;
|
||||||
import org.schabi.newpipe.extractor.utils.Utils;
|
import org.schabi.newpipe.extractor.utils.Utils;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.fixThumbnailUrl;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.fixThumbnailUrl;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getValidJsonResponseBody;
|
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getTextFromObject;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getTextFromObject;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getUrlFromNavigationEndpoint;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getUrlFromNavigationEndpoint;
|
||||||
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getValidJsonResponseBody;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_ALBUMS;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_ALBUMS;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_ARTISTS;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_ARTISTS;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_PLAYLISTS;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_PLAYLISTS;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_SONGS;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_SONGS;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_VIDEOS;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_VIDEOS;
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
|
|
||||||
public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
private JsonObject initialData;
|
private JsonObject initialData;
|
||||||
|
@ -128,14 +127,10 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSearchSuggestion() throws ParsingException {
|
public String getSearchSuggestion() throws ParsingException {
|
||||||
final JsonObject itemSectionRenderer = initialData.getObject("contents").getObject("sectionListRenderer")
|
final JsonObject didYouMeanRenderer = initialData.getObject("contents").getObject("sectionListRenderer")
|
||||||
.getArray("contents").getObject(0).getObject("itemSectionRenderer");
|
.getArray("contents").getObject(0).getObject("itemSectionRenderer")
|
||||||
if (itemSectionRenderer == null) {
|
.getArray("contents").getObject(0).getObject("didYouMeanRenderer");
|
||||||
return "";
|
if (!didYouMeanRenderer.has("correctedQuery")) {
|
||||||
}
|
|
||||||
final JsonObject didYouMeanRenderer = itemSectionRenderer.getArray("contents")
|
|
||||||
.getObject(0).getObject("didYouMeanRenderer");
|
|
||||||
if (didYouMeanRenderer == null) {
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return getTextFromObject(didYouMeanRenderer.getObject("correctedQuery"));
|
return getTextFromObject(didYouMeanRenderer.getObject("correctedQuery"));
|
||||||
|
@ -149,7 +144,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
final JsonArray contents = initialData.getObject("contents").getObject("sectionListRenderer").getArray("contents");
|
final JsonArray contents = initialData.getObject("contents").getObject("sectionListRenderer").getArray("contents");
|
||||||
|
|
||||||
for (Object content : contents) {
|
for (Object content : contents) {
|
||||||
if (((JsonObject) content).getObject("musicShelfRenderer") != null) {
|
if (((JsonObject) content).has("musicShelfRenderer")) {
|
||||||
collectMusicStreamsFrom(collector, ((JsonObject) content).getObject("musicShelfRenderer").getArray("contents"));
|
collectMusicStreamsFrom(collector, ((JsonObject) content).getObject("musicShelfRenderer").getArray("contents"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +157,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
final JsonArray contents = initialData.getObject("contents").getObject("sectionListRenderer").getArray("contents");
|
final JsonArray contents = initialData.getObject("contents").getObject("sectionListRenderer").getArray("contents");
|
||||||
|
|
||||||
for (Object content : contents) {
|
for (Object content : contents) {
|
||||||
if (((JsonObject) content).getObject("musicShelfRenderer") != null) {
|
if (((JsonObject) content).has("musicShelfRenderer")) {
|
||||||
return getNextPageUrlFrom(((JsonObject) content).getObject("musicShelfRenderer").getArray("continuations"));
|
return getNextPageUrlFrom(((JsonObject) content).getObject("musicShelfRenderer").getArray("continuations"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,10 +219,6 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
throw new ParsingException("Could not parse JSON", e);
|
throw new ParsingException("Could not parse JSON", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ajaxJson.getObject("continuationContents") == null) {
|
|
||||||
return InfoItemsPage.emptyPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
final JsonObject musicShelfContinuation = ajaxJson.getObject("continuationContents").getObject("musicShelfContinuation");
|
final JsonObject musicShelfContinuation = ajaxJson.getObject("continuationContents").getObject("musicShelfContinuation");
|
||||||
|
|
||||||
collectMusicStreamsFrom(collector, musicShelfContinuation.getArray("contents"));
|
collectMusicStreamsFrom(collector, musicShelfContinuation.getArray("contents"));
|
||||||
|
@ -240,7 +231,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
||||||
|
|
||||||
for (Object item : videos) {
|
for (Object item : videos) {
|
||||||
final JsonObject info = ((JsonObject) item).getObject("musicResponsiveListItemRenderer");
|
final JsonObject info = ((JsonObject) item).getObject("musicResponsiveListItemRenderer", null);
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
final String searchType = getLinkHandler().getContentFilters().get(0);
|
final String searchType = getLinkHandler().getContentFilters().get(0);
|
||||||
if (searchType.equals(MUSIC_SONGS) || searchType.equals(MUSIC_VIDEOS)) {
|
if (searchType.equals(MUSIC_SONGS) || searchType.equals(MUSIC_VIDEOS)) {
|
||||||
|
@ -258,7 +249,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
public String getName() throws ParsingException {
|
public String getName() throws ParsingException {
|
||||||
final String name = getTextFromObject(info.getArray("flexColumns").getObject(0)
|
final String name = getTextFromObject(info.getArray("flexColumns").getObject(0)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
if (name != null && !name.isEmpty()) {
|
if (!name.isEmpty()) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get name");
|
throw new ParsingException("Could not get name");
|
||||||
|
@ -268,7 +259,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
public long getDuration() throws ParsingException {
|
public long getDuration() throws ParsingException {
|
||||||
final String duration = getTextFromObject(info.getArray("flexColumns").getObject(3)
|
final String duration = getTextFromObject(info.getArray("flexColumns").getObject(3)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
if (duration != null && !duration.isEmpty()) {
|
if (!duration.isEmpty()) {
|
||||||
return YoutubeParsingHelper.parseDurationString(duration);
|
return YoutubeParsingHelper.parseDurationString(duration);
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get duration");
|
throw new ParsingException("Could not get duration");
|
||||||
|
@ -278,7 +269,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
public String getUploaderName() throws ParsingException {
|
public String getUploaderName() throws ParsingException {
|
||||||
final String name = getTextFromObject(info.getArray("flexColumns").getObject(1)
|
final String name = getTextFromObject(info.getArray("flexColumns").getObject(1)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
if (name != null && !name.isEmpty()) {
|
if (!name.isEmpty()) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get uploader name");
|
throw new ParsingException("Could not get uploader name");
|
||||||
|
@ -290,7 +281,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
JsonArray items = info.getObject("menu").getObject("menuRenderer").getArray("items");
|
JsonArray items = info.getObject("menu").getObject("menuRenderer").getArray("items");
|
||||||
for (Object item : items) {
|
for (Object item : items) {
|
||||||
final JsonObject menuNavigationItemRenderer = ((JsonObject) item).getObject("menuNavigationItemRenderer");
|
final JsonObject menuNavigationItemRenderer = ((JsonObject) item).getObject("menuNavigationItemRenderer");
|
||||||
if (menuNavigationItemRenderer != null && menuNavigationItemRenderer.getObject("icon").getString("iconType").equals("ARTIST")) {
|
if (menuNavigationItemRenderer.getObject("icon").getString("iconType", EMPTY_STRING).equals("ARTIST")) {
|
||||||
return getUrlFromNavigationEndpoint(menuNavigationItemRenderer.getObject("navigationEndpoint"));
|
return getUrlFromNavigationEndpoint(menuNavigationItemRenderer.getObject("navigationEndpoint"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,16 +292,13 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
.getObject(1).getObject("musicResponsiveListItemFlexColumnRenderer")
|
.getObject(1).getObject("musicResponsiveListItemFlexColumnRenderer")
|
||||||
.getObject("text").getArray("runs").getObject(0).getObject("navigationEndpoint");
|
.getObject("text").getArray("runs").getObject(0).getObject("navigationEndpoint");
|
||||||
|
|
||||||
if (navigationEndpoint == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String url = getUrlFromNavigationEndpoint(navigationEndpoint);
|
final String url = getUrlFromNavigationEndpoint(navigationEndpoint);
|
||||||
|
|
||||||
if (url != null && !url.isEmpty()) {
|
if (url != null && !url.isEmpty()) {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get uploader url");
|
|
||||||
|
throw new ParsingException("Could not get uploader URL");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,7 +319,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
}
|
}
|
||||||
final String viewCount = getTextFromObject(info.getArray("flexColumns").getObject(2)
|
final String viewCount = getTextFromObject(info.getArray("flexColumns").getObject(2)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
if (viewCount != null && !viewCount.isEmpty()) {
|
if (!viewCount.isEmpty()) {
|
||||||
return Utils.mixedNumberWordToLong(viewCount);
|
return Utils.mixedNumberWordToLong(viewCount);
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get view count");
|
throw new ParsingException("Could not get view count");
|
||||||
|
@ -371,7 +359,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
public String getName() throws ParsingException {
|
public String getName() throws ParsingException {
|
||||||
final String name = getTextFromObject(info.getArray("flexColumns").getObject(0)
|
final String name = getTextFromObject(info.getArray("flexColumns").getObject(0)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
if (name != null && !name.isEmpty()) {
|
if (!name.isEmpty()) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get name");
|
throw new ParsingException("Could not get name");
|
||||||
|
@ -390,7 +378,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
public long getSubscriberCount() throws ParsingException {
|
public long getSubscriberCount() throws ParsingException {
|
||||||
final String viewCount = getTextFromObject(info.getArray("flexColumns").getObject(2)
|
final String viewCount = getTextFromObject(info.getArray("flexColumns").getObject(2)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
if (viewCount != null && !viewCount.isEmpty()) {
|
if (!viewCount.isEmpty()) {
|
||||||
return Utils.mixedNumberWordToLong(viewCount);
|
return Utils.mixedNumberWordToLong(viewCount);
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get subscriber count");
|
throw new ParsingException("Could not get subscriber count");
|
||||||
|
@ -426,7 +414,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
public String getName() throws ParsingException {
|
public String getName() throws ParsingException {
|
||||||
final String name = getTextFromObject(info.getArray("flexColumns").getObject(0)
|
final String name = getTextFromObject(info.getArray("flexColumns").getObject(0)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
if (name != null && !name.isEmpty()) {
|
if (!name.isEmpty()) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get name");
|
throw new ParsingException("Could not get name");
|
||||||
|
@ -451,7 +439,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
name = getTextFromObject(info.getArray("flexColumns").getObject(1)
|
name = getTextFromObject(info.getArray("flexColumns").getObject(1)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
}
|
}
|
||||||
if (name != null && !name.isEmpty()) {
|
if (!name.isEmpty()) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get uploader name");
|
throw new ParsingException("Could not get uploader name");
|
||||||
|
@ -464,7 +452,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
}
|
}
|
||||||
final String count = getTextFromObject(info.getArray("flexColumns").getObject(2)
|
final String count = getTextFromObject(info.getArray("flexColumns").getObject(2)
|
||||||
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
.getObject("musicResponsiveListItemFlexColumnRenderer").getObject("text"));
|
||||||
if (count != null && !count.isEmpty()) {
|
if (!count.isEmpty()) {
|
||||||
if (count.contains("100+")) {
|
if (count.contains("100+")) {
|
||||||
return ITEM_COUNT_MORE_THAN_100;
|
return ITEM_COUNT_MORE_THAN_100;
|
||||||
} else {
|
} else {
|
||||||
|
@ -480,7 +468,7 @@ public class YoutubeMusicSearchExtractor extends SearchExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNextPageUrlFrom(final JsonArray continuations) throws ParsingException, IOException, ReCaptchaException {
|
private String getNextPageUrlFrom(final JsonArray continuations) throws ParsingException, IOException, ReCaptchaException {
|
||||||
if (continuations == null) {
|
if (continuations == null || continuations.isEmpty()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
|
||||||
|
|
||||||
import com.grack.nanojson.JsonArray;
|
import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
@ -15,9 +14,8 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
import org.schabi.newpipe.extractor.utils.Utils;
|
import org.schabi.newpipe.extractor.utils.Utils;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.fixThumbnailUrl;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.fixThumbnailUrl;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getJsonResponse;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getJsonResponse;
|
||||||
|
@ -47,23 +45,16 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
|
||||||
|
|
||||||
private JsonObject getUploaderInfo() throws ParsingException {
|
private JsonObject getUploaderInfo() throws ParsingException {
|
||||||
JsonArray items = initialData.getObject("sidebar").getObject("playlistSidebarRenderer").getArray("items");
|
JsonArray items = initialData.getObject("sidebar").getObject("playlistSidebarRenderer").getArray("items");
|
||||||
try {
|
|
||||||
JsonObject uploaderInfo = items.getObject(1).getObject("playlistSidebarSecondaryInfoRenderer")
|
JsonObject videoOwner = items.getObject(1).getObject("playlistSidebarSecondaryInfoRenderer").getObject("videoOwner");
|
||||||
.getObject("videoOwner").getObject("videoOwnerRenderer");
|
if (videoOwner.has("videoOwnerRenderer")) {
|
||||||
if (uploaderInfo != null) {
|
return videoOwner.getObject("videoOwnerRenderer");
|
||||||
return uploaderInfo;
|
}
|
||||||
}
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
// we might want to create a loop here instead of using duplicated code
|
// we might want to create a loop here instead of using duplicated code
|
||||||
try {
|
videoOwner = items.getObject(items.size()).getObject("playlistSidebarSecondaryInfoRenderer").getObject("videoOwner");
|
||||||
JsonObject uploaderInfo = items.getObject(items.size()).getObject("playlistSidebarSecondaryInfoRenderer")
|
if (videoOwner.has("videoOwnerRenderer")) {
|
||||||
.getObject("videoOwner").getObject("videoOwnerRenderer");
|
return videoOwner.getObject("videoOwnerRenderer");
|
||||||
if (uploaderInfo != null) {
|
|
||||||
return uploaderInfo;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ParsingException("Could not get uploader info", e);
|
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get uploader info");
|
throw new ParsingException("Could not get uploader info");
|
||||||
}
|
}
|
||||||
|
@ -89,33 +80,22 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getName() throws ParsingException {
|
public String getName() throws ParsingException {
|
||||||
try {
|
String name = getTextFromObject(playlistInfo.getObject("title"));
|
||||||
String name = getTextFromObject(playlistInfo.getObject("title"));
|
if (!name.isEmpty()) return name;
|
||||||
if (name != null) return name;
|
|
||||||
} catch (Exception ignored) {}
|
return initialData.getObject("microformat").getObject("microformatDataRenderer").getString("title");
|
||||||
try {
|
|
||||||
return initialData.getObject("microformat").getObject("microformatDataRenderer").getString("title");
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ParsingException("Could not get playlist name", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getThumbnailUrl() throws ParsingException {
|
public String getThumbnailUrl() throws ParsingException {
|
||||||
String url = null;
|
String url = playlistInfo.getObject("thumbnailRenderer").getObject("playlistVideoThumbnailRenderer")
|
||||||
|
.getObject("thumbnail").getArray("thumbnails").getObject(0).getString("url");
|
||||||
|
|
||||||
try {
|
if (url == null || url.isEmpty()) {
|
||||||
url = playlistInfo.getObject("thumbnailRenderer").getObject("playlistVideoThumbnailRenderer")
|
url = initialData.getObject("microformat").getObject("microformatDataRenderer").getObject("thumbnail")
|
||||||
.getObject("thumbnail").getArray("thumbnails").getObject(0).getString("url");
|
.getArray("thumbnails").getObject(0).getString("url");
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (url == null) {
|
if (url == null || url.isEmpty()) throw new ParsingException("Could not get playlist thumbnail");
|
||||||
try {
|
|
||||||
url = initialData.getObject("microformat").getObject("microformatDataRenderer").getObject("thumbnail")
|
|
||||||
.getArray("thumbnails").getObject(0).getString("url");
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (url == null) throw new ParsingException("Could not get playlist thumbnail");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fixThumbnailUrl(url);
|
return fixThumbnailUrl(url);
|
||||||
|
@ -123,8 +103,9 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBannerUrl() {
|
public String getBannerUrl() {
|
||||||
return ""; // Banner can't be handled by frontend right now.
|
// Banner can't be handled by frontend right now.
|
||||||
// Whoever is willing to implement this should also implement it in the frontend.
|
// Whoever is willing to implement this should also implement it in the frontend.
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -199,7 +180,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNextPageUrlFrom(JsonArray continuations) {
|
private String getNextPageUrlFrom(JsonArray continuations) {
|
||||||
if (continuations == null) {
|
if (continuations == null || continuations.isEmpty()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +197,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
|
||||||
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
||||||
|
|
||||||
for (Object video : videos) {
|
for (Object video : videos) {
|
||||||
if (((JsonObject) video).getObject("playlistVideoRenderer") != null) {
|
if (((JsonObject) video).has("playlistVideoRenderer")) {
|
||||||
collector.commit(new YoutubeStreamInfoItemExtractor(((JsonObject) video).getObject("playlistVideoRenderer"), timeAgoParser) {
|
collector.commit(new YoutubeStreamInfoItemExtractor(((JsonObject) video).getObject("playlistVideoRenderer"), timeAgoParser) {
|
||||||
@Override
|
@Override
|
||||||
public long getViewCount() {
|
public long getViewCount() {
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
||||||
.getObject("sectionListRenderer").getArray("contents").getObject(0)
|
.getObject("sectionListRenderer").getArray("contents").getObject(0)
|
||||||
.getObject("itemSectionRenderer").getArray("contents").getObject(0)
|
.getObject("itemSectionRenderer").getArray("contents").getObject(0)
|
||||||
.getObject("showingResultsForRenderer");
|
.getObject("showingResultsForRenderer");
|
||||||
if (showingResultsForRenderer == null) {
|
if (!showingResultsForRenderer.has("correctedQuery")) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return getTextFromObject(showingResultsForRenderer.getObject("correctedQuery"));
|
return getTextFromObject(showingResultsForRenderer.getObject("correctedQuery"));
|
||||||
|
@ -119,21 +119,21 @@ public class YoutubeSearchExtractor extends SearchExtractor {
|
||||||
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
||||||
|
|
||||||
for (Object item : videos) {
|
for (Object item : videos) {
|
||||||
if (((JsonObject) item).getObject("backgroundPromoRenderer") != null) {
|
if (((JsonObject) item).has("backgroundPromoRenderer")) {
|
||||||
throw new NothingFoundException(getTextFromObject(((JsonObject) item)
|
throw new NothingFoundException(getTextFromObject(((JsonObject) item)
|
||||||
.getObject("backgroundPromoRenderer").getObject("bodyText")));
|
.getObject("backgroundPromoRenderer").getObject("bodyText")));
|
||||||
} else if (((JsonObject) item).getObject("videoRenderer") != null) {
|
} else if (((JsonObject) item).has("videoRenderer")) {
|
||||||
collector.commit(new YoutubeStreamInfoItemExtractor(((JsonObject) item).getObject("videoRenderer"), timeAgoParser));
|
collector.commit(new YoutubeStreamInfoItemExtractor(((JsonObject) item).getObject("videoRenderer"), timeAgoParser));
|
||||||
} else if (((JsonObject) item).getObject("channelRenderer") != null) {
|
} else if (((JsonObject) item).has("channelRenderer")) {
|
||||||
collector.commit(new YoutubeChannelInfoItemExtractor(((JsonObject) item).getObject("channelRenderer")));
|
collector.commit(new YoutubeChannelInfoItemExtractor(((JsonObject) item).getObject("channelRenderer")));
|
||||||
} else if (((JsonObject) item).getObject("playlistRenderer") != null) {
|
} else if (((JsonObject) item).has("playlistRenderer")) {
|
||||||
collector.commit(new YoutubePlaylistInfoItemExtractor(((JsonObject) item).getObject("playlistRenderer")));
|
collector.commit(new YoutubePlaylistInfoItemExtractor(((JsonObject) item).getObject("playlistRenderer")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNextPageUrlFrom(final JsonArray continuations) throws ParsingException {
|
private String getNextPageUrlFrom(final JsonArray continuations) throws ParsingException {
|
||||||
if (continuations == null) {
|
if (continuations == null || continuations.isEmpty()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
|
||||||
import com.grack.nanojson.JsonArray;
|
import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
import com.grack.nanojson.JsonParser;
|
import com.grack.nanojson.JsonParser;
|
||||||
|
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
import org.mozilla.javascript.Function;
|
import org.mozilla.javascript.Function;
|
||||||
import org.mozilla.javascript.ScriptableObject;
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
|
@ -33,10 +32,11 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
import org.schabi.newpipe.extractor.utils.JsonUtils;
|
|
||||||
import org.schabi.newpipe.extractor.utils.Parser;
|
import org.schabi.newpipe.extractor.utils.Parser;
|
||||||
import org.schabi.newpipe.extractor.utils.Utils;
|
import org.schabi.newpipe.extractor.utils.Utils;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -50,13 +50,11 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.fixThumbnailUrl;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.fixThumbnailUrl;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getJsonResponse;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getJsonResponse;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getTextFromObject;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getTextFromObject;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getUrlFromNavigationEndpoint;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getUrlFromNavigationEndpoint;
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Created by Christian Schabesberger on 06.08.15.
|
* Created by Christian Schabesberger on 06.08.15.
|
||||||
|
@ -117,18 +115,12 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
@Override
|
@Override
|
||||||
public String getName() throws ParsingException {
|
public String getName() throws ParsingException {
|
||||||
assertPageFetched();
|
assertPageFetched();
|
||||||
String title = null;
|
String title = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("title"));
|
||||||
|
|
||||||
try {
|
if (title.isEmpty()) {
|
||||||
title = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("title"));
|
title = playerResponse.getObject("videoDetails").getString("title");
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (title == null) {
|
if (title == null || title.isEmpty()) throw new ParsingException("Could not get name");
|
||||||
try {
|
|
||||||
title = playerResponse.getObject("videoDetails").getString("title");
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (title == null) throw new ParsingException("Could not get name");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return title;
|
return title;
|
||||||
|
@ -140,35 +132,31 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
JsonObject micro = playerResponse.getObject("microformat").getObject("playerMicroformatRenderer");
|
||||||
JsonObject micro = playerResponse.getObject("microformat").getObject("playerMicroformatRenderer");
|
if (micro.isString("uploadDate") && !micro.getString("uploadDate").isEmpty()) {
|
||||||
if (micro.getString("uploadDate") != null && !micro.getString("uploadDate").isEmpty()) {
|
return micro.getString("uploadDate");
|
||||||
return micro.getString("uploadDate");
|
}
|
||||||
}
|
if (micro.isString("publishDate") && !micro.getString("publishDate").isEmpty()) {
|
||||||
if (micro.getString("publishDate") != null && !micro.getString("publishDate").isEmpty()) {
|
return micro.getString("publishDate");
|
||||||
return micro.getString("publishDate");
|
}
|
||||||
}
|
|
||||||
} catch (Exception ignored) {}
|
if (getTextFromObject(getVideoPrimaryInfoRenderer().getObject("dateText")).startsWith("Premiered")) {
|
||||||
|
String time = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("dateText")).substring(10);
|
||||||
|
|
||||||
|
try { // Premiered 20 hours ago
|
||||||
|
TimeAgoParser timeAgoParser = TimeAgoPatternsManager.getTimeAgoParserFor(Localization.fromLocalizationCode("en"));
|
||||||
|
Calendar parsedTime = timeAgoParser.parse(time).date();
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd").format(parsedTime.getTime());
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
|
||||||
|
try { // Premiered Feb 21, 2020
|
||||||
|
Date d = new SimpleDateFormat("MMM dd, YYYY", Locale.ENGLISH).parse(time);
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd").format(d.getTime());
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (getTextFromObject(getVideoPrimaryInfoRenderer().getObject("dateText")).startsWith("Premiered")) {
|
// TODO: this parses English formatted dates only, we need a better approach to parse the textual date
|
||||||
String time = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("dateText")).substring(10);
|
|
||||||
|
|
||||||
try { // Premiered 20 hours ago
|
|
||||||
TimeAgoParser timeAgoParser = TimeAgoPatternsManager.getTimeAgoParserFor(Localization.fromLocalizationCode("en"));
|
|
||||||
Calendar parsedTime = timeAgoParser.parse(time).date();
|
|
||||||
return new SimpleDateFormat("yyyy-MM-dd").format(parsedTime.getTime());
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
try { // Premiered Feb 21, 2020
|
|
||||||
Date d = new SimpleDateFormat("MMM dd, YYYY", Locale.ENGLISH).parse(time);
|
|
||||||
return new SimpleDateFormat("yyyy-MM-dd").format(d.getTime());
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
}
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// TODO this parses English formatted dates only, we need a better approach to parse the textual date
|
|
||||||
Date d = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH).parse(
|
Date d = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH).parse(
|
||||||
getTextFromObject(getVideoPrimaryInfoRenderer().getObject("dateText")));
|
getTextFromObject(getVideoPrimaryInfoRenderer().getObject("dateText")));
|
||||||
return new SimpleDateFormat("yyyy-MM-dd").format(d);
|
return new SimpleDateFormat("yyyy-MM-dd").format(d);
|
||||||
|
@ -180,7 +168,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
public DateWrapper getUploadDate() throws ParsingException {
|
public DateWrapper getUploadDate() throws ParsingException {
|
||||||
final String textualUploadDate = getTextualUploadDate();
|
final String textualUploadDate = getTextualUploadDate();
|
||||||
|
|
||||||
if (textualUploadDate == null) {
|
if (textualUploadDate == null || textualUploadDate.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,17 +196,11 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
public Description getDescription() throws ParsingException {
|
public Description getDescription() throws ParsingException {
|
||||||
assertPageFetched();
|
assertPageFetched();
|
||||||
// description with more info on links
|
// description with more info on links
|
||||||
try {
|
String description = getTextFromObject(getVideoSecondaryInfoRenderer().getObject("description"), true);
|
||||||
String description = getTextFromObject(getVideoSecondaryInfoRenderer().getObject("description"), true);
|
if (!description.isEmpty()) return new Description(description, Description.HTML);
|
||||||
return new Description(description, Description.HTML);
|
|
||||||
} catch (Exception ignored) { }
|
|
||||||
|
|
||||||
// raw non-html description
|
// raw non-html description
|
||||||
try {
|
return new Description(playerResponse.getObject("videoDetails").getString("shortDescription"), Description.PLAIN_TEXT);
|
||||||
return new Description(playerResponse.getObject("videoDetails").getString("shortDescription"), Description.PLAIN_TEXT);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
throw new ParsingException("Could not get description");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -264,19 +246,13 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
@Override
|
@Override
|
||||||
public long getViewCount() throws ParsingException {
|
public long getViewCount() throws ParsingException {
|
||||||
assertPageFetched();
|
assertPageFetched();
|
||||||
String views = null;
|
String views = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("viewCount")
|
||||||
|
|
||||||
try {
|
|
||||||
views = getTextFromObject(getVideoPrimaryInfoRenderer().getObject("viewCount")
|
|
||||||
.getObject("videoViewCountRenderer").getObject("viewCount"));
|
.getObject("videoViewCountRenderer").getObject("viewCount"));
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (views == null) {
|
if (views.isEmpty()) {
|
||||||
try {
|
views = playerResponse.getObject("videoDetails").getString("viewCount");
|
||||||
views = playerResponse.getObject("videoDetails").getString("viewCount");
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (views == null) throw new ParsingException("Could not get view count");
|
if (views == null || views.isEmpty()) throw new ParsingException("Could not get view count");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (views.toLowerCase().contains("no views")) return 0;
|
if (views.toLowerCase().contains("no views")) return 0;
|
||||||
|
@ -334,16 +310,16 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderUrl() throws ParsingException {
|
public String getUploaderUrl() throws ParsingException {
|
||||||
assertPageFetched();
|
assertPageFetched();
|
||||||
try {
|
|
||||||
String uploaderUrl = getUrlFromNavigationEndpoint(getVideoSecondaryInfoRenderer()
|
String uploaderUrl = getUrlFromNavigationEndpoint(getVideoSecondaryInfoRenderer()
|
||||||
.getObject("owner").getObject("videoOwnerRenderer").getObject("navigationEndpoint"));
|
.getObject("owner").getObject("videoOwnerRenderer").getObject("navigationEndpoint"));
|
||||||
if (uploaderUrl != null) return uploaderUrl;
|
if (uploaderUrl != null && !uploaderUrl.isEmpty()) return uploaderUrl;
|
||||||
} catch (Exception ignored) {}
|
|
||||||
try {
|
|
||||||
String uploaderId = playerResponse.getObject("videoDetails").getString("channelId");
|
String uploaderId = playerResponse.getObject("videoDetails").getString("channelId");
|
||||||
if (uploaderId != null)
|
if (uploaderId != null && !uploaderId.isEmpty())
|
||||||
return YoutubeChannelLinkHandlerFactory.getInstance().getUrl("channel/" + uploaderId);
|
return YoutubeChannelLinkHandlerFactory.getInstance().getUrl("channel/" + uploaderId);
|
||||||
} catch (Exception ignored) {}
|
|
||||||
throw new ParsingException("Could not get uploader url");
|
throw new ParsingException("Could not get uploader url");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,19 +327,13 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderName() throws ParsingException {
|
public String getUploaderName() throws ParsingException {
|
||||||
assertPageFetched();
|
assertPageFetched();
|
||||||
String uploaderName = null;
|
String uploaderName = getTextFromObject(getVideoSecondaryInfoRenderer().getObject("owner")
|
||||||
|
|
||||||
try {
|
|
||||||
uploaderName = getTextFromObject(getVideoSecondaryInfoRenderer().getObject("owner")
|
|
||||||
.getObject("videoOwnerRenderer").getObject("title"));
|
.getObject("videoOwnerRenderer").getObject("title"));
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (uploaderName == null) {
|
if (uploaderName.isEmpty()) {
|
||||||
try {
|
uploaderName = playerResponse.getObject("videoDetails").getString("author");
|
||||||
uploaderName = playerResponse.getObject("videoDetails").getString("author");
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (uploaderName == null) throw new ParsingException("Could not get uploader name");
|
if (uploaderName == null || uploaderName.isEmpty()) throw new ParsingException("Could not get uploader name");
|
||||||
}
|
}
|
||||||
|
|
||||||
return uploaderName;
|
return uploaderName;
|
||||||
|
@ -392,7 +362,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
if (videoInfoPage.containsKey("dashmpd")) {
|
if (videoInfoPage.containsKey("dashmpd")) {
|
||||||
dashManifestUrl = videoInfoPage.get("dashmpd");
|
dashManifestUrl = videoInfoPage.get("dashmpd");
|
||||||
} else if (playerArgs != null && playerArgs.isString("dashmpd")) {
|
} else if (playerArgs != null && playerArgs.isString("dashmpd")) {
|
||||||
dashManifestUrl = playerArgs.getString("dashmpd", "");
|
dashManifestUrl = playerArgs.getString("dashmpd", EMPTY_STRING);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -561,9 +531,9 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
final TimeAgoParser timeAgoParser = getTimeAgoParser();
|
||||||
|
|
||||||
for (Object ul : results) {
|
for (Object ul : results) {
|
||||||
final JsonObject videoInfo = ((JsonObject) ul).getObject("compactVideoRenderer");
|
if (((JsonObject) ul).has("compactVideoRenderer")) {
|
||||||
|
collector.commit(new YoutubeStreamInfoItemExtractor(((JsonObject) ul).getObject("compactVideoRenderer"), timeAgoParser));
|
||||||
if (videoInfo != null) collector.commit(new YoutubeStreamInfoItemExtractor(videoInfo, timeAgoParser));
|
}
|
||||||
}
|
}
|
||||||
return collector;
|
return collector;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -612,7 +582,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
|
|
||||||
final String playerUrl;
|
final String playerUrl;
|
||||||
|
|
||||||
if (initialAjaxJson.getObject(2).getObject("response") != null) { // age-restricted videos
|
if (initialAjaxJson.getObject(2).has("response")) { // age-restricted videos
|
||||||
initialData = initialAjaxJson.getObject(2).getObject("response");
|
initialData = initialAjaxJson.getObject(2).getObject("response");
|
||||||
ageLimit = 18;
|
ageLimit = 18;
|
||||||
|
|
||||||
|
@ -631,7 +601,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
|
|
||||||
playerResponse = getPlayerResponse();
|
playerResponse = getPlayerResponse();
|
||||||
|
|
||||||
final JsonObject playabilityStatus = playerResponse.getObject("playabilityStatus", JsonUtils.EMPTY_OBJECT);
|
final JsonObject playabilityStatus = playerResponse.getObject("playabilityStatus");
|
||||||
final String status = playabilityStatus.getString("status");
|
final String status = playabilityStatus.getString("status");
|
||||||
// If status exist, and is not "OK", throw a ContentNotAvailableException with the reason.
|
// If status exist, and is not "OK", throw a ContentNotAvailableException with the reason.
|
||||||
if (status != null && !status.toLowerCase().equals("ok")) {
|
if (status != null && !status.toLowerCase().equals("ok")) {
|
||||||
|
@ -808,10 +778,10 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
}
|
}
|
||||||
captions = playerResponse.getObject("captions");
|
captions = playerResponse.getObject("captions");
|
||||||
|
|
||||||
final JsonObject renderer = captions.getObject("playerCaptionsTracklistRenderer", new JsonObject());
|
final JsonObject renderer = captions.getObject("playerCaptionsTracklistRenderer");
|
||||||
final JsonArray captionsArray = renderer.getArray("captionTracks", new JsonArray());
|
final JsonArray captionsArray = renderer.getArray("captionTracks");
|
||||||
// todo: use this to apply auto translation to different language from a source language
|
// todo: use this to apply auto translation to different language from a source language
|
||||||
// final JsonArray autoCaptionsArray = renderer.getArray("translationLanguages", new JsonArray());
|
// final JsonArray autoCaptionsArray = renderer.getArray("translationLanguages");
|
||||||
|
|
||||||
// This check is necessary since there may be cases where subtitles metadata do not contain caption track info
|
// This check is necessary since there may be cases where subtitles metadata do not contain caption track info
|
||||||
// e.g. https://www.youtube.com/watch?v=-Vpwatutnko
|
// e.g. https://www.youtube.com/watch?v=-Vpwatutnko
|
||||||
|
@ -876,7 +846,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
JsonObject videoPrimaryInfoRenderer = null;
|
JsonObject videoPrimaryInfoRenderer = null;
|
||||||
|
|
||||||
for (Object content : contents) {
|
for (Object content : contents) {
|
||||||
if (((JsonObject) content).getObject("videoPrimaryInfoRenderer") != null) {
|
if (((JsonObject) content).has("videoPrimaryInfoRenderer")) {
|
||||||
videoPrimaryInfoRenderer = ((JsonObject) content).getObject("videoPrimaryInfoRenderer");
|
videoPrimaryInfoRenderer = ((JsonObject) content).getObject("videoPrimaryInfoRenderer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -898,7 +868,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
|
||||||
JsonObject videoSecondaryInfoRenderer = null;
|
JsonObject videoSecondaryInfoRenderer = null;
|
||||||
|
|
||||||
for (Object content : contents) {
|
for (Object content : contents) {
|
||||||
if (((JsonObject) content).getObject("videoSecondaryInfoRenderer") != null) {
|
if (((JsonObject) content).has("videoSecondaryInfoRenderer")) {
|
||||||
videoSecondaryInfoRenderer = ((JsonObject) content).getObject("videoSecondaryInfoRenderer");
|
videoSecondaryInfoRenderer = ((JsonObject) content).getObject("videoSecondaryInfoRenderer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.*;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.*;
|
||||||
|
import static org.schabi.newpipe.extractor.utils.JsonUtils.EMPTY_STRING;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||||
|
@ -37,7 +38,6 @@ import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeP
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
|
|
||||||
private JsonObject videoInfo;
|
private JsonObject videoInfo;
|
||||||
private final TimeAgoParser timeAgoParser;
|
private final TimeAgoParser timeAgoParser;
|
||||||
private StreamType cachedStreamType;
|
private StreamType cachedStreamType;
|
||||||
|
@ -59,23 +59,18 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
return cachedStreamType;
|
return cachedStreamType;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
final JsonArray badges = videoInfo.getArray("badges");
|
||||||
JsonArray badges = videoInfo.getArray("badges");
|
for (Object badge : badges) {
|
||||||
for (Object badge : badges) {
|
if (((JsonObject) badge).getObject("metadataBadgeRenderer").getString("label", EMPTY_STRING).equals("LIVE NOW")) {
|
||||||
if (((JsonObject) badge).getObject("metadataBadgeRenderer").getString("label").equals("LIVE NOW")) {
|
|
||||||
return cachedStreamType = StreamType.LIVE_STREAM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final String style = videoInfo.getArray("thumbnailOverlays").getObject(0)
|
|
||||||
.getObject("thumbnailOverlayTimeStatusRenderer").getString("style");
|
|
||||||
if (style.equalsIgnoreCase("LIVE")) {
|
|
||||||
return cachedStreamType = StreamType.LIVE_STREAM;
|
return cachedStreamType = StreamType.LIVE_STREAM;
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {}
|
}
|
||||||
|
|
||||||
|
final String style = videoInfo.getArray("thumbnailOverlays").getObject(0)
|
||||||
|
.getObject("thumbnailOverlayTimeStatusRenderer").getString("style", EMPTY_STRING);
|
||||||
|
if (style.equalsIgnoreCase("LIVE")) {
|
||||||
|
return cachedStreamType = StreamType.LIVE_STREAM;
|
||||||
|
}
|
||||||
|
|
||||||
return cachedStreamType = StreamType.VIDEO_STREAM;
|
return cachedStreamType = StreamType.VIDEO_STREAM;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +93,7 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
@Override
|
@Override
|
||||||
public String getName() throws ParsingException {
|
public String getName() throws ParsingException {
|
||||||
String name = getTextFromObject(videoInfo.getObject("title"));
|
String name = getTextFromObject(videoInfo.getObject("title"));
|
||||||
if (name != null && !name.isEmpty()) return name;
|
if (!name.isEmpty()) return name;
|
||||||
throw new ParsingException("Could not get name");
|
throw new ParsingException("Could not get name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,23 +103,17 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
String duration = null;
|
String duration = getTextFromObject(videoInfo.getObject("lengthText"));
|
||||||
|
|
||||||
try {
|
if (duration.isEmpty()) {
|
||||||
duration = getTextFromObject(videoInfo.getObject("lengthText"));
|
for (Object thumbnailOverlay : videoInfo.getArray("thumbnailOverlays")) {
|
||||||
} catch (Exception ignored) {}
|
if (((JsonObject) thumbnailOverlay).has("thumbnailOverlayTimeStatusRenderer")) {
|
||||||
|
duration = getTextFromObject(((JsonObject) thumbnailOverlay)
|
||||||
if (duration == null) {
|
.getObject("thumbnailOverlayTimeStatusRenderer").getObject("text"));
|
||||||
try {
|
|
||||||
for (Object thumbnailOverlay : videoInfo.getArray("thumbnailOverlays")) {
|
|
||||||
if (((JsonObject) thumbnailOverlay).getObject("thumbnailOverlayTimeStatusRenderer") != null) {
|
|
||||||
duration = getTextFromObject(((JsonObject) thumbnailOverlay)
|
|
||||||
.getObject("thumbnailOverlayTimeStatusRenderer").getObject("text"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {}
|
}
|
||||||
|
|
||||||
if (duration == null) throw new ParsingException("Could not get duration");
|
if (duration.isEmpty()) throw new ParsingException("Could not get duration");
|
||||||
}
|
}
|
||||||
|
|
||||||
return YoutubeParsingHelper.parseDurationString(duration);
|
return YoutubeParsingHelper.parseDurationString(duration);
|
||||||
|
@ -132,23 +121,15 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderName() throws ParsingException {
|
public String getUploaderName() throws ParsingException {
|
||||||
String name = null;
|
String name = getTextFromObject(videoInfo.getObject("longBylineText"));
|
||||||
|
|
||||||
try {
|
if (name.isEmpty()) {
|
||||||
name = getTextFromObject(videoInfo.getObject("longBylineText"));
|
name = getTextFromObject(videoInfo.getObject("ownerText"));
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (name == null) {
|
if (name.isEmpty()) {
|
||||||
try {
|
name = getTextFromObject(videoInfo.getObject("shortBylineText"));
|
||||||
name = getTextFromObject(videoInfo.getObject("ownerText"));
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (name == null) {
|
if (name.isEmpty()) throw new ParsingException("Could not get uploader name");
|
||||||
try {
|
|
||||||
name = getTextFromObject(videoInfo.getObject("shortBylineText"));
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (name == null) throw new ParsingException("Could not get uploader name");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,26 +138,18 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUploaderUrl() throws ParsingException {
|
public String getUploaderUrl() throws ParsingException {
|
||||||
String url = null;
|
String url = getUrlFromNavigationEndpoint(videoInfo.getObject("longBylineText")
|
||||||
|
.getArray("runs").getObject(0).getObject("navigationEndpoint"));
|
||||||
|
|
||||||
try {
|
if (url == null || url.isEmpty()) {
|
||||||
url = getUrlFromNavigationEndpoint(videoInfo.getObject("longBylineText")
|
url = getUrlFromNavigationEndpoint(videoInfo.getObject("ownerText")
|
||||||
.getArray("runs").getObject(0).getObject("navigationEndpoint"));
|
.getArray("runs").getObject(0).getObject("navigationEndpoint"));
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (url == null) {
|
if (url == null || url.isEmpty()) {
|
||||||
try {
|
url = getUrlFromNavigationEndpoint(videoInfo.getObject("shortBylineText")
|
||||||
url = getUrlFromNavigationEndpoint(videoInfo.getObject("ownerText")
|
|
||||||
.getArray("runs").getObject(0).getObject("navigationEndpoint"));
|
.getArray("runs").getObject(0).getObject("navigationEndpoint"));
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (url == null) {
|
if (url == null || url.isEmpty()) throw new ParsingException("Could not get uploader url");
|
||||||
try {
|
|
||||||
url = getUrlFromNavigationEndpoint(videoInfo.getObject("shortBylineText")
|
|
||||||
.getArray("runs").getObject(0).getObject("navigationEndpoint"));
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
|
|
||||||
if (url == null) throw new ParsingException("Could not get uploader url");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,12 +168,10 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
return new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date);
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
final String publishedTimeText = getTextFromObject(videoInfo.getObject("publishedTimeText"));
|
||||||
return getTextFromObject(videoInfo.getObject("publishedTimeText"));
|
if (!publishedTimeText.isEmpty()) return publishedTimeText;
|
||||||
} catch (Exception e) {
|
|
||||||
// upload date is not always available, e.g. in playlists
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -228,17 +199,16 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
@Override
|
@Override
|
||||||
public long getViewCount() throws ParsingException {
|
public long getViewCount() throws ParsingException {
|
||||||
try {
|
try {
|
||||||
if (videoInfo.getObject("topStandaloneBadge") != null || isPremium()) {
|
if (videoInfo.has("topStandaloneBadge") || isPremium()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
final JsonObject viewCountObject = videoInfo.getObject("viewCountText");
|
if (!videoInfo.has("viewCountText")) {
|
||||||
if (viewCountObject == null) {
|
|
||||||
// This object is null when a video has its views hidden.
|
// This object is null when a video has its views hidden.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String viewCount = getTextFromObject(viewCountObject);
|
final String viewCount = getTextFromObject(videoInfo.getObject("viewCountText"));
|
||||||
|
|
||||||
if (viewCount.toLowerCase().contains("no views")) {
|
if (viewCount.toLowerCase().contains("no views")) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -266,14 +236,11 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPremium() {
|
private boolean isPremium() {
|
||||||
try {
|
JsonArray badges = videoInfo.getArray("badges");
|
||||||
JsonArray badges = videoInfo.getArray("badges");
|
for (Object badge : badges) {
|
||||||
for (Object badge : badges) {
|
if (((JsonObject) badge).getObject("metadataBadgeRenderer").getString("label", EMPTY_STRING).equals("Premium")) {
|
||||||
if (((JsonObject) badge).getObject("metadataBadgeRenderer").getString("label").equals("Premium")) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ public class YoutubeSuggestionExtractor extends SuggestionExtractor {
|
||||||
// trim JSONP part "JP(...)"
|
// trim JSONP part "JP(...)"
|
||||||
response = response.substring(3, response.length() - 1);
|
response = response.substring(3, response.length() - 1);
|
||||||
try {
|
try {
|
||||||
JsonArray collection = JsonParser.array().from(response).getArray(1, new JsonArray());
|
JsonArray collection = JsonParser.array().from(response).getArray(1);
|
||||||
for (Object suggestion : collection) {
|
for (Object suggestion : collection) {
|
||||||
if (!(suggestion instanceof JsonArray)) continue;
|
if (!(suggestion instanceof JsonArray)) continue;
|
||||||
String suggestionStr = ((JsonArray) suggestion).getString(0);
|
String suggestionStr = ((JsonArray) suggestion).getString(0);
|
||||||
|
|
|
@ -22,7 +22,6 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
|
||||||
|
|
||||||
import com.grack.nanojson.JsonArray;
|
import com.grack.nanojson.JsonArray;
|
||||||
import com.grack.nanojson.JsonObject;
|
import com.grack.nanojson.JsonObject;
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.downloader.Downloader;
|
import org.schabi.newpipe.extractor.downloader.Downloader;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
@ -33,9 +32,8 @@ import org.schabi.newpipe.extractor.localization.TimeAgoParser;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getJsonResponse;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getJsonResponse;
|
||||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getTextFromObject;
|
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper.getTextFromObject;
|
||||||
|
@ -72,13 +70,8 @@ public class YoutubeTrendingExtractor extends KioskExtractor<StreamInfoItem> {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String getName() throws ParsingException {
|
public String getName() throws ParsingException {
|
||||||
String name;
|
String name = getTextFromObject(initialData.getObject("header").getObject("feedTabbedHeaderRenderer").getObject("title"));
|
||||||
try {
|
if (!name.isEmpty()) {
|
||||||
name = getTextFromObject(initialData.getObject("header").getObject("feedTabbedHeaderRenderer").getObject("title"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new ParsingException("Could not get Trending name", e);
|
|
||||||
}
|
|
||||||
if (name != null && !name.isEmpty()) {
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
throw new ParsingException("Could not get Trending name");
|
throw new ParsingException("Could not get Trending name");
|
||||||
|
@ -97,14 +90,11 @@ public class YoutubeTrendingExtractor extends KioskExtractor<StreamInfoItem> {
|
||||||
JsonObject expandedShelfContentsRenderer = ((JsonObject) itemSectionRenderer).getObject("itemSectionRenderer")
|
JsonObject expandedShelfContentsRenderer = ((JsonObject) itemSectionRenderer).getObject("itemSectionRenderer")
|
||||||
.getArray("contents").getObject(0).getObject("shelfRenderer").getObject("content")
|
.getArray("contents").getObject(0).getObject("shelfRenderer").getObject("content")
|
||||||
.getObject("expandedShelfContentsRenderer");
|
.getObject("expandedShelfContentsRenderer");
|
||||||
if (expandedShelfContentsRenderer != null) {
|
for (Object ul : expandedShelfContentsRenderer.getArray("items")) {
|
||||||
for (Object ul : expandedShelfContentsRenderer.getArray("items")) {
|
final JsonObject videoInfo = ((JsonObject) ul).getObject("videoRenderer");
|
||||||
final JsonObject videoInfo = ((JsonObject) ul).getObject("videoRenderer");
|
collector.commit(new YoutubeStreamInfoItemExtractor(videoInfo, timeAgoParser));
|
||||||
collector.commit(new YoutubeStreamInfoItemExtractor(videoInfo, timeAgoParser));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new InfoItemsPage<>(collector, getNextPageUrl());
|
return new InfoItemsPage<>(collector, getNextPageUrl());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,7 +334,7 @@ public class YoutubeParsingHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getUrlFromNavigationEndpoint(JsonObject navigationEndpoint) throws ParsingException {
|
public static String getUrlFromNavigationEndpoint(JsonObject navigationEndpoint) throws ParsingException {
|
||||||
if (navigationEndpoint.getObject("urlEndpoint") != null) {
|
if (navigationEndpoint.has("urlEndpoint")) {
|
||||||
String internUrl = navigationEndpoint.getObject("urlEndpoint").getString("url");
|
String internUrl = navigationEndpoint.getObject("urlEndpoint").getString("url");
|
||||||
if (internUrl.startsWith("/redirect?")) {
|
if (internUrl.startsWith("/redirect?")) {
|
||||||
// q parameter can be the first parameter
|
// q parameter can be the first parameter
|
||||||
|
@ -354,7 +354,7 @@ public class YoutubeParsingHelper {
|
||||||
} else if (internUrl.startsWith("http")) {
|
} else if (internUrl.startsWith("http")) {
|
||||||
return internUrl;
|
return internUrl;
|
||||||
}
|
}
|
||||||
} else if (navigationEndpoint.getObject("browseEndpoint") != null) {
|
} else if (navigationEndpoint.has("browseEndpoint")) {
|
||||||
final JsonObject browseEndpoint = navigationEndpoint.getObject("browseEndpoint");
|
final JsonObject browseEndpoint = navigationEndpoint.getObject("browseEndpoint");
|
||||||
final String canonicalBaseUrl = browseEndpoint.getString("canonicalBaseUrl");
|
final String canonicalBaseUrl = browseEndpoint.getString("canonicalBaseUrl");
|
||||||
final String browseId = browseEndpoint.getString("browseId");
|
final String browseId = browseEndpoint.getString("browseId");
|
||||||
|
@ -369,7 +369,7 @@ public class YoutubeParsingHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ParsingException("canonicalBaseUrl is null and browseId is not a channel (\"" + browseEndpoint + "\")");
|
throw new ParsingException("canonicalBaseUrl is null and browseId is not a channel (\"" + browseEndpoint + "\")");
|
||||||
} else if (navigationEndpoint.getObject("watchEndpoint") != null) {
|
} else if (navigationEndpoint.has("watchEndpoint")) {
|
||||||
StringBuilder url = new StringBuilder();
|
StringBuilder url = new StringBuilder();
|
||||||
url.append("https://www.youtube.com/watch?v=").append(navigationEndpoint.getObject("watchEndpoint").getString("videoId"));
|
url.append("https://www.youtube.com/watch?v=").append(navigationEndpoint.getObject("watchEndpoint").getString("videoId"));
|
||||||
if (navigationEndpoint.getObject("watchEndpoint").has("playlistId"))
|
if (navigationEndpoint.getObject("watchEndpoint").has("playlistId"))
|
||||||
|
@ -377,20 +377,26 @@ public class YoutubeParsingHelper {
|
||||||
if (navigationEndpoint.getObject("watchEndpoint").has("startTimeSeconds"))
|
if (navigationEndpoint.getObject("watchEndpoint").has("startTimeSeconds"))
|
||||||
url.append("&t=").append(navigationEndpoint.getObject("watchEndpoint").getInt("startTimeSeconds"));
|
url.append("&t=").append(navigationEndpoint.getObject("watchEndpoint").getInt("startTimeSeconds"));
|
||||||
return url.toString();
|
return url.toString();
|
||||||
} else if (navigationEndpoint.getObject("watchPlaylistEndpoint") != null) {
|
} else if (navigationEndpoint.has("watchPlaylistEndpoint")) {
|
||||||
return "https://www.youtube.com/playlist?list=" +
|
return "https://www.youtube.com/playlist?list=" +
|
||||||
navigationEndpoint.getObject("watchPlaylistEndpoint").getString("playlistId");
|
navigationEndpoint.getObject("watchPlaylistEndpoint").getString("playlistId");
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text from a JSON object that has either a simpleText or a runs array.
|
||||||
|
* @param textObject JSON object to get the text from
|
||||||
|
* @param html whether to return HTML, by parsing the navigationEndpoint
|
||||||
|
* @return text in the JSON object or an empty string
|
||||||
|
*/
|
||||||
public static String getTextFromObject(JsonObject textObject, boolean html) throws ParsingException {
|
public static String getTextFromObject(JsonObject textObject, boolean html) throws ParsingException {
|
||||||
if (textObject.has("simpleText")) return textObject.getString("simpleText");
|
if (textObject.has("simpleText")) return textObject.getString("simpleText");
|
||||||
|
|
||||||
StringBuilder textBuilder = new StringBuilder();
|
StringBuilder textBuilder = new StringBuilder();
|
||||||
for (Object textPart : textObject.getArray("runs")) {
|
for (Object textPart : textObject.getArray("runs")) {
|
||||||
String text = ((JsonObject) textPart).getString("text");
|
String text = ((JsonObject) textPart).getString("text");
|
||||||
if (html && ((JsonObject) textPart).getObject("navigationEndpoint") != null) {
|
if (html && ((JsonObject) textPart).has("navigationEndpoint")) {
|
||||||
String url = getUrlFromNavigationEndpoint(((JsonObject) textPart).getObject("navigationEndpoint"));
|
String url = getUrlFromNavigationEndpoint(((JsonObject) textPart).getObject("navigationEndpoint"));
|
||||||
if (url != null && !url.isEmpty()) {
|
if (url != null && !url.isEmpty()) {
|
||||||
textBuilder.append("<a href=\"").append(url).append("\">").append(text).append("</a>");
|
textBuilder.append("<a href=\"").append(url).append("\">").append(text).append("</a>");
|
||||||
|
@ -486,7 +492,7 @@ public class YoutubeParsingHelper {
|
||||||
*/
|
*/
|
||||||
public static void defaultAlertsCheck(JsonObject initialData) throws ContentNotAvailableException {
|
public static void defaultAlertsCheck(JsonObject initialData) throws ContentNotAvailableException {
|
||||||
final JsonArray alerts = initialData.getArray("alerts");
|
final JsonArray alerts = initialData.getArray("alerts");
|
||||||
if (alerts != null && !alerts.isEmpty()) {
|
if (!alerts.isEmpty()) {
|
||||||
final JsonObject alertRenderer = alerts.getObject(0).getObject("alertRenderer");
|
final JsonObject alertRenderer = alerts.getObject(0).getObject("alertRenderer");
|
||||||
final String alertText = alertRenderer.getObject("text").getString("simpleText");
|
final String alertText = alertRenderer.getObject("text").getString("simpleText");
|
||||||
final String alertType = alertRenderer.getString("type");
|
final String alertType = alertRenderer.getString("type");
|
||||||
|
|
|
@ -14,7 +14,6 @@ import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
|
||||||
* Test {@link MediaCCCConferenceExtractor}
|
* Test {@link MediaCCCConferenceExtractor}
|
||||||
*/
|
*/
|
||||||
public class MediaCCCConferenceExtractorTest {
|
public class MediaCCCConferenceExtractorTest {
|
||||||
|
|
||||||
public static class FrOSCon2017 {
|
public static class FrOSCon2017 {
|
||||||
private static MediaCCCConferenceExtractor extractor;
|
private static MediaCCCConferenceExtractor extractor;
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ public class MediaCCCConferenceExtractorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetUrl() throws Exception {
|
public void testGetUrl() throws Exception {
|
||||||
assertEquals("https://api.media.ccc.de/public/conferences/froscon2017", extractor.getUrl());
|
assertEquals("https://media.ccc.de/public/conferences/froscon2017", extractor.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -68,7 +67,7 @@ public class MediaCCCConferenceExtractorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetUrl() throws Exception {
|
public void testGetUrl() throws Exception {
|
||||||
assertEquals("https://api.media.ccc.de/public/conferences/oscal19", extractor.getUrl());
|
assertEquals("https://media.ccc.de/public/conferences/oscal19", extractor.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -15,14 +15,14 @@ import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
|
||||||
* Test {@link MediaCCCStreamExtractor}
|
* Test {@link MediaCCCStreamExtractor}
|
||||||
*/
|
*/
|
||||||
public class MediaCCCOggTest {
|
public class MediaCCCOggTest {
|
||||||
// test against https://api.media.ccc.de/public/events/1317
|
// test against https://media.ccc.de/public/events/1317
|
||||||
private static StreamExtractor extractor;
|
private static StreamExtractor extractor;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setUpClass() throws Exception {
|
public static void setUpClass() throws Exception {
|
||||||
NewPipe.init(DownloaderTestImpl.getInstance());
|
NewPipe.init(DownloaderTestImpl.getInstance());
|
||||||
|
|
||||||
extractor = MediaCCC.getStreamExtractor("https://api.media.ccc.de/public/events/1317");
|
extractor = MediaCCC.getStreamExtractor("https://media.ccc.de/public/events/1317");
|
||||||
extractor.fetchPage();
|
extractor.fetchPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||||
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCStreamExtractor;
|
import org.schabi.newpipe.extractor.services.media_ccc.extractors.MediaCCCStreamExtractor;
|
||||||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
import org.schabi.newpipe.extractor.utils.UtilsTest;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -25,7 +24,6 @@ import static org.schabi.newpipe.extractor.ServiceList.MediaCCC;
|
||||||
* Test {@link MediaCCCStreamExtractor}
|
* Test {@link MediaCCCStreamExtractor}
|
||||||
*/
|
*/
|
||||||
public class MediaCCCStreamExtractorTest {
|
public class MediaCCCStreamExtractorTest {
|
||||||
|
|
||||||
public static class Gpn18Tmux {
|
public static class Gpn18Tmux {
|
||||||
private static MediaCCCStreamExtractor extractor;
|
private static MediaCCCStreamExtractor extractor;
|
||||||
|
|
||||||
|
@ -55,7 +53,7 @@ public class MediaCCCStreamExtractorTest {
|
||||||
@Test
|
@Test
|
||||||
public void testUrl() throws Exception {
|
public void testUrl() throws Exception {
|
||||||
assertIsSecureUrl(extractor.getUrl());
|
assertIsSecureUrl(extractor.getUrl());
|
||||||
assertEquals("https://api.media.ccc.de/public/events/gpn18-105-tmux-warum-ein-schwarzes-fenster-am-bildschirm-reicht", extractor.getUrl());
|
assertEquals("https://media.ccc.de/public/events/gpn18-105-tmux-warum-ein-schwarzes-fenster-am-bildschirm-reicht", extractor.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -141,7 +139,7 @@ public class MediaCCCStreamExtractorTest {
|
||||||
@Test
|
@Test
|
||||||
public void testUrl() throws Exception {
|
public void testUrl() throws Exception {
|
||||||
assertIsSecureUrl(extractor.getUrl());
|
assertIsSecureUrl(extractor.getUrl());
|
||||||
assertEquals("https://api.media.ccc.de/public/events/36c3-10565-what_s_left_for_private_messaging", extractor.getUrl());
|
assertEquals("https://media.ccc.de/public/events/36c3-10565-what_s_left_for_private_messaging", extractor.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -164,7 +162,7 @@ public class MediaCCCStreamExtractorTest {
|
||||||
@Test
|
@Test
|
||||||
public void testUploaderUrl() throws Exception {
|
public void testUploaderUrl() throws Exception {
|
||||||
assertIsSecureUrl(extractor.getUploaderUrl());
|
assertIsSecureUrl(extractor.getUploaderUrl());
|
||||||
assertEquals("https://api.media.ccc.de/public/conferences/36c3", extractor.getUploaderUrl());
|
assertEquals("https://media.ccc.de/public/conferences/36c3", extractor.getUploaderUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -203,4 +201,4 @@ public class MediaCCCStreamExtractorTest {
|
||||||
assertEquals(instance, requireNonNull(extractor.getUploadDate()).date());
|
assertEquals(instance, requireNonNull(extractor.getUploadDate()).date());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaC
|
||||||
import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.EVENTS;
|
import static org.schabi.newpipe.extractor.services.media_ccc.linkHandler.MediaCCCSearchQueryHandlerFactory.EVENTS;
|
||||||
|
|
||||||
public class MediaCCCSearchExtractorTest {
|
public class MediaCCCSearchExtractorTest {
|
||||||
|
|
||||||
public static class All extends DefaultSearchExtractorTest {
|
public static class All extends DefaultSearchExtractorTest {
|
||||||
private static SearchExtractor extractor;
|
private static SearchExtractor extractor;
|
||||||
private static final String QUERY = "kde";
|
private static final String QUERY = "kde";
|
||||||
|
@ -32,8 +31,8 @@ public class MediaCCCSearchExtractorTest {
|
||||||
@Override public StreamingService expectedService() { return MediaCCC; }
|
@Override public StreamingService expectedService() { return MediaCCC; }
|
||||||
@Override public String expectedName() { return QUERY; }
|
@Override public String expectedName() { return QUERY; }
|
||||||
@Override public String expectedId() { return QUERY; }
|
@Override public String expectedId() { return QUERY; }
|
||||||
@Override public String expectedUrlContains() { return "api.media.ccc.de/public/events/search?q=" + QUERY; }
|
@Override public String expectedUrlContains() { return "media.ccc.de/public/events/search?q=" + QUERY; }
|
||||||
@Override public String expectedOriginalUrlContains() { return "api.media.ccc.de/public/events/search?q=" + QUERY; }
|
@Override public String expectedOriginalUrlContains() { return "media.ccc.de/public/events/search?q=" + QUERY; }
|
||||||
@Override public String expectedSearchString() { return QUERY; }
|
@Override public String expectedSearchString() { return QUERY; }
|
||||||
@Nullable @Override public String expectedSearchSuggestion() { return null; }
|
@Nullable @Override public String expectedSearchSuggestion() { return null; }
|
||||||
|
|
||||||
|
@ -55,8 +54,8 @@ public class MediaCCCSearchExtractorTest {
|
||||||
@Override public StreamingService expectedService() { return MediaCCC; }
|
@Override public StreamingService expectedService() { return MediaCCC; }
|
||||||
@Override public String expectedName() { return QUERY; }
|
@Override public String expectedName() { return QUERY; }
|
||||||
@Override public String expectedId() { return QUERY; }
|
@Override public String expectedId() { return QUERY; }
|
||||||
@Override public String expectedUrlContains() { return "api.media.ccc.de/public/events/search?q=" + QUERY; }
|
@Override public String expectedUrlContains() { return "media.ccc.de/public/events/search?q=" + QUERY; }
|
||||||
@Override public String expectedOriginalUrlContains() { return "api.media.ccc.de/public/events/search?q=" + QUERY; }
|
@Override public String expectedOriginalUrlContains() { return "media.ccc.de/public/events/search?q=" + QUERY; }
|
||||||
@Override public String expectedSearchString() { return QUERY; }
|
@Override public String expectedSearchString() { return QUERY; }
|
||||||
@Nullable @Override public String expectedSearchSuggestion() { return null; }
|
@Nullable @Override public String expectedSearchSuggestion() { return null; }
|
||||||
|
|
||||||
|
@ -79,8 +78,8 @@ public class MediaCCCSearchExtractorTest {
|
||||||
@Override public StreamingService expectedService() { return MediaCCC; }
|
@Override public StreamingService expectedService() { return MediaCCC; }
|
||||||
@Override public String expectedName() { return QUERY; }
|
@Override public String expectedName() { return QUERY; }
|
||||||
@Override public String expectedId() { return QUERY; }
|
@Override public String expectedId() { return QUERY; }
|
||||||
@Override public String expectedUrlContains() { return "api.media.ccc.de/public/events/search?q=" + QUERY; }
|
@Override public String expectedUrlContains() { return "media.ccc.de/public/events/search?q=" + QUERY; }
|
||||||
@Override public String expectedOriginalUrlContains() { return "api.media.ccc.de/public/events/search?q=" + QUERY; }
|
@Override public String expectedOriginalUrlContains() { return "media.ccc.de/public/events/search?q=" + QUERY; }
|
||||||
@Override public String expectedSearchString() { return QUERY; }
|
@Override public String expectedSearchString() { return QUERY; }
|
||||||
@Nullable @Override public String expectedSearchSuggestion() { return null; }
|
@Nullable @Override public String expectedSearchSuggestion() { return null; }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
|
|
||||||
implementation 'com.github.wb9688:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
||||||
implementation 'com.github.spotbugs:spotbugs-annotations:3.1.0'
|
implementation 'com.github.spotbugs:spotbugs-annotations:3.1.0'
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue