small hacky error handling refactoring, and add link to c3s
This commit is contained in:
parent
8760792426
commit
bd6cc22e63
8 changed files with 199 additions and 135 deletions
|
@ -16,6 +16,8 @@ import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.services.VideoInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 18.08.15.
|
* Created by Christian Schabesberger on 18.08.15.
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,7 +33,7 @@ class VideoInfoItemViewCreator {
|
||||||
this.inflater = inflater;
|
this.inflater = inflater;
|
||||||
}
|
}
|
||||||
|
|
||||||
public View getViewByVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info) {
|
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info) {
|
||||||
ViewHolder holder;
|
ViewHolder holder;
|
||||||
if(convertView == null) {
|
if(convertView == null) {
|
||||||
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
@ -31,6 +32,7 @@ import android.widget.ProgressBar;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
@ -45,6 +47,7 @@ import java.util.Vector;
|
||||||
import org.schabi.newpipe.services.VideoExtractor;
|
import org.schabi.newpipe.services.VideoExtractor;
|
||||||
import org.schabi.newpipe.services.ServiceList;
|
import org.schabi.newpipe.services.ServiceList;
|
||||||
import org.schabi.newpipe.services.StreamingService;
|
import org.schabi.newpipe.services.StreamingService;
|
||||||
|
import org.schabi.newpipe.services.VideoInfo;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,7 +117,7 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
this.videoExtractor = service.getExtractorInstance(videoUrl);
|
this.videoExtractor = service.getExtractorInstance(videoUrl);
|
||||||
VideoInfo videoInfo = videoExtractor.getVideoInfo();
|
VideoInfo videoInfo = videoExtractor.getVideoInfo();
|
||||||
h.post(new VideoResultReturnedRunnable(videoInfo));
|
h.post(new VideoResultReturnedRunnable(videoInfo));
|
||||||
if (videoInfo.videoAvailableStatus == VideoInfo.VIDEO_AVAILABLE) {
|
if (videoInfo.errorCode == VideoInfo.NO_ERROR) {
|
||||||
h.post(new SetThumbnailRunnable(
|
h.post(new SetThumbnailRunnable(
|
||||||
BitmapFactory.decodeStream(
|
BitmapFactory.decodeStream(
|
||||||
new URL(videoInfo.thumbnail_url)
|
new URL(videoInfo.thumbnail_url)
|
||||||
|
@ -224,22 +227,28 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
FrameLayout nextVideoFrame = (FrameLayout) activity.findViewById(R.id.detailNextVideoFrame);
|
FrameLayout nextVideoFrame = (FrameLayout) activity.findViewById(R.id.detailNextVideoFrame);
|
||||||
RelativeLayout nextVideoRootFrame =
|
RelativeLayout nextVideoRootFrame =
|
||||||
(RelativeLayout) activity.findViewById(R.id.detailNextVideoRootLayout);
|
(RelativeLayout) activity.findViewById(R.id.detailNextVideoRootLayout);
|
||||||
View nextVideoView = videoItemViewCreator
|
Button backgroundButton = (Button)
|
||||||
.getViewByVideoInfoItem(null, nextVideoFrame, info.nextVideo);
|
activity.findViewById(R.id.detailVideoThumbnailWindowBackgroundButton);
|
||||||
nextVideoFrame.addView(nextVideoView);
|
|
||||||
Button nextVideoButton = (Button) activity.findViewById(R.id.detailNextVideoButton);
|
|
||||||
Button similarVideosButton = (Button) activity.findViewById(R.id.detailShowSimilarButton);
|
|
||||||
|
|
||||||
textContentLayout.setVisibility(View.VISIBLE);
|
|
||||||
playVideoButton.setVisibility(View.VISIBLE);
|
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
if(!showNextVideoItem) {
|
|
||||||
nextVideoRootFrame.setVisibility(View.GONE);
|
|
||||||
similarVideosButton.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (info.videoAvailableStatus) {
|
switch (info.errorCode) {
|
||||||
case VideoInfo.VIDEO_AVAILABLE: {
|
case VideoInfo.NO_ERROR: {
|
||||||
|
View nextVideoView = videoItemViewCreator
|
||||||
|
.getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo);
|
||||||
|
nextVideoFrame.addView(nextVideoView);
|
||||||
|
|
||||||
|
|
||||||
|
Button nextVideoButton = (Button) activity.findViewById(R.id.detailNextVideoButton);
|
||||||
|
Button similarVideosButton = (Button) activity.findViewById(R.id.detailShowSimilarButton);
|
||||||
|
|
||||||
|
textContentLayout.setVisibility(View.VISIBLE);
|
||||||
|
playVideoButton.setVisibility(View.VISIBLE);
|
||||||
|
if (!showNextVideoItem) {
|
||||||
|
nextVideoRootFrame.setVisibility(View.GONE);
|
||||||
|
similarVideosButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
videoTitleView.setText(info.title);
|
videoTitleView.setText(info.title);
|
||||||
uploaderView.setText(info.uploader);
|
uploaderView.setText(info.uploader);
|
||||||
actionBarHandler.setChannelName(info.uploader);
|
actionBarHandler.setChannelName(info.uploader);
|
||||||
|
@ -287,30 +296,41 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
streamList[i] = streamsToUse.get(i);
|
streamList[i] = streamsToUse.get(i);
|
||||||
}
|
}
|
||||||
actionBarHandler.setStreams(streamList, info.audioStreams);
|
actionBarHandler.setStreams(streamList, info.audioStreams);
|
||||||
}
|
|
||||||
|
|
||||||
nextVideoButton.setOnClickListener(new View.OnClickListener() {
|
nextVideoButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Intent detailIntent =
|
Intent detailIntent =
|
||||||
new Intent(getActivity(), VideoItemDetailActivity.class);
|
new Intent(getActivity(), VideoItemDetailActivity.class);
|
||||||
/*detailIntent.putExtra(
|
/*detailIntent.putExtra(
|
||||||
VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */
|
VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */
|
||||||
detailIntent.putExtra(
|
detailIntent.putExtra(
|
||||||
VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url);
|
VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url);
|
||||||
//todo: make id dynamic the following line is crap
|
//todo: make id dynamic the following line is crap
|
||||||
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
|
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
|
||||||
startActivity(detailIntent);
|
startActivity(detailIntent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case VideoInfo.VIDEO_UNAVAILABLE_GEMA:
|
case VideoInfo.ERROR_BLOCKED_BY_GEMA:
|
||||||
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
||||||
getResources(), R.drawable.gruese_die_gema_unangebracht));
|
getResources(), R.drawable.gruese_die_gema_unangebracht));
|
||||||
|
backgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(Intent.ACTION_VIEW);
|
||||||
|
intent.setData(Uri.parse(activity.getString(R.string.c3sUrl)));
|
||||||
|
activity.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case VideoInfo.VIDEO_UNAVAILABLE:
|
case VideoInfo.ERROR_NO_SPECIFIED_ERROR:
|
||||||
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
||||||
getResources(), R.drawable.not_available_monkey));
|
getResources(), R.drawable.not_available_monkey));
|
||||||
|
Toast.makeText(activity, info.errorMessage, Toast.LENGTH_LONG)
|
||||||
|
.show();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.e(TAG, "Video Available Status not known.");
|
Log.e(TAG, "Video Available Status not known.");
|
||||||
|
|
|
@ -96,7 +96,7 @@ class VideoListAdapter extends BaseAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
convertView = viewCreator.getViewByVideoInfoItem(convertView, parent, videoList.get(position));
|
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position));
|
||||||
|
|
||||||
if(listView.isItemChecked(position)) {
|
if(listView.isItemChecked(position)) {
|
||||||
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube));
|
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube));
|
||||||
|
|
|
@ -20,8 +20,6 @@ package org.schabi.newpipe.services;
|
||||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.schabi.newpipe.VideoInfo;
|
|
||||||
|
|
||||||
/**Scrapes information from a video streaming service (eg, YouTube).*/
|
/**Scrapes information from a video streaming service (eg, YouTube).*/
|
||||||
|
|
||||||
@SuppressWarnings("ALL")
|
@SuppressWarnings("ALL")
|
||||||
|
@ -46,54 +44,60 @@ public abstract class VideoExtractor {
|
||||||
videoInfo.webpage_url = pageUrl;
|
videoInfo.webpage_url = pageUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoInfo.title.isEmpty()) {
|
if(getErrorCode() == VideoInfo.NO_ERROR) {
|
||||||
videoInfo.title = getTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(videoInfo.duration < 1) {
|
if (videoInfo.title.isEmpty()) {
|
||||||
videoInfo.duration = getLength();
|
videoInfo.title = getTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (videoInfo.duration < 1) {
|
||||||
|
videoInfo.duration = getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(videoInfo.uploader.isEmpty()) {
|
if (videoInfo.uploader.isEmpty()) {
|
||||||
videoInfo.uploader = getUploader();
|
videoInfo.uploader = getUploader();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoInfo.description.isEmpty()) {
|
if (videoInfo.description.isEmpty()) {
|
||||||
videoInfo.description = getDescription();
|
videoInfo.description = getDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoInfo.view_count == -1) {
|
if (videoInfo.view_count == -1) {
|
||||||
videoInfo.view_count = getViews();
|
videoInfo.view_count = getViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoInfo.upload_date.isEmpty()) {
|
if (videoInfo.upload_date.isEmpty()) {
|
||||||
videoInfo.upload_date = getUploadDate();
|
videoInfo.upload_date = getUploadDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoInfo.thumbnail_url.isEmpty()) {
|
if (videoInfo.thumbnail_url.isEmpty()) {
|
||||||
videoInfo.thumbnail_url = getThumbnailUrl();
|
videoInfo.thumbnail_url = getThumbnailUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoInfo.id.isEmpty()) {
|
if (videoInfo.id.isEmpty()) {
|
||||||
videoInfo.id = getVideoId(pageUrl);
|
videoInfo.id = getVideoId(pageUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Load and extract audio*/
|
/** Load and extract audio*/
|
||||||
if(videoInfo.audioStreams == null) {
|
if (videoInfo.audioStreams == null) {
|
||||||
videoInfo.audioStreams = getAudioStreams();
|
videoInfo.audioStreams = getAudioStreams();
|
||||||
}
|
}
|
||||||
/** Extract video stream url*/
|
/** Extract video stream url*/
|
||||||
if(videoInfo.videoStreams == null) {
|
if (videoInfo.videoStreams == null) {
|
||||||
videoInfo.videoStreams = getVideoStreams();
|
videoInfo.videoStreams = getVideoStreams();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoInfo.uploader_thumbnail_url.isEmpty()) {
|
if (videoInfo.uploader_thumbnail_url.isEmpty()) {
|
||||||
videoInfo.uploader_thumbnail_url = getUploaderThumbnailUrl();
|
videoInfo.uploader_thumbnail_url = getUploaderThumbnailUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(videoInfo.startPosition < 0) {
|
if (videoInfo.startPosition < 0) {
|
||||||
videoInfo.startPosition = getTimeStamp();
|
videoInfo.startPosition = getTimeStamp();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
videoInfo.errorCode = getErrorCode();
|
||||||
|
videoInfo.errorMessage = getErrorMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bitmap thumbnail = null;
|
//Bitmap thumbnail = null;
|
||||||
|
@ -102,6 +106,9 @@ public abstract class VideoExtractor {
|
||||||
return videoInfo;
|
return videoInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract int getErrorCode();
|
||||||
|
protected abstract String getErrorMessage();
|
||||||
protected abstract String getVideoUrl(String videoId);
|
protected abstract String getVideoUrl(String videoId);
|
||||||
protected abstract String getVideoId(String siteUrl);
|
protected abstract String getVideoId(String siteUrl);
|
||||||
protected abstract int getTimeStamp();
|
protected abstract int getTimeStamp();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe.services;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.VideoPreviewInfo;
|
||||||
import org.schabi.newpipe.services.AbstractVideoInfo;
|
import org.schabi.newpipe.services.AbstractVideoInfo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -28,11 +29,20 @@ import java.util.List;
|
||||||
@SuppressWarnings("ALL")
|
@SuppressWarnings("ALL")
|
||||||
public class VideoInfo extends AbstractVideoInfo {
|
public class VideoInfo extends AbstractVideoInfo {
|
||||||
|
|
||||||
|
// If a video could not be parsed, this predefined error codes
|
||||||
|
// will be returned AND can be parsed by the frontend of the app.
|
||||||
|
// Error codes:
|
||||||
|
public final static int NO_ERROR = 0x0;
|
||||||
|
public final static int ERROR_NO_SPECIFIED_ERROR = 0x1;
|
||||||
|
// GEMA a german music colecting society.
|
||||||
|
public final static int ERROR_BLOCKED_BY_GEMA = 0x2;
|
||||||
|
|
||||||
public String uploader_thumbnail_url = "";
|
public String uploader_thumbnail_url = "";
|
||||||
public String description = "";
|
public String description = "";
|
||||||
public VideoStream[] videoStreams = null;
|
public VideoStream[] videoStreams = null;
|
||||||
public AudioStream[] audioStreams = null;
|
public AudioStream[] audioStreams = null;
|
||||||
public int videoAvailableStatus = VIDEO_AVAILABLE;
|
public int errorCode = NO_ERROR;
|
||||||
|
public String errorMessage = "";
|
||||||
public int duration = -1;
|
public int duration = -1;
|
||||||
|
|
||||||
/*YouTube-specific fields
|
/*YouTube-specific fields
|
||||||
|
@ -45,11 +55,6 @@ public class VideoInfo extends AbstractVideoInfo {
|
||||||
public List<VideoPreviewInfo> relatedVideos = null;
|
public List<VideoPreviewInfo> relatedVideos = null;
|
||||||
public int startPosition = -1;//in seconds. some metadata is not passed using a VideoInfo object!
|
public int startPosition = -1;//in seconds. some metadata is not passed using a VideoInfo object!
|
||||||
|
|
||||||
public static final int VIDEO_AVAILABLE = 0x00;
|
|
||||||
public static final int VIDEO_UNAVAILABLE = 0x01;
|
|
||||||
public static final int VIDEO_UNAVAILABLE_GEMA = 0x02;//German DRM organisation
|
|
||||||
|
|
||||||
|
|
||||||
public VideoInfo() {}
|
public VideoInfo() {}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import org.mozilla.javascript.ScriptableObject;
|
||||||
import org.schabi.newpipe.Downloader;
|
import org.schabi.newpipe.Downloader;
|
||||||
import org.schabi.newpipe.services.VideoExtractor;
|
import org.schabi.newpipe.services.VideoExtractor;
|
||||||
import org.schabi.newpipe.MediaFormat;
|
import org.schabi.newpipe.MediaFormat;
|
||||||
import org.schabi.newpipe.VideoInfo;
|
import org.schabi.newpipe.services.VideoInfo;
|
||||||
import org.schabi.newpipe.VideoPreviewInfo;
|
import org.schabi.newpipe.VideoPreviewInfo;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
@ -53,6 +53,8 @@ public class YoutubeVideoExtractor extends VideoExtractor {
|
||||||
private final Document doc;
|
private final Document doc;
|
||||||
private JSONObject jsonObj;
|
private JSONObject jsonObj;
|
||||||
private JSONObject playerArgs;
|
private JSONObject playerArgs;
|
||||||
|
private int errorCode = VideoInfo.NO_ERROR;
|
||||||
|
private String errorMessage = "";
|
||||||
|
|
||||||
// static values
|
// static values
|
||||||
private static final String DECRYPTION_FUNC_NAME="decrypt";
|
private static final String DECRYPTION_FUNC_NAME="decrypt";
|
||||||
|
@ -60,7 +62,6 @@ public class YoutubeVideoExtractor extends VideoExtractor {
|
||||||
// cached values
|
// cached values
|
||||||
private static volatile String decryptionCode = "";
|
private static volatile String decryptionCode = "";
|
||||||
|
|
||||||
|
|
||||||
public YoutubeVideoExtractor(String pageUrl) {
|
public YoutubeVideoExtractor(String pageUrl) {
|
||||||
super(pageUrl);//most common videoInfo fields are now set in our superclass, for all services
|
super(pageUrl);//most common videoInfo fields are now set in our superclass, for all services
|
||||||
String pageContents = Downloader.download(cleanUrl(pageUrl));
|
String pageContents = Downloader.download(cleanUrl(pageUrl));
|
||||||
|
@ -69,12 +70,18 @@ public class YoutubeVideoExtractor extends VideoExtractor {
|
||||||
//attempt to load the youtube js player JSON arguments
|
//attempt to load the youtube js player JSON arguments
|
||||||
try {
|
try {
|
||||||
String jsonString = matchGroup1("ytplayer.config\\s*=\\s*(\\{.*?\\});", pageContents);
|
String jsonString = matchGroup1("ytplayer.config\\s*=\\s*(\\{.*?\\});", pageContents);
|
||||||
|
//todo: implement this by try and catch. TESTING THE STRING AGAINST EMPTY IS CONSIDERED POOR STYLE !!!
|
||||||
|
if(jsonString.isEmpty()) {
|
||||||
|
errorCode = findErrorReason(doc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
jsonObj = new JSONObject(jsonString);
|
jsonObj = new JSONObject(jsonString);
|
||||||
playerArgs = jsonObj.getJSONObject("args");
|
playerArgs = jsonObj.getJSONObject("args");
|
||||||
|
|
||||||
} catch (Exception e) {//if this fails, the video is most likely not available.
|
} catch (Exception e) {//if this fails, the video is most likely not available.
|
||||||
// Determining why is done later.
|
// Determining why is done later.
|
||||||
videoInfo.videoAvailableStatus = VideoInfo.VIDEO_UNAVAILABLE;
|
videoInfo.errorCode = VideoInfo.ERROR_NO_SPECIFIED_ERROR;
|
||||||
Log.e(TAG, "Could not load JSON data for Youtube video \""+pageUrl+"\". This most likely means the video is unavailable");
|
Log.e(TAG, "Could not load JSON data for Youtube video \""+pageUrl+"\". This most likely means the video is unavailable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,80 +374,95 @@ public class YoutubeVideoExtractor extends VideoExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VideoInfo getVideoInfo() {
|
public VideoInfo getVideoInfo() {
|
||||||
|
//todo: @medovax i like your work, but what the fuck:
|
||||||
videoInfo = super.getVideoInfo();
|
videoInfo = super.getVideoInfo();
|
||||||
//todo: replace this with a call to getVideoId, if possible
|
|
||||||
videoInfo.id = matchGroup1("v=([0-9a-zA-Z_-]{11})", pageUrl);
|
|
||||||
|
|
||||||
if(videoInfo.audioStreams == null
|
if(errorCode == VideoInfo.NO_ERROR) {
|
||||||
|| videoInfo.audioStreams.length == 0) {
|
//todo: replace this with a call to getVideoId, if possible
|
||||||
Log.e(TAG, "uninitialised audio streams!");
|
videoInfo.id = matchGroup1("v=([0-9a-zA-Z_-]{11})", pageUrl);
|
||||||
}
|
|
||||||
|
|
||||||
if(videoInfo.videoStreams == null
|
if (videoInfo.audioStreams == null
|
||||||
|| videoInfo.videoStreams.length == 0) {
|
|| videoInfo.audioStreams.length == 0) {
|
||||||
Log.e(TAG, "uninitialised video streams!");
|
Log.e(TAG, "uninitialised audio streams!");
|
||||||
}
|
}
|
||||||
|
|
||||||
videoInfo.age_limit = 0;
|
if (videoInfo.videoStreams == null
|
||||||
|
|| videoInfo.videoStreams.length == 0) {
|
||||||
|
Log.e(TAG, "uninitialised video streams!");
|
||||||
|
}
|
||||||
|
|
||||||
//average rating
|
videoInfo.age_limit = 0;
|
||||||
try {
|
|
||||||
videoInfo.average_rating = playerArgs.getString("avg_rating");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------
|
//average rating
|
||||||
// extracting information from html page
|
try {
|
||||||
//---------------------------------------
|
videoInfo.average_rating = playerArgs.getString("avg_rating");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------
|
||||||
|
// extracting information from html page
|
||||||
|
//---------------------------------------
|
||||||
|
|
||||||
|
/* Code does not work here anymore.
|
||||||
// Determine what went wrong when the Video is not available
|
// Determine what went wrong when the Video is not available
|
||||||
if(videoInfo.videoAvailableStatus == VideoInfo.VIDEO_UNAVAILABLE) {
|
if(videoInfo.errorCode == VideoInfo.ERROR_NO_SPECIFIED_ERROR) {
|
||||||
if(doc.select("h1[id=\"unavailable-message\"]").first().text().contains("GEMA")) {
|
if(doc.select("h1[id=\"unavailable-message\"]").first().text().contains("GEMA")) {
|
||||||
videoInfo.videoAvailableStatus = VideoInfo.VIDEO_UNAVAILABLE_GEMA;
|
videoInfo.videoAvailableStatus = VideoInfo.VIDEO_UNAVAILABLE_GEMA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
String likesString = "";
|
String likesString = "";
|
||||||
String dislikesString = "";
|
String dislikesString = "";
|
||||||
try {
|
try {
|
||||||
// likes
|
// likes
|
||||||
likesString = doc.select("button.like-button-renderer-like-button").first()
|
likesString = doc.select("button.like-button-renderer-like-button").first()
|
||||||
.select("span.yt-uix-button-content").first().text();
|
.select("span.yt-uix-button-content").first().text();
|
||||||
videoInfo.like_count = Integer.parseInt(likesString.replaceAll("[^\\d]", ""));
|
videoInfo.like_count = Integer.parseInt(likesString.replaceAll("[^\\d]", ""));
|
||||||
// dislikes
|
// dislikes
|
||||||
dislikesString = doc.select("button.like-button-renderer-dislike-button").first()
|
dislikesString = doc.select("button.like-button-renderer-dislike-button").first()
|
||||||
.select("span.yt-uix-button-content").first().text();
|
.select("span.yt-uix-button-content").first().text();
|
||||||
|
|
||||||
videoInfo.dislike_count = Integer.parseInt(dislikesString.replaceAll("[^\\d]", ""));
|
videoInfo.dislike_count = Integer.parseInt(dislikesString.replaceAll("[^\\d]", ""));
|
||||||
} catch(NumberFormatException nfe) {
|
} catch (NumberFormatException nfe) {
|
||||||
Log.e(TAG, "failed to parse likesString \""+likesString+"\" and dislikesString \""+
|
Log.e(TAG, "failed to parse likesString \"" + likesString + "\" and dislikesString \"" +
|
||||||
dislikesString+"\" as integers");
|
dislikesString + "\" as integers");
|
||||||
} catch(Exception e) {
|
} catch (Exception e) {
|
||||||
// if it fails we know that the video does not offer dislikes.
|
// if it fails we know that the video does not offer dislikes.
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
videoInfo.like_count = 0;
|
videoInfo.like_count = 0;
|
||||||
videoInfo.dislike_count = 0;
|
videoInfo.dislike_count = 0;
|
||||||
}
|
|
||||||
|
|
||||||
// next video
|
|
||||||
videoInfo.nextVideo = extractVideoPreviewInfo(doc.select("div[class=\"watch-sidebar-section\"]").first()
|
|
||||||
.select("li").first());
|
|
||||||
|
|
||||||
// related videos
|
|
||||||
Vector<VideoPreviewInfo> relatedVideos = new Vector<>();
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// next video
|
||||||
|
videoInfo.nextVideo = extractVideoPreviewInfo(doc.select("div[class=\"watch-sidebar-section\"]").first()
|
||||||
|
.select("li").first());
|
||||||
|
|
||||||
|
// related videos
|
||||||
|
Vector<VideoPreviewInfo> relatedVideos = new Vector<>();
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//todo: replace conversion
|
||||||
|
videoInfo.relatedVideos = relatedVideos;
|
||||||
|
//videoInfo.relatedVideos = relatedVideos.toArray(new VideoPreviewInfo[relatedVideos.size()]);
|
||||||
}
|
}
|
||||||
//todo: replace conversion
|
|
||||||
videoInfo.relatedVideos = relatedVideos;
|
|
||||||
//videoInfo.relatedVideos = relatedVideos.toArray(new VideoPreviewInfo[relatedVideos.size()]);
|
|
||||||
return videoInfo;
|
return videoInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getErrorCode() {
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
private VideoInfo.AudioStream[] parseDashManifest(String dashManifest, String decryptoinCode) {
|
private VideoInfo.AudioStream[] parseDashManifest(String dashManifest, String decryptoinCode) {
|
||||||
if(!dashManifest.contains("/signature/")) {
|
if(!dashManifest.contains("/signature/")) {
|
||||||
|
@ -610,6 +632,13 @@ public class YoutubeVideoExtractor extends VideoExtractor {
|
||||||
new Exception("failed to find pattern \""+pattern+"\"").printStackTrace();
|
new Exception("failed to find pattern \""+pattern+"\"").printStackTrace();
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findErrorReason(Document doc) {
|
||||||
|
errorMessage = doc.select("h1[id=\"unavailable-message\"]").first().text();
|
||||||
|
if(errorMessage.contains("GEMA")) {
|
||||||
|
return VideoInfo.ERROR_BLOCKED_BY_GEMA;
|
||||||
|
}
|
||||||
|
return VideoInfo.ERROR_NO_SPECIFIED_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
<string name="settingsCategoryEtcTitle">ETC</string>
|
<string name="settingsCategoryEtcTitle">ETC</string>
|
||||||
<string name="backgroundPlayerTickerText" translatable="false">%1$s - NewPipe</string>
|
<string name="backgroundPlayerTickerText" translatable="false">%1$s - NewPipe</string>
|
||||||
<string name="backgroundPlayerStartPlayingToast">Playing in background</string>
|
<string name="backgroundPlayerStartPlayingToast">Playing in background</string>
|
||||||
|
<string name="c3sUrl" translatable="false">https://www.c3s.cc/</string>
|
||||||
|
|
||||||
<!-- Content descriptions (for better accessibility) -->
|
<!-- Content descriptions (for better accessibility) -->
|
||||||
<string name="itemThumbnailViewDescription">Video preview thumbnail</string>
|
<string name="itemThumbnailViewDescription">Video preview thumbnail</string>
|
||||||
|
|
Loading…
Reference in a new issue