Merge branch 'master' into subtitles-feature

This commit is contained in:
Christian Schabesberger 2018-09-15 22:33:17 +02:00 committed by GitHub
commit 8ac46e834c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
97 changed files with 2416 additions and 1909 deletions

View File

@ -1,8 +1,8 @@
package org.schabi.newpipe.extractor;
import edu.umd.cs.findbugs.annotations.NonNull;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -15,27 +15,27 @@ public abstract class Extractor {
*/
private final StreamingService service;
private final UrlIdHandler urlIdHandler;
private final LinkHandler uIHandler;
@Nullable
private boolean pageFetched = false;
private final Downloader downloader;
public Extractor(final StreamingService service, final UrlIdHandler urlIdHandler) {
public Extractor(final StreamingService service, final LinkHandler uIHandler) {
if(service == null) throw new NullPointerException("service is null");
if(urlIdHandler == null) throw new NullPointerException("UrlIdHandler is null");
if(uIHandler == null) throw new NullPointerException("LinkHandler is null");
this.service = service;
this.urlIdHandler = urlIdHandler;
this.uIHandler = uIHandler;
this.downloader = NewPipe.getDownloader();
if(downloader == null) throw new NullPointerException("downloader is null");
}
/**
* @return The {@link UrlIdHandler} of the current extractor object (e.g. a ChannelExtractor should return a channel url handler).
* @return The {@link LinkHandler} of the current extractor object (e.g. a ChannelExtractor should return a channel url handler).
*/
@Nonnull
protected UrlIdHandler getUrlIdHandler() {
return urlIdHandler;
public LinkHandler getUIHandler() {
return uIHandler;
}
/**
@ -67,7 +67,7 @@ public abstract class Extractor {
@Nonnull
public String getId() throws ParsingException {
return urlIdHandler.getId();
return uIHandler.getId();
}
/**
@ -80,12 +80,12 @@ public abstract class Extractor {
@Nonnull
public String getOriginalUrl() throws ParsingException {
return urlIdHandler.getOriginalUrl();
return uIHandler.getOriginalUrl();
}
@Nonnull
public String getUrl() throws ParsingException {
return urlIdHandler.getUrl();
return uIHandler.getUrl();
}
@Nonnull
@ -96,4 +96,8 @@ public abstract class Extractor {
public int getServiceId() {
return service.getServiceId();
}
public Downloader getDownloader() {
return downloader;
}
}

View File

@ -1,5 +1,7 @@
package org.schabi.newpipe.extractor;
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
@ -16,8 +18,8 @@ public abstract class Info implements Serializable {
/**
* Different than the {@link #originalUrl} in the sense that it <i>may</i> be set as a cleaned url.
*
* @see UrlIdHandler#cleanUrl(String)
* @see Extractor#getCleanUrl()
* @see LinkHandler#getUrl()
* @see Extractor#getOriginalUrl()
*/
private final String url;
/**
@ -46,6 +48,14 @@ public abstract class Info implements Serializable {
this.name = name;
}
public Info(int serviceId, LinkHandler linkHandler, String name) {
this(serviceId,
linkHandler.getId(),
linkHandler.getUrl(),
linkHandler.getOriginalUrl(),
name);
}
@Override
public String toString() {
final String ifDifferentString = !url.equals(originalUrl) ? " (originalUrl=\"" + originalUrl + "\")" : "";

View File

@ -1,6 +1,7 @@
package org.schabi.newpipe.extractor;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import javax.annotation.Nonnull;
import java.io.IOException;
@ -12,8 +13,8 @@ import java.util.List;
*/
public abstract class ListExtractor<R extends InfoItem> extends Extractor {
public ListExtractor(StreamingService service, ListUrlIdHandler urlIdHandler) {
super(service, urlIdHandler);
public ListExtractor(StreamingService service, ListLinkHandler uiHandler) {
super(service, uiHandler);
}
/**
@ -37,18 +38,23 @@ public abstract class ListExtractor<R extends InfoItem> extends Extractor {
/**
* Get a list of items corresponding to the specific requested page.
*
* @param nextPageUrl any next page url got from the exclusive implementation of the list extractor
* @param pageUrl any page url got from the exclusive implementation of the list extractor
* @return a {@link InfoItemsPage} corresponding to the requested page
* @see #getNextPageUrl()
* @see InfoItemsPage#getNextPageUrl()
*/
public abstract InfoItemsPage<R> getPage(final String nextPageUrl) throws IOException, ExtractionException;
public abstract InfoItemsPage<R> getPage(final String pageUrl) throws IOException, ExtractionException;
public boolean hasNextPage() throws IOException, ExtractionException {
final String nextPageUrl = getNextPageUrl();
return nextPageUrl != null && !nextPageUrl.isEmpty();
}
@Override
public ListLinkHandler getUIHandler() {
return (ListLinkHandler) super.getUIHandler();
}
/*//////////////////////////////////////////////////////////////////////////
// Inner
//////////////////////////////////////////////////////////////////////////*/

View File

@ -1,13 +1,31 @@
package org.schabi.newpipe.extractor;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import java.util.List;
public abstract class ListInfo<T extends InfoItem> extends Info {
private List<T> relatedItems;
private String nextPageUrl = null;
private final List<String> contentFilters;
private final String sortFilter;
public ListInfo(int serviceId, String id, String url, String originalUrl, String name) {
public ListInfo(int serviceId,
String id,
String url,
String originalUrl,
String name,
List<String> contentFilter,
String sortFilter) {
super(serviceId, id, url, originalUrl, name);
this.contentFilters = contentFilter;
this.sortFilter = sortFilter;
}
public ListInfo(int serviceId, ListLinkHandler listUrlIdHandler, String name) {
super(serviceId, listUrlIdHandler, name);
this.contentFilters = listUrlIdHandler.getContentFilters();
this.sortFilter = listUrlIdHandler.getSortFilter();
}
public List<T> getRelatedItems() {
@ -29,4 +47,12 @@ public abstract class ListInfo<T extends InfoItem> extends Info {
public void setNextPageUrl(String pageUrl) {
this.nextPageUrl = pageUrl;
}
public List<String> getContentFilters() {
return contentFilters;
}
public String getSortFilter() {
return sortFilter;
}
}

View File

@ -1,42 +0,0 @@
package org.schabi.newpipe.extractor;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
public abstract class ListUrlIdHandler extends UrlIdHandler {
protected String[] contentFilter;
protected String sortFilter;
public ListUrlIdHandler setQuery(String id, String[] contentFilter, String softFilter) throws ParsingException {
setId(id);
this.contentFilter = contentFilter;
this.sortFilter = softFilter;
return this;
}
public ListUrlIdHandler setUrl(String url) throws ParsingException {
return (ListUrlIdHandler) super.setUrl(url);
}
public ListUrlIdHandler setId(String id) throws ParsingException {
return (ListUrlIdHandler) super.setId(id);
}
/**
* Will returns content filter the corresponding extractor can handle like "channels", "videos", "music", etc.
*
* @return filter that can be applied when building a query for getting a list
*/
public String[] getAvailableContentFilter() {
return new String[0];
}
/**
* Will returns sort filter the corresponding extractor can handle like "A-Z", "oldest first", "size", etc.
*
* @return filter that can be applied when building a query for getting a list
*/
public String[] getAvailableSortFilter() {
return new String[0];
}
}

View File

@ -19,11 +19,11 @@ public final class ServiceList {
public static final YoutubeService YouTube;
public static final SoundcloudService SoundCloud;
private static final List<StreamingService> SERVICES = unmodifiableList(asList(
YouTube = new YoutubeService(0),
SoundCloud = new SoundcloudService(1)
// DailyMotion = new DailyMotionService(2);
));
private static final List<StreamingService> SERVICES = unmodifiableList(
asList(
YouTube = new YoutubeService(0),
SoundCloud = new SoundcloudService(1)
));
/**
* Get all the supported services.

View File

@ -5,7 +5,8 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.kiosk.KioskList;
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.linkhandler.*;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
@ -66,41 +67,50 @@ public abstract class StreamingService {
////////////////////////////////////////////
// Url Id handler
////////////////////////////////////////////
public abstract UrlIdHandler getStreamUrlIdHandler();
public abstract ListUrlIdHandler getChannelUrlIdHandler();
public abstract ListUrlIdHandler getPlaylistUrlIdHandler();
public abstract LinkHandlerFactory getStreamLHFactory();
public abstract ListLinkHandlerFactory getChannelLHFactory();
public abstract ListLinkHandlerFactory getPlaylistLHFactory();
public abstract SearchQueryHandlerFactory getSearchQHFactory();
////////////////////////////////////////////
// Extractor
////////////////////////////////////////////
public abstract SearchEngine getSearchEngine();
public abstract SearchExtractor getSearchExtractor(SearchQueryHandler queryHandler, String contentCountry);
public abstract SuggestionExtractor getSuggestionExtractor();
public abstract SubscriptionExtractor getSubscriptionExtractor();
public abstract KioskList getKioskList() throws ExtractionException;
public abstract ChannelExtractor getChannelExtractor(ListUrlIdHandler urlIdHandler) throws ExtractionException;
public abstract PlaylistExtractor getPlaylistExtractor(ListUrlIdHandler urlIdHandler) throws ExtractionException;
public abstract StreamExtractor getStreamExtractor(UrlIdHandler urlIdHandler) throws ExtractionException;
public abstract ChannelExtractor getChannelExtractor(ListLinkHandler urlIdHandler) throws ExtractionException;
public abstract PlaylistExtractor getPlaylistExtractor(ListLinkHandler urlIdHandler) throws ExtractionException;
public abstract StreamExtractor getStreamExtractor(LinkHandler UIHFactory) throws ExtractionException;
public ChannelExtractor getChannelExtractor(String id, String[] contentFilter, String sortFilter) throws ExtractionException {
return getChannelExtractor(getChannelUrlIdHandler().setQuery(id, contentFilter, sortFilter));
public SearchExtractor getSearchExtractor(String query, List<String> contentFilter, String sortFilter, String contentCountry) throws ExtractionException {
return getSearchExtractor(getSearchQHFactory().fromQuery(query, contentFilter, sortFilter), contentCountry);
}
public PlaylistExtractor getPlaylistExtractor(String id, String[] contentFilter, String sortFilter) throws ExtractionException {
return getPlaylistExtractor(getPlaylistUrlIdHandler().setQuery(id, contentFilter, sortFilter));
public ChannelExtractor getChannelExtractor(String id, List<String> contentFilter, String sortFilter) throws ExtractionException {
return getChannelExtractor(getChannelLHFactory().fromQuery(id, contentFilter, sortFilter));
}
public PlaylistExtractor getPlaylistExtractor(String id, List<String> contentFilter, String sortFilter) throws ExtractionException {
return getPlaylistExtractor(getPlaylistLHFactory().fromQuery(id, contentFilter, sortFilter));
}
public SearchExtractor getSearchExtractor(String query, String contentCountry) throws ExtractionException {
return getSearchExtractor(getSearchQHFactory().fromQuery(query), contentCountry);
}
public ChannelExtractor getChannelExtractor(String url) throws ExtractionException {
return getChannelExtractor(getChannelUrlIdHandler().setUrl(url));
return getChannelExtractor(getChannelLHFactory().fromUrl(url));
}
public PlaylistExtractor getPlaylistExtractor(String url) throws ExtractionException {
return getPlaylistExtractor(getPlaylistUrlIdHandler().setUrl(url));
return getPlaylistExtractor(getPlaylistLHFactory().fromUrl(url));
}
public StreamExtractor getStreamExtractor(String url) throws ExtractionException {
return getStreamExtractor(getStreamUrlIdHandler().setUrl(url));
return getStreamExtractor(getStreamLHFactory().fromUrl(url));
}
@ -109,9 +119,9 @@ public abstract class StreamingService {
* figure out where the link is pointing to (a channel, video, playlist, etc.)
*/
public final LinkType getLinkTypeByUrl(String url) throws ParsingException {
UrlIdHandler sH = getStreamUrlIdHandler();
UrlIdHandler cH = getChannelUrlIdHandler();
UrlIdHandler pH = getPlaylistUrlIdHandler();
LinkHandlerFactory sH = getStreamLHFactory();
LinkHandlerFactory cH = getChannelLHFactory();
LinkHandlerFactory pH = getPlaylistLHFactory();
if (sH.acceptUrl(url)) {
return LinkType.STREAM;

View File

@ -1,14 +1,10 @@
package org.schabi.newpipe.extractor.channel;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import javax.annotation.Nonnull;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
/*
* Created by Christian Schabesberger on 25.07.16.
@ -32,16 +28,10 @@ import javax.annotation.Nonnull;
public abstract class ChannelExtractor extends ListExtractor<StreamInfoItem> {
public ChannelExtractor(StreamingService service, ListUrlIdHandler urlIdHandler) {
public ChannelExtractor(StreamingService service, ListLinkHandler urlIdHandler) {
super(service, urlIdHandler);
}
@Nonnull
@Override
protected UrlIdHandler getUrlIdHandler() {
return getService().getChannelUrlIdHandler();
}
public abstract String getAvatarUrl() throws ParsingException;
public abstract String getBannerUrl() throws ParsingException;
public abstract String getFeedUrl() throws ParsingException;

View File

@ -5,7 +5,9 @@ import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.utils.ExtractorHelper;
import java.io.IOException;
@ -32,8 +34,8 @@ import java.io.IOException;
public class ChannelInfo extends ListInfo<StreamInfoItem> {
public ChannelInfo(int serviceId, String id, String url, String originalUrl, String name) {
super(serviceId, id, url, originalUrl, name);
public ChannelInfo(int serviceId, ListLinkHandler urlIdHandler, String name) throws ParsingException {
super(serviceId, urlIdHandler, name);
}
public static ChannelInfo getInfo(String url) throws IOException, ExtractionException {
@ -52,14 +54,9 @@ public class ChannelInfo extends ListInfo<StreamInfoItem> {
public static ChannelInfo getInfo(ChannelExtractor extractor) throws IOException, ExtractionException {
// important data
int serviceId = extractor.getServiceId();
String url = extractor.getUrl();
String originalUrl = extractor.getOriginalUrl();
String id = extractor.getId();
String name = extractor.getName();
ChannelInfo info = new ChannelInfo(serviceId, id, url, originalUrl, name);
ChannelInfo info = new ChannelInfo(extractor.getServiceId(),
extractor.getUIHandler(),
extractor.getName());
try {

View File

@ -21,11 +21,10 @@ package org.schabi.newpipe.extractor.kiosk;
*/
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import javax.annotation.Nonnull;
@ -34,7 +33,7 @@ public abstract class KioskExtractor extends ListExtractor<StreamInfoItem> {
private final String id;
public KioskExtractor(StreamingService streamingService,
ListUrlIdHandler urlIdHandler,
ListLinkHandler urlIdHandler,
String kioskId) {
super(streamingService, urlIdHandler);
this.id = kioskId;

View File

@ -20,20 +20,19 @@ package org.schabi.newpipe.extractor.kiosk;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.utils.ExtractorHelper;
import java.io.IOException;
public class KioskInfo extends ListInfo<StreamInfoItem> {
private KioskInfo(int serviceId, String id, String url, String originalUrl, String name) {
super(serviceId, id, url, originalUrl, name);
private KioskInfo(int serviceId, ListLinkHandler urlIdHandler, String name) throws ParsingException {
super(serviceId, urlIdHandler, name);
}
public static ListExtractor.InfoItemsPage<StreamInfoItem> getMoreItems(StreamingService service,
@ -68,13 +67,9 @@ public class KioskInfo extends ListInfo<StreamInfoItem> {
*/
public static KioskInfo getInfo(KioskExtractor extractor) throws ExtractionException {
int serviceId = extractor.getServiceId();
String name = extractor.getName();
String id = extractor.getId();
String url = extractor.getUrl();
String originalUrl = extractor.getOriginalUrl();
KioskInfo info = new KioskInfo(serviceId, id, url, originalUrl, name);
final KioskInfo info = new KioskInfo(extractor.getServiceId(),
extractor.getUIHandler(),
extractor.getName());
final ListExtractor.InfoItemsPage<StreamInfoItem> itemsPage = ExtractorHelper.getItemsPageOrLogError(info, extractor);
info.setRelatedItems(itemsPage.getItems());

View File

@ -2,7 +2,7 @@ package org.schabi.newpipe.extractor.kiosk;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import java.io.IOException;
@ -23,24 +23,24 @@ public class KioskList {
private String defaultKiosk = null;
private class KioskEntry {
public KioskEntry(KioskExtractorFactory ef, UrlIdHandler h) {
public KioskEntry(KioskExtractorFactory ef, ListLinkHandlerFactory h) {
extractorFactory = ef;
handler = h;
handlerFactory = h;
}
final KioskExtractorFactory extractorFactory;
final UrlIdHandler handler;
final ListLinkHandlerFactory handlerFactory;
}
public KioskList(int service_id) {
this.service_id = service_id;
}
public void addKioskEntry(KioskExtractorFactory extractorFactory, UrlIdHandler handler, String id)
public void addKioskEntry(KioskExtractorFactory extractorFactory, ListLinkHandlerFactory handlerFactory, String id)
throws Exception {
if(kioskList.get(id) != null) {
throw new Exception("Kiosk with type " + id + " already exists.");
}
kioskList.put(id, new KioskEntry(extractorFactory, handler));
kioskList.put(id, new KioskEntry(extractorFactory, handlerFactory));
}
public void setDefaultKiosk(String kioskType) {
@ -73,7 +73,7 @@ public class KioskList {
throw new ExtractionException("No kiosk found with the type: " + kioskId);
} else {
return ke.extractorFactory.createNewKiosk(NewPipe.getService(service_id),
ke.handler.setId(kioskId).getUrl(), kioskId);
ke.handlerFactory.fromId(kioskId).getUrl(), kioskId);
}
}
@ -85,14 +85,14 @@ public class KioskList {
throws ExtractionException, IOException {
for(Map.Entry<String, KioskEntry> e : kioskList.entrySet()) {
KioskEntry ke = e.getValue();
if(ke.handler.acceptUrl(url)) {
if(ke.handlerFactory.acceptUrl(url)) {
return getExtractorById(e.getKey(), nextPageUrl);
}
}
throw new ExtractionException("Could not find a kiosk that fits to the url: " + url);
}
public UrlIdHandler getUrlIdHandlerByType(String type) {
return kioskList.get(type).handler;
public ListLinkHandlerFactory getListLinkHandlerFactoryByType(String type) {
return kioskList.get(type).handlerFactory;
}
}

View File

@ -0,0 +1,31 @@
package org.schabi.newpipe.extractor.linkhandler;
import java.io.Serializable;
public class LinkHandler implements Serializable {
protected final String originalUrl;
protected final String url;
protected final String id;
public LinkHandler(String originalUrl, String url, String id) {
this.originalUrl = originalUrl;
this.url = url;
this.id = id;
}
public LinkHandler(LinkHandler handler) {
this(handler.originalUrl, handler.url, handler.id);
}
public String getOriginalUrl() {
return originalUrl;
}
public String getUrl() {
return url;
}
public String getId() {
return id;
}
}

View File

@ -1,13 +1,13 @@
package org.schabi.newpipe.extractor;
package org.schabi.newpipe.extractor.linkhandler;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
/*
* Created by Christian Schabesberger on 26.07.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* UrlIdHandler.java is part of NewPipe.
* LinkHandlerFactory.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -23,40 +23,34 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public abstract class UrlIdHandler {
public abstract class LinkHandlerFactory {
protected String id = "";
protected String originalUrl = "";
///////////////////////////////////
// To Override
///////////////////////////////////
public abstract String onGetIdFromUrl(String url) throws ParsingException;
public abstract String getUrl() throws ParsingException;
public abstract String getId(String url) throws ParsingException;
public abstract String getUrl(String id) throws ParsingException;
public abstract boolean onAcceptUrl(final String url) throws ParsingException;
///////////////////////////////////
// Logic
///////////////////////////////////
public UrlIdHandler setUrl(String url) throws ParsingException {
public LinkHandler fromUrl(String url) throws ParsingException {
if(url == null) throw new IllegalArgumentException("url can not be null");
originalUrl = url;
id = onGetIdFromUrl(url);
return this;
}
public UrlIdHandler setId(String id) throws ParsingException {
if(id == null) throw new IllegalArgumentException("id can not be null");
this.id = id;
if(!acceptUrl(getUrl())) {
throw new ParsingException("Malformed unacceptable url: " + getUrl());
if(!acceptUrl(url)) {
throw new ParsingException("Malformed unacceptable url: " + url);
}
return this;
final String id = getId(url);
return new LinkHandler(url, getUrl(id), id);
}
public String getId() {
return id;
}
public String getOriginalUrl() throws ParsingException {
return (originalUrl == null || originalUrl.isEmpty())
? getUrl()
: originalUrl;
public LinkHandler fromId(String id) throws ParsingException {
if(id == null) throw new IllegalArgumentException("id can not be null");
final String url = getUrl(id);
return new LinkHandler(url, url, id);
}
/**
@ -64,11 +58,11 @@ public abstract class UrlIdHandler {
* Intent was meant to be watched with this Service.
* Return false if this service shall not allow to be called through ACTIONs.
*/
public boolean acceptUrl(final String url) {
public boolean acceptUrl(final String url) throws ParsingException {
try {
return onAcceptUrl(url);
} catch (Exception e) {
return false;
} catch (FoundAdException fe) {
throw fe;
}
}
}

View File

@ -0,0 +1,45 @@
package org.schabi.newpipe.extractor.linkhandler;
import java.util.Collections;
import java.util.List;
public class ListLinkHandler extends LinkHandler {
protected final List<String> contentFilters;
protected final String sortFilter;
public ListLinkHandler(String originalUrl,
String url,
String id,
List<String> contentFilters,
String sortFilter) {
super(originalUrl, url, id);
this.contentFilters = Collections.unmodifiableList(contentFilters);
this.sortFilter = sortFilter;
}
public ListLinkHandler(ListLinkHandler handler) {
this(handler.originalUrl,
handler.url,
handler.id,
handler.contentFilters,
handler.sortFilter);
}
public ListLinkHandler(LinkHandler handler,
List<String> contentFilters,
String sortFilter) {
this(handler.originalUrl,
handler.url,
handler.id,
contentFilters,
sortFilter);
}
public List<String> getContentFilters() {
return contentFilters;
}
public String getSortFilter() {
return sortFilter;
}
}

View File

@ -0,0 +1,70 @@
package org.schabi.newpipe.extractor.linkhandler;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import java.util.ArrayList;
import java.util.List;
public abstract class ListLinkHandlerFactory extends LinkHandlerFactory {
///////////////////////////////////
// To Override
///////////////////////////////////
public List<String> getContentFilter(String url) throws ParsingException { return new ArrayList<>(0);}
public String getSortFilter(String url) throws ParsingException {return ""; }
public abstract String getUrl(String id, List<String> contentFilter, String sortFilter) throws ParsingException;
///////////////////////////////////
// Logic
///////////////////////////////////
@Override
public ListLinkHandler fromUrl(String url) throws ParsingException {
if(url == null) throw new IllegalArgumentException("url may not be null");
return new ListLinkHandler(super.fromUrl(url), getContentFilter(url), getSortFilter(url));
}
@Override
public ListLinkHandler fromId(String id) throws ParsingException {
return new ListLinkHandler(super.fromId(id), new ArrayList<String>(0), "");
}
public ListLinkHandler fromQuery(String id,
List<String> contentFilters,
String sortFilter) throws ParsingException {
final String url = getUrl(id, contentFilters, sortFilter);
return new ListLinkHandler(url, url, id, contentFilters, sortFilter);
}
/**
* For makeing ListLinkHandlerFactory compatible with LinkHandlerFactory we need to override this,
* however it should not be overridden by the actual implementation.
* @param id
* @return the url coresponding to id without any filters applied
*/
public String getUrl(String id) throws ParsingException {
return getUrl(id, new ArrayList<String>(0), "");
}
/**
* Will returns content filter the corresponding extractor can handle like "channels", "videos", "music", etc.
*
* @return filter that can be applied when building a query for getting a list
*/
public String[] getAvailableContentFilter() {
return new String[0];
}
/**
* Will returns sort filter the corresponding extractor can handle like "A-Z", "oldest first", "size", etc.
*
* @return filter that can be applied when building a query for getting a list
*/
public String[] getAvailableSortFilter() {
return new String[0];
}
}

View File

@ -0,0 +1,32 @@
package org.schabi.newpipe.extractor.linkhandler;
import java.util.List;
public class SearchQueryHandler extends ListLinkHandler {
public SearchQueryHandler(String originalUrl,
String url,
String searchString,
List<String> contentFilters,
String sortFilter) {
super(originalUrl, url, searchString, contentFilters, sortFilter);
}
public SearchQueryHandler(ListLinkHandler handler) {
this(handler.originalUrl,
handler.url,
handler.id,
handler.contentFilters,
handler.sortFilter);
}
/**
* Returns the search string. Since ListQIHandler is based on ListLinkHandler
* getSearchString() is equivalent to calling getId().
* @return the search string
*/
public String getSearchString() {
return getId();
}
}

View File

@ -0,0 +1,43 @@
package org.schabi.newpipe.extractor.linkhandler;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import java.util.ArrayList;
import java.util.List;
public abstract class SearchQueryHandlerFactory extends ListLinkHandlerFactory {
///////////////////////////////////
// To Override
///////////////////////////////////
@Override
public abstract String getUrl(String querry, List<String> contentFilter, String sortFilter) throws ParsingException;
public String getSearchString(String url) { return "";}
///////////////////////////////////
// Logic
///////////////////////////////////
@Override
public String getId(String url) { return getSearchString(url); }
@Override
public SearchQueryHandler fromQuery(String querry,
List<String> contentFilter,
String sortFilter) throws ParsingException {
return new SearchQueryHandler(super.fromQuery(querry, contentFilter, sortFilter));
}
public SearchQueryHandler fromQuery(String querry) throws ParsingException {
return fromQuery(querry, new ArrayList<String>(0), "");
}
/**
* It's not mandatorry for NewPipe to handle the Url
* @param url
* @return
*/
@Override
public boolean onAcceptUrl(String url) { return false; }
}

View File

@ -1,27 +1,17 @@
package org.schabi.newpipe.extractor.playlist;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import javax.annotation.Nonnull;
public abstract class PlaylistExtractor extends ListExtractor<StreamInfoItem> {
public PlaylistExtractor(StreamingService service, ListUrlIdHandler urlIdHandler) {
public PlaylistExtractor(StreamingService service, ListLinkHandler urlIdHandler) {
super(service, urlIdHandler);
}
@Nonnull
@Override
protected UrlIdHandler getUrlIdHandler() {
return getService().getPlaylistUrlIdHandler();
}
public abstract String getThumbnailUrl() throws ParsingException;
public abstract String getBannerUrl() throws ParsingException;

View File

@ -5,6 +5,8 @@ import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.utils.ExtractorHelper;
@ -12,8 +14,8 @@ import java.io.IOException;
public class PlaylistInfo extends ListInfo<StreamInfoItem> {
public PlaylistInfo(int serviceId, String id, String url, String originalUrl, String name) {
super(serviceId, id, url, originalUrl, name);
private PlaylistInfo(int serviceId, ListLinkHandler urlIdHandler, String name) throws ParsingException {
super(serviceId, urlIdHandler, name);
}
public static PlaylistInfo getInfo(String url) throws IOException, ExtractionException {
@ -35,14 +37,12 @@ public class PlaylistInfo extends ListInfo<StreamInfoItem> {
*
* @param extractor an extractor where fetchPage() was already got called on.
*/
public static PlaylistInfo getInfo(PlaylistExtractor extractor) throws IOException, ExtractionException {
public static PlaylistInfo getInfo(PlaylistExtractor extractor) throws ExtractionException {
int serviceId = extractor.getServiceId();
String url = extractor.getUrl();
String originalUrl = extractor.getOriginalUrl();
String id = extractor.getId();
String name = extractor.getName();
PlaylistInfo info = new PlaylistInfo(serviceId, id, url, originalUrl, name);
final PlaylistInfo info = new PlaylistInfo(
extractor.getServiceId(),
extractor.getUIHandler(),
extractor.getName());
try {
info.setStreamCount(extractor.getStreamCount());

View File

@ -45,7 +45,6 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
* other extractor type will raise an exception.
*/
public class InfoItemsSearchCollector extends InfoItemsCollector<InfoItem, InfoItemExtractor> {
private String suggestion = "";
private final StreamInfoItemsCollector streamCollector;
private final ChannelInfoItemsCollector userCollector;
private final PlaylistInfoItemsCollector playlistCollector;
@ -57,14 +56,6 @@ public class InfoItemsSearchCollector extends InfoItemsCollector<InfoItem, InfoI
playlistCollector = new PlaylistInfoItemsCollector(serviceId);
}
public void setSuggestion(String suggestion) {
this.suggestion = suggestion;
}
public SearchResult getSearchResult() throws ExtractionException {
return new SearchResult(getServiceId(), suggestion, getItems(), getErrors());
}
@Override
public InfoItem extract(InfoItemExtractor extractor) throws ParsingException {
// Use the corresponding collector for each item extractor type

View File

@ -1,50 +0,0 @@
package org.schabi.newpipe.extractor.search;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import java.io.IOException;
/*
* Created by Christian Schabesberger on 10.08.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* SearchEngine.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public abstract class SearchEngine {
public enum Filter {
ANY, STREAM, CHANNEL, PLAYLIST
}
public static class NothingFoundException extends ExtractionException {
public NothingFoundException(String message) {
super(message);
}
}
private final InfoItemsSearchCollector collector;
public SearchEngine(int serviceId) {
collector = new InfoItemsSearchCollector(serviceId);
}
protected InfoItemsSearchCollector getInfoItemSearchCollector() {
return collector;
}
public abstract InfoItemsSearchCollector search(String query, int page, String contentCountry, Filter filter)
throws IOException, ExtractionException;
}

View File

@ -0,0 +1,50 @@
package org.schabi.newpipe.extractor.search;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
public abstract class SearchExtractor extends ListExtractor<InfoItem> {
public static class NothingFoundException extends ExtractionException {
public NothingFoundException(String message) {
super(message);
}
}
private final InfoItemsSearchCollector collector;
private final String contentCountry;
public SearchExtractor(StreamingService service, SearchQueryHandler urlIdHandler, String contentCountry) {
super(service, urlIdHandler);
collector = new InfoItemsSearchCollector(service.getServiceId());
this.contentCountry = contentCountry;
}
public String getSearchString() {
return getUIHandler().getSearchString();
}
public abstract String getSearchSuggestion() throws ParsingException;
protected InfoItemsSearchCollector getInfoItemSearchCollector() {
return collector;
}
@Override
public SearchQueryHandler getUIHandler() {
return (SearchQueryHandler) super.getUIHandler();
}
@Override
public String getName() {
return getUIHandler().getSearchString();
}
protected String getContentCountry() {
return contentCountry;
}
}

View File

@ -0,0 +1,69 @@
package org.schabi.newpipe.extractor.search;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
import org.schabi.newpipe.extractor.utils.ExtractorHelper;
import java.io.IOException;
public class SearchInfo extends ListInfo<InfoItem> {
private String searchString;
private String searchSuggestion;
public SearchInfo(int serviceId,
SearchQueryHandler qIHandler,
String searchString) {
super(serviceId, qIHandler, "Search");
this.searchString = searchString;
}
public static SearchInfo getInfo(StreamingService service, SearchQueryHandler searchQuery, String contentCountry) throws ExtractionException, IOException {
SearchExtractor extractor = service.getSearchExtractor(searchQuery, contentCountry);
extractor.fetchPage();
return getInfo(extractor);
}
public static SearchInfo getInfo(SearchExtractor extractor) throws ExtractionException, IOException {
final SearchInfo info = new SearchInfo(
extractor.getServiceId(),
extractor.getUIHandler(),
extractor.getSearchString());
try {
info.searchSuggestion = extractor.getSearchSuggestion();
} catch (Exception e) {
info.addError(e);
}
ListExtractor.InfoItemsPage<InfoItem> page = ExtractorHelper.getItemsPageOrLogError(info, extractor);
info.setRelatedItems(page.getItems());
info.setNextPageUrl(page.getNextPageUrl());
return info;
}
public static ListExtractor.InfoItemsPage<InfoItem> getMoreItems(StreamingService service,
SearchQueryHandler query,
String contentCountry,
String pageUrl)
throws IOException, ExtractionException {
return service.getSearchExtractor(query, contentCountry).getPage(pageUrl);
}
// Getter
public String getSearchString() {
return searchString;
}
public String getSearchSuggestion() {
return searchSuggestion;
}
}

View File

@ -1,71 +0,0 @@
package org.schabi.newpipe.extractor.search;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
* Created by Christian Schabesberger on 29.02.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* SearchResult.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class SearchResult {
private final int serviceId;
public final String suggestion;
@Nonnull
public final List<InfoItem> resultList;
@Nonnull
public final List<Throwable> errors;
public SearchResult(int serviceId, String suggestion, List<InfoItem> results, List<Throwable> errors) {
this.serviceId = serviceId;
this.suggestion = suggestion;
this.resultList = Collections.unmodifiableList(new ArrayList<>(results));
this.errors = Collections.unmodifiableList(new ArrayList<>(errors));
}
public static SearchResult getSearchResult(@Nonnull final SearchEngine engine, final String query, final int page,
final String languageCode, final SearchEngine.Filter filter)
throws IOException, ExtractionException {
return engine.search(query, page, languageCode, filter).getSearchResult();
}
public String getSuggestion() {
return suggestion;
}
@Nonnull
public List<InfoItem> getResults() {
return Collections.unmodifiableList(resultList);
}
@Nonnull
public List<Throwable> getErrors() {
return errors;
}
public int getServiceId() {
return serviceId;
}
}

View File

@ -5,7 +5,7 @@ import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonParser;
import com.grack.nanojson.JsonParserException;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@ -16,8 +16,6 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
import javax.annotation.Nonnull;
import java.io.IOException;
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
@SuppressWarnings("WeakerAccess")
public class SoundcloudChannelExtractor extends ChannelExtractor {
private String userId;
@ -26,14 +24,14 @@ public class SoundcloudChannelExtractor extends ChannelExtractor {
private StreamInfoItemsCollector streamInfoItemsCollector = null;
private String nextPageUrl = null;
public SoundcloudChannelExtractor(StreamingService service, ListUrlIdHandler urlIdHandler) {
public SoundcloudChannelExtractor(StreamingService service, ListLinkHandler urlIdHandler) {
super(service, urlIdHandler);
}
@Override
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
userId = getUrlIdHandler().getId();
userId = getUIHandler().getId();
String apiUrl = "https://api-v2.soundcloud.com/users/" + userId +
"?client_id=" + SoundcloudParsingHelper.clientId();

View File

@ -1,28 +1,24 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.utils.Parser;
import org.schabi.newpipe.extractor.utils.Utils;
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
import java.util.List;
public class SoundcloudChannelUrlIdHandler extends ListUrlIdHandler {
private static final SoundcloudChannelUrlIdHandler instance = new SoundcloudChannelUrlIdHandler();
public class SoundcloudChannelLinkHandlerFactory extends ListLinkHandlerFactory {
private static final SoundcloudChannelLinkHandlerFactory instance = new SoundcloudChannelLinkHandlerFactory();
private final String URL_PATTERN = "^https?://(www\\.|m\\.)?soundcloud.com/[0-9a-z_-]+" +
"(/((tracks|albums|sets|reposts|followers|following)/?)?)?([#?].*)?$";
public static SoundcloudChannelUrlIdHandler getInstance() {
public static SoundcloudChannelLinkHandlerFactory getInstance() {
return instance;
}
@Override
public String onGetIdFromUrl(String url) throws ParsingException {
public String getId(String url) throws ParsingException {
Utils.checkUrl(URL_PATTERN, url);
try {
@ -33,7 +29,7 @@ public class SoundcloudChannelUrlIdHandler extends ListUrlIdHandler {
}
@Override
public String getUrl() throws ParsingException {
public String getUrl(String id, List<String> contentFilter, String sortFilter) throws ParsingException {
try {
return SoundcloudParsingHelper.resolveUrlWithEmbedPlayer("https://api.soundcloud.com/users/" + id);
} catch (Exception e) {

View File

@ -1,9 +1,8 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
@ -18,7 +17,7 @@ public class SoundcloudChartsExtractor extends KioskExtractor {
private StreamInfoItemsCollector collector = null;
private String nextPageUrl = null;
public SoundcloudChartsExtractor(StreamingService service, ListUrlIdHandler urlIdHandler, String kioskId) {
public SoundcloudChartsExtractor(StreamingService service, ListLinkHandler urlIdHandler, String kioskId) {
super(service, urlIdHandler, kioskId);
}
@ -32,12 +31,6 @@ public class SoundcloudChartsExtractor extends KioskExtractor {
return getId();
}
@Nonnull
@Override
public UrlIdHandler getUrlIdHandler() {
return new SoundcloudChartsUrlIdHandler();
}
@Override
public InfoItemsPage<StreamInfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
if (pageUrl == null || pageUrl.isEmpty()) {
@ -64,11 +57,11 @@ public class SoundcloudChartsExtractor extends KioskExtractor {
apiUrl += "&kind=trending";
}
List<String> supportedCountries = Arrays.asList("AU", "CA", "FR", "DE", "IE", "NL", "NZ", "GB", "US");
/*List<String> supportedCountries = Arrays.asList("AU", "CA", "FR", "DE", "IE", "NL", "NZ", "GB", "US");
String contentCountry = getContentCountry();
if (supportedCountries.contains(contentCountry)) {
apiUrl += "&region=soundcloud:regions:" + contentCountry;
}
}*/
nextPageUrl = SoundcloudParsingHelper.getStreamsFromApi(collector, apiUrl, true);
}

View File

@ -1,17 +1,17 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.utils.Parser;
public class SoundcloudChartsUrlIdHandler extends ListUrlIdHandler {
import java.util.List;
public class SoundcloudChartsLinkHandlerFactory extends ListLinkHandlerFactory {
private final String TOP_URL_PATTERN = "^https?://(www\\.|m\\.)?soundcloud.com/charts(/top)?/?([#?].*)?$";
private final String URL_PATTERN = "^https?://(www\\.|m\\.)?soundcloud.com/charts(/top|/new)?/?([#?].*)?$";
@Override
public String onGetIdFromUrl(String url) {
public String getId(String url) {
if (Parser.isMatch(TOP_URL_PATTERN, url.toLowerCase())) {
return "Top 50";
} else {
@ -19,7 +19,8 @@ public class SoundcloudChartsUrlIdHandler extends ListUrlIdHandler {
}
}
public String getUrl() {
@Override
public String getUrl(String id, List<String> contentFilter, String sortFilter) {
if (id.equals("Top 50")) {
return "https://soundcloud.com/charts/top";
} else {

View File

@ -4,7 +4,7 @@ import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonParser;
import com.grack.nanojson.JsonParserException;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
@ -15,8 +15,6 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
import javax.annotation.Nonnull;
import java.io.IOException;
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
@SuppressWarnings("WeakerAccess")
public class SoundcloudPlaylistExtractor extends PlaylistExtractor {
private String playlistId;
@ -25,14 +23,14 @@ public class SoundcloudPlaylistExtractor extends PlaylistExtractor {
private StreamInfoItemsCollector streamInfoItemsCollector = null;
private String nextPageUrl = null;
public SoundcloudPlaylistExtractor(StreamingService service, ListUrlIdHandler urlIdHandler) {
public SoundcloudPlaylistExtractor(StreamingService service, ListLinkHandler urlIdHandler) {
super(service, urlIdHandler);
}
@Override
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
playlistId = getUrlIdHandler().getId();
playlistId = getUIHandler().getId();
String apiUrl = "https://api.soundcloud.com/playlists/" + playlistId +
"?client_id=" + SoundcloudParsingHelper.clientId() +
"&representation=compact";

View File

@ -1,21 +1,23 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.utils.Parser;
import org.schabi.newpipe.extractor.utils.Utils;
public class SoundcloudPlaylistUrlIdHandler extends ListUrlIdHandler {
private static final SoundcloudPlaylistUrlIdHandler instance = new SoundcloudPlaylistUrlIdHandler();
import java.util.List;
public class SoundcloudPlaylistLinkHandlerFactory extends ListLinkHandlerFactory {
private static final SoundcloudPlaylistLinkHandlerFactory instance = new SoundcloudPlaylistLinkHandlerFactory();
private final String URL_PATTERN = "^https?://(www\\.|m\\.)?soundcloud.com/[0-9a-z_-]+" +
"/sets/[0-9a-z_-]+/?([#?].*)?$";
public static SoundcloudPlaylistUrlIdHandler getInstance() {
public static SoundcloudPlaylistLinkHandlerFactory getInstance() {
return instance;
}
@Override
public String onGetIdFromUrl(String url) throws ParsingException {
public String getId(String url) throws ParsingException {
Utils.checkUrl(URL_PATTERN, url);
try {
@ -26,7 +28,7 @@ public class SoundcloudPlaylistUrlIdHandler extends ListUrlIdHandler {
}
@Override
public String getUrl() throws ParsingException {
public String getUrl(String id, List<String> contentFilter, String sortFilter) throws ParsingException {
try {
return SoundcloudParsingHelper.resolveUrlWithEmbedPlayer("https://api.soundcloud.com/playlists/" + id);
} catch (Exception e) {

View File

@ -1,84 +0,0 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import com.grack.nanojson.JsonArray;
import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonParser;
import com.grack.nanojson.JsonParserException;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
import org.schabi.newpipe.extractor.search.SearchEngine;
import java.io.IOException;
import java.net.URLEncoder;
public class SoundcloudSearchEngine extends SearchEngine {
public static final String CHARSET_UTF_8 = "UTF-8";
public SoundcloudSearchEngine(int serviceId) {
super(serviceId);
}
@Override
public InfoItemsSearchCollector search(String query, int page, String languageCode, Filter filter) throws IOException, ExtractionException {
InfoItemsSearchCollector collector = getInfoItemSearchCollector();
Downloader dl = NewPipe.getDownloader();
String url = "https://api-v2.soundcloud.com/search";
switch (filter) {
case STREAM:
url += "/tracks";
break;
case CHANNEL:
url += "/users";
break;
case PLAYLIST:
url += "/playlists";
break;
case ANY:
// Don't append any parameter to search for everything
default:
break;
}
url += "?q=" + URLEncoder.encode(query, CHARSET_UTF_8)
+ "&client_id=" + SoundcloudParsingHelper.clientId()
+ "&limit=10"
+ "&offset=" + Integer.toString(page * 10);
JsonArray searchCollection;
try {
searchCollection = JsonParser.object().from(dl.download(url)).getArray("collection");
} catch (JsonParserException e) {
throw new ParsingException("Could not parse json response", e);
}
if (searchCollection.size() == 0) {
throw new NothingFoundException("Nothing found");
}
for (Object result : searchCollection) {
if (!(result instanceof JsonObject)) continue;
//noinspection ConstantConditions
JsonObject searchResult = (JsonObject) result;
String kind = searchResult.getString("kind", "");
switch (kind) {
case "user":
collector.commit(new SoundcloudChannelInfoItemExtractor(searchResult));
break;
case "track":
collector.commit(new SoundcloudStreamInfoItemExtractor(searchResult));
break;
case "playlist":
collector.commit(new SoundcloudPlaylistInfoItemExtractor(searchResult));
break;
}
}
return collector;
}
}

View File

@ -0,0 +1,112 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import com.grack.nanojson.JsonArray;
import com.grack.nanojson.JsonObject;
import com.grack.nanojson.JsonParser;
import com.grack.nanojson.JsonParserException;
import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
import org.schabi.newpipe.extractor.utils.Parser;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.ITEMS_PER_PAGE;
public class SoundcloudSearchExtractor extends SearchExtractor {
private JsonArray searchCollection;
public SoundcloudSearchExtractor(StreamingService service,
SearchQueryHandler urlIdHandler,
String contentCountry) {
super(service, urlIdHandler, contentCountry);
}
@Override
public String getSearchSuggestion() throws ParsingException {
return null;
}
@Nonnull
@Override
public InfoItemsPage<InfoItem> getInitialPage() throws IOException, ExtractionException {
return new InfoItemsPage<>(collectItems(searchCollection), getNextPageUrl());
}
@Override
public String getNextPageUrl() throws IOException, ExtractionException {
return getNextPageUrlFromCurrentUrl(getUrl());
}
@Override
public InfoItemsPage<InfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
final Downloader dl = getDownloader();
try {
searchCollection = JsonParser.object().from(dl.download(pageUrl)).getArray("collection");
} catch (JsonParserException e) {
throw new ParsingException("Could not parse json response", e);
}
return new InfoItemsPage<>(collectItems(searchCollection), getNextPageUrlFromCurrentUrl(pageUrl));
}
@Override
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
final Downloader dl = getDownloader();
final String url = getUrl();
try {
searchCollection = JsonParser.object().from(dl.download(url)).getArray("collection");
} catch (JsonParserException e) {
throw new ParsingException("Could not parse json response", e);
}
if (searchCollection.size() == 0) {
throw new SearchExtractor.NothingFoundException("Nothing found");
}
}
private InfoItemsCollector<InfoItem, InfoItemExtractor> collectItems(JsonArray searchCollection) {
final InfoItemsSearchCollector collector = getInfoItemSearchCollector();
for (Object result : searchCollection) {
if (!(result instanceof JsonObject)) continue;
//noinspection ConstantConditions
JsonObject searchResult = (JsonObject) result;
String kind = searchResult.getString("kind", "");
switch (kind) {
case "user":
collector.commit(new SoundcloudChannelInfoItemExtractor(searchResult));
break;
case "track":
collector.commit(new SoundcloudStreamInfoItemExtractor(searchResult));
break;
case "playlist":
collector.commit(new SoundcloudPlaylistInfoItemExtractor(searchResult));
break;
}
}
return collector;
}
private String getNextPageUrlFromCurrentUrl(String currentUrl)
throws MalformedURLException, UnsupportedEncodingException {
final int pageOffset = Integer.parseInt(
Parser.compatParseMap(
new URL(currentUrl)
.getQuery())
.get("offset"));
return currentUrl.replace("&offset=" +
Integer.toString(pageOffset),
"&offset=" + Integer.toString(pageOffset + ITEMS_PER_PAGE));
}
}

View File

@ -0,0 +1,66 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
public class SoundcloudSearchQueryHandlerFactory extends SearchQueryHandlerFactory {
public static final String CHARSET_UTF_8 = "UTF-8";
public static final String TRACKS = "tracks";
public static final String USERS = "users";
public static final String PLAYLISTS = "playlists";
public static final String ALL = "all";
public static final int ITEMS_PER_PAGE = 10;
@Override
public String getUrl(String id, List<String> contentFilter, String sortFilter) throws ParsingException {
try {
String url = "https://api-v2.soundcloud.com/search";
if(contentFilter.size() > 0) {
switch (contentFilter.get(0)) {
case TRACKS:
url += "/tracks";
break;
case USERS:
url += "/users";
break;
case PLAYLISTS:
url += "/playlists";
break;
case ALL:
default:
break;
}
}
return url + "?q=" + URLEncoder.encode(id, CHARSET_UTF_8)
+ "&client_id=" + SoundcloudParsingHelper.clientId()
+ "&limit=" + ITEMS_PER_PAGE
+ "&offset=0";
} catch (UnsupportedEncodingException e) {
throw new ParsingException("Could not encode query", e);
} catch (IOException e) {
throw new ParsingException("Could not get client id", e);
} catch (ReCaptchaException e) {
throw new ParsingException("ReCaptcha required", e);
}
}
@Override
public String[] getAvailableContentFilter() {
return new String[] {
ALL,
TRACKS,
USERS,
PLAYLISTS};
}
}

View File

@ -1,15 +1,13 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.SuggestionExtractor;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.extractor.linkhandler.*;
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
import org.schabi.newpipe.extractor.kiosk.KioskList;
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
@ -23,38 +21,43 @@ public class SoundcloudService extends StreamingService {
}
@Override
public SearchEngine getSearchEngine() {
return new SoundcloudSearchEngine(getServiceId());
public SearchExtractor getSearchExtractor(SearchQueryHandler queryHandler, String contentCountry) {
return new SoundcloudSearchExtractor(this, queryHandler, contentCountry);
}
@Override
public UrlIdHandler getStreamUrlIdHandler() {
return SoundcloudStreamUrlIdHandler.getInstance();
public SearchQueryHandlerFactory getSearchQHFactory() {
return new SoundcloudSearchQueryHandlerFactory();
}
@Override
public ListUrlIdHandler getChannelUrlIdHandler() {
return SoundcloudChannelUrlIdHandler.getInstance();
public LinkHandlerFactory getStreamLHFactory() {
return SoundcloudStreamLinkHandlerFactory.getInstance();
}
@Override
public ListUrlIdHandler getPlaylistUrlIdHandler() {
return SoundcloudPlaylistUrlIdHandler.getInstance();
public ListLinkHandlerFactory getChannelLHFactory() {
return SoundcloudChannelLinkHandlerFactory.getInstance();
}
@Override
public ListLinkHandlerFactory getPlaylistLHFactory() {
return SoundcloudPlaylistLinkHandlerFactory.getInstance();
}
@Override
public StreamExtractor getStreamExtractor(UrlIdHandler urlIdHandler) throws ExtractionException {
return new SoundcloudStreamExtractor(this, urlIdHandler);
public StreamExtractor getStreamExtractor(LinkHandler LinkHandler) {
return new SoundcloudStreamExtractor(this, LinkHandler);
}
@Override
public ChannelExtractor getChannelExtractor(ListUrlIdHandler urlIdHandler) throws ExtractionException {
public ChannelExtractor getChannelExtractor(ListLinkHandler urlIdHandler) {
return new SoundcloudChannelExtractor(this, urlIdHandler);
}
@Override
public PlaylistExtractor getPlaylistExtractor(ListUrlIdHandler urlIdHandler) throws ExtractionException {
public PlaylistExtractor getPlaylistExtractor(ListLinkHandler urlIdHandler) {
return new SoundcloudPlaylistExtractor(this, urlIdHandler);
}
@ -72,14 +75,14 @@ public class SoundcloudService extends StreamingService {
String id)
throws ExtractionException {
return new SoundcloudChartsExtractor(SoundcloudService.this,
new SoundcloudChartsUrlIdHandler().setUrl(url), id);
new SoundcloudChartsLinkHandlerFactory().fromUrl(url), id);
}
};
KioskList list = new KioskList(getServiceId());
// add kiosks here e.g.:
final SoundcloudChartsUrlIdHandler h = new SoundcloudChartsUrlIdHandler();
final SoundcloudChartsLinkHandlerFactory h = new SoundcloudChartsLinkHandlerFactory();
try {
list.addKioskEntry(chartsFactory, h, "Top 50");
list.addKioskEntry(chartsFactory, h, "New & hot");

View File

@ -7,6 +7,7 @@ import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
import org.schabi.newpipe.extractor.stream.*;
import javax.annotation.Nonnull;
@ -17,13 +18,11 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
public class SoundcloudStreamExtractor extends StreamExtractor {
private JsonObject track;
public SoundcloudStreamExtractor(StreamingService service, UrlIdHandler urlIdHandler) {
super(service, urlIdHandler);
public SoundcloudStreamExtractor(StreamingService service, LinkHandler uIHandler) {
super(service, uIHandler);
}
@Override
@ -203,16 +202,6 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
return collector;
}
@Override
public String[] getDonationLinks() {
return new String[0];
}
@Override
public String[] getAffiliateLinks() {
return new String[0];
}
@Override
public String getErrorMessage() {
return null;

View File

@ -1,29 +1,24 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.utils.Parser;
import org.schabi.newpipe.extractor.utils.Utils;
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
public class SoundcloudStreamUrlIdHandler extends UrlIdHandler {
private static final SoundcloudStreamUrlIdHandler instance = new SoundcloudStreamUrlIdHandler();
public class SoundcloudStreamLinkHandlerFactory extends LinkHandlerFactory {
private static final SoundcloudStreamLinkHandlerFactory instance = new SoundcloudStreamLinkHandlerFactory();
private final String URL_PATTERN = "^https?://(www\\.|m\\.)?soundcloud.com/[0-9a-z_-]+" +
"/(?!(tracks|albums|sets|reposts|followers|following)/?$)[0-9a-z_-]+/?([#?].*)?$";
private SoundcloudStreamUrlIdHandler() {
private SoundcloudStreamLinkHandlerFactory() {
}
public static SoundcloudStreamUrlIdHandler getInstance() {
public static SoundcloudStreamLinkHandlerFactory getInstance() {
return instance;
}
@Override
public String getUrl() throws ParsingException {
public String getUrl(String id) throws ParsingException {
try {
return SoundcloudParsingHelper.resolveUrlWithEmbedPlayer("https://api.soundcloud.com/tracks/" + id);
} catch (Exception e) {
@ -32,7 +27,7 @@ public class SoundcloudStreamUrlIdHandler extends UrlIdHandler {
}
@Override
public String onGetIdFromUrl(String url) throws ParsingException {
public String getId(String url) throws ParsingException {
Utils.checkUrl(URL_PATTERN, url);
try {

View File

@ -31,7 +31,7 @@ public class SoundcloudSubscriptionExtractor extends SubscriptionExtractor {
String id;
try {
id = service.getChannelUrlIdHandler().setUrl(getUrlFrom(channelUrl)).getId();
id = service.getChannelLHFactory().fromUrl(getUrlFrom(channelUrl)).getId();
} catch (ExtractionException e) {
throw new InvalidSourceException(e);
}

View File

@ -34,10 +34,6 @@ public class ItagItem {
////////////////////////////////////////////////////////////////////
// AUDIO ID ItagType Format Bitrate ///
//////////////////////////////////////////////////////////////////
// Disable Opus codec as it's not well supported in older devices
// new ItagItem(249, AUDIO, WEBMA, 50),
// new ItagItem(250, AUDIO, WEBMA, 70),
// new ItagItem(251, AUDIO, WEBMA, 160),
new ItagItem(171, AUDIO, WEBMA, 128),
new ItagItem(172, AUDIO, WEBMA, 256),
new ItagItem(139, AUDIO, M4A, 48),
@ -45,7 +41,7 @@ public class ItagItem {
new ItagItem(141, AUDIO, M4A, 256),
new ItagItem(249, AUDIO, OPUS, 50),
new ItagItem(250, AUDIO, OPUS, 70),
new ItagItem(160, AUDIO, OPUS, 160),
new ItagItem(251, AUDIO, OPUS, 160),
/// VIDEO ONLY ////////////////////////////////////////////
// ID Type Format Resolution FPS ///

View File

@ -1,20 +1,15 @@
package org.schabi.newpipe.extractor.services.youtube;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.SuggestionExtractor;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.extractor.linkhandler.*;
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
import org.schabi.newpipe.extractor.kiosk.KioskList;
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.services.youtube.extractors.*;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeChannelUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubePlaylistUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeStreamUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeTrendingUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.*;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
@ -25,7 +20,7 @@ import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCap
/*
* Created by Christian Schabesberger on 23.08.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeService.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
@ -49,37 +44,42 @@ public class YoutubeService extends StreamingService {
}
@Override
public SearchEngine getSearchEngine() {
return new YoutubeSearchEngine(getServiceId());
public SearchExtractor getSearchExtractor(SearchQueryHandler query, String contentCountry) {
return new YoutubeSearchExtractor(this, query, contentCountry);
}
@Override
public UrlIdHandler getStreamUrlIdHandler() {
return YoutubeStreamUrlIdHandler.getInstance();
public LinkHandlerFactory getStreamLHFactory() {
return YoutubeStreamLinkHandlerFactory.getInstance();
}
@Override
public ListUrlIdHandler getChannelUrlIdHandler() {
return YoutubeChannelUrlIdHandler.getInstance();
public ListLinkHandlerFactory getChannelLHFactory() {
return YoutubeChannelLinkHandlerFactory.getInstance();
}
@Override
public ListUrlIdHandler getPlaylistUrlIdHandler() {
return YoutubePlaylistUrlIdHandler.getInstance();
public ListLinkHandlerFactory getPlaylistLHFactory() {
return YoutubePlaylistLinkHandlerFactory.getInstance();
}
@Override
public StreamExtractor getStreamExtractor(UrlIdHandler urlIdHandler) throws ExtractionException {
return new YoutubeStreamExtractor(this, urlIdHandler);
public SearchQueryHandlerFactory getSearchQHFactory() {
return YoutubeSearchQueryHandlerFactory.getInstance();
}
@Override
public ChannelExtractor getChannelExtractor(ListUrlIdHandler urlIdHandler) throws ExtractionException {
public StreamExtractor getStreamExtractor(LinkHandler linkHandler) throws ExtractionException {
return new YoutubeStreamExtractor(this, linkHandler);
}
@Override
public ChannelExtractor getChannelExtractor(ListLinkHandler urlIdHandler) throws ExtractionException {
return new YoutubeChannelExtractor(this, urlIdHandler);
}
@Override
public PlaylistExtractor getPlaylistExtractor(ListUrlIdHandler urlIdHandler) throws ExtractionException {
public PlaylistExtractor getPlaylistExtractor(ListLinkHandler urlIdHandler) throws ExtractionException {
return new YoutubePlaylistExtractor(this, urlIdHandler);
}
@ -99,9 +99,9 @@ public class YoutubeService extends StreamingService {
public KioskExtractor createNewKiosk(StreamingService streamingService, String url, String id)
throws ExtractionException {
return new YoutubeTrendingExtractor(YoutubeService.this,
new YoutubeTrendingUrlIdHandler().setUrl(url), id);
new YoutubeTrendingLinkHandlerFactory().fromUrl(url), id);
}
}, new YoutubeTrendingUrlIdHandler(), "Trending");
}, new YoutubeTrendingLinkHandlerFactory(), "Trending");
list.setDefaultKiosk("Trending");
} catch (Exception e) {
throw new ExtractionException(e);

View File

@ -7,10 +7,13 @@ import com.grack.nanojson.JsonParserException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
import org.schabi.newpipe.extractor.utils.DonationLinkHelper;
@ -24,7 +27,7 @@ import java.util.ArrayList;
/*
* Created by Christian Schabesberger on 25.07.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeChannelExtractor.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
@ -48,7 +51,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
private Document doc;
public YoutubeChannelExtractor(StreamingService service, ListUrlIdHandler urlIdHandler) {
public YoutubeChannelExtractor(StreamingService service, ListLinkHandler urlIdHandler) {
super(service, urlIdHandler);
}
@ -130,11 +133,16 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
@Override
public long getSubscriberCount() throws ParsingException {
Element el = doc.select("span[class*=\"yt-subscription-button-subscriber-count\"]").first();
final Element el = doc.select("span[class*=\"yt-subscription-button-subscriber-count\"]").first();
if (el != null) {
return Long.parseLong(Utils.removeNonDigitCharacters(el.text()));
try {
return Long.parseLong(Utils.removeNonDigitCharacters(el.text()));
} catch (NumberFormatException e) {
throw new ParsingException("Could not get subscriber count", e);
}
} else {
throw new ParsingException("Could not get subscriber count");
// If the element is null, the channel have the subscriber count disabled
return -1;
}
}

View File

@ -59,11 +59,16 @@ public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor
@Override
public long getSubscriberCount() throws ParsingException {
Element subsEl = el.select("span[class*=\"yt-subscriber-count\"]").first();
if (subsEl == null) {
return 0;
final Element subsEl = el.select("span[class*=\"yt-subscriber-count\"]").first();
if (subsEl != null) {
try {
return Long.parseLong(Utils.removeNonDigitCharacters(subsEl.text()));
} catch (NumberFormatException e) {
throw new ParsingException("Could not get subscriber count", e);
}
} else {
return Long.parseLong(Utils.removeNonDigitCharacters(subsEl.text()));
// If the element is null, the channel have the subscriber count disabled
return -1;
}
}

View File

@ -6,17 +6,21 @@ import com.grack.nanojson.JsonParserException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.*;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.playlist.PlaylistExtractor;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper;
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.utils.Utils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
@SuppressWarnings("WeakerAccess")
@ -24,7 +28,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
private Document doc;
public YoutubePlaylistExtractor(StreamingService service, ListUrlIdHandler urlIdHandler) throws ExtractionException {
public YoutubePlaylistExtractor(StreamingService service, ListLinkHandler urlIdHandler) throws ExtractionException {
super(service, urlIdHandler);
}
@ -116,7 +120,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
@Nonnull
@Override
public InfoItemsPage<StreamInfoItem> getInitialPage() throws IOException, ExtractionException {
public InfoItemsPage<StreamInfoItem> getInitialPage() throws ExtractionException {
StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
Element tbody = doc.select("tbody[id=\"pl-load-more-destination\"]").first();
collectStreamsFrom(collector, tbody);
@ -132,7 +136,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
StreamInfoItemsCollector collector = new StreamInfoItemsCollector(getServiceId());
JsonObject pageJson;
try {
pageJson = JsonParser.object().from(NewPipe.getDownloader().download(pageUrl));
pageJson = JsonParser.object().from(getDownloader().download(pageUrl));
} catch (JsonParserException pe) {
throw new ParsingException("Could not parse ajax json", pe);
}
@ -170,10 +174,14 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
}
}
private void collectStreamsFrom(StreamInfoItemsCollector collector, Element element) throws ParsingException {
private void collectStreamsFrom(@Nonnull StreamInfoItemsCollector collector, @Nullable Element element) {
collector.reset();
final UrlIdHandler streamUrlIdHandler = getService().getStreamUrlIdHandler();
if (element == null) {
return;
}
final LinkHandlerFactory streamLinkHandlerFactory = getService().getStreamLHFactory();
for (final Element li : element.children()) {
if(isDeletedItem(li)) {
continue;
@ -183,14 +191,14 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
public Element uploaderLink;
@Override
public boolean isAd() throws ParsingException {
public boolean isAd() {
return false;
}
@Override
public String getUrl() throws ParsingException {
try {
return streamUrlIdHandler.setId(li.attr("data-video-id")).getUrl();
return streamLinkHandlerFactory.fromId(li.attr("data-video-id")).getUrl();
} catch (Exception e) {
throw new ParsingException("Could not get web page url for the video", e);
}
@ -255,7 +263,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
@Override
public String getThumbnailUrl() throws ParsingException {
try {
return "https://i.ytimg.com/vi/" + streamUrlIdHandler.setUrl(getUrl()).getId() + "/hqdefault.jpg";
return "https://i.ytimg.com/vi/" + streamLinkHandlerFactory.fromUrl(getUrl()).getId() + "/hqdefault.jpg";
} catch (Exception e) {
throw new ParsingException("Could not get thumbnail url", e);
}

View File

@ -48,18 +48,22 @@ public class YoutubePlaylistInfoItemExtractor implements PlaylistInfoItemExtract
@Override
public String getUrl() throws ParsingException {
String url;
try {
final Element href = el.select("div[class=\"yt-lockup-meta\"]").first()
.select("a").first();
final Element div = el.select("div[class=\"yt-lockup-meta\"]").first();
if(div != null) {
final Element a = div.select("a").first();
return a.attr("abs:href");
}
// this is for yt premium playlists
return el.select("h3[class=\"yt-lockup-title\"").first()
.select("a").first()
.attr("abs:href");
url = href.attr("abs:href");
} catch (Exception e) {
throw new ParsingException("Failed to extract playlist url", e);
}
return url;
}
@Override

View File

@ -1,125 +0,0 @@
package org.schabi.newpipe.extractor.services.youtube.extractors;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
import org.schabi.newpipe.extractor.search.SearchEngine;
import java.io.IOException;
import java.net.URLEncoder;
/*
* Created by Christian Schabesberger on 09.08.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngine.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class YoutubeSearchEngine extends SearchEngine {
private static final String TAG = YoutubeSearchEngine.class.toString();
public static final String CHARSET_UTF_8 = "UTF-8";
public YoutubeSearchEngine(int serviceId) {
super(serviceId);
}
@Override
public InfoItemsSearchCollector search(String query, int page, String languageCode, Filter filter)
throws IOException, ExtractionException {
InfoItemsSearchCollector collector = getInfoItemSearchCollector();
Downloader downloader = NewPipe.getDownloader();
String url = "https://www.youtube.com/results"
+ "?q=" + URLEncoder.encode(query, CHARSET_UTF_8)
+ "&page=" + Integer.toString(page + 1);
switch (filter) {
case STREAM:
url += "&sp=EgIQAVAU";
break;
case CHANNEL:
url += "&sp=EgIQAlAU"; //EgIQA( lowercase L )AU
break;
case PLAYLIST:
url += "&sp=EgIQA1AU"; //EgIQA( one )AU
break;
case ANY:
// Don't append any parameter to search for everything
default:
break;
}
String site;
//String url = builder.build().toString();
//if we've been passed a valid language code, append it to the URL
if (!languageCode.isEmpty()) {
//assert Pattern.matches("[a-z]{2}(-([A-Z]{2}|[0-9]{1,3}))?", languageCode);
site = downloader.download(url, languageCode);
} else {
site = downloader.download(url);
}
Document doc = Jsoup.parse(site, url);
Element list = doc.select("ol[class=\"item-section\"]").first();
for (Element item : list.children()) {
/* First we need to determine which kind of item we are working with.
Youtube depicts five different kinds of items on its search result page. These are
regular videos, playlists, channels, two types of video suggestions, and a "no video
found" item. Since we only want videos, we need to filter out all the others.
An example for this can be seen here:
https://www.youtube.com/results?search_query=asdf&page=1
We already applied a filter to the url, so we don't need to care about channels and
playlists now.
*/
Element el;
// both types of spell correction item
if ((el = item.select("div[class*=\"spell-correction\"]").first()) != null) {
collector.setSuggestion(el.select("a").first().text());
if (list.children().size() == 1) {
throw new NothingFoundException("Did you mean: " + el.select("a").first().text());
}
// search message item
} else if ((el = item.select("div[class*=\"search-message\"]").first()) != null) {
throw new NothingFoundException(el.text());
// video item type
} else if ((el = item.select("div[class*=\"yt-lockup-video\"]").first()) != null) {
collector.commit(new YoutubeStreamInfoItemExtractor(el));
} else if ((el = item.select("div[class*=\"yt-lockup-channel\"]").first()) != null) {
collector.commit(new YoutubeChannelInfoItemExtractor(el));
} else if ((el = item.select("div[class*=\"yt-lockup-playlist\"]").first()) != null &&
item.select(".yt-pl-icon-mix").isEmpty()) {
collector.commit(new YoutubePlaylistInfoItemExtractor(el));
} else {
// noinspection ConstantConditions
// simply ignore not known items
// throw new ExtractionException("unexpected element found: \"" + item + "\"");
}
}
return collector;
}
}

View File

@ -0,0 +1,145 @@
package org.schabi.newpipe.extractor.services.youtube.extractors;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
import org.schabi.newpipe.extractor.utils.Parser;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
/*
* Created by Christian Schabesberger on 22.07.2018
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeSearchExtractor.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class YoutubeSearchExtractor extends SearchExtractor {
private Document doc;
public YoutubeSearchExtractor(StreamingService service,
SearchQueryHandler urlIdHandler,
String contentCountry) {
super(service, urlIdHandler, contentCountry);
}
@Override
public void onFetchPage(@Nonnull Downloader downloader) throws IOException, ExtractionException {
final String site;
final String url = getUrl();
final String contentCountry = getContentCountry();
//String url = builder.build().toString();
//if we've been passed a valid language code, append it to the URL
if (!contentCountry.isEmpty()) {
//assert Pattern.matches("[a-z]{2}(-([A-Z]{2}|[0-9]{1,3}))?", languageCode);
site = downloader.download(url, contentCountry);
} else {
site = downloader.download(url);
}
doc = Jsoup.parse(site, url);
}
@Override
public String getSearchSuggestion() throws ParsingException {
final Element el = doc.select("div[class*=\"spell-correction\"]").first();
if (el != null) {
return el.select("a").first().text();
} else {
return "";
}
}
@Nonnull
@Override
public InfoItemsPage<InfoItem> getInitialPage() throws IOException, ExtractionException {
return new InfoItemsPage<>(collectItems(doc), getNextPageUrl());
}
@Override
public String getNextPageUrl() throws ExtractionException {
return getUrl() + "&page=" + Integer.toString( 2);
}
@Override
public InfoItemsPage<InfoItem> getPage(String pageUrl) throws IOException, ExtractionException {
String site = getDownloader().download(pageUrl);
doc = Jsoup.parse(site, pageUrl);
return new InfoItemsPage<>(collectItems(doc), getNextPageUrlFromCurrentUrl(pageUrl));
}
private String getNextPageUrlFromCurrentUrl(String currentUrl)
throws MalformedURLException, UnsupportedEncodingException {
final int pageNr = Integer.parseInt(
Parser.compatParseMap(
new URL(currentUrl)
.getQuery())
.get("page"));
return currentUrl.replace("&page=" + Integer.toString( pageNr),
"&page=" + Integer.toString(pageNr + 1));
}
private InfoItemsSearchCollector collectItems(Document doc) throws NothingFoundException {
InfoItemsSearchCollector collector = getInfoItemSearchCollector();
Element list = doc.select("ol[class=\"item-section\"]").first();
for (Element item : list.children()) {
/* First we need to determine which kind of item we are working with.
Youtube depicts five different kinds of items on its search result page. These are
regular videos, playlists, channels, two types of video suggestions, and a "no video
found" item. Since we only want videos, we need to filter out all the others.
An example for this can be seen here:
https://www.youtube.com/results?search_query=asdf&page=1
We already applied a filter to the url, so we don't need to care about channels and
playlists now.
*/
Element el;
if ((el = item.select("div[class*=\"search-message\"]").first()) != null) {
throw new NothingFoundException(el.text());
// video item type
} else if ((el = item.select("div[class*=\"yt-lockup-video\"]").first()) != null) {
collector.commit(new YoutubeStreamInfoItemExtractor(el));
} else if ((el = item.select("div[class*=\"yt-lockup-channel\"]").first()) != null) {
collector.commit(new YoutubeChannelInfoItemExtractor(el));
} else if ((el = item.select("div[class*=\"yt-lockup-playlist\"]").first()) != null &&
item.select(".yt-pl-icon-mix").isEmpty()) {
collector.commit(new YoutubePlaylistInfoItemExtractor(el));
}
}
return collector;
}
}

View File

@ -16,21 +16,24 @@ import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
import org.schabi.newpipe.extractor.services.youtube.ItagItem;
import org.schabi.newpipe.extractor.stream.*;
import org.schabi.newpipe.extractor.utils.DonationLinkHelper;
import org.schabi.newpipe.extractor.utils.Parser;
import org.schabi.newpipe.extractor.utils.Utils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
/*
* Created by Christian Schabesberger on 06.08.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeStreamExtractor.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
@ -85,8 +88,8 @@ public class YoutubeStreamExtractor extends StreamExtractor {
private boolean isAgeRestricted;
public YoutubeStreamExtractor(StreamingService service, UrlIdHandler urlIdHandler) throws ExtractionException {
super(service, urlIdHandler);
public YoutubeStreamExtractor(StreamingService service, LinkHandler linkHandler) {
super(service, linkHandler);
}
/*//////////////////////////////////////////////////////////////////////////
@ -152,12 +155,41 @@ public class YoutubeStreamExtractor extends StreamExtractor {
public String getDescription() throws ParsingException {
assertPageFetched();
try {
return doc.select("p[id=\"eow-description\"]").first().html();
} catch (Exception e) {//todo: add fallback method <-- there is no ... as long as i know
return parseHtmlAndGetFullLinks(doc.select("p[id=\"eow-description\"]").first().html());
} catch (Exception e) {
throw new ParsingException("Could not get the description", e);
}
}
private String parseHtmlAndGetFullLinks(String descriptionHtml)
throws MalformedURLException, UnsupportedEncodingException, ParsingException {
final Document description = Jsoup.parse(descriptionHtml, getUrl());
for(Element a : description.select("a")) {
final URL redirectLink = new URL(
a.attr("abs:href"));
final String queryString = redirectLink.getQuery();
if(queryString != null) {
// if the query string is null we are not dealing with a redirect link,
// so we don't need to override it.
final String link =
Parser.compatParseMap(queryString).get("q");
if(link != null) {
// if link is null the a tag is a hashtag.
// They refer to the youtube search. We do not handle them.
a.text(link);
}
} else if(redirectLink.toString().contains("watch?v=")
|| redirectLink.toString().contains("https://www.youtube.com/")) {
// Another posibility is that this link is pointing to another video
// we need to put the redirectLink in here explicitly in order to add the domain part to the link.
a.text(redirectLink.toString());
}
}
return description.select("body").first().html();
}
@Override
public int getAgeLimit() throws ParsingException {
assertPageFetched();
@ -409,7 +441,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
}
@Override
public List<VideoStream> getVideoOnlyStreams() throws IOException, ExtractionException {
public List<VideoStream> getVideoOnlyStreams() throws ExtractionException {
assertPageFetched();
List<VideoStream> videoOnlyStreams = new ArrayList<>();
try {
@ -523,41 +555,6 @@ public class YoutubeStreamExtractor extends StreamExtractor {
return errorReason != null ? errorReason.toString() : null;
}
@Override
public String[] getDonationLinks() throws ParsingException {
try {
ArrayList<String> donationLinks = new ArrayList<>();
for (String s : Parser.getLinksFromString(getDescription())) {
if (DonationLinkHelper.getDonatoinServiceByLink(s) != DonationLinkHelper.DonationService.NO_DONATION) {
donationLinks.add(s);
}
}
String[] donlret = new String[donationLinks.size()];
donlret = donationLinks.toArray(donlret);
return donlret;
} catch (Exception e) {
throw new ParsingException("Could not get donation links", e);
}
}
@Override
public String[] getAffiliateLinks() throws ParsingException {
try {
ArrayList<String> donationLinks = new ArrayList<>();
for (String s : Parser.getLinksFromString(getDescription())) {
if (DonationLinkHelper.getAffiliateServiceByLink(s) != DonationLinkHelper.AffiliateService.NO_AFILIATE) {
donationLinks.add(s);
}
}
String[] donlret = new String[donationLinks.size()];
donlret = donationLinks.toArray(donlret);
return donlret;
} catch (Exception e) {
throw new ParsingException("Could not get afiliate links", e);
}
}
/*//////////////////////////////////////////////////////////////////////////
// Fetch page
//////////////////////////////////////////////////////////////////////////*/
@ -570,6 +567,13 @@ public class YoutubeStreamExtractor extends StreamExtractor {
private static final String VERIFIED_URL_PARAMS = "&has_verified=1&bpctr=9999999999";
private final static String DECYRYPTION_SIGNATURE_FUNCTION_REGEX =
"(\\w+)\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\(\"\"\\)\\s*;";
private final static String DECRYPTION_AKAMAIZED_STRING_REGEX =
"yt\\.akamaized\\.net/\\)\\s*\\|\\|\\s*.*?\\s*c\\s*&&\\s*d\\.set\\([^,]+\\s*,\\s*([a-zA-Z0-9$]+)\\(";
private final static String DECRYPTION_AKAMAIZED_SHORT_STRING_REGEX =
"\\bc\\s*&&\\s*d\\.set\\([^,]+\\s*,\\s*([a-zA-Z0-9$]+)\\(";
private volatile String decryptionCode = "";
private String pageHtml = null;
@ -692,13 +696,6 @@ public class YoutubeStreamExtractor extends StreamExtractor {
}
private String loadDecryptionCode(String playerUrl) throws DecryptException {
String decryptionFuncName;
String decryptionFunc;
String helperObjectName;
String helperObject;
String callerFunc = "function " + DECRYPTION_FUNC_NAME + "(a){return %%(a);}";
String decryptionCode;
try {
Downloader downloader = NewPipe.getDownloader();
if (!playerUrl.contains("https://youtube.com")) {
@ -706,33 +703,38 @@ public class YoutubeStreamExtractor extends StreamExtractor {
//than we have to add it by hand
playerUrl = "https://youtube.com" + playerUrl;
}
String playerCode = downloader.download(playerUrl);
decryptionFuncName =
Parser.matchGroup("([\"\\'])signature\\1\\s*,\\s*([a-zA-Z0-9$]+)\\(", playerCode, 2);
final String playerCode = downloader.download(playerUrl);
String functionPattern = "("
+ decryptionFuncName.replace("$", "\\$")
final String decryptionFunctionName;
if (Parser.isMatch(DECRYPTION_AKAMAIZED_SHORT_STRING_REGEX, playerCode)) {
decryptionFunctionName = Parser.matchGroup1(DECRYPTION_AKAMAIZED_SHORT_STRING_REGEX, playerCode);
} else if (Parser.isMatch(DECRYPTION_AKAMAIZED_STRING_REGEX, playerCode)) {
decryptionFunctionName = Parser.matchGroup1(DECRYPTION_AKAMAIZED_STRING_REGEX, playerCode);
} else {
decryptionFunctionName = Parser.matchGroup1(DECYRYPTION_SIGNATURE_FUNCTION_REGEX, playerCode);
}
final String functionPattern = "("
+ decryptionFunctionName.replace("$", "\\$")
+ "=function\\([a-zA-Z0-9_]+\\)\\{.+?\\})";
decryptionFunc = "var " + Parser.matchGroup1(functionPattern, playerCode) + ";";
final String decryptionFunction = "var " + Parser.matchGroup1(functionPattern, playerCode) + ";";
helperObjectName = Parser
.matchGroup1(";([A-Za-z0-9_\\$]{2})\\...\\(", decryptionFunc);
final String helperObjectName =
Parser.matchGroup1(";([A-Za-z0-9_\\$]{2})\\...\\(", decryptionFunction);
final String helperPattern =
"(var " + helperObjectName.replace("$", "\\$") + "=\\{.+?\\}\\};)";
final String helperObject =
Parser.matchGroup1(helperPattern, playerCode.replace("\n", ""));
String helperPattern = "(var "
+ helperObjectName.replace("$", "\\$") + "=\\{.+?\\}\\};)";
helperObject = Parser.matchGroup1(helperPattern, playerCode.replace("\n", ""));
final String callerFunction =
"function " + DECRYPTION_FUNC_NAME + "(a){return " + decryptionFunctionName + "(a);}";
callerFunc = callerFunc.replace("%%", decryptionFuncName);
decryptionCode = helperObject + decryptionFunc + callerFunc;
return helperObject + decryptionFunction + callerFunction;
} catch (IOException ioe) {
throw new DecryptException("Could not load decrypt function", ioe);
} catch (Exception e) {
throw new DecryptException("Could not parse decrypt function ", e);
}
return decryptionCode;
}
private String decryptSignature(String encryptedSig, String decryptionCode) throws DecryptException {

View File

@ -2,7 +2,7 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.extractor.utils.Utils;
@ -45,7 +45,17 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
@Override
public boolean isAd() throws ParsingException {
return !item.select("span[class*=\"icon-not-available\"]").isEmpty()
|| !item.select("span[class*=\"yt-badge-ad\"]").isEmpty();
|| !item.select("span[class*=\"yt-badge-ad\"]").isEmpty()
|| isPremiumVideo();
}
private boolean isPremiumVideo() {
Element premiumSpan = item.select("span[class=\"standalone-collection-badge-renderer-red-text\"]").first();
if(premiumSpan == null) return false;
// if this span has text it most likely says ("Free Video") so we can play this
if(premiumSpan.hasText()) return false;
return true;
}
@Override
@ -119,6 +129,9 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
Element meta = item.select("div[class=\"yt-lockup-meta\"]").first();
if (meta == null) return "";
Element li = meta.select("li").first();
if(li == null) return "";
return meta.select("li").first().text();
} catch (Exception e) {
throw new ParsingException("Could not get upload date", e);

View File

@ -3,7 +3,7 @@ package org.schabi.newpipe.extractor.services.youtube.extractors;
/*
* Created by Christian Schabesberger on 12.08.17.
*
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeTrendingExtractor.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
@ -25,13 +25,11 @@ import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.kiosk.KioskExtractor;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeTrendingUrlIdHandler;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
@ -42,8 +40,9 @@ public class YoutubeTrendingExtractor extends KioskExtractor {
private Document doc;
public YoutubeTrendingExtractor(StreamingService service, ListUrlIdHandler urlIdHandler, String kioskId)
throws ExtractionException {
public YoutubeTrendingExtractor(StreamingService service,
ListLinkHandler urlIdHandler,
String kioskId) {
super(service, urlIdHandler, kioskId);
}
@ -59,12 +58,6 @@ public class YoutubeTrendingExtractor extends KioskExtractor {
doc = Jsoup.parse(pageContent, url);
}
@Nonnull
@Override
public UrlIdHandler getUrlIdHandler() {
return new YoutubeTrendingUrlIdHandler();
}
@Override
public String getNextPageUrl() {
return "";

View File

@ -1,14 +1,16 @@
package org.schabi.newpipe.extractor.services.youtube.urlIdHandlers;
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.utils.Parser;
import java.util.List;
/*
* Created by Christian Schabesberger on 25.07.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* YoutubeChannelUrlIdHandler.java is part of NewPipe.
* Copyright (C) Christian Schabesberger 2018 <chrźis.schabesberger@mailbox.org>
* YoutubeChannelLinkHandlerFactory.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -24,22 +26,22 @@ import org.schabi.newpipe.extractor.utils.Parser;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class YoutubeChannelUrlIdHandler extends ListUrlIdHandler {
public class YoutubeChannelLinkHandlerFactory extends ListLinkHandlerFactory {
private static final YoutubeChannelUrlIdHandler instance = new YoutubeChannelUrlIdHandler();
private static final YoutubeChannelLinkHandlerFactory instance = new YoutubeChannelLinkHandlerFactory();
private static final String ID_PATTERN = "/(user/[A-Za-z0-9_-]*|channel/[A-Za-z0-9_-]*)";
public static YoutubeChannelUrlIdHandler getInstance() {
public static YoutubeChannelLinkHandlerFactory getInstance() {
return instance;
}
@Override
public String onGetIdFromUrl(String url) throws ParsingException {
public String getId(String url) throws ParsingException {
return Parser.matchGroup1(ID_PATTERN, url);
}
@Override
public String getUrl() {
public String getUrl(String id, List<String> contentFilters, String searchFilter) {
return "https://www.youtube.com/" + id;
}

View File

@ -1,4 +1,4 @@
package org.schabi.newpipe.extractor.services.youtube.urlIdHandlers;
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
@ -30,11 +30,17 @@ public class YoutubeParsingHelper {
public static long parseDurationString(String input)
throws ParsingException, NumberFormatException {
String[] splitInput = input.split(":");
// If time separator : is not detected, try . instead
final String[] splitInput = input.contains(":")
? input.split(":")
: input.split("\\.");
String days = "0";
String hours = "0";
String minutes = "0";
String seconds;
final String seconds;
switch (splitInput.length) {
case 4:

View File

@ -1,26 +1,28 @@
package org.schabi.newpipe.extractor.services.youtube.urlIdHandlers;
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.utils.Parser;
public class YoutubePlaylistUrlIdHandler extends ListUrlIdHandler {
import java.util.List;
private static final YoutubePlaylistUrlIdHandler instance = new YoutubePlaylistUrlIdHandler();
public class YoutubePlaylistLinkHandlerFactory extends ListLinkHandlerFactory {
private static final YoutubePlaylistLinkHandlerFactory instance = new YoutubePlaylistLinkHandlerFactory();
private static final String ID_PATTERN = "([\\-a-zA-Z0-9_]{10,})";
public static YoutubePlaylistUrlIdHandler getInstance() {
public static YoutubePlaylistLinkHandlerFactory getInstance() {
return instance;
}
@Override
public String getUrl() {
public String getUrl(String id, List<String> contentFilters, String sortFilter) {
return "https://www.youtube.com/playlist?list=" + id;
}
@Override
public String onGetIdFromUrl(String url) throws ParsingException {
public String getId(String url) throws ParsingException {
try {
return Parser.matchGroup1("list=" + ID_PATTERN, url);
} catch (final Exception exception) {

View File

@ -0,0 +1,53 @@
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
public class YoutubeSearchQueryHandlerFactory extends SearchQueryHandlerFactory {
public static final String CHARSET_UTF_8 = "UTF-8";
public static final String VIDEOS = "videos";
public static final String CHANNELS = "channels";
public static final String PLAYLISTS = "playlists";
public static final String ALL = "all";
public static YoutubeSearchQueryHandlerFactory getInstance() {
return new YoutubeSearchQueryHandlerFactory();
}
@Override
public String getUrl(String searchString, List<String> contentFilters, String sortFilter) throws ParsingException {
try {
final String url = "https://www.youtube.com/results"
+ "?q=" + URLEncoder.encode(searchString, CHARSET_UTF_8);
if(contentFilters.size() > 0) {
switch (contentFilters.get(0)) {
case VIDEOS: return url + "&sp=EgIQAVAU";
case CHANNELS: return url + "&sp=EgIQAlAU";
case PLAYLISTS: return url + "&sp=EgIQA1AU";
case ALL:
default:
}
}
return url;
} catch (UnsupportedEncodingException e) {
throw new ParsingException("Could not encode query", e);
}
}
@Override
public String[] getAvailableContentFilter() {
return new String[] {
ALL,
VIDEOS,
CHANNELS,
PLAYLISTS};
}
}

View File

@ -0,0 +1,133 @@
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.utils.Parser;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
/*
* Created by Christian Schabesberger on 02.02.16.
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeStreamLinkHandlerFactory.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class YoutubeStreamLinkHandlerFactory extends LinkHandlerFactory {
private static final YoutubeStreamLinkHandlerFactory instance = new YoutubeStreamLinkHandlerFactory();
private static final String ID_PATTERN = "([\\-a-zA-Z0-9_]{11})";
private YoutubeStreamLinkHandlerFactory() {
}
public static YoutubeStreamLinkHandlerFactory getInstance() {
return instance;
}
@Override
public String getUrl(String id) {
return "https://www.youtube.com/watch?v=" + id;
}
@Override
public String getId(String url) throws ParsingException, IllegalArgumentException {
if (url.isEmpty()) {
throw new IllegalArgumentException("The url parameter should not be empty");
}
String lowercaseUrl = url.toLowerCase();
if (lowercaseUrl.contains("youtube")) {
if (lowercaseUrl.contains("list=")) {
throw new ParsingException("Error no suitable url: " + url);
}
if (url.contains("attribution_link")) {
try {
String escapedQuery = Parser.matchGroup1("u=(.[^&|$]*)", url);
String query = URLDecoder.decode(escapedQuery, "UTF-8");
return Parser.matchGroup1("v=" + ID_PATTERN, query);
} catch (UnsupportedEncodingException uee) {
throw new ParsingException("Could not parse attribution_link", uee);
}
}
if (url.contains("vnd.youtube")) {
return Parser.matchGroup1(ID_PATTERN, url);
}
if (url.contains("embed")) {
return Parser.matchGroup1("embed/" + ID_PATTERN, url);
}
if (url.contains("googleads")) {
throw new FoundAdException("Error found add: " + url);
}
return Parser.matchGroup1("[?&]v=" + ID_PATTERN, url);
}
if (lowercaseUrl.contains("youtu.be")) {
if (lowercaseUrl.contains("list=")) {
throw new ParsingException("Error no suitable url: " + url);
}
if (url.contains("v=")) {
return Parser.matchGroup1("v=" + ID_PATTERN, url);
}
return Parser.matchGroup1("[Yy][Oo][Uu][Tt][Uu]\\.[Bb][Ee]/" + ID_PATTERN, url);
}
if (lowercaseUrl.contains("hooktube")) {
if (lowercaseUrl.contains("&v=")
|| lowercaseUrl.contains("?v=")) {
return Parser.matchGroup1("[?&]v=" + ID_PATTERN, url);
}
if (url.contains("/embed/")) {
return Parser.matchGroup1("embed/" + ID_PATTERN, url);
}
if (url.contains("/v/")) {
return Parser.matchGroup1("v/" + ID_PATTERN, url);
}
if (url.contains("/watch/")) {
return Parser.matchGroup1("watch/" + ID_PATTERN, url);
}
}
throw new ParsingException("Error no suitable url: " + url);
}
@Override
public boolean onAcceptUrl(final String url) throws FoundAdException {
final String lowercaseUrl = url.toLowerCase();
if (!lowercaseUrl.contains("youtube") &&
!lowercaseUrl.contains("youtu.be") &&
!lowercaseUrl.contains("hooktube")) {
return false;
// bad programming I know <-- nice meme
}
try {
getId(url);
return true;
} catch (FoundAdException fe) {
throw fe;
} catch (ParsingException e) {
return false;
}
}
}

View File

@ -1,10 +1,10 @@
package org.schabi.newpipe.extractor.services.youtube.urlIdHandlers;
package org.schabi.newpipe.extractor.services.youtube.linkHandler;
/*
* Created by Christian Schabesberger on 12.08.17.
*
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
* YoutubeTrendingUrlIdHandler.java is part of NewPipe.
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeTrendingLinkHandlerFactory.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,19 +20,19 @@ package org.schabi.newpipe.extractor.services.youtube.urlIdHandlers;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
import org.schabi.newpipe.extractor.ListUrlIdHandler;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.utils.Parser;
public class YoutubeTrendingUrlIdHandler extends ListUrlIdHandler {
import java.util.List;
public String getUrl() {
public class YoutubeTrendingLinkHandlerFactory extends ListLinkHandlerFactory {
public String getUrl(String id, List<String> contentFilters, String sortFilter) {
return "https://www.youtube.com/feed/trending";
}
@Override
public String onGetIdFromUrl(String url) {
public String getId(String url) {
return "Trending";
}

View File

@ -1,186 +0,0 @@
package org.schabi.newpipe.extractor.services.youtube.urlIdHandlers;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.utils.Parser;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
/*
* Created by Christian Schabesberger on 02.02.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* YoutubeStreamUrlIdHandler.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class YoutubeStreamUrlIdHandler extends UrlIdHandler {
private static final YoutubeStreamUrlIdHandler instance = new YoutubeStreamUrlIdHandler();
private static final String ID_PATTERN = "([\\-a-zA-Z0-9_]{11})";
private YoutubeStreamUrlIdHandler() {
}
public static YoutubeStreamUrlIdHandler getInstance() {
return instance;
}
@Override
public String getUrl() {
return "https://www.youtube.com/watch?v=" + id;
}
@Override
public String onGetIdFromUrl(String url) throws ParsingException, IllegalArgumentException {
if (url.isEmpty()) {
throw new IllegalArgumentException("The url parameter should not be empty");
}
String id;
String lowercaseUrl = url.toLowerCase();
if (lowercaseUrl.contains("youtube")) {
if (url.contains("attribution_link")) {
try {
String escapedQuery = Parser.matchGroup1("u=(.[^&|$]*)", url);
String query = URLDecoder.decode(escapedQuery, "UTF-8");
id = Parser.matchGroup1("v=" + ID_PATTERN, query);
} catch (UnsupportedEncodingException uee) {
throw new ParsingException("Could not parse attribution_link", uee);
}
} else if (lowercaseUrl.contains("youtube.com/shared?ci=")) {
return getRealIdFromSharedLink(url);
} else if (url.contains("vnd.youtube")) {
id = Parser.matchGroup1(ID_PATTERN, url);
} else if (url.contains("embed")) {
id = Parser.matchGroup1("embed/" + ID_PATTERN, url);
} else if (url.contains("googleads")) {
throw new FoundAdException("Error found add: " + url);
} else {
id = Parser.matchGroup1("[?&]v=" + ID_PATTERN, url);
}
} else if (lowercaseUrl.contains("youtu.be")) {
if (url.contains("v=")) {
id = Parser.matchGroup1("v=" + ID_PATTERN, url);
} else {
id = Parser.matchGroup1("[Yy][Oo][Uu][Tt][Uu]\\.[Bb][Ee]/" + ID_PATTERN, url);
}
} else if(lowercaseUrl.contains("hooktube")) {
if(lowercaseUrl.contains("&v=")
|| lowercaseUrl.contains("?v=")) {
id = Parser.matchGroup1("[?&]v=" + ID_PATTERN, url);
} else if (url.contains("/embed/")) {
id = Parser.matchGroup1("embed/" + ID_PATTERN, url);
} else if (url.contains("/v/")) {
id = Parser.matchGroup1("v/" + ID_PATTERN, url);
} else if (url.contains("/watch/")) {
id = Parser.matchGroup1("watch/" + ID_PATTERN, url);
} else {
throw new ParsingException("Error no suitable url: " + url);
}
} else {
throw new ParsingException("Error no suitable url: " + url);
}
if (!id.isEmpty()) {
return id;
} else {
throw new ParsingException("Error could not parse url: " + url);
}
}
/**
* Get the real url from a shared uri.
* <p>
* Shared URI's look like this:
* <pre>
* * https://www.youtube.com/shared?ci=PJICrTByb3E
* * vnd.youtube://www.youtube.com/shared?ci=PJICrTByb3E&amp;feature=twitter-deep-link
* </pre>
*
* @param url The shared url
* @return the id of the stream
* @throws ParsingException
*/
private String getRealIdFromSharedLink(String url) throws ParsingException {
URI uri;
try {
uri = new URI(url);
} catch (URISyntaxException e) {
throw new ParsingException("Invalid shared link", e);
}
String sharedId = getSharedId(uri);
Downloader downloader = NewPipe.getDownloader();
String content;
try {
content = downloader.download("https://www.youtube.com/shared?ci=" + sharedId);
} catch (IOException | ReCaptchaException e) {
throw new ParsingException("Unable to resolve shared link", e);
}
Document document = Jsoup.parse(content);
String urlWithRealId;
Element element = document.select("link[rel=\"canonical\"]").first();
if (element != null) {
urlWithRealId = element.attr("abs:href");
} else {
urlWithRealId = document.select("meta[property=\"og:url\"]").first()
.attr("abs:content");
}
String realId = Parser.matchGroup1(ID_PATTERN, urlWithRealId);
if (sharedId.equals(realId)) {
throw new ParsingException("Got same id for as shared info_id: " + sharedId);
}
return realId;
}
private String getSharedId(URI uri) throws ParsingException {
if (!"/shared".equals(uri.getPath())) {
throw new ParsingException("Not a shared link: " + uri.toString() + " (path != " + uri.getPath() + ")");
}
return Parser.matchGroup1("ci=" + ID_PATTERN, uri.getQuery());
}
@Override
public boolean onAcceptUrl(final String url) {
final String lowercaseUrl = url.toLowerCase();
if (lowercaseUrl.contains("youtube")
|| lowercaseUrl.contains("youtu.be")
|| lowercaseUrl.contains("hooktube")) {
// bad programming I know
try {
onGetIdFromUrl(url);
return true;
} catch (Exception e) {
return false;
}
} else {
return false;
}
}
}

View File

@ -23,9 +23,10 @@ package org.schabi.newpipe.extractor.stream;
import org.schabi.newpipe.extractor.Extractor;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.Subtitles;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
import org.schabi.newpipe.extractor.utils.Parser;
import javax.annotation.Nonnull;
@ -39,14 +40,8 @@ public abstract class StreamExtractor extends Extractor {
public static final int NO_AGE_LIMIT = 0;
public StreamExtractor(StreamingService service, UrlIdHandler urlIdHandler) {
super(service, urlIdHandler);
}
@Nonnull
@Override
protected UrlIdHandler getUrlIdHandler() {
return getService().getStreamUrlIdHandler();
public StreamExtractor(StreamingService service, LinkHandler linkHandler) {
super(service, linkHandler);
}
@Nonnull
@ -141,9 +136,6 @@ public abstract class StreamExtractor extends Extractor {
public abstract StreamInfoItem getNextVideo() throws IOException, ExtractionException;
public abstract StreamInfoItemsCollector getRelatedVideos() throws IOException, ExtractionException;
public abstract String[] getDonationLinks() throws ExtractionException;
public abstract String[] getAffiliateLinks() throws ExtractionException;
/**
* Analyses the webpage's document and extracts any error message there might be.
*

View File

@ -147,7 +147,10 @@ public class StreamInfo extends Info {
Exception dashMpdError = null;
if (streamInfo.getDashMpdUrl() != null && !streamInfo.getDashMpdUrl().isEmpty()) {
try {
DashMpdParser.getStreams(streamInfo);
DashMpdParser.ParserResult result = DashMpdParser.getStreams(streamInfo);
streamInfo.getVideoOnlyStreams().addAll(result.getVideoOnlyStreams());
streamInfo.getAudioStreams().addAll(result.getAudioStreams());
streamInfo.getVideoStreams().addAll(result.getVideoStreams());
} catch (Exception e) {
// Sometimes we receive 403 (forbidden) error when trying to download the manifest (similar to what happens with youtube-dl),
// just skip the exception (but store it somewhere), as we later check if we have streams anyway.
@ -242,16 +245,6 @@ public class StreamInfo extends Info {
} catch (Exception e) {
streamInfo.addError(e);
}
try {
streamInfo.setAffiliateLinks(extractor.getAffiliateLinks());
} catch (Exception e) {
streamInfo.addError(e);
}
try {
streamInfo.setDonationLinks(extractor.getDonationLinks());
} catch (Exception e) {
streamInfo.addError(e);
}
streamInfo.setRelatedStreams(ExtractorHelper.getRelatedVideosOrLogError(streamInfo, extractor));
return streamInfo;
@ -284,9 +277,6 @@ public class StreamInfo extends Info {
private long startPosition = 0;
private List<SubtitlesStream> subtitles;
private String[] donationLinks;
private String[] affiliateLinks;
/**
* Get the stream type
*
@ -480,19 +470,4 @@ public class StreamInfo extends Info {
this.subtitles = subtitles;
}
public String[] getDonationLinks() {
return donationLinks;
}
public void setDonationLinks(String[] donationLinks) {
this.donationLinks = donationLinks;
}
public String[] getAffiliateLinks() {
return affiliateLinks;
}
public void setAffiliateLinks(String[] affiliateLinks) {
this.affiliateLinks = affiliateLinks;
}
}

View File

@ -12,6 +12,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
@ -19,6 +20,8 @@ import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/*
* Created by Christian Schabesberger on 02.02.16.
@ -51,6 +54,30 @@ public class DashMpdParser {
}
}
public static class ParserResult {
private final List<VideoStream> videoStreams;
private final List<AudioStream> audioStreams;
private final List<VideoStream> videoOnlyStreams;
public ParserResult(List<VideoStream> videoStreams, List<AudioStream> audioStreams, List<VideoStream> videoOnlyStreams) {
this.videoStreams = videoStreams;
this.audioStreams = audioStreams;
this.videoOnlyStreams = videoOnlyStreams;
}
public List<VideoStream> getVideoStreams() {
return videoStreams;
}
public List<AudioStream> getAudioStreams() {
return audioStreams;
}
public List<VideoStream> getVideoOnlyStreams() {
return videoOnlyStreams;
}
}
/**
* Will try to download (using {@link StreamInfo#dashMpdUrl}) and parse the dash manifest,
* then it will search for any stream that the ItagItem has (by the id).
@ -58,9 +85,12 @@ public class DashMpdParser {
* It has video, video only and audio streams and will only add to the list if it don't
* find a similar stream in the respective lists (calling {@link Stream#equalStats}).
*
* Info about dash MPD can be found here
* @see <a href="https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html">www.brendanlog.com</a>
*
* @param streamInfo where the parsed streams will be added
*/
public static void getStreams(StreamInfo streamInfo) throws DashMpdParsingException, ReCaptchaException {
public static ParserResult getStreams(final StreamInfo streamInfo) throws DashMpdParsingException, ReCaptchaException {
String dashDoc;
Downloader downloader = NewPipe.getDownloader();
try {
@ -72,45 +102,58 @@ public class DashMpdParser {
}
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(dashDoc.getBytes());
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final InputStream stream = new ByteArrayInputStream(dashDoc.getBytes());
Document doc = builder.parse(stream);
NodeList representationList = doc.getElementsByTagName("Representation");
final Document doc = builder.parse(stream);
final NodeList representationList = doc.getElementsByTagName("Representation");
final List<VideoStream> videoStreams = new ArrayList<>();
final List<AudioStream> audioStreams = new ArrayList<>();
final List<VideoStream> videoOnlyStreams = new ArrayList<>();
for (int i = 0; i < representationList.getLength(); i++) {
Element representation = ((Element) representationList.item(i));
final Element representation = (Element) representationList.item(i);
try {
String mimeType = ((Element) representation.getParentNode()).getAttribute("mimeType");
String id = representation.getAttribute("id");
String url = representation.getElementsByTagName("BaseURL").item(0).getTextContent();
ItagItem itag = ItagItem.getItag(Integer.parseInt(id));
if (itag != null) {
MediaFormat mediaFormat = MediaFormat.getFromMimeType(mimeType);
final String mimeType = ((Element) representation.getParentNode()).getAttribute("mimeType");
final String id = representation.getAttribute("id");
final String url = representation.getElementsByTagName("BaseURL").item(0).getTextContent();
final ItagItem itag = ItagItem.getItag(Integer.parseInt(id));
final Node segmentationList = representation.getElementsByTagName("SegmentList").item(0);
// if SegmentList is not null this means that BaseUrl is not representing the url to the stream.
// instead we need to add the "media=" value from the <SegementURL/> tags inside the <SegmentList/>
// tag in order to get a full working url. However each of these is just pointing to a part of the
// video, so we can not return a URL with a working stream here.
// We decided not to ignore such streams for the moment.
if (itag != null && segmentationList == null) {
final MediaFormat mediaFormat = MediaFormat.getFromMimeType(mimeType);
if (itag.itagType.equals(ItagItem.ItagType.AUDIO)) {
AudioStream audioStream = new AudioStream(url, mediaFormat, itag.avgBitrate);
final AudioStream audioStream = new AudioStream(url, mediaFormat, itag.avgBitrate);
if (!Stream.containSimilarStream(audioStream, streamInfo.getAudioStreams())) {
streamInfo.getAudioStreams().add(audioStream);
audioStreams.add(audioStream);
}
} else {
boolean isVideoOnly = itag.itagType.equals(ItagItem.ItagType.VIDEO_ONLY);
VideoStream videoStream = new VideoStream(url, mediaFormat, itag.resolutionString, isVideoOnly);
final VideoStream videoStream = new VideoStream(url, mediaFormat, itag.resolutionString, isVideoOnly);
if (isVideoOnly) {
if (!Stream.containSimilarStream(videoStream, streamInfo.getVideoOnlyStreams())) {
streamInfo.getVideoOnlyStreams().add(videoStream);
videoOnlyStreams.add(videoStream);
}
} else if (!Stream.containSimilarStream(videoStream, streamInfo.getVideoStreams())) {
streamInfo.getVideoStreams().add(videoStream);
videoStreams.add(videoStream);
}
}
}
} catch (Exception ignored) {
}
}
return new ParserResult(videoStreams, audioStreams, videoOnlyStreams);
} catch (Exception e) {
throw new DashMpdParsingException("Could not parse Dash mpd", e);
}

View File

@ -6,7 +6,6 @@ import java.util.HashSet;
import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.NewPipe.getServiceByUrl;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
public class NewPipeTest {
@ -28,17 +27,11 @@ public class NewPipeTest {
@Test
public void getServiceWithId() throws Exception {
assertEquals(NewPipe.getService(YouTube.getServiceId()), YouTube);
assertEquals(NewPipe.getService(SoundCloud.getServiceId()), SoundCloud);
assertNotEquals(NewPipe.getService(SoundCloud.getServiceId()), YouTube);
}
@Test
public void getServiceWithName() throws Exception {
assertEquals(NewPipe.getService(YouTube.getServiceInfo().getName()), YouTube);
assertEquals(NewPipe.getService(SoundCloud.getServiceInfo().getName()), SoundCloud);
assertNotEquals(NewPipe.getService(YouTube.getServiceInfo().getName()), SoundCloud);
}
@Test
@ -46,27 +39,17 @@ public class NewPipeTest {
assertEquals(getServiceByUrl("https://www.youtube.com/watch?v=_r6CgaFNAGg"), YouTube);
assertEquals(getServiceByUrl("https://www.youtube.com/channel/UCi2bIyFtz-JdI-ou8kaqsqg"), YouTube);
assertEquals(getServiceByUrl("https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZiZxtDDRCi6uhfTH4FilpH"), YouTube);
assertEquals(getServiceByUrl("https://soundcloud.com/shupemoosic/pegboard-nerds-try-this"), SoundCloud);
assertEquals(getServiceByUrl("https://soundcloud.com/deluxe314/sets/pegboard-nerds"), SoundCloud);
assertEquals(getServiceByUrl("https://soundcloud.com/pegboardnerds"), SoundCloud);
assertNotEquals(getServiceByUrl("https://soundcloud.com/pegboardnerds"), YouTube);
assertNotEquals(getServiceByUrl("https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZiZxtDDRCi6uhfTH4FilpH"), SoundCloud);
}
@Test
public void getIdWithServiceName() throws Exception {
assertEquals(NewPipe.getIdOfService(YouTube.getServiceInfo().getName()), YouTube.getServiceId());
assertEquals(NewPipe.getIdOfService(SoundCloud.getServiceInfo().getName()), SoundCloud.getServiceId());
assertNotEquals(NewPipe.getIdOfService(SoundCloud.getServiceInfo().getName()), YouTube.getServiceId());
}
@Test
public void getServiceNameWithId() throws Exception {
assertEquals(NewPipe.getNameOfService(YouTube.getServiceId()), YouTube.getServiceInfo().getName());
assertEquals(NewPipe.getNameOfService(SoundCloud.getServiceId()), SoundCloud.getServiceInfo().getName());
assertNotEquals(NewPipe.getNameOfService(YouTube.getServiceId()), SoundCloud.getServiceInfo().getName());
}
}

View File

@ -1,57 +0,0 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.junit.Test;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
import org.schabi.newpipe.extractor.search.SearchResult;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.StreamType;
import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
public abstract class BaseSoundcloudSearchTest {
protected static SearchResult result;
@Test
public void testResultList() {
assertFalse("Got empty result list", result.resultList.isEmpty());
for(InfoItem infoItem: result.resultList) {
assertIsSecureUrl(infoItem.getUrl());
assertIsSecureUrl(infoItem.getThumbnailUrl());
assertFalse(infoItem.getName().isEmpty());
assertFalse("Name is probably a URI: " + infoItem.getName(),
infoItem.getName().contains("://"));
if(infoItem instanceof StreamInfoItem) {
// test stream item
StreamInfoItem streamInfoItem = (StreamInfoItem) infoItem;
assertIsSecureUrl(streamInfoItem.getUploaderUrl());
assertFalse(streamInfoItem.getUploadDate().isEmpty());
assertFalse(streamInfoItem.getUploaderName().isEmpty());
assertEquals(StreamType.AUDIO_STREAM, streamInfoItem.getStreamType());
} else if(infoItem instanceof ChannelInfoItem) {
// Nothing special to check?
} else if(infoItem instanceof PlaylistInfoItem) {
// test playlist item
assertTrue(infoItem.getUrl().contains("/sets/"));
long streamCount = ((PlaylistInfoItem) infoItem).getStreamCount();
assertTrue(streamCount > 0);
} else {
fail("Unknown infoItem type: " + infoItem);
}
}
}
@Test
public void testResultErrors() {
assertNotNull(result.errors);
if (!result.errors.isEmpty()) {
for (Throwable error : result.errors) {
error.printStackTrace();
}
}
assertTrue(result.errors.isEmpty());
}
}

View File

@ -15,7 +15,7 @@ import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
/**
* Test for {@link SoundcloudChartsUrlIdHandler}
* Test for {@link SoundcloudChartsLinkHandlerFactory}
*/
public class SoundcloudChartsExtractorTest {

View File

@ -11,27 +11,27 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Test for {@link SoundcloudChartsUrlIdHandler}
* Test for {@link SoundcloudChartsLinkHandlerFactory}
*/
public class SoundcloudChartsUrlIdHandlerTest {
private static SoundcloudChartsUrlIdHandler urlIdHandler;
public class SoundcloudChartsLinkHandlerFactoryTest {
private static SoundcloudChartsLinkHandlerFactory urlIdHandler;
@BeforeClass
public static void setUp() throws Exception {
urlIdHandler = new SoundcloudChartsUrlIdHandler();
urlIdHandler = new SoundcloudChartsLinkHandlerFactory();
NewPipe.init(Downloader.getInstance());
}
@Test
public void getUrl() throws Exception {
assertEquals(urlIdHandler.setId("Top 50").getUrl(), "https://soundcloud.com/charts/top");
assertEquals(urlIdHandler.setId("New & hot").getUrl(), "https://soundcloud.com/charts/new");
assertEquals(urlIdHandler.fromId("Top 50").getUrl(), "https://soundcloud.com/charts/top");
assertEquals(urlIdHandler.fromId("New & hot").getUrl(), "https://soundcloud.com/charts/new");
}
@Test
public void getId() throws ParsingException {
assertEquals(urlIdHandler.setUrl("http://soundcloud.com/charts/top?genre=all-music").getId(), "Top 50");
assertEquals(urlIdHandler.setUrl("HTTP://www.soundcloud.com/charts/new/?genre=all-music&country=all-countries").getId(), "New & hot");
assertEquals(urlIdHandler.fromUrl("http://soundcloud.com/charts/top?genre=all-music").getId(), "Top 50");
assertEquals(urlIdHandler.fromUrl("HTTP://www.soundcloud.com/charts/new/?genre=all-music&country=all-countries").getId(), "New & hot");
}
@Test

View File

@ -1,35 +0,0 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.search.SearchEngine;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
/**
* Test for {@link SearchEngine}
*/
public class SoundcloudSearchEngineAllTest extends BaseSoundcloudSearchTest {
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
SearchEngine engine = SoundCloud.getSearchEngine();
// SoundCloud will suggest "lil uzi vert" instead of "lill uzi vert"
// keep in mind that the suggestions can NOT change by country (the parameter "de")
result = engine.search("lill uzi vert", 0, "de", SearchEngine.Filter.ANY)
.getSearchResult();
}
@Ignore
@Test
public void testSuggestion() {
//todo write a real test
assertTrue(result.suggestion != null);
}
}

View File

@ -1,44 +0,0 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.search.SearchEngine;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
/**
* Test for {@link SearchEngine}
*/
public class SoundcloudSearchEngineChannelTest extends BaseSoundcloudSearchTest {
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
SearchEngine engine = SoundCloud.getSearchEngine();
// SoundCloud will suggest "lil uzi vert" instead of "lill uzi vert"
// keep in mind that the suggestions can NOT change by country (the parameter "de")
result = engine.search("lill uzi vert", 0, "de", SearchEngine.Filter.CHANNEL)
.getSearchResult();
}
@Test
public void testResultsItemType() {
for (InfoItem infoItem : result.resultList) {
assertEquals(InfoItem.InfoType.CHANNEL, infoItem.getInfoType());
}
}
@Ignore
@Test
public void testSuggestion() {
//todo write a real test
assertTrue(result.suggestion != null);
}
}

View File

@ -1,64 +0,0 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.search.SearchEngine;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
/*
* Created by Christian Schabesberger on 29.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngineStreamTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link SearchEngine}
*/
public class SoundcloudSearchEnginePlaylistTest extends BaseSoundcloudSearchTest {
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
SearchEngine engine = SoundCloud.getSearchEngine();
// Search by country not yet implemented
result = engine.search("parkmemme", 0, "", SearchEngine.Filter.PLAYLIST)
.getSearchResult();
}
@Test
public void testUserItemType() {
for (InfoItem infoItem : result.resultList) {
assertEquals(InfoItem.InfoType.PLAYLIST, infoItem.getInfoType());
}
}
@Ignore
@Test
public void testSuggestion() {
//todo write a real test
assertTrue(result.suggestion != null);
}
}

View File

@ -1,44 +0,0 @@
package org.schabi.newpipe.extractor.services.soundcloud;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.search.SearchEngine;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
/**
* Test for {@link SearchEngine}
*/
public class SoundcloudSearchEngineStreamTest extends BaseSoundcloudSearchTest {
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
SearchEngine engine = SoundCloud.getSearchEngine();
// SoundCloud will suggest "lil uzi vert" instead of "lill uzi vert",
// keep in mind that the suggestions can NOT change by country (the parameter "de")
result = engine.search("lill uzi vert", 0, "de", SearchEngine.Filter.STREAM)
.getSearchResult();
}
@Test
public void testResultsItemType() {
for (InfoItem infoItem : result.resultList) {
assertEquals(InfoItem.InfoType.STREAM, infoItem.getInfoType());
}
}
@Ignore
@Test
public void testSuggestion() {
//todo write a real test
assertTrue(result.suggestion != null);
}
}

View File

@ -12,20 +12,20 @@ import java.util.List;
import static org.junit.Assert.*;
/**
* Test for {@link SoundcloudStreamUrlIdHandler}
* Test for {@link SoundcloudStreamLinkHandlerFactory}
*/
public class SoundcloudStreamUrlIdHandlerTest {
private static SoundcloudStreamUrlIdHandler urlIdHandler;
public class SoundcloudStreamLinkHandlerFactoryTest {
private static SoundcloudStreamLinkHandlerFactory urlIdHandler;
@BeforeClass
public static void setUp() throws Exception {
urlIdHandler = SoundcloudStreamUrlIdHandler.getInstance();
urlIdHandler = SoundcloudStreamLinkHandlerFactory.getInstance();
NewPipe.init(Downloader.getInstance());
}
@Test(expected = IllegalArgumentException.class)
public void getIdWithNullAsUrl() throws ParsingException {
urlIdHandler.setUrl(null).getId();
urlIdHandler.fromUrl(null).getId();
}
@Test
@ -37,7 +37,7 @@ public class SoundcloudStreamUrlIdHandlerTest {
for (String invalidUrl : invalidUrls) {
Throwable exception = null;
try {
urlIdHandler.setUrl(invalidUrl).getId();
urlIdHandler.fromUrl(invalidUrl).getId();
} catch (ParsingException e) {
exception = e;
}
@ -49,16 +49,16 @@ public class SoundcloudStreamUrlIdHandlerTest {
@Test
public void getId() throws Exception {
assertEquals("309689103", urlIdHandler.setUrl("https://soundcloud.com/liluzivert/15-ysl").getId());
assertEquals("309689082", urlIdHandler.setUrl("https://www.soundcloud.com/liluzivert/15-luv-scars-ko").getId());
assertEquals("309689035", urlIdHandler.setUrl("http://soundcloud.com/liluzivert/15-boring-shit").getId());
assertEquals("294488599", urlIdHandler.setUrl("http://www.soundcloud.com/liluzivert/secure-the-bag-produced-by-glohan-beats").getId());
assertEquals("294488438", urlIdHandler.setUrl("HtTpS://sOuNdClOuD.cOm/LiLuZiVeRt/In-O4-pRoDuCeD-bY-dP-bEaTz").getId());
assertEquals("294488147", urlIdHandler.setUrl("https://soundcloud.com/liluzivert/fresh-produced-by-zaytoven#t=69").getId());
assertEquals("294487876", urlIdHandler.setUrl("https://soundcloud.com/liluzivert/threesome-produced-by-zaytoven#t=1:09").getId());
assertEquals("294487684", urlIdHandler.setUrl("https://soundcloud.com/liluzivert/blonde-brigitte-produced-manny-fresh#t=1:9").getId());
assertEquals("294487428", urlIdHandler.setUrl("https://soundcloud.com/liluzivert/today-produced-by-c-note#t=1m9s").getId());
assertEquals("294487157", urlIdHandler.setUrl("https://soundcloud.com/liluzivert/changed-my-phone-produced-by-c-note#t=1m09s").getId());
assertEquals("309689103", urlIdHandler.fromUrl("https://soundcloud.com/liluzivert/15-ysl").getId());
assertEquals("309689082", urlIdHandler.fromUrl("https://www.soundcloud.com/liluzivert/15-luv-scars-ko").getId());
assertEquals("309689035", urlIdHandler.fromUrl("http://soundcloud.com/liluzivert/15-boring-shit").getId());
assertEquals("294488599", urlIdHandler.fromUrl("http://www.soundcloud.com/liluzivert/secure-the-bag-produced-by-glohan-beats").getId());
assertEquals("294488438", urlIdHandler.fromUrl("HtTpS://sOuNdClOuD.cOm/LiLuZiVeRt/In-O4-pRoDuCeD-bY-dP-bEaTz").getId());
assertEquals("294488147", urlIdHandler.fromUrl("https://soundcloud.com/liluzivert/fresh-produced-by-zaytoven#t=69").getId());
assertEquals("294487876", urlIdHandler.fromUrl("https://soundcloud.com/liluzivert/threesome-produced-by-zaytoven#t=1:09").getId());
assertEquals("294487684", urlIdHandler.fromUrl("https://soundcloud.com/liluzivert/blonde-brigitte-produced-manny-fresh#t=1:9").getId());
assertEquals("294487428", urlIdHandler.fromUrl("https://soundcloud.com/liluzivert/today-produced-by-c-note#t=1m9s").getId());
assertEquals("294487157", urlIdHandler.fromUrl("https://soundcloud.com/liluzivert/changed-my-phone-produced-by-c-note#t=1m09s").getId());
}

View File

@ -5,7 +5,7 @@ import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
@ -21,13 +21,13 @@ import static org.junit.Assert.*;
*/
public class SoundcloudSubscriptionExtractorTest {
private static SoundcloudSubscriptionExtractor subscriptionExtractor;
private static UrlIdHandler urlHandler;
private static LinkHandlerFactory urlHandler;
@BeforeClass
public static void setupClass() {
NewPipe.init(Downloader.getInstance());
subscriptionExtractor = new SoundcloudSubscriptionExtractor(ServiceList.SoundCloud);
urlHandler = ServiceList.SoundCloud.getChannelUrlIdHandler();
urlHandler = ServiceList.SoundCloud.getChannelLHFactory();
}
@Test

View File

@ -0,0 +1,55 @@
package org.schabi.newpipe.extractor.services.soundcloud.search;
import org.junit.Test;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchExtractor;
import static org.junit.Assert.assertTrue;
/*
* Created by Christian Schabesberger on 17.06.18
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* SoundcloudSearchExtractorBaseTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link SoundcloudSearchExtractor}
*/
public abstract class SoundcloudSearchExtractorBaseTest {
protected static SoundcloudSearchExtractor extractor;
protected static ListExtractor.InfoItemsPage<InfoItem> itemsPage;
protected static String removeClientId(String url) {
String[] splitUrl = url.split("client_id=[a-zA-Z0-9]*&");
return splitUrl[0] + splitUrl[1];
}
@Test
public void testResultListElementsLength() {
assertTrue(Integer.toString(itemsPage.getItems().size()),
itemsPage.getItems().size() >= 3);
}
@Test
public void testUrl() throws Exception {
assertTrue(extractor.getUrl(), extractor.getUrl().startsWith("https://api-v2.soundcloud.com/search"));
}
}

View File

@ -0,0 +1,65 @@
package org.schabi.newpipe.extractor.services.soundcloud.search;
import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchExtractor;
import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory;
import static java.util.Arrays.asList;
import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
public class SoundcloudSearchExtractorChannelOnlyTest extends SoundcloudSearchExtractorBaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (SoundcloudSearchExtractor) SoundCloud.getSearchExtractor("lill uzi vert",
asList(SoundcloudSearchQueryHandlerFactory.USERS), null, "de");
extractor.fetchPage();
itemsPage = extractor.getInitialPage();
}
@Test
public void testGetSecondPage() throws Exception {
SoundcloudSearchExtractor secondExtractor = (SoundcloudSearchExtractor) SoundCloud.getSearchExtractor("lill uzi vert",
asList(SoundcloudSearchQueryHandlerFactory.USERS), null, "de");
ListExtractor.InfoItemsPage<InfoItem> secondPage = secondExtractor.getPage(itemsPage.getNextPageUrl());
assertTrue(Integer.toString(secondPage.getItems().size()),
secondPage.getItems().size() >= 3);
// check if its the same result
boolean equals = true;
for (int i = 0; i < secondPage.getItems().size()
&& i < itemsPage.getItems().size(); i++) {
if(!secondPage.getItems().get(i).getUrl().equals(
itemsPage.getItems().get(i).getUrl())) {
equals = false;
}
}
assertFalse("First and second page are equal", equals);
assertEquals("https://api-v2.soundcloud.com/search/users?q=lill+uzi+vert&limit=10&offset=20",
removeClientId(secondPage.getNextPageUrl()));
}
@Test
public void testGetSecondPageUrl() throws Exception {
assertEquals("https://api-v2.soundcloud.com/search/users?q=lill+uzi+vert&limit=10&offset=10",
removeClientId(extractor.getNextPageUrl()));
}
@Test
public void testOnlyContainChannels() {
for(InfoItem item : itemsPage.getItems()) {
if(!(item instanceof ChannelInfoItem)) {
fail("The following item is no channel item: " + item.toString());
}
}
}
}

View File

@ -0,0 +1,109 @@
package org.schabi.newpipe.extractor.services.soundcloud.search;
import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchExtractor;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/*
* Created by Christian Schabesberger on 27.05.18
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeSearchExtractorStreamTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link YoutubeSearchExtractor}
*/
public class SoundcloudSearchExtractorDefaultTest extends SoundcloudSearchExtractorBaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (SoundcloudSearchExtractor) SoundCloud.getSearchExtractor("lill uzi vert", "de");
extractor.fetchPage();
itemsPage = extractor.getInitialPage();
}
@Test
public void testGetSecondPageUrl() throws Exception {
assertEquals("https://api-v2.soundcloud.com/search?q=lill+uzi+vert&limit=10&offset=10",
removeClientId(extractor.getNextPageUrl()));
}
@Test
public void testResultList_FirstElement() {
InfoItem firstInfoItem = itemsPage.getItems().get(0);
// THe channel should be the first item
assertEquals("name", "Bad and Boujee (Feat. Lil Uzi Vert) [Prod. By Metro Boomin]", firstInfoItem.getName());
assertEquals("url","https://soundcloud.com/migosatl/bad-and-boujee-feat-lil-uzi-vert-prod-by-metro-boomin", firstInfoItem.getUrl());
}
@Test
public void testResultListCheckIfContainsStreamItems() {
boolean hasStreams = false;
for(InfoItem item : itemsPage.getItems()) {
if(item instanceof StreamInfoItem) {
hasStreams = true;
}
}
assertTrue("Has no InfoItemStreams", hasStreams);
}
@Test
public void testGetSecondPage() throws Exception {
SoundcloudSearchExtractor secondExtractor = (SoundcloudSearchExtractor) SoundCloud.getSearchExtractor("lill uzi vert", "de");
ListExtractor.InfoItemsPage<InfoItem> secondPage = secondExtractor.getPage(itemsPage.getNextPageUrl());
assertTrue(Integer.toString(secondPage.getItems().size()),
secondPage.getItems().size() >= 10);
// check if its the same result
boolean equals = true;
for (int i = 0; i < secondPage.getItems().size()
&& i < itemsPage.getItems().size(); i++) {
if(!secondPage.getItems().get(i).getUrl().equals(
itemsPage.getItems().get(i).getUrl())) {
equals = false;
}
}
assertFalse("First and second page are equal", equals);
assertEquals("https://api-v2.soundcloud.com/search?q=lill+uzi+vert&limit=10&offset=20",
removeClientId(secondPage.getNextPageUrl()));
}
@Test
public void testId() throws Exception {
assertEquals("lill uzi vert", extractor.getId());
}
@Test
public void testName() {
assertEquals("lill uzi vert", extractor.getName());
}
}

View File

@ -0,0 +1,76 @@
package org.schabi.newpipe.extractor.services.soundcloud.search;
import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.PLAYLISTS;
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.TRACKS;
import static org.schabi.newpipe.extractor.services.soundcloud.SoundcloudSearchQueryHandlerFactory.USERS;
public class SoundcloudSearchQHTest {
@BeforeClass
public static void setUpClass() throws Exception {
NewPipe.init(Downloader.getInstance());
}
private static String removeClientId(String url) {
String[] splitUrl = url.split("client_id=[a-zA-Z0-9]*&");
return splitUrl[0] + splitUrl[1];
}
@Test
public void testRegularValues() throws Exception {
assertEquals("https://api-v2.soundcloud.com/search?q=asdf&limit=10&offset=0",
removeClientId(SoundCloud.getSearchQHFactory().fromQuery("asdf").getUrl()));
assertEquals("https://api-v2.soundcloud.com/search?q=hans&limit=10&offset=0",
removeClientId(SoundCloud.getSearchQHFactory().fromQuery("hans").getUrl()));
assertEquals("https://api-v2.soundcloud.com/search?q=Poifj%26jaijf&limit=10&offset=0",
removeClientId(SoundCloud.getSearchQHFactory().fromQuery("Poifj&jaijf").getUrl()));
assertEquals("https://api-v2.soundcloud.com/search?q=G%C3%BCl%C3%BCm&limit=10&offset=0",
removeClientId(SoundCloud.getSearchQHFactory().fromQuery("Gülüm").getUrl()));
assertEquals("https://api-v2.soundcloud.com/search?q=%3Fj%24%29H%C2%A7B&limit=10&offset=0",
removeClientId(SoundCloud.getSearchQHFactory().fromQuery("?j$)H§B").getUrl()));
}
@Test
public void testGetContentFilter() throws Exception {
assertEquals("tracks", SoundCloud.getSearchQHFactory()
.fromQuery("", asList(new String[]{"tracks"}), "").getContentFilters().get(0));
assertEquals("users", SoundCloud.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{"users"}), "").getContentFilters().get(0));
}
@Test
public void testWithContentfilter() throws Exception {
assertEquals("https://api-v2.soundcloud.com/search/tracks?q=asdf&limit=10&offset=0", removeClientId(SoundCloud.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{TRACKS}), "").getUrl()));
assertEquals("https://api-v2.soundcloud.com/search/users?q=asdf&limit=10&offset=0", removeClientId(SoundCloud.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{USERS}), "").getUrl()));
assertEquals("https://api-v2.soundcloud.com/search/playlists?q=asdf&limit=10&offset=0", removeClientId(SoundCloud.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{PLAYLISTS}), "").getUrl()));
assertEquals("https://api-v2.soundcloud.com/search?q=asdf&limit=10&offset=0", removeClientId(SoundCloud.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{"fjiijie"}), "").getUrl()));
}
@Test
public void testGetAvailableContentFilter() {
final String[] contentFilter = SoundCloud.getSearchQHFactory().getAvailableContentFilter();
assertEquals(4, contentFilter.length);
assertEquals("all", contentFilter[0]);
assertEquals("tracks", contentFilter[1]);
assertEquals("users", contentFilter[2]);
assertEquals("playlists", contentFilter[3]);
}
@Test
public void testGetAvailableSortFilter() {
final String[] contentFilter = SoundCloud.getSearchQHFactory().getAvailableSortFilter();
assertEquals(0, contentFilter.length);
}
}

View File

@ -1,54 +0,0 @@
package org.schabi.newpipe.extractor.services.youtube;
import org.junit.Test;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
import org.schabi.newpipe.extractor.search.SearchResult;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
public abstract class BaseYoutubeSearchTest {
protected static SearchResult result;
@Test
public void testResultList() {
assertFalse("Got empty result list", result.resultList.isEmpty());
for(InfoItem infoItem: result.resultList) {
assertIsSecureUrl(infoItem.getUrl());
assertIsSecureUrl(infoItem.getThumbnailUrl());
assertFalse(infoItem.getName().isEmpty());
assertFalse("Name is probably a URI: " + infoItem.getName(),
infoItem.getName().contains("://"));
if(infoItem instanceof StreamInfoItem) {
// test stream item
StreamInfoItem streamInfoItem = (StreamInfoItem) infoItem;
assertIsSecureUrl(streamInfoItem.getUploaderUrl());
assertFalse(streamInfoItem.getUploadDate().isEmpty());
assertFalse(streamInfoItem.getUploaderName().isEmpty());
} else if(infoItem instanceof ChannelInfoItem) {
// Nothing special to check?
} else if(infoItem instanceof PlaylistInfoItem) {
// test playlist item
long streamCount = ((PlaylistInfoItem) infoItem).getStreamCount();
assertTrue(streamCount > 0);
} else {
fail("Unknown infoItem type: " + infoItem);
}
}
}
@Test
public void testResultErrors() {
assertNotNull(result.errors);
if (!result.errors.isEmpty()) {
for (Throwable error : result.errors) {
error.printStackTrace();
}
}
assertTrue(result.errors.isEmpty());
}
}

View File

@ -114,6 +114,103 @@ public class YoutubeChannelExtractorTest {
}
}
// Youtube RED/Premium ad blocking test
public static class VSauce implements BaseChannelExtractorTest {
private static YoutubeChannelExtractor extractor;
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeChannelExtractor) YouTube
.getChannelExtractor("https://www.youtube.com/user/Vsauce");
extractor.fetchPage();
}
/*//////////////////////////////////////////////////////////////////////////
// Extractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testServiceId() {
assertEquals(YouTube.getServiceId(), extractor.getServiceId());
}
@Test
public void testName() throws Exception {
assertEquals("Vsauce", extractor.getName());
}
@Test
public void testId() throws Exception {
assertEquals("UC6nSFpj9HTCZ5t-N3Rm3-HA", extractor.getId());
}
@Test
public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/channel/UC6nSFpj9HTCZ5t-N3Rm3-HA", extractor.getUrl());
}
@Test
public void testOriginalUrl() throws ParsingException {
assertEquals("https://www.youtube.com/user/Vsauce", extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
// ListExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testRelatedItems() throws Exception {
defaultTestRelatedItems(extractor, YouTube.getServiceId());
}
@Test
public void testMoreRelatedItems() throws Exception {
defaultTestMoreItems(extractor, ServiceList.YouTube.getServiceId());
}
/*//////////////////////////////////////////////////////////////////////////
// ChannelExtractor
//////////////////////////////////////////////////////////////////////////*/
@Test
public void testDescription() throws Exception {
assertTrue("What it actually was: " + extractor.getDescription(),
extractor.getDescription().contains("Our World is Amazing. Questions? Ideas? Tweet me:"));
}
@Test
public void testAvatarUrl() throws Exception {
String avatarUrl = extractor.getAvatarUrl();
assertIsSecureUrl(avatarUrl);
assertTrue(avatarUrl, avatarUrl.contains("yt3"));
}
@Test
public void testBannerUrl() throws Exception {
String bannerUrl = extractor.getBannerUrl();
assertIsSecureUrl(bannerUrl);
assertTrue(bannerUrl, bannerUrl.contains("yt3"));
}
@Test
public void testFeedUrl() throws Exception {
assertEquals("https://www.youtube.com/feeds/videos.xml?channel_id=UC6nSFpj9HTCZ5t-N3Rm3-HA", extractor.getFeedUrl());
}
@Test
public void testSubscriberCount() throws Exception {
assertTrue("Wrong subscriber count", extractor.getSubscriberCount() >= 0);
}
@Test
public void testChannelDonation() throws Exception {
// this needs to be ignored since wed have to upgrade channel extractor to the new yt interface
// in order to make this work
assertTrue(extractor.getDonationLinks().length == 0);
}
}
public static class Kurzgesagt implements BaseChannelExtractorTest {
private static YoutubeChannelExtractor extractor;

View File

@ -5,26 +5,26 @@ import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeChannelUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeChannelLinkHandlerFactory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Test for {@link YoutubeChannelUrlIdHandler}
* Test for {@link YoutubeChannelLinkHandlerFactory}
*/
public class YoutubeChannelUrlIdHandlerTest {
public class YoutubeChannelLinkHandlerFactoryTest {
private static YoutubeChannelUrlIdHandler urlIdHandler;
private static YoutubeChannelLinkHandlerFactory urlIdHandler;
@BeforeClass
public static void setUp() {
urlIdHandler = YoutubeChannelUrlIdHandler.getInstance();
urlIdHandler = YoutubeChannelLinkHandlerFactory.getInstance();
NewPipe.init(Downloader.getInstance());
}
@Test
public void acceptrUrlTest() {
public void acceptrUrlTest() throws ParsingException {
assertTrue(urlIdHandler.acceptUrl("https://www.youtube.com/user/Gronkh"));
assertTrue(urlIdHandler.acceptUrl("https://www.youtube.com/user/Netzkino/videos"));
@ -40,17 +40,17 @@ public class YoutubeChannelUrlIdHandlerTest {
@Test
public void getIdFromUrl() throws ParsingException {
assertEquals("user/Gronkh", urlIdHandler.setUrl("https://www.youtube.com/user/Gronkh").getId());
assertEquals("user/Netzkino", urlIdHandler.setUrl("https://www.youtube.com/user/Netzkino/videos").getId());
assertEquals("user/Gronkh", urlIdHandler.fromUrl("https://www.youtube.com/user/Gronkh").getId());
assertEquals("user/Netzkino", urlIdHandler.fromUrl("https://www.youtube.com/user/Netzkino/videos").getId());
assertEquals("channel/UClq42foiSgl7sSpLupnugGA", urlIdHandler.setUrl("https://www.youtube.com/channel/UClq42foiSgl7sSpLupnugGA").getId());
assertEquals("channel/UClq42foiSgl7sSpLupnugGA", urlIdHandler.setUrl("https://www.youtube.com/channel/UClq42foiSgl7sSpLupnugGA/videos?disable_polymer=1").getId());
assertEquals("channel/UClq42foiSgl7sSpLupnugGA", urlIdHandler.fromUrl("https://www.youtube.com/channel/UClq42foiSgl7sSpLupnugGA").getId());
assertEquals("channel/UClq42foiSgl7sSpLupnugGA", urlIdHandler.fromUrl("https://www.youtube.com/channel/UClq42foiSgl7sSpLupnugGA/videos?disable_polymer=1").getId());
assertEquals("user/Gronkh", urlIdHandler.setUrl("https://hooktube.com/user/Gronkh").getId());
assertEquals("user/Netzkino", urlIdHandler.setUrl("https://hooktube.com/user/Netzkino/videos").getId());
assertEquals("user/Gronkh", urlIdHandler.fromUrl("https://hooktube.com/user/Gronkh").getId());
assertEquals("user/Netzkino", urlIdHandler.fromUrl("https://hooktube.com/user/Netzkino/videos").getId());
assertEquals("channel/UClq42foiSgl7sSpLupnugGA", urlIdHandler.setUrl("https://hooktube.com/channel/UClq42foiSgl7sSpLupnugGA").getId());
assertEquals("channel/UClq42foiSgl7sSpLupnugGA", urlIdHandler.setUrl("https://hooktube.com/channel/UClq42foiSgl7sSpLupnugGA/videos?disable_polymer=1").getId());
assertEquals("channel/UClq42foiSgl7sSpLupnugGA", urlIdHandler.fromUrl("https://hooktube.com/channel/UClq42foiSgl7sSpLupnugGA").getId());
assertEquals("channel/UClq42foiSgl7sSpLupnugGA", urlIdHandler.fromUrl("https://hooktube.com/channel/UClq42foiSgl7sSpLupnugGA/videos?disable_polymer=1").getId());
}
}

View File

@ -46,7 +46,7 @@ public class YoutubePlaylistExtractorTest {
@Test
public void testName() throws Exception {
String name = extractor.getName();
assertTrue(name, name.startsWith("Pop Music Playlist: Timeless Pop Hits"));
assertTrue(name, name.startsWith("Pop Music Playlist"));
}
@Test
@ -120,14 +120,14 @@ public class YoutubePlaylistExtractorTest {
}
}
public static class ImportantVideos implements BasePlaylistExtractorTest {
public static class HugePlaylist implements BasePlaylistExtractorTest {
private static YoutubePlaylistExtractor extractor;
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubePlaylistExtractor) YouTube
.getPlaylistExtractor("https://www.youtube.com/playlist?list=PLOy0j9AvlVZPto6IkjKfpu0Scx--7PGTC");
.getPlaylistExtractor("https://www.youtube.com/watch?v=8SbUC-UaAxE&list=PLWwAypAcFRgKAIIFqBr9oy-ZYZnixa_Fj");
extractor.fetchPage();
}
@ -152,23 +152,23 @@ public class YoutubePlaylistExtractorTest {
@Test
public void testName() throws Exception {
String name = extractor.getName();
assertTrue(name, name.contains("Important videos"));
final String name = extractor.getName();
assertEquals("I Wanna Rock Super Gigantic Playlist 1: Hardrock, AOR, Metal and more !!! 5000 music videos !!!", name);
}
@Test
public void testId() throws Exception {
assertEquals("PLOy0j9AvlVZPto6IkjKfpu0Scx--7PGTC", extractor.getId());
assertEquals("PLWwAypAcFRgKAIIFqBr9oy-ZYZnixa_Fj", extractor.getId());
}
@Test
public void testUrl() throws ParsingException {
assertEquals("https://www.youtube.com/playlist?list=PLOy0j9AvlVZPto6IkjKfpu0Scx--7PGTC", extractor.getUrl());
assertEquals("https://www.youtube.com/playlist?list=PLWwAypAcFRgKAIIFqBr9oy-ZYZnixa_Fj", extractor.getUrl());
}
@Test
public void testOriginalUrl() throws ParsingException {
assertEquals("https://www.youtube.com/playlist?list=PLOy0j9AvlVZPto6IkjKfpu0Scx--7PGTC", extractor.getOriginalUrl());
assertEquals("https://www.youtube.com/watch?v=8SbUC-UaAxE&list=PLWwAypAcFRgKAIIFqBr9oy-ZYZnixa_Fj", extractor.getOriginalUrl());
}
/*//////////////////////////////////////////////////////////////////////////
@ -182,8 +182,10 @@ public class YoutubePlaylistExtractorTest {
@Test
public void testMoreRelatedItems() throws Exception {
ListExtractor.InfoItemsPage<StreamInfoItem> currentPage = defaultTestMoreItems(extractor, ServiceList.YouTube.getServiceId());
ListExtractor.InfoItemsPage<StreamInfoItem> currentPage
= defaultTestMoreItems(extractor, ServiceList.YouTube.getServiceId());
// Test for 2 more levels
for (int i = 0; i < 2; i++) {
currentPage = extractor.getPage(currentPage.getNextPageUrl());
defaultTestListOfItems(YouTube.getServiceId(), currentPage.getItems(), currentPage.getErrors());
@ -216,7 +218,7 @@ public class YoutubePlaylistExtractorTest {
@Test
public void testUploaderName() throws Exception {
assertEquals("Crazy Horse", extractor.getUploaderName());
assertEquals("Tomas Nilsson", extractor.getUploaderName());
}
@Test

View File

@ -1,66 +0,0 @@
package org.schabi.newpipe.extractor.services.youtube;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchEngine;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/*
* Created by Christian Schabesberger on 29.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngineStreamTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link SearchEngine}
*/
public class YoutubeSearchEngineAllTest extends BaseYoutubeSearchTest {
@BeforeClass
public static void setUpClass() throws Exception {
NewPipe.init(Downloader.getInstance());
YoutubeSearchEngine engine = new YoutubeSearchEngine(1);
result = engine.search("pewdiepie", 0, "de", SearchEngine.Filter.ANY)
.getSearchResult();
}
@Test
public void testResultList_FirstElement() {
InfoItem firstInfoItem = result.getResults().get(0);
// THe channel should be the first item
assertTrue(firstInfoItem instanceof ChannelInfoItem);
assertEquals("name", "PewDiePie", firstInfoItem.getName());
assertEquals("url","https://www.youtube.com/user/PewDiePie", firstInfoItem.getUrl());
}
@Ignore
@Test
public void testSuggestion() {
//todo write a real test
assertTrue(result.getSuggestion() != null);
}
}

View File

@ -1,65 +0,0 @@
package org.schabi.newpipe.extractor.services.youtube;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.search.SearchEngine;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/*
* Created by Christian Schabesberger on 29.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngineStreamTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link SearchEngine}
*/
public class YoutubeSearchEngineChannelTest extends BaseYoutubeSearchTest {
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
SearchEngine engine = YouTube.getSearchEngine();
// Youtube will suggest "gronkh" instead of "grrunkh"
// keep in mind that the suggestions can change by country (the parameter "de")
result = engine.search("grrunkh", 0, "de", SearchEngine.Filter.CHANNEL)
.getSearchResult();
}
@Test
public void testResultsItemType() {
for (InfoItem infoItem : result.resultList) {
assertEquals(InfoItem.InfoType.CHANNEL, infoItem.getInfoType());
}
}
@Ignore
@Test
public void testSuggestion() {
//todo write a real test
assertTrue(result.suggestion != null);
}
}

View File

@ -1,67 +0,0 @@
package org.schabi.newpipe.extractor.services.youtube;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
import org.schabi.newpipe.extractor.search.SearchEngine;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/*
* Created by Christian Schabesberger on 29.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngineStreamTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link SearchEngine}
*/
public class YoutubeSearchEnginePlaylistTest extends BaseYoutubeSearchTest {
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
SearchEngine engine = YouTube.getSearchEngine();
// Youtube will suggest "gronkh" instead of "grrunkh"
// keep in mind that the suggestions can change by country (the parameter "de")
result = engine.search("grrunkh", 0, "de", SearchEngine.Filter.PLAYLIST)
.getSearchResult();
}
@Test
public void testInfoItemType() {
for (InfoItem infoItem : result.resultList) {
assertTrue(infoItem instanceof PlaylistInfoItem);
assertEquals(InfoItem.InfoType.PLAYLIST, infoItem.getInfoType());
}
}
@Ignore
@Test
public void testSuggestion() {
//todo write a real test
assertTrue(result.suggestion != null);
}
}

View File

@ -1,65 +0,0 @@
package org.schabi.newpipe.extractor.services.youtube;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.search.SearchEngine;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/*
* Created by Christian Schabesberger on 29.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngineStreamTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link SearchEngine}
*/
public class YoutubeSearchEngineStreamTest extends BaseYoutubeSearchTest {
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
SearchEngine engine = YouTube.getSearchEngine();
// Youtube will suggest "results" instead of "rsults",
// keep in mind that the suggestions can change by country (the parameter "de")
result = engine.search("abc", 0, "de", SearchEngine.Filter.STREAM)
.getSearchResult();
}
@Test
public void testResultsItemType() {
for (InfoItem infoItem : result.resultList) {
assertEquals(InfoItem.InfoType.STREAM, infoItem.getInfoType());
}
}
@Ignore
@Test
public void testSuggestion() {
//todo write a real test
assertTrue(result.suggestion != null);
}
}

View File

@ -4,7 +4,7 @@ package org.schabi.newpipe.extractor.services.youtube;
* Created by Christian Schabesberger on 29.12.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeSearchEngineStreamTest.java is part of NewPipe.
* YoutubeSearchExtractorStreamTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -8,7 +8,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeStreamUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.stream.SubtitlesFormat;
import org.schabi.newpipe.extractor.stream.VideoStream;
@ -22,9 +22,9 @@ import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/**
* Test for {@link YoutubeStreamUrlIdHandler}
* Test for {@link YoutubeStreamLinkHandlerFactory}
*/
public class YoutubeStreamExtractorRestrictedTest {
public class YoutubeStreamExtractorAgeRestrictedTest {
public static final String HTTPS = "https://";
private static YoutubeStreamExtractor extractor;
@ -32,7 +32,7 @@ public class YoutubeStreamExtractorRestrictedTest {
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeStreamExtractor) YouTube
.getStreamExtractor("https://www.youtube.com/watch?v=i6JTvzrpBy0");
.getStreamExtractor("https://www.youtube.com/watch?v=MmBeUZqv1QA");
extractor.fetchPage();
}

View File

@ -8,7 +8,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeStreamUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.stream.SubtitlesFormat;
import org.schabi.newpipe.extractor.stream.VideoStream;
@ -22,7 +22,7 @@ import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/**
* Test for {@link YoutubeStreamUrlIdHandler}
* Test for {@link YoutubeStreamLinkHandlerFactory}
*/
public class YoutubeStreamExtractorControversialTest {
private static YoutubeStreamExtractor extractor;
@ -61,7 +61,7 @@ public class YoutubeStreamExtractorControversialTest {
@Test
public void testGetDescription() throws ParsingException {
assertNotNull(extractor.getDescription());
assertFalse(extractor.getDescription().isEmpty());
// assertFalse(extractor.getDescription().isEmpty());
}
@Test
@ -112,13 +112,14 @@ public class YoutubeStreamExtractorControversialTest {
assertTrue(streams.size() > 0);
}
@Ignore
@Test
public void testGetSubtitlesListDefault() throws IOException, ExtractionException {
// Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null
assertTrue(!extractor.getSubtitlesDefault().isEmpty());
}
@Ignore
@Test
public void testGetSubtitlesList() throws IOException, ExtractionException {
// Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null

View File

@ -4,8 +4,8 @@ package org.schabi.newpipe.extractor.services.youtube;
/*
* Created by Christian Schabesberger on 30.12.15.
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeStreamExtractorDonationTest.java is part of NewPipe.
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* YoutubeVideoExtractorDefault.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -25,35 +25,36 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/**
* Test for {@link StreamExtractor}
*/
public class YoutubeStreamExtractorDonationTest {
private static YoutubeStreamExtractor extractor;
public class YoutubeStreamExtractorDASHTest {
private static StreamInfo info;
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeStreamExtractor) YouTube
.getStreamExtractor("https://www.youtube.com/watch?v=pXb3jERMoI0");
extractor.fetchPage();
info = StreamInfo.getInfo(YouTube, "https://www.youtube.com/watch?v=00Q4SUnVQK4");
}
@Test
public void getDonationLinksTest() throws Exception {
assertTrue(String.valueOf(extractor.getDonationLinks().length),
extractor.getDonationLinks().length == 2);
public void testGetDashMpd() {
System.out.println(info.getDashMpdUrl());
assertTrue(info.getDashMpdUrl(),
info.getDashMpdUrl() != null && !info.getDashMpdUrl().isEmpty());
}
@Test
public void getAffiliateLinksTest() throws Exception {
assertTrue(String.valueOf(extractor.getAffiliateLinks().length),
extractor.getAffiliateLinks().length == 1);
public void testDashMpdParser() {
assertEquals(0, info.getAudioStreams().size());
assertEquals(0, info.getVideoOnlyStreams().size());
assertEquals(4, info.getVideoStreams().size());
}
}

View File

@ -8,6 +8,7 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.stream.*;
import org.schabi.newpipe.extractor.utils.DashMpdParser;
import org.schabi.newpipe.extractor.utils.Utils;
import java.io.IOException;
@ -15,6 +16,7 @@ import java.io.IOException;
import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.youtube.YoutubeTrendingExtractorTest.extractor;
/*
* Created by Christian Schabesberger on 30.12.15.
@ -40,120 +42,161 @@ import static org.schabi.newpipe.extractor.ServiceList.YouTube;
* Test for {@link StreamExtractor}
*/
public class YoutubeStreamExtractorDefaultTest {
private static YoutubeStreamExtractor extractor;
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeStreamExtractor) YouTube
.getStreamExtractor("https://www.youtube.com/watch?v=rYEDA3JcQqw");
extractor.fetchPage();
}
public static class AdeleHello {
private static YoutubeStreamExtractor extractor;
@Test
public void testGetInvalidTimeStamp() throws ParsingException {
assertTrue(extractor.getTimeStamp() + "",
extractor.getTimeStamp() <= 0);
}
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeStreamExtractor) YouTube
.getStreamExtractor("https://www.youtube.com/watch?v=rYEDA3JcQqw");
extractor.fetchPage();
}
@Test
public void testGetValidTimeStamp() throws IOException, ExtractionException {
StreamExtractor extractor = YouTube.getStreamExtractor("https://youtu.be/FmG385_uUys?t=174");
assertEquals(extractor.getTimeStamp() + "", "174");
}
@Test
public void testGetInvalidTimeStamp() throws ParsingException {
assertTrue(extractor.getTimeStamp() + "",
extractor.getTimeStamp() <= 0);
}
@Test
public void testGetTitle() throws ParsingException {
assertFalse(extractor.getName().isEmpty());
}
@Test
public void testGetValidTimeStamp() throws ExtractionException {
StreamExtractor extractor = YouTube.getStreamExtractor("https://youtu.be/FmG385_uUys?t=174");
assertEquals(extractor.getTimeStamp() + "", "174");
}
@Test
public void testGetDescription() throws ParsingException {
assertNotNull(extractor.getDescription());
assertFalse(extractor.getDescription().isEmpty());
}
@Test
public void testGetTitle() throws ParsingException {
assertFalse(extractor.getName().isEmpty());
}
@Test
public void testGetUploaderName() throws ParsingException {
assertNotNull(extractor.getUploaderName());
assertFalse(extractor.getUploaderName().isEmpty());
}
@Test
public void testGetDescription() throws ParsingException {
assertNotNull(extractor.getDescription());
assertFalse(extractor.getDescription().isEmpty());
}
@Test
public void testGetFullLinksInDescriptlion() throws ParsingException {
assertTrue(extractor.getDescription().contains("http://smarturl.it/SubscribeAdele?IQid=yt"));
assertFalse(extractor.getDescription().contains("http://smarturl.it/SubscribeAdele?IQi..."));
}
@Test
public void testGetUploaderName() throws ParsingException {
assertNotNull(extractor.getUploaderName());
assertFalse(extractor.getUploaderName().isEmpty());
}
@Test
public void testGetLength() throws ParsingException {
assertTrue(extractor.getLength() > 0);
}
@Test
public void testGetLength() throws ParsingException {
assertTrue(extractor.getLength() > 0);
}
@Test
public void testGetViewCount() throws ParsingException {
Long count = extractor.getViewCount();
assertTrue(Long.toString(count), count >= /* specific to that video */ 1220025784);
}
@Test
public void testGetViewCount() throws ParsingException {
Long count = extractor.getViewCount();
assertTrue(Long.toString(count), count >= /* specific to that video */ 1220025784);
}
@Test
public void testGetUploadDate() throws ParsingException {
assertTrue(extractor.getUploadDate().length() > 0);
}
@Test
public void testGetUploadDate() throws ParsingException {
assertTrue(extractor.getUploadDate().length() > 0);
}
@Test
public void testGetUploaderUrl() throws ParsingException {
assertTrue(extractor.getUploaderUrl().length() > 0);
}
@Test
public void testGetUploaderUrl() throws ParsingException {
assertTrue(extractor.getUploaderUrl().length() > 0);
}
@Test
public void testGetThumbnailUrl() throws ParsingException {
assertIsSecureUrl(extractor.getThumbnailUrl());
}
@Test
public void testGetThumbnailUrl() throws ParsingException {
assertIsSecureUrl(extractor.getThumbnailUrl());
}
@Test
public void testGetUploaderAvatarUrl() throws ParsingException {
assertIsSecureUrl(extractor.getUploaderAvatarUrl());
}
@Test
public void testGetUploaderAvatarUrl() throws ParsingException {
assertIsSecureUrl(extractor.getUploaderAvatarUrl());
}
@Test
public void testGetAudioStreams() throws IOException, ExtractionException {
assertFalse(extractor.getAudioStreams().isEmpty());
}
@Test
public void testGetAudioStreams() throws IOException, ExtractionException {
assertFalse(extractor.getAudioStreams().isEmpty());
}
@Test
public void testGetVideoStreams() throws IOException, ExtractionException {
for (VideoStream s : extractor.getVideoStreams()) {
assertIsSecureUrl(s.url);
assertTrue(s.resolution.length() > 0);
assertTrue(Integer.toString(s.getFormatId()),
0 <= s.getFormatId() && s.getFormatId() <= 4);
@Test
public void testGetVideoStreams() throws IOException, ExtractionException {
for (VideoStream s : extractor.getVideoStreams()) {
assertIsSecureUrl(s.url);
assertTrue(s.resolution.length() > 0);
assertTrue(Integer.toString(s.getFormatId()),
0 <= s.getFormatId() && s.getFormatId() <= 4);
}
}
@Test
public void testStreamType() throws ParsingException {
assertTrue(extractor.getStreamType() == StreamType.VIDEO_STREAM);
}
@Test
public void testGetDashMpd() throws ParsingException {
// we dont expect this particular video to have a DASH file. For this purpouse we use a different test class.
assertTrue(extractor.getDashMpdUrl(),
extractor.getDashMpdUrl() != null && extractor.getDashMpdUrl().isEmpty());
}
@Test
public void testGetRelatedVideos() throws ExtractionException, IOException {
StreamInfoItemsCollector relatedVideos = extractor.getRelatedVideos();
Utils.printErrors(relatedVideos.getErrors());
assertFalse(relatedVideos.getItems().isEmpty());
assertTrue(relatedVideos.getErrors().isEmpty());
}
@Test
public void testGetSubtitlesListDefault() throws IOException, ExtractionException {
// Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null
assertTrue(extractor.getSubtitlesDefault().isEmpty());
}
@Test
public void testGetSubtitlesList() throws IOException, ExtractionException {
// Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null
assertTrue(extractor.getSubtitles(SubtitlesFormat.TTML).isEmpty());
}
}
@Test
public void testStreamType() throws ParsingException {
assertTrue(extractor.getStreamType() == StreamType.VIDEO_STREAM);
}
public static class DescriptionTestPewdiepie {
private static YoutubeStreamExtractor extractor;
@Test
public void testGetDashMpd() throws ParsingException {
assertTrue(extractor.getDashMpdUrl(),
extractor.getDashMpdUrl() != null || !extractor.getDashMpdUrl().isEmpty());
}
@BeforeClass
public static void setUp() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeStreamExtractor) YouTube
.getStreamExtractor("https://www.youtube.com/watch?v=dJY8iT341F4");
extractor.fetchPage();
}
@Test
public void testGetRelatedVideos() throws ExtractionException, IOException {
StreamInfoItemsCollector relatedVideos = extractor.getRelatedVideos();
Utils.printErrors(relatedVideos.getErrors());
assertFalse(relatedVideos.getItems().isEmpty());
assertTrue(relatedVideos.getErrors().isEmpty());
}
@Test
public void testGetDescription() throws ParsingException {
assertNotNull(extractor.getDescription());
assertFalse(extractor.getDescription().isEmpty());
}
@Test
public void testGetSubtitlesListDefault() throws IOException, ExtractionException {
// Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null
assertTrue(extractor.getSubtitlesDefault().isEmpty());
}
@Test
public void testGetFullLinksInDescriptlion() throws ParsingException {
assertTrue(extractor.getDescription().contains("https://www.reddit.com/r/PewdiepieSubmissions/"));
assertTrue(extractor.getDescription().contains("https://www.youtube.com/channel/UC3e8EMTOn4g6ZSKggHTnNng"));
@Test
public void testGetSubtitlesList() throws IOException, ExtractionException {
// Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null
assertTrue(extractor.getSubtitles(SubtitlesFormat.TTML).isEmpty());
assertFalse(extractor.getDescription().contains("https://www.reddit.com/r/PewdiepieSub..."));
assertFalse(extractor.getDescription().contains("https://usa.clutchchairz.com/product/..."));
assertFalse(extractor.getDescription().contains("https://europe.clutchchairz.com/en/pr..."));
assertFalse(extractor.getDescription().contains("https://canada.clutchchairz.com/produ..."));
assertFalse(extractor.getDescription().contains("http://store.steampowered.com/app/703..."));
assertFalse(extractor.getDescription().contains("https://www.youtube.com/channel/UC3e8..."));
}
}
}

View File

@ -6,7 +6,7 @@ import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeStreamUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory;
import java.util.ArrayList;
import java.util.List;
@ -14,26 +14,26 @@ import java.util.List;
import static org.junit.Assert.*;
/**
* Test for {@link YoutubeStreamUrlIdHandler}
* Test for {@link YoutubeStreamLinkHandlerFactory}
*/
public class YoutubeStreamUrlIdHandlerTest {
public class YoutubeStreamLinkHandlerFactoryTest {
private static String AD_URL = "https://googleads.g.doubleclick.net/aclk?sa=l&ai=C-2IPgeVTWPf4GcOStgfOnIOADf78n61GvKmmobYDrgIQASDj-5MDKAJg9ZXOgeAEoAGgy_T-A8gBAakC2gkpmquIsT6oAwGqBJMBT9BgD5kVgbN0dX602bFFaDw9vsxq-We-S8VkrXVBi6W_e7brZ36GCz1WO3EPEeklYuJjXLUowwCOKsd-8xr1UlS_tusuFJv9iX35xoBHKTRvs8-0aDbfEIm6in37QDfFuZjqgEMB8-tg0Jn_Pf1RU5OzbuU40B4Gy25NUTnOxhDKthOhKBUSZEksCEerUV8GMu10iAXCxquwApIFBggDEAEYAaAGGsgGlIjthrUDgAfItIsBqAemvhvYBwHSCAUIgGEQAbgT6AE&num=1&sig=AOD64_1DybDd4qAm5O7o9UAbTNRdqXXHFQ&ctype=21&video_id=dMO_IXYPZew&client=ca-pub-6219811747049371&adurl=http://www.youtube.com/watch%3Fv%3DdMO_IXYPZew";
private static YoutubeStreamUrlIdHandler urlIdHandler;
private static YoutubeStreamLinkHandlerFactory urlIdHandler;
@BeforeClass
public static void setUp() {
urlIdHandler = YoutubeStreamUrlIdHandler.getInstance();
urlIdHandler = YoutubeStreamLinkHandlerFactory.getInstance();
NewPipe.init(Downloader.getInstance());
}
@Test(expected = IllegalArgumentException.class)
public void getIdWithNullAsUrl() throws ParsingException {
urlIdHandler.setId(null);
urlIdHandler.fromId(null);
}
@Test(expected = FoundAdException.class)
public void getIdForAd() throws ParsingException {
urlIdHandler.setUrl(AD_URL).getId();
urlIdHandler.fromUrl(AD_URL).getId();
}
@Test
@ -45,7 +45,7 @@ public class YoutubeStreamUrlIdHandlerTest {
for (String invalidUrl : invalidUrls) {
Throwable exception = null;
try {
urlIdHandler.setUrl(invalidUrl).getId();
urlIdHandler.fromUrl(invalidUrl).getId();
} catch (ParsingException e) {
exception = e;
}
@ -57,40 +57,30 @@ public class YoutubeStreamUrlIdHandlerTest {
@Test
public void getIdfromYt() throws Exception {
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("https://www.youtube.com/watch?v=jZViOEv90dI").getId());
assertEquals("W-fFHeTX70Q", urlIdHandler.setUrl("https://www.youtube.com/watch?v=W-fFHeTX70Q").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("https://www.youtube.com/watch?v=jZViOEv90dI?t=100").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("https://WWW.YouTube.com/watch?v=jZViOEv90dI?t=100").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("HTTPS://www.youtube.com/watch?v=jZViOEv90dI?t=100").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("https://youtu.be/jZViOEv90dI?t=9s").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("HTTPS://Youtu.be/jZViOEv90dI?t=9s").getId());
assertEquals("uEJuoEs1UxY", urlIdHandler.setUrl("http://www.youtube.com/watch_popup?v=uEJuoEs1UxY").getId());
assertEquals("uEJuoEs1UxY", urlIdHandler.setUrl("http://www.Youtube.com/watch_popup?v=uEJuoEs1UxY").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("https://www.youtube.com/embed/jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("https://www.youtube-nocookie.com/embed/jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("http://www.youtube.com/watch?v=jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("http://youtube.com/watch?v=jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("http://youtu.be/jZViOEv90dI?t=9s").getId());
assertEquals("7_WWz2DSnT8", urlIdHandler.setUrl("https://youtu.be/7_WWz2DSnT8").getId());
assertEquals("oy6NvWeVruY", urlIdHandler.setUrl("https://m.youtube.com/watch?v=oy6NvWeVruY").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("http://www.youtube.com/embed/jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("http://www.Youtube.com/embed/jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("http://www.youtube-nocookie.com/embed/jZViOEv90dI").getId());
assertEquals("EhxJLojIE_o", urlIdHandler.setUrl("http://www.youtube.com/attribution_link?a=JdfC0C9V6ZI&u=%2Fwatch%3Fv%3DEhxJLojIE_o%26feature%3Dshare").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("vnd.youtube://www.youtube.com/watch?v=jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.setUrl("vnd.youtube:jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("https://www.youtube.com/watch?v=jZViOEv90dI").getId());
assertEquals("W-fFHeTX70Q", urlIdHandler.fromUrl("https://www.youtube.com/watch?v=W-fFHeTX70Q").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("https://www.youtube.com/watch?v=jZViOEv90dI?t=100").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("https://WWW.YouTube.com/watch?v=jZViOEv90dI?t=100").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("HTTPS://www.youtube.com/watch?v=jZViOEv90dI?t=100").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("https://youtu.be/jZViOEv90dI?t=9s").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("HTTPS://Youtu.be/jZViOEv90dI?t=9s").getId());
assertEquals("uEJuoEs1UxY", urlIdHandler.fromUrl("http://www.youtube.com/watch_popup?v=uEJuoEs1UxY").getId());
assertEquals("uEJuoEs1UxY", urlIdHandler.fromUrl("http://www.Youtube.com/watch_popup?v=uEJuoEs1UxY").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("https://www.youtube.com/embed/jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("https://www.youtube-nocookie.com/embed/jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("http://www.youtube.com/watch?v=jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("http://youtube.com/watch?v=jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("http://youtu.be/jZViOEv90dI?t=9s").getId());
assertEquals("7_WWz2DSnT8", urlIdHandler.fromUrl("https://youtu.be/7_WWz2DSnT8").getId());
assertEquals("oy6NvWeVruY", urlIdHandler.fromUrl("https://m.youtube.com/watch?v=oy6NvWeVruY").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("http://www.youtube.com/embed/jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("http://www.Youtube.com/embed/jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("http://www.youtube-nocookie.com/embed/jZViOEv90dI").getId());
assertEquals("EhxJLojIE_o", urlIdHandler.fromUrl("http://www.youtube.com/attribution_link?a=JdfC0C9V6ZI&u=%2Fwatch%3Fv%3DEhxJLojIE_o%26feature%3Dshare").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("vnd.youtube://www.youtube.com/watch?v=jZViOEv90dI").getId());
assertEquals("jZViOEv90dI", urlIdHandler.fromUrl("vnd.youtube:jZViOEv90dI").getId());
}
@Test
public void getIdfromSharedLinksYt() throws Exception {
String sharedId = "7JIArTByb3E";
String realId = "Q7JsK50NGaA";
assertEquals(realId, urlIdHandler.setUrl("vnd.youtube://www.YouTube.com/shared?ci=" + sharedId + "&feature=twitter-deep-link").getId());
assertEquals(realId, urlIdHandler.setUrl("vnd.youtube://www.youtube.com/shared?ci=" + sharedId).getId());
assertEquals(realId, urlIdHandler.setUrl("https://www.youtube.com/shared?ci=" + sharedId).getId());
}
@Test
public void testAcceptYtUrl() throws ParsingException {
assertTrue(urlIdHandler.acceptUrl("https://www.youtube.com/watch?v=jZViOEv90dI"));
@ -111,14 +101,6 @@ public class YoutubeStreamUrlIdHandlerTest {
assertTrue(urlIdHandler.acceptUrl("vnd.youtube:jZViOEv90dI"));
}
@Test
public void testAcceptSharedYtUrl() throws ParsingException {
String sharedId = "8A940MXKFmQ";
assertTrue(urlIdHandler.acceptUrl("vnd.youtube://www.youtube.com/shared?ci=" + sharedId + "&feature=twitter-deep-link"));
assertTrue(urlIdHandler.acceptUrl("vnd.youtube://www.youtube.com/shared?ci=" + sharedId));
assertTrue(urlIdHandler.acceptUrl("https://www.youtube.com/shared?ci=" + sharedId));
}
@Test
public void testAcceptHookUrl() throws ParsingException {
assertTrue(urlIdHandler.acceptUrl("https://hooktube.com/watch?v=TglNG-yjabU"));
@ -131,11 +113,11 @@ public class YoutubeStreamUrlIdHandlerTest {
@Test
public void testGetHookIdfromUrl() throws ParsingException {
assertEquals("TglNG-yjabU", urlIdHandler.setUrl("https://hooktube.com/watch?v=TglNG-yjabU").getId());
assertEquals("3msbfr6pBNE", urlIdHandler.setUrl("hooktube.com/watch?v=3msbfr6pBNE").getId());
assertEquals("ocH3oSnZG3c", urlIdHandler.setUrl("https://hooktube.com/watch?v=ocH3oSnZG3c&list=PLS2VU1j4vzuZwooPjV26XM9UEBY2CPNn2").getId());
assertEquals("3msbfr6pBNE", urlIdHandler.setUrl("hooktube.com/watch/3msbfr6pBNE").getId());
assertEquals("3msbfr6pBNE", urlIdHandler.setUrl("hooktube.com/v/3msbfr6pBNE").getId());
assertEquals("3msbfr6pBNE", urlIdHandler.setUrl("hooktube.com/embed/3msbfr6pBNE").getId());
assertEquals("TglNG-yjabU", urlIdHandler.fromUrl("https://hooktube.com/watch?v=TglNG-yjabU").getId());
assertEquals("3msbfr6pBNE", urlIdHandler.fromUrl("hooktube.com/watch?v=3msbfr6pBNE").getId());
assertEquals("ocH3oSnZG3c", urlIdHandler.fromUrl("https://hooktube.com/watch?v=ocH3oSnZG3c&list=PLS2VU1j4vzuZwooPjV26XM9UEBY2CPNn2").getId());
assertEquals("3msbfr6pBNE", urlIdHandler.fromUrl("hooktube.com/watch/3msbfr6pBNE").getId());
assertEquals("3msbfr6pBNE", urlIdHandler.fromUrl("hooktube.com/v/3msbfr6pBNE").getId());
assertEquals("3msbfr6pBNE", urlIdHandler.fromUrl("hooktube.com/embed/3msbfr6pBNE").getId());
}
}

View File

@ -5,7 +5,7 @@ import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSubscriptionExtractor;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
@ -23,13 +23,13 @@ import static org.junit.Assert.*;
*/
public class YoutubeSubscriptionExtractorTest {
private static YoutubeSubscriptionExtractor subscriptionExtractor;
private static UrlIdHandler urlHandler;
private static LinkHandlerFactory urlHandler;
@BeforeClass
public static void setupClass() {
NewPipe.init(Downloader.getInstance());
subscriptionExtractor = new YoutubeSubscriptionExtractor(ServiceList.YouTube);
urlHandler = ServiceList.YouTube.getChannelUrlIdHandler();
urlHandler = ServiceList.YouTube.getChannelLHFactory();
}
@Test

View File

@ -26,7 +26,7 @@ import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeTrendingExtractor;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeTrendingUrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingLinkHandlerFactory;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.utils.Utils;
@ -37,7 +37,7 @@ import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/**
* Test for {@link YoutubeTrendingUrlIdHandler}
* Test for {@link YoutubeTrendingLinkHandlerFactory}
*/
public class YoutubeTrendingExtractorTest {

View File

@ -25,7 +25,7 @@ import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import static org.junit.Assert.assertFalse;
@ -43,9 +43,9 @@ public class YoutubeTrendingKioskInfoTest {
throws Exception {
NewPipe.init(Downloader.getInstance());
StreamingService service = YouTube;
UrlIdHandler urlIdHandler = service.getKioskList().getUrlIdHandlerByType("Trending");
LinkHandlerFactory LinkHandlerFactory = service.getKioskList().getListLinkHandlerFactoryByType("Trending");
kioskInfo = KioskInfo.getInfo(YouTube, urlIdHandler.setId("Trending").getUrl(), null);
kioskInfo = KioskInfo.getInfo(YouTube, LinkHandlerFactory.fromId("Trending").getUrl(), null);
}
@Test

View File

@ -0,0 +1,83 @@
package org.schabi.newpipe.extractor.services.youtube;
/*
* Created by Christian Schabesberger on 12.08.17.
*
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
* YoutubeTrendingLinkHandlerFactoryTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeTrendingLinkHandlerFactory;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/**
* Test for {@link YoutubeTrendingLinkHandlerFactory}
*/
public class YoutubeTrendingLinkHandlerFactoryTest {
private static LinkHandlerFactory LinkHandlerFactory;
@BeforeClass
public static void setUp() throws Exception {
LinkHandlerFactory = YouTube.getKioskList().getListLinkHandlerFactoryByType("Trending");
NewPipe.init(Downloader.getInstance());
}
@Test
public void getUrl()
throws Exception {
assertEquals(LinkHandlerFactory.fromId("").getUrl(), "https://www.youtube.com/feed/trending");
}
@Test
public void getId()
throws Exception {
assertEquals(LinkHandlerFactory.fromUrl("https://www.youtube.com/feed/trending").getId(), "Trending");
}
@Test
public void acceptUrl() throws ParsingException {
assertTrue(LinkHandlerFactory.acceptUrl("https://www.youtube.com/feed/trending"));
assertTrue(LinkHandlerFactory.acceptUrl("https://www.youtube.com/feed/trending?adsf=fjaj#fhe"));
assertTrue(LinkHandlerFactory.acceptUrl("http://www.youtube.com/feed/trending"));
assertTrue(LinkHandlerFactory.acceptUrl("www.youtube.com/feed/trending"));
assertTrue(LinkHandlerFactory.acceptUrl("youtube.com/feed/trending"));
assertTrue(LinkHandlerFactory.acceptUrl("youtube.com/feed/trending?akdsakjf=dfije&kfj=dkjak"));
assertTrue(LinkHandlerFactory.acceptUrl("https://youtube.com/feed/trending"));
assertTrue(LinkHandlerFactory.acceptUrl("m.youtube.com/feed/trending"));
assertFalse(LinkHandlerFactory.acceptUrl("https://youtu.be/feed/trending"));
assertFalse(LinkHandlerFactory.acceptUrl("kdskjfiiejfia"));
assertFalse(LinkHandlerFactory.acceptUrl("https://www.youtube.com/bullshit/feed/trending"));
assertFalse(LinkHandlerFactory.acceptUrl("https://www.youtube.com/feed/trending/bullshit"));
assertFalse(LinkHandlerFactory.acceptUrl("https://www.youtube.com/feed/bullshit/trending"));
assertFalse(LinkHandlerFactory.acceptUrl("peter klaut aepferl youtube.com/feed/trending"));
assertFalse(LinkHandlerFactory.acceptUrl("youtube.com/feed/trending askjkf"));
assertFalse(LinkHandlerFactory.acceptUrl("askdjfi youtube.com/feed/trending askjkf"));
assertFalse(LinkHandlerFactory.acceptUrl(" youtube.com/feed/trending"));
assertFalse(LinkHandlerFactory.acceptUrl("https://www.youtube.com/feed/trending.html"));
assertFalse(LinkHandlerFactory.acceptUrl(""));
}
}

View File

@ -1,82 +0,0 @@
package org.schabi.newpipe.extractor.services.youtube;
/*
* Created by Christian Schabesberger on 12.08.17.
*
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
* YoutubeTrendingUrlIdHandlerTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.services.youtube.urlIdHandlers.YoutubeTrendingUrlIdHandler;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/**
* Test for {@link YoutubeTrendingUrlIdHandler}
*/
public class YoutubeTrendingUrlIdHandlerTest {
private static UrlIdHandler urlIdHandler;
@BeforeClass
public static void setUp() throws Exception {
urlIdHandler = YouTube.getKioskList().getUrlIdHandlerByType("Trending");
NewPipe.init(Downloader.getInstance());
}
@Test
public void getUrl()
throws Exception {
assertEquals(urlIdHandler.setId("").getUrl(), "https://www.youtube.com/feed/trending");
}
@Test
public void getId()
throws Exception {
assertEquals(urlIdHandler.setUrl("").getId(), "Trending");
}
@Test
public void acceptUrl() {
assertTrue(urlIdHandler.acceptUrl("https://www.youtube.com/feed/trending"));
assertTrue(urlIdHandler.acceptUrl("https://www.youtube.com/feed/trending?adsf=fjaj#fhe"));
assertTrue(urlIdHandler.acceptUrl("http://www.youtube.com/feed/trending"));
assertTrue(urlIdHandler.acceptUrl("www.youtube.com/feed/trending"));
assertTrue(urlIdHandler.acceptUrl("youtube.com/feed/trending"));
assertTrue(urlIdHandler.acceptUrl("youtube.com/feed/trending?akdsakjf=dfije&kfj=dkjak"));
assertTrue(urlIdHandler.acceptUrl("https://youtube.com/feed/trending"));
assertTrue(urlIdHandler.acceptUrl("m.youtube.com/feed/trending"));
assertFalse(urlIdHandler.acceptUrl("https://youtu.be/feed/trending"));
assertFalse(urlIdHandler.acceptUrl("kdskjfiiejfia"));
assertFalse(urlIdHandler.acceptUrl("https://www.youtube.com/bullshit/feed/trending"));
assertFalse(urlIdHandler.acceptUrl("https://www.youtube.com/feed/trending/bullshit"));
assertFalse(urlIdHandler.acceptUrl("https://www.youtube.com/feed/bullshit/trending"));
assertFalse(urlIdHandler.acceptUrl("peter klaut aepferl youtube.com/feed/trending"));
assertFalse(urlIdHandler.acceptUrl("youtube.com/feed/trending askjkf"));
assertFalse(urlIdHandler.acceptUrl("askdjfi youtube.com/feed/trending askjkf"));
assertFalse(urlIdHandler.acceptUrl(" youtube.com/feed/trending"));
assertFalse(urlIdHandler.acceptUrl("https://www.youtube.com/feed/trending.html"));
assertFalse(urlIdHandler.acceptUrl(""));
}
}

View File

@ -0,0 +1,35 @@
package org.schabi.newpipe.extractor.services.youtube.search;
import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory;
import static java.util.Collections.singletonList;
import static junit.framework.TestCase.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
public class YoutubeSearchCountTest {
public static class YoutubeChannelViewCountTest extends YoutubeSearchExtractorBaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie",
singletonList(YoutubeSearchQueryHandlerFactory.CHANNELS), null,"de");
extractor.fetchPage();
itemsPage = extractor.getInitialPage();
}
@Test
public void testViewCount() throws Exception {
boolean foundKnownChannel = false;
ChannelInfoItem ci = (ChannelInfoItem) itemsPage.getItems().get(0);
assertTrue("Count does not fit: " + Long.toString(ci.getSubscriberCount()),
65043316 < ci.getSubscriberCount() && ci.getSubscriberCount() < 68043316);
}
}
}

View File

@ -0,0 +1,52 @@
package org.schabi.newpipe.extractor.services.youtube.search;
import org.junit.Test;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.services.BaseListExtractorTest;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/*
* Created by Christian Schabesberger on 27.05.18
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeSearchExtractorBaseTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link YoutubeSearchExtractor}
*/
public abstract class YoutubeSearchExtractorBaseTest {
protected static YoutubeSearchExtractor extractor;
protected static ListExtractor.InfoItemsPage<InfoItem> itemsPage;
@Test
public void testResultListElementsLength() {
assertTrue(Integer.toString(itemsPage.getItems().size()),
itemsPage.getItems().size() > 10);
}
@Test
public void testUrl() throws Exception {
assertTrue(extractor.getUrl(), extractor.getUrl().startsWith("https://www.youtube.com"));
}
}

View File

@ -0,0 +1,63 @@
package org.schabi.newpipe.extractor.services.youtube.search;
import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory;
import static java.util.Arrays.asList;
import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
public class YoutubeSearchExtractorChannelOnlyTest extends YoutubeSearchExtractorBaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie",
asList(YoutubeSearchQueryHandlerFactory.CHANNELS), null, "de");
extractor.fetchPage();
itemsPage = extractor.getInitialPage();
}
@Test
public void testGetSecondPage() throws Exception {
YoutubeSearchExtractor secondExtractor = (YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie",
asList(YoutubeSearchQueryHandlerFactory.CHANNELS), null, "de");
ListExtractor.InfoItemsPage<InfoItem> secondPage = secondExtractor.getPage(itemsPage.getNextPageUrl());
assertTrue(Integer.toString(secondPage.getItems().size()),
secondPage.getItems().size() > 10);
// check if its the same result
boolean equals = true;
for (int i = 0; i < secondPage.getItems().size()
&& i < itemsPage.getItems().size(); i++) {
if(!secondPage.getItems().get(i).getUrl().equals(
itemsPage.getItems().get(i).getUrl())) {
equals = false;
}
}
assertFalse("First and second page are equal", equals);
assertEquals("https://www.youtube.com/results?q=pewdiepie&sp=EgIQAlAU&page=3", secondPage.getNextPageUrl());
}
@Test
public void testGetSecondPageUrl() throws Exception {
assertEquals("https://www.youtube.com/results?q=pewdiepie&sp=EgIQAlAU&page=2", extractor.getNextPageUrl());
}
@Test
public void testOnlyContainChannels() {
for(InfoItem item : itemsPage.getItems()) {
if(!(item instanceof ChannelInfoItem)) {
fail("The following item is no channel item: " + item.toString());
}
}
}
}

View File

@ -0,0 +1,117 @@
package org.schabi.newpipe.extractor.services.youtube.search;
import org.junit.BeforeClass;
import org.junit.Test;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeSearchExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
/*
* Created by Christian Schabesberger on 27.05.18
*
* Copyright (C) Christian Schabesberger 2018 <chris.schabesberger@mailbox.org>
* YoutubeSearchExtractorStreamTest.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Test for {@link YoutubeSearchExtractor}
*/
public class YoutubeSearchExtractorDefaultTest extends YoutubeSearchExtractorBaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
NewPipe.init(Downloader.getInstance());
extractor = (YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie", "de");
extractor.fetchPage();
itemsPage = extractor.getInitialPage();
}
@Test
public void testGetSecondPageUrl() throws Exception {
assertEquals("https://www.youtube.com/results?q=pewdiepie&page=2", extractor.getNextPageUrl());
}
@Test
public void testResultList_FirstElement() {
InfoItem firstInfoItem = itemsPage.getItems().get(0);
// THe channel should be the first item
assertTrue(firstInfoItem instanceof ChannelInfoItem);
assertEquals("name", "PewDiePie", firstInfoItem.getName());
assertEquals("url","https://www.youtube.com/user/PewDiePie", firstInfoItem.getUrl());
}
@Test
public void testResultListCheckIfContainsStreamItems() {
boolean hasStreams = false;
for(InfoItem item : itemsPage.getItems()) {
if(item instanceof StreamInfoItem) {
hasStreams = true;
}
}
assertTrue("Has no InfoItemStreams", hasStreams);
}
@Test
public void testGetSecondPage() throws Exception {
YoutubeSearchExtractor secondExtractor =
(YoutubeSearchExtractor) YouTube.getSearchExtractor("pewdiepie", "de");
ListExtractor.InfoItemsPage<InfoItem> secondPage = secondExtractor.getPage(itemsPage.getNextPageUrl());
assertTrue(Integer.toString(secondPage.getItems().size()),
secondPage.getItems().size() > 10);
// check if its the same result
boolean equals = true;
for (int i = 0; i < secondPage.getItems().size()
&& i < itemsPage.getItems().size(); i++) {
if(!secondPage.getItems().get(i).getUrl().equals(
itemsPage.getItems().get(i).getUrl())) {
equals = false;
}
}
assertFalse("First and second page are equal", equals);
assertEquals("https://www.youtube.com/results?q=pewdiepie&page=3", secondPage.getNextPageUrl());
}
@Test
public void testSuggestionNotNull() throws Exception {
//todo write a real test
assertTrue(extractor.getSearchSuggestion() != null);
}
@Test
public void testId() throws Exception {
assertEquals("pewdiepie", extractor.getId());
}
@Test
public void testName() {
assertEquals("pewdiepie", extractor.getName());
}
}

View File

@ -0,0 +1,59 @@
package org.schabi.newpipe.extractor.services.youtube.search;
import org.junit.Test;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.CHANNELS;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.PLAYLISTS;
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.VIDEOS;
public class YoutubeSearchQHTest {
@Test
public void testRegularValues() throws Exception {
assertEquals("https://www.youtube.com/results?q=asdf", YouTube.getSearchQHFactory().fromQuery("asdf").getUrl());
assertEquals("https://www.youtube.com/results?q=hans",YouTube.getSearchQHFactory().fromQuery("hans").getUrl());
assertEquals("https://www.youtube.com/results?q=Poifj%26jaijf", YouTube.getSearchQHFactory().fromQuery("Poifj&jaijf").getUrl());
assertEquals("https://www.youtube.com/results?q=G%C3%BCl%C3%BCm", YouTube.getSearchQHFactory().fromQuery("Gülüm").getUrl());
assertEquals("https://www.youtube.com/results?q=%3Fj%24%29H%C2%A7B", YouTube.getSearchQHFactory().fromQuery("?j$)H§B").getUrl());
}
@Test
public void testGetContentFilter() throws Exception {
assertEquals(VIDEOS, YouTube.getSearchQHFactory()
.fromQuery("", asList(new String[]{VIDEOS}), "").getContentFilters().get(0));
assertEquals(CHANNELS, YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{CHANNELS}), "").getContentFilters().get(0));
}
@Test
public void testWithContentfilter() throws Exception {
assertEquals("https://www.youtube.com/results?q=asdf&sp=EgIQAVAU", YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{VIDEOS}), "").getUrl());
assertEquals("https://www.youtube.com/results?q=asdf&sp=EgIQAlAU", YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{CHANNELS}), "").getUrl());
assertEquals("https://www.youtube.com/results?q=asdf&sp=EgIQA1AU", YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{PLAYLISTS}), "").getUrl());
assertEquals("https://www.youtube.com/results?q=asdf", YouTube.getSearchQHFactory()
.fromQuery("asdf", asList(new String[]{"fjiijie"}), "").getUrl());
}
@Test
public void testGetAvailableContentFilter() {
final String[] contentFilter = YouTube.getSearchQHFactory().getAvailableContentFilter();
assertEquals(4, contentFilter.length);
assertEquals("all", contentFilter[0]);
assertEquals("videos", contentFilter[1]);
assertEquals("channels", contentFilter[2]);
assertEquals("playlists", contentFilter[3]);
}
@Test
public void testGetAvailableSortFilter() {
final String[] contentFilter = YouTube.getSearchQHFactory().getAvailableSortFilter();
assertEquals(0, contentFilter.length);
}
}