made StreamExtractor use StreamPreviewInfoCollector

This commit is contained in:
Christian Schabesberger 2016-05-22 12:39:57 +02:00
parent a4ce6c707c
commit c5544df64c
10 changed files with 180 additions and 80 deletions

View file

@ -88,7 +88,7 @@ public class VideoInfoItemViewCreator {
} else {
holder.itemViewCountView.setVisibility(View.GONE);
}
if(!info.upload_date.isEmpty()) {
if(info.upload_date != null && !info.upload_date.isEmpty()) {
holder.itemUploadDateView.setText(info.upload_date + "");
}

View file

@ -33,13 +33,13 @@ public abstract class SearchEngine {
}
}
private StreamPreviewInfoCollector collector;
private StreamPreviewInfoSearchCollector collector;
public SearchEngine(StreamUrlIdHandler urlIdHandler, int serviceId) {
collector = new StreamPreviewInfoCollector(urlIdHandler, serviceId);
collector = new StreamPreviewInfoSearchCollector(urlIdHandler, serviceId);
}
public StreamPreviewInfoCollector getStreamPreviewInfoCollector() {
protected StreamPreviewInfoSearchCollector getStreamPreviewInfoSearchCollector() {
return collector;
}
@ -48,7 +48,7 @@ public abstract class SearchEngine {
throws ExtractionException, IOException;
//Result search(String query, int page);
public abstract StreamPreviewInfoCollector search(
public abstract StreamPreviewInfoSearchCollector search(
String query, int page, String contentCountry, Downloader dl)
throws ExtractionException, IOException;
}

View file

@ -42,6 +42,6 @@ public class SearchResult {
}
public String suggestion = "";
public final List<StreamPreviewInfo> resultList = new Vector<>();
public List<StreamPreviewInfo> resultList = new Vector<>();
public List<Exception> errors = new Vector<>();
}

View file

@ -29,6 +29,10 @@ import java.util.List;
public abstract class StreamExtractor {
private int serviceId;
private String url;
private StreamUrlIdHandler urlIdHandler;
private Downloader downloader;
private StreamPreviewInfoCollector previewInfoCollector;
public class ExctractorInitException extends ExtractionException {
public ExctractorInitException(String message) {
@ -51,8 +55,26 @@ public abstract class StreamExtractor {
}
}
public StreamExtractor(String url, Downloader dl, int serviceId) {
public StreamExtractor(StreamUrlIdHandler urlIdHandler, String url, Downloader dl, int serviceId) {
this.serviceId = serviceId;
this.urlIdHandler = urlIdHandler;
previewInfoCollector = new StreamPreviewInfoCollector(urlIdHandler, serviceId);
}
protected StreamPreviewInfoCollector getStreamPreviewInfoCollector() {
return previewInfoCollector;
}
public String getUrl() {
return url;
}
public StreamUrlIdHandler getUrlIdHandler() {
return urlIdHandler;
}
public Downloader getDownloader() {
return downloader;
}
public abstract int getTimeStamp() throws ParsingException;
@ -72,9 +94,8 @@ public abstract class StreamExtractor {
public abstract String getAverageRating() throws ParsingException;
public abstract int getLikeCount() throws ParsingException;
public abstract int getDislikeCount() throws ParsingException;
public abstract StreamPreviewInfo getNextVideo() throws ParsingException;
public abstract List<StreamPreviewInfo> getRelatedVideos() throws ParsingException;
public abstract StreamUrlIdHandler getUrlIdConverter();
public abstract StreamPreviewInfoExtractor getNextVideo() throws ParsingException;
public abstract StreamPreviewInfoCollector getRelatedVideos() throws ParsingException;
public abstract String getPageUrl();
public abstract StreamInfo.StreamType getStreamType() throws ParsingException;
public int getServiceId() {

View file

@ -85,7 +85,7 @@ public class StreamInfo extends AbstractVideoInfo {
/* ---- importand data, withoug the video can't be displayed goes here: ---- */
// if one of these is not available an exception is ment to be thrown directly into the frontend.
StreamUrlIdHandler uiconv = extractor.getUrlIdConverter();
StreamUrlIdHandler uiconv = extractor.getUrlIdHandler();
streamInfo.service_id = extractor.getServiceId();
streamInfo.webpage_url = extractor.getPageUrl();
@ -229,12 +229,23 @@ public class StreamInfo extends AbstractVideoInfo {
streamInfo.addException(e);
}
try {
streamInfo.next_video = extractor.getNextVideo();
// get next video
System.out.println(extractor.getUrlIdHandler());
StreamPreviewInfoCollector c = new StreamPreviewInfoCollector(
extractor.getUrlIdHandler(), extractor.getServiceId());
c.commit(extractor.getNextVideo());
if(c.getItemList().size() != 0) {
streamInfo.next_video = c.getItemList().get(0);
}
streamInfo.errors.addAll(c.getErrors());
} catch(Exception e) {
streamInfo.addException(e);
}
try {
streamInfo.related_videos = extractor.getRelatedVideos();
// get related videos
StreamPreviewInfoCollector c = extractor.getRelatedVideos();
streamInfo.related_videos = c.getItemList();
streamInfo.errors.addAll(c.getErrors());
} catch(Exception e) {
streamInfo.addException(e);
}

View file

@ -2,6 +2,9 @@ package org.schabi.newpipe.extractor;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamUrlIdHandler;
import java.util.List;
import java.util.Vector;
/**
* Created by Christian Schabesberger on 28.02.16.
*
@ -23,7 +26,8 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamUrlIdHandler;
*/
public class StreamPreviewInfoCollector {
private SearchResult result = new SearchResult();
private List<StreamPreviewInfo> itemList = new Vector<>();
private List<Exception> errors = new Vector<>();
private StreamUrlIdHandler urlIdHandler = null;
private int serviceId = -1;
@ -32,16 +36,16 @@ public class StreamPreviewInfoCollector {
this.serviceId = serviceId;
}
public void setSuggestion(String suggestion) {
result.suggestion = suggestion;
public List<StreamPreviewInfo> getItemList() {
return itemList;
}
public List<Exception> getErrors() {
return errors;
}
public void addError(Exception e) {
result.errors.add(e);
}
public SearchResult getSearchResult() {
return result;
errors.add(e);
}
public void commit(StreamPreviewInfoExtractor extractor) throws ParsingException {
@ -84,11 +88,9 @@ public class StreamPreviewInfoCollector {
} catch (Exception e) {
addError(e);
}
result.resultList.add(resultItem);
itemList.add(resultItem);
} catch (Exception e) {
addError(e);
}
}
}

View file

@ -0,0 +1,42 @@
package org.schabi.newpipe.extractor;
/**
* Created by Christian Schabesberger on 11.05.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* StreamPreviewInfoSearchCollector.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 StreamPreviewInfoSearchCollector extends StreamPreviewInfoCollector {
private String suggestion = "";
public StreamPreviewInfoSearchCollector(StreamUrlIdHandler handler, int serviceId) {
super(handler, serviceId);
}
public void setSuggestion(String suggestion) {
this.suggestion = suggestion;
}
public SearchResult getSearchResult() {
SearchResult result = new SearchResult();
result.suggestion = suggestion;
result.errors = getErrors();
result.resultList = getItemList();
return result;
}
}

View file

@ -11,6 +11,7 @@ import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.SearchEngine;
import org.schabi.newpipe.extractor.StreamPreviewInfoCollector;
import org.schabi.newpipe.extractor.StreamPreviewInfoExtractor;
import org.schabi.newpipe.extractor.StreamPreviewInfoSearchCollector;
import org.schabi.newpipe.extractor.StreamUrlIdHandler;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@ -55,9 +56,9 @@ public class YoutubeSearchEngine extends SearchEngine {
}
@Override
public StreamPreviewInfoCollector search(String query, int page, String languageCode, Downloader downloader)
public StreamPreviewInfoSearchCollector search(String query, int page, String languageCode, Downloader downloader)
throws IOException, ExtractionException {
StreamPreviewInfoCollector collector = getStreamPreviewInfoCollector();
StreamPreviewInfoSearchCollector collector = getStreamPreviewInfoSearchCollector();
/* Cant use Uri.Bilder since it's android code.
// Android code is baned from the extractor side.

View file

@ -47,7 +47,7 @@ public class YoutubeService extends StreamingService {
throws ExtractionException, IOException {
StreamUrlIdHandler urlIdHandler = new YoutubeStreamUrlIdHandler();
if(urlIdHandler.acceptUrl(url)) {
return new YoutubeStreamExtractor(url, downloader, getServiceId());
return new YoutubeStreamExtractor(urlIdHandler, url, downloader, getServiceId());
}
else {
throw new IllegalArgumentException("supplied String is not a valid Youtube URL");

View file

@ -8,6 +8,7 @@ import org.jsoup.nodes.Element;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.ScriptableObject;
import org.schabi.newpipe.extractor.AbstractVideoInfo;
import org.schabi.newpipe.extractor.AudioStream;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.Downloader;
@ -15,6 +16,8 @@ import org.schabi.newpipe.extractor.Parser;
import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.StreamInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfoCollector;
import org.schabi.newpipe.extractor.StreamPreviewInfoExtractor;
import org.schabi.newpipe.extractor.StreamUrlIdHandler;
import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.MediaFormat;
@ -181,9 +184,10 @@ public class YoutubeStreamExtractor extends StreamExtractor {
private Downloader downloader;
public YoutubeStreamExtractor(String pageUrl, Downloader dl, int serviceId)
public YoutubeStreamExtractor(StreamUrlIdHandler urlIdHandler, String pageUrl,
Downloader dl, int serviceId)
throws ExtractionException, IOException {
super(pageUrl, dl, serviceId);
super(urlIdHandler ,pageUrl, dl, serviceId);
//most common videoInfo fields are now set in our superclass, for all services
downloader = dl;
this.pageUrl = pageUrl;
@ -648,7 +652,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
}
@Override
public StreamPreviewInfo getNextVideo() throws ParsingException {
public StreamPreviewInfoExtractor getNextVideo() throws ParsingException {
try {
return extractVideoPreviewInfo(doc.select("div[class=\"watch-sidebar-section\"]").first()
.select("li").first());
@ -658,26 +662,21 @@ public class YoutubeStreamExtractor extends StreamExtractor {
}
@Override
public Vector<StreamPreviewInfo> getRelatedVideos() throws ParsingException {
public StreamPreviewInfoCollector getRelatedVideos() throws ParsingException {
try {
Vector<StreamPreviewInfo> relatedVideos = new Vector<>();
StreamPreviewInfoCollector collector = getStreamPreviewInfoCollector();
for (Element li : doc.select("ul[id=\"watch-related\"]").first().children()) {
// first check if we have a playlist. If so leave them out
if (li.select("a[class*=\"content-link\"]").first() != null) {
relatedVideos.add(extractVideoPreviewInfo(li));
collector.commit(extractVideoPreviewInfo(li));
}
}
return relatedVideos;
return collector;
} catch(Exception e) {
throw new ParsingException("Could not get related videos", e);
}
}
@Override
public StreamUrlIdHandler getUrlIdConverter() {
return new YoutubeStreamUrlIdHandler();
}
@Override
public String getPageUrl() {
return pageUrl;
@ -692,54 +691,78 @@ public class YoutubeStreamExtractor extends StreamExtractor {
/**Provides information about links to other videos on the video page, such as related videos.
* This is encapsulated in a StreamPreviewInfo object,
* which is a subset of the fields in a full StreamInfo.*/
private StreamPreviewInfo extractVideoPreviewInfo(Element li) throws ParsingException {
StreamPreviewInfo info = new StreamPreviewInfo();
try {
info.webpage_url = li.select("a.content-link").first()
.attr("abs:href");
info.id = Parser.matchGroup1("v=([0-9a-zA-Z-]*)", info.webpage_url);
//todo: check NullPointerException causing
info.title = li.select("span.title").first().text();
//this page causes the NullPointerException, after finding it by searching for "tjvg":
//https://www.youtube.com/watch?v=Uqg0aEhLFAg
//this line is unused
//String views = li.select("span.view-count").first().text();
//Log.i(TAG, "title:"+info.title);
//Log.i(TAG, "view count:"+views);
try {
info.view_count = Long.parseLong(li.select("span.view-count")
.first().text().replaceAll("[^\\d]", ""));
} catch (Exception e) {//related videos sometimes have no view count
info.view_count = 0;
private StreamPreviewInfoExtractor extractVideoPreviewInfo(final Element li) {
return new StreamPreviewInfoExtractor() {
@Override
public AbstractVideoInfo.StreamType getStreamType() throws ParsingException {
return null;
}
info.uploader = li.select("span.g-hovercard").first().text();
info.duration = YoutubeParsingHelper.parseDurationString(
li.select("span.video-time").first().text());
@Override
public String getWebPageUrl() throws ParsingException {
return li.select("a.content-link").first().attr("abs:href");
}
Element img = li.select("img").first();
info.thumbnail_url = img.attr("abs:src");
// Sometimes youtube sends links to gif files which somehow seem to not exist
// anymore. Items with such gif also offer a secondary image source. So we are going
// to use that if we caught such an item.
if (info.thumbnail_url.contains(".gif")) {
info.thumbnail_url = img.attr("data-thumb");
@Override
public String getTitle() throws ParsingException {
//todo: check NullPointerException causing
return li.select("span.title").first().text();
//this page causes the NullPointerException, after finding it by searching for "tjvg":
//https://www.youtube.com/watch?v=Uqg0aEhLFAg
}
if (info.thumbnail_url.startsWith("//")) {
info.thumbnail_url = "https:" + info.thumbnail_url;
@Override
public int getDuration() throws ParsingException {
return YoutubeParsingHelper.parseDurationString(
li.select("span.video-time").first().text());
}
} catch (Exception e) {
throw new ParsingException("Could not get video preview info", e);
}
return info;
@Override
public String getUploader() throws ParsingException {
return li.select("span.g-hovercard").first().text();
}
@Override
public String getUploadDate() throws ParsingException {
return null;
}
@Override
public long getViewCount() throws ParsingException {
//this line is unused
//String views = li.select("span.view-count").first().text();
//Log.i(TAG, "title:"+info.title);
//Log.i(TAG, "view count:"+views);
try {
return Long.parseLong(li.select("span.view-count")
.first().text().replaceAll("[^\\d]", ""));
} catch (Exception e) {
//related videos sometimes have no view count
return 0;
}
}
@Override
public String getThumbnailUrl() throws ParsingException {
Element img = li.select("img").first();
String thumbnailUrl = img.attr("abs:src");
// Sometimes youtube sends links to gif files which somehow seem to not exist
// anymore. Items with such gif also offer a secondary image source. So we are going
// to use that if we caught such an item.
if (thumbnailUrl.contains(".gif")) {
thumbnailUrl = img.attr("data-thumb");
}
if (thumbnailUrl.startsWith("//")) {
thumbnailUrl = "https:" + thumbnailUrl;
}
return thumbnailUrl;
}
};
}
private String loadDecryptionCode(String playerUrl) throws DecryptException {
String decryptionFuncName;
String decryptionFunc;