Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Refactor and improvements #19

Merged
merged 1 commit into from
Aug 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ dependencies {
implementation 'org.mozilla:rhino:1.7.7.1'

testImplementation 'junit:junit:4.12'

sourceCompatibility = 1.7
targetCompatibility = 1.7
}

78 changes: 58 additions & 20 deletions src/main/java/org/schabi/newpipe/extractor/Extractor.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,73 @@
package org.schabi.newpipe.extractor;

import org.schabi.newpipe.extractor.stream.StreamInfoItemCollector;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;

import java.io.Serializable;
import java.io.IOException;

public abstract class Extractor implements Serializable {
private final int serviceId;
private final String url;
private final UrlIdHandler urlIdHandler;
private final StreamInfoItemCollector previewInfoCollector;
public abstract class Extractor {
/**
* {@link StreamingService} currently related to this extractor.<br/>
* Useful for getting other things from a service (like the url handlers for cleaning/accepting/get id from urls).
*/
private final StreamingService service;

public Extractor(UrlIdHandler urlIdHandler, int serviceId, String url) {
this.urlIdHandler = urlIdHandler;
this.serviceId = serviceId;
this.url = url;
this.previewInfoCollector = new StreamInfoItemCollector(serviceId);
/**
* Dirty/original url that was passed in the constructor.
* <p>
* What makes a url "dirty" or not is, for example, the additional parameters
* (not important as—in this case—the id):
* <pre>
* https://www.youtube.com/watch?v=a9Zf_258aTI<i>&t=4s</i> → <i><b>&t=4s</b></i>
* </pre>
* But as you can imagine, the time parameter is very important when calling, for example, {@link org.schabi.newpipe.extractor.stream.StreamExtractor#getTimeStamp()}.
*/
private final String originalUrl;

/**
* The cleaned url, result of passing the {@link #originalUrl} to the associated urlIdHandler ({@link #getUrlIdHandler()}).
* <p>
* Is lazily-cleaned by calling {@link #getCleanUrl()}
*/
private String cleanUrl;

public Extractor(StreamingService service, String url) throws ExtractionException {
this.service = service;
this.originalUrl = url;
}

public String getUrl() {
return url;
/**
* @return a {@link UrlIdHandler} of the current extractor type (e.g. a ChannelExtractor should return a channel url handler).
*/
protected abstract UrlIdHandler getUrlIdHandler() throws ParsingException;

/**
* Fetch the current page.
*/
public abstract void fetchPage() throws IOException, ExtractionException;

public String getOriginalUrl() {
return originalUrl;
}

public UrlIdHandler getUrlIdHandler() {
return urlIdHandler;
public String getCleanUrl() {
if (cleanUrl != null && !cleanUrl.isEmpty()) return cleanUrl;

try {
cleanUrl = getUrlIdHandler().cleanUrl(originalUrl);
} catch (Exception e) {
cleanUrl = null;
// Fallback to the original url
return originalUrl;
}
return cleanUrl;
}

public int getServiceId() {
return serviceId;
public StreamingService getService() {
return service;
}

protected StreamInfoItemCollector getStreamPreviewInfoCollector() {
return previewInfoCollector;
public int getServiceId() {
return service.getServiceId();
}
}
4 changes: 2 additions & 2 deletions src/main/java/org/schabi/newpipe/extractor/Info.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.schabi.newpipe.extractor;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public abstract class Info implements Serializable {

Expand All @@ -15,5 +15,5 @@ public abstract class Info implements Serializable {
public String url;
public String name;

public List<Throwable> errors = new Vector<>();
public List<Throwable> errors = new ArrayList<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.schabi.newpipe.extractor.exceptions.ExtractionException;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/*
* Created by Christian Schabesberger on 12.02.17.
Expand All @@ -26,8 +26,8 @@
*/

public abstract class InfoItemCollector {
private List<InfoItem> itemList = new Vector<>();
private List<Throwable> errors = new Vector<>();
private List<InfoItem> itemList = new ArrayList<>();
private List<Throwable> errors = new ArrayList<>();
private int serviceId = -1;

public InfoItemCollector(int serviceId) {
Expand All @@ -46,7 +46,7 @@ protected void addFromCollector(InfoItemCollector otherC) throws ExtractionExcep
if (serviceId != otherC.serviceId) {
throw new ExtractionException("Service Id does not equal: "
+ NewPipe.getNameOfService(serviceId)
+ " and " + NewPipe.getNameOfService(otherC.serviceId));
+ " and " + NewPipe.getNameOfService((otherC.serviceId)));
}
errors.addAll(otherC.errors);
itemList.addAll(otherC.itemList);
Expand Down
60 changes: 55 additions & 5 deletions src/main/java/org/schabi/newpipe/extractor/ListExtractor.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,47 @@
import org.schabi.newpipe.extractor.stream.StreamInfoItemCollector;

import java.io.IOException;
import java.util.List;

/**
* Base class to extractors that have a list (e.g. playlists, channels).
*/
public abstract class ListExtractor extends Extractor {
protected String nextStreamsUrl;

public ListExtractor(UrlIdHandler urlIdHandler, int serviceId, String url) {
super(urlIdHandler, serviceId, url);
/**
* Get a new ListExtractor with the given nextStreamsUrl set.
* <p>
* The extractor <b>WILL</b> fetch the page if {@link #fetchPageUponCreation()} return true, otherwise, it will <b>NOT</b>.
* <p>
* You can call {@link #fetchPage()} later, but this is mainly used just to get more items, so we don't waste bandwidth
* downloading the whole page, but if the service that is being implemented need it, just do its own logic in {@link #fetchPageUponCreation()}.
*/
public ListExtractor(StreamingService service, String url, String nextStreamsUrl) throws IOException, ExtractionException {
super(service, url);
setNextStreamsUrl(nextStreamsUrl);

if (fetchPageUponCreation()) {
fetchPage();
}
}

public boolean hasMoreStreams(){
return nextStreamsUrl != null && !nextStreamsUrl.isEmpty();
/**
* Decide if the page will be fetched upon creation.
* <p>
* The default implementation checks if the nextStreamsUrl is null or empty (indication that the caller
* don't need or know what is the next page, thus, fetch the page).
*/
protected boolean fetchPageUponCreation() {
return nextStreamsUrl == null || nextStreamsUrl.isEmpty();
}

public abstract StreamInfoItemCollector getNextStreams() throws ExtractionException, IOException;
public abstract StreamInfoItemCollector getStreams() throws IOException, ExtractionException;
public abstract NextItemsResult getNextStreams() throws IOException, ExtractionException;

public boolean hasMoreStreams() {
return nextStreamsUrl != null && !nextStreamsUrl.isEmpty();
}

public String getNextStreamsUrl() {
return nextStreamsUrl;
Expand All @@ -29,4 +54,29 @@ public void setNextStreamsUrl(String nextStreamsUrl) {
this.nextStreamsUrl = nextStreamsUrl;
}

/*//////////////////////////////////////////////////////////////////////////
// Inner
//////////////////////////////////////////////////////////////////////////*/

public static class NextItemsResult {
/**
* The current list of items to this result
*/
public final List<InfoItem> nextItemsList;

/**
* Next url to fetch more items
*/
public final String nextItemsUrl;

public NextItemsResult(List<InfoItem> nextItemsList, String nextItemsUrl) {
this.nextItemsList = nextItemsList;
this.nextItemsUrl = nextItemsUrl;
}

public boolean hasMoreStreams() {
return nextItemsUrl != null && !nextItemsUrl.isEmpty();
}
}

}
9 changes: 9 additions & 0 deletions src/main/java/org/schabi/newpipe/extractor/ListInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.schabi.newpipe.extractor;

import java.util.List;

public abstract class ListInfo extends Info {
public List<InfoItem> related_streams;
public boolean has_more_streams;
public String next_streams_url;
}
89 changes: 50 additions & 39 deletions src/main/java/org/schabi/newpipe/extractor/NewPipe.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.schabi.newpipe.extractor;

import org.schabi.newpipe.extractor.exceptions.ExtractionException;

/*
* Created by Christian Schabesberger on 23.08.15.
*
Expand All @@ -22,70 +20,83 @@
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/

import org.schabi.newpipe.extractor.exceptions.ExtractionException;

/**
* Provides access to the video streaming services supported by NewPipe.
* Currently only Youtube until the API becomes more stable.
* Provides access to streaming services supported by NewPipe.
*/

@SuppressWarnings("ALL")
public class NewPipe {
private static final String TAG = NewPipe.class.toString();
private static Downloader downloader = null;

private NewPipe() {
}

private static Downloader downloader = null;
public static void init(Downloader d) {
downloader = d;
}

public static Downloader getDownloader() {
return downloader;
}

/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/

public static StreamingService[] getServices() {
return ServiceList.serviceList;
final ServiceList[] values = ServiceList.values();
final StreamingService[] streamingServices = new StreamingService[values.length];

for (int i = 0; i < values.length; i++) streamingServices[i] = values[i].getService();

return streamingServices;
}

public static StreamingService getService(int serviceId) throws ExtractionException {
for (StreamingService s : ServiceList.serviceList) {
if (s.getServiceId() == serviceId) {
return s;
for (ServiceList item : ServiceList.values()) {
if (item.getService().getServiceId() == serviceId) {
return item.getService();
}
}
return null;
throw new ExtractionException("There's no service with the id = \"" + serviceId + "\"");
}

public static StreamingService getService(String serviceName) throws ExtractionException {
return ServiceList.serviceList[getIdOfService(serviceName)];
}

public static String getNameOfService(int id) {
try {
return getService(id).getServiceInfo().name;
} catch (Exception e) {
System.err.println("Service id not known");
e.printStackTrace();
return "";
for (ServiceList item : ServiceList.values()) {
if (item.getService().getServiceInfo().name.equals(serviceName)) {
return item.getService();
}
}
throw new ExtractionException("There's no service with the name = \"" + serviceName + "\"");
}

public static int getIdOfService(String serviceName) {
for (int i = 0; i < ServiceList.serviceList.length; i++) {
if (ServiceList.serviceList[i].getServiceInfo().name.equals(serviceName)) {
return i;
public static StreamingService getServiceByUrl(String url) throws ExtractionException {
for (ServiceList item : ServiceList.values()) {
if (item.getService().getLinkTypeByUrl(url) != StreamingService.LinkType.NONE) {
return item.getService();
}
}
return -1;
throw new ExtractionException("No service can handle the url = \"" + url + "\"");
}

public static void init(Downloader d) {
downloader = d;
}

public static Downloader getDownloader() {
return downloader;
public static int getIdOfService(String serviceName) {
try {
//noinspection ConstantConditions
return getService(serviceName).getServiceId();
} catch (ExtractionException ignored) {
return -1;
}
}

public static StreamingService getServiceByUrl(String url) {
for (StreamingService s : ServiceList.serviceList) {
if (s.getLinkTypeByUrl(url) != StreamingService.LinkType.NONE) {
return s;
}
public static String getNameOfService(int id) {
try {
//noinspection ConstantConditions
return getService(id).getServiceInfo().name;
} catch (Exception e) {
System.err.println("Service id not known");
e.printStackTrace();
return "<unknown>";
}
return null;
}
}
Loading