about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--viewtube.js268
1 files changed, 94 insertions, 174 deletions
diff --git a/viewtube.js b/viewtube.js
index 0233b52..fbefce8 100644
--- a/viewtube.js
+++ b/viewtube.js
@@ -111,11 +111,7 @@
     function cleanMyContent(content, unesc) {
 	var myNewContent = content;
 	if (unesc) myNewContent = unescape(myNewContent);
-	myNewContent = myNewContent.replace(/\\u0025/g,'%');
-	myNewContent = myNewContent.replace(/\\u0026/g,'&');
-	myNewContent = myNewContent.replace(/\\/g,'');
-	myNewContent = myNewContent.replace(/\n/g,'');
-	return myNewContent;
+	return myNewContent.replace(/\\u0025/g,'%').replace(/\\u0026/g,'&').replace(/\\/g,'').replace(/\n/g,'');
     }
 
     function getMyContent(url, pattern, clean) {
@@ -147,12 +143,9 @@
 
     /* Video Availability */
     var ytVideoUnavailable = document.querySelector("#player-unavailable");
-    if (ytVideoUnavailable) {
-	if (ytVideoUnavailable.className.indexOf('hid') == -1) {
-	    var ytAgeGateContent = document.querySelector("#watch7-player-age-gate-content");
-	    if (!ytAgeGateContent) return;
-	    else if (ytAgeGateContent.indexOf('feature=private_video') != -1) return;
-	}
+    if (ytVideoUnavailable && (ytVideoUnavailable.className.indexOf('hid') == -1)) {
+	var ytAgeGateContent = document.querySelector("#watch7-player-age-gate-content");
+	if ((!ytAgeGateContent) || (ytAgeGateContent.indexOf('feature=private_video') != -1)) return;
     }
 
     /* Decrypt Signature */
@@ -161,19 +154,12 @@
     function ytDecryptFunction() {
 	var ytSignFuncName, ytSignFuncBody, ytSwapFuncName, ytSwapFuncBody, ytFuncMatch;
 	ytScriptSrc = ytScriptSrc.replace(/(\r\n|\n|\r)/gm, '');
-	ytSignFuncName = ytScriptSrc.match(/"signature"\s*,\s*([^\)]*?)\(/);
-	ytSignFuncName = (ytSignFuncName) ? ytSignFuncName[1] : null;
-	if (ytSignFuncName) {
+	if (ytSignFuncName = (ytScriptSrc.match(/"signature"\s*,\s*([^\)]*?)\(/) || [])[1]) {
 	    ytFuncMatch = ytSignFuncName.replace(/\$/, '\\$') + '\\s*=\\s*function\\s*' + '\\s*\\(\\w+\\)\\s*\\{(.*?)\\}';
-	    ytSignFuncBody = ytScriptSrc.match(ytFuncMatch);
-	    ytSignFuncBody = (ytSignFuncBody) ? ytSignFuncBody[1] : null;
-	    if (ytSignFuncBody) {
-		ytSwapFuncName = ytSignFuncBody.match(/((\$|_|\w)+)\.(\$|_|\w)+\(\w,[0-9]+\)/);
-		ytSwapFuncName = (ytSwapFuncName) ? ytSwapFuncName[1] : null;
-		if (ytSwapFuncName) {
+	    if (ytSignFuncBody = (ytScriptSrc.match(ytFuncMatch) || [])[1]) {
+		if (ytSwapFuncName = (ytSignFuncBody.match(/((\$|_|\w)+)\.(\$|_|\w)+\(\w,[0-9]+\)/) || [])[1]) {
 		    ytFuncMatch = 'var\\s+' + ytSwapFuncName.replace(/\$/, '\\$') + '=\\s*\\{(.*?)\\};';
-		    ytSwapFuncBody = ytScriptSrc.match(ytFuncMatch);
-		    ytSwapFuncBody = (ytSwapFuncBody) ? ytSwapFuncBody[1] : null;
+		    ytSwapFuncBody = (ytScriptSrc.match(ytFuncMatch) || [])[1];
 		}
 		if (ytSwapFuncBody) ytSignFuncBody = 'var ' + ytSwapFuncName + '={' + ytSwapFuncBody + '};' + ytSignFuncBody;
 		ytSignFuncBody = 'try {' + ytSignFuncBody + '} catch(e) {return null}';
@@ -192,39 +178,28 @@
 	    || ('https://img.youtube.com/vi/' + page.url.match(/(\?|&)v=(.*?)(&|$)/)[2] + '/0.jpg');
 
 	/* Get Videos Content */
-	var ytVideosEncodedFmts, ytVideosAdaptiveFmts, ytVideosContent, ytHLSVideos, ytHLSContent;
-	ytVideosEncodedFmts = getMyContent(page.url, '"url_encoded_fmt_stream_map":\\s*"(.*?)"', false)
-	    || getMyContent(page.url, '\\\\"url_encoded_fmt_stream_map\\\\":\\s*\\\\"(.*?)\\\\"', false);
+	var ytVideosEncodedFmts, ytVideosAdaptiveFmts, ytVideosContent, ytHLSVideos, ytHLSContent, ytVideoID, ytVideosInfo;
 	ytVideosAdaptiveFmts = getMyContent(page.url, '"adaptive_fmts":\\s*"(.*?)"', false)
 	    || getMyContent(page.url, '\\\\"adaptive_fmts\\\\":\\s*\\\\"(.*?)\\\\"', false);
-	if (ytVideosEncodedFmts) ytVideosContent = ytVideosEncodedFmts;
-	else {
-	    ytHLSVideos = getMyContent(page.url, '"hlsvp":\\s*"(.*?)"', false)
-		|| getMyContent(page.url, '\\\\"hlsvp\\\\":\\s*\\\\"(.*?)\\\\"', false);
-	    if (ytHLSVideos) {
-		ytHLSVideos = cleanMyContent(ytHLSVideos, false);
-		if (ytHLSVideos.indexOf('keepalive/yes/') != -1)
-		    ytHLSVideos = ytHLSVideos.replace('keepalive/yes/', '');
-	    }
-	    else {
-		var ytVideoID = page.url.match(/(\?|&)v=(.*?)(&|$)/)[2];
-		if (ytVideoID) {
-		    var ytVideoSts = getMyContent(page.url.replace(/watch.*?v=/, 'embed/').replace(/&.*$/, ''), '"sts"\\s*:\\s*(\\d+)', false);
-		    var ytVideosInfoURL = page.win.location.protocol + '//' + page.win.location.hostname + '/get_video_info?video_id=' + ytVideoID + '&eurl=https://youtube.googleapis.com/v/' + ytVideoID + '&sts=' + ytVideoSts;
-		    var ytVideosInfo = getMyContent(ytVideosInfoURL, 'TEXT', false);
-		    if (ytVideosInfo) {
-			ytVideosEncodedFmts = ytVideosInfo.match(/url_encoded_fmt_stream_map=(.*?)&/)[1];
-			if (ytVideosEncodedFmts)
-			    ytVideosContent = cleanMyContent(ytVideosEncodedFmts, true);
-			if (!ytVideosAdaptiveFmts) {
-			    ytVideosAdaptiveFmts = ytVideosInfo.match(/adaptive_fmts=(.*?)&/)[1];
-			    if (ytVideosAdaptiveFmts)
-				ytVideosAdaptiveFmts = cleanMyContent(ytVideosAdaptiveFmts, true);
-			}
-		    }
-		}
-	    }
+	if (ytVideosEncodedFmts = getMyContent(page.url, '"url_encoded_fmt_stream_map":\\s*"(.*?)"', false)
+	    || getMyContent(page.url, '\\\\"url_encoded_fmt_stream_map\\\\":\\s*\\\\"(.*?)\\\\"', false))
+	    ytVideosContent = ytVideosEncodedFmts;
+	else if (ytHLSVideos = getMyContent(page.url, '"hlsvp":\\s*"(.*?)"', false)
+		 || getMyContent(page.url, '\\\\"hlsvp\\\\":\\s*\\\\"(.*?)\\\\"', false)) {
+	    ytHLSVideos = cleanMyContent(ytHLSVideos, false);
+	    if (ytHLSVideos.indexOf('keepalive/yes/') != -1)
+		ytHLSVideos = ytHLSVideos.replace('keepalive/yes/', '');
 	}
+	else if (ytVideoID = page.url.match(/(\?|&)v=(.*?)(&|$)/)[2]) {
+	    var ytVideoSts = getMyContent(page.url.replace(/watch.*?v=/, 'embed/').replace(/&.*$/, ''), '"sts"\\s*:\\s*(\\d+)', false);
+	    var ytVideosInfoURL = page.win.location.protocol + '//' + page.win.location.hostname + '/get_video_info?video_id=' + ytVideoID + '&eurl=https://youtube.googleapis.com/v/' + ytVideoID + '&sts=' + ytVideoSts;
+	    if ((ytVideosInfo = getMyContent(ytVideosInfoURL, 'TEXT', false)) &&
+		(ytVideosEncodedFmts = ytVideosInfo.match(/url_encoded_fmt_stream_map=(.*?)&/)[1]))
+		ytVideosContent = cleanMyContent(ytVideosEncodedFmts, true);
+	    if (!ytVideosAdaptiveFmts && (ytVideosAdaptiveFmts = ytVideosInfo.match(/adaptive_fmts=(.*?)&/)[1]))
+		ytVideosAdaptiveFmts = cleanMyContent(ytVideosAdaptiveFmts, true);
+	}
+
 	if (ytVideosAdaptiveFmts && !ytHLSVideos) {
 	    if (ytVideosContent) ytVideosContent += ',' + ytVideosAdaptiveFmts;
 	    else ytVideosContent = ytVideosAdaptiveFmts;
@@ -241,26 +216,22 @@
 	removeElements("#watch7-sidebar-ads");
 
 	/* Playlist */
-	var ytPlaylist = document.querySelector("#player-playlist");
-	if (ytPlaylist) {
-	    var ytPlaceholderPlaylist = document.querySelector("#placeholder-playlist");
-	    if (ytPlaceholderPlaylist) ytPlaceholderPlaylist.appendChild(ytPlaylist);
-	}
-
-	/* My Player Window */
-	var myPlayerWindow = document.querySelector("#player-api");
+	var ytPlaylist, ytPlaceholderPlaylist;
+	if ((ytPlaylist = document.querySelector("#player-playlist"))
+	    && (ytPlaceholderPlaylist = document.querySelector("#placeholder-playlist")))
+	    ytPlaceholderPlaylist.appendChild(ytPlaylist);
 
 	/* Create Player */
 	var ytDefaultVideo = 'Low Definition MP4';
 	function ytPlayer() {
 	    player = {
 		'playerSocket': ytPlayerWindow,
-		'playerWindow': myPlayerWindow,
+		'playerWindow': document.querySelector("#player-api"),
 		'videoList': ytVideoList,
 		'videoPlay': ytDefaultVideo,
 		'videoThumb': ytVideoThumb
 	    };
-	    createMyPlayer();
+	    playMyVideo();
 	}
 
 	/* Parse Videos */
@@ -309,79 +280,46 @@
 		'303': 'Full High Definition Video WebM',
 		'313': 'Ultra High Definition Video WebM'
 	    };
-	    var ytVideoFound = false;
-	    var ytVideos = ytVideosContent.split(',');
-	    var ytVideoParse, ytVideoCodeParse, ytVideoCode, myVideoCode, ytVideo;
-	    for (var ytVideo of ytVideos) {
-		if (!ytVideo.match(/^url/)) {
-		    ytVideoParse = ytVideo.match(/(.*)(url=.*$)/);
-		    if (ytVideoParse) ytVideo = ytVideoParse[2] + '&' + ytVideoParse[1];
-		}
-		ytVideoCodeParse = ytVideo.match(/itag=(\d{1,3})/);
-		ytVideoCode = (ytVideoCodeParse) ? ytVideoCodeParse[1] : null;
-		if (ytVideoCode) {
-		    myVideoCode = ytVideoFormats[ytVideoCode];
-		    if (myVideoCode) {
-			ytVideo = cleanMyContent(ytVideo, true);
-			ytVideo = ytVideo.replace(/url=/, '').replace(/&$/, '');
-			if (ytVideo.match(/itag=/) && ytVideo.match(/itag=/g).length > 1) {
-			    if (ytVideo.match(/itag=\d{1,3}&/)) ytVideo = ytVideo.replace(/itag=\d{1,3}&/, '');
-			    else if (ytVideo.match(/&itag=\d{1,3}/)) ytVideo = ytVideo.replace(/&itag=\d{1,3}/, '');
-			}
-			if (ytVideo.match(/clen=/) && ytVideo.match(/clen=/g).length > 1) {
-			    if (ytVideo.match(/clen=\d+&/)) ytVideo = ytVideo.replace(/clen=\d+&/, '');
-			    else if (ytVideo.match(/&clen=\d+/)) ytVideo = ytVideo.replace(/&clen=\d+/, '');
-			}
-			if (ytVideo.match(/lmt=/) && ytVideo.match(/lmt=/g).length > 1) {
-			    if (ytVideo.match(/lmt=\d+&/)) ytVideo = ytVideo.replace(/lmt=\d+&/, '');
-			    else if (ytVideo.match(/&lmt=\d+/)) ytVideo = ytVideo.replace(/&lmt=\d+/, '');
-			}
-			if (ytVideo.match(/type=(video|audio).*?&/)) ytVideo = ytVideo.replace(/type=(video|audio).*?&/, '');
-			else ytVideo = ytVideo.replace(/&type=(video|audio).*$/, '');
-			if (ytVideo.match(/xtags=[^%=]*&/)) ytVideo = ytVideo.replace(/xtags=[^%=]*?&/, '');
-			else if (ytVideo.match(/&xtags=[^%=]*$/)) ytVideo = ytVideo.replace(/&xtags=[^%=]*$/, '');
-			if (ytVideo.match(/&sig=/)) ytVideo = ytVideo.replace(/&sig=/, '&signature=');
-			else if (ytVideo.match(/&s=/)) {
-			    var ytSig = ytVideo.match(/&s=(.*?)(&|$)/);
-			    if (ytSig) {
-				var s = ytSig[1];
-				s = ytDecryptSignature(s);
-				if (s) ytVideo = ytVideo.replace(/&s=.*?(&|$)/, '&signature=' + s + '$1');
-				else ytVideo = '';
-			    }
-			    else ytVideo = '';
-			}
-			ytVideo = cleanMyContent(ytVideo, true);
-			if (ytVideo.indexOf('ratebypass') == -1) ytVideo += '&ratebypass=yes';
-			if (ytVideo && ytVideo.indexOf('http') == 0) {
-			    ytVideoFound = true;
-			    ytVideoList[myVideoCode] = ytVideo;
-			}
-		    }
+	    var ytVideoParse, ytVideoCode, myVideoCode;
+	    for (var ytVideo of ytVideosContent.split(',')) {
+		if ((!ytVideo.match(/^url/)) && (ytVideoParse = ytVideo.match(/(.*)(url=.*$)/)))
+		    ytVideo = ytVideoParse[2] + '&' + ytVideoParse[1];
+		if ((ytVideoCode = (ytVideo.match(/itag=(\d{1,3})/) || [])[1])
+		    && (myVideoCode = ytVideoFormats[ytVideoCode])) {
+		    ytVideo = cleanMyContent(ytVideo, true);
+		    ytVideo = ytVideo.replace(/url=/, "");
+		    if ((ytVideo.match(/itag=/g) || []).length > 1)
+			ytVideo = ytVideo.replace(/itag=\d{1,3}/, "");
+		    if ((ytVideo.match(/clen=/g) || []).length > 1)
+			ytVideo = ytVideo.replace(/clen=\d+/, "");
+		    if ((ytVideo.match(/lmt=/g) || []).length > 1)
+			ytVideo = ytVideo.replace(/lmt=\d+/, "");
+		    ytVideo = ytVideo.replace(/type=(video|audio).*?/, "").replace(/xtags=[^%=]*?/, "");
+		    ytVideo = ytVideo.replace(/&&/g, "&").replace(/^&/, "").replace(/&$/, "");
+		    if (ytVideo.match(/&sig=/)) ytVideo = ytVideo.replace(/&sig=/, '&signature=');
+		    else if (ytVideo.match(/&s=/))
+			if ((ytSig = ytVideo.match(/&s=(.*?)(&|$)/)) &&
+			    (s = ytDecryptSignature(ytSig[1])))
+			    ytVideo = ytVideo.replace(/&s=.*?(&|$)/, '&signature=' + s + '$1');
+			else ytVideo = '';
+		    ytVideo = cleanMyContent(ytVideo, true);
+		    if (ytVideo.indexOf('ratebypass') == -1) ytVideo += '&ratebypass=yes';
+		    if (ytVideo && ytVideo.indexOf('http') == 0)
+			ytVideoList[myVideoCode] = ytVideo;
 		}
 	    }
 
-	    if (ytVideoFound) {
-		/* DASH */
-		if (!ytVideoList['Standard Definition MP4'] && ytVideoList['Standard Definition Video MP4']) ytVideoList['Standard Definition MP4'] = 'DASH';
-		if (!ytVideoList['High Definition MP4'] && ytVideoList['High Definition Video MP4']) ytVideoList['High Definition MP4'] = 'DASH';
-		if (!ytVideoList['Full High Definition MP4'] && ytVideoList['Full High Definition Video MP4']) ytVideoList['Full High Definition MP4'] = 'DASH';
-		if (!ytVideoList['Ultra High Definition MP4'] && ytVideoList['Ultra High Definition Video MP4']) ytVideoList['Ultra High Definition MP4'] = 'DASH';
-		if (!ytVideoList['Standard Definition WebM'] && ytVideoList['Standard Definition Video WebM']) ytVideoList['Standard Definition WebM'] = 'DASH';
-		if (!ytVideoList['High Definition WebM'] && ytVideoList['High Definition Video WebM']) ytVideoList['High Definition WebM'] = 'DASH';
-		if (!ytVideoList['Full High Definition WebM'] && ytVideoList['Full High Definition Video WebM']) ytVideoList['Full High Definition WebM'] = 'DASH';
-		if (!ytVideoList['Ultra High Definition WebM'] && ytVideoList['Ultra High Definition Video WebM']) ytVideoList['Ultra High Definition WebM'] = 'DASH';
-
-		/* DVL */
-		ytVideoList['Direct Video Link'] = page.url;
-
+	    if (Object.keys(ytVideoList).length > 0) {
+		for (var container of ["Standard", "High", "Full High", "Ultra High"])
+		    for (var definition of ["MP4", "WebM"])
+			if (!ytVideoList[definition + " Definition " + container] &&
+			    ytVideoList[definition + " Definition Video " + container])
+			    ytVideoList[definition + " Definition " + container] = "DASH";
 		ytPlayer();
 	    }
-	    else {
-		if (ytVideosContent.indexOf("conn=rtmp") != -1)
-		    console.log("This video uses the RTMP protocol and is not supported.");
-		else console.log("Couldn't get any video.");
-	    }
+	    else if (ytVideosContent.indexOf("conn=rtmp") != -1)
+		console.log("This video uses the RTMP protocol and is not supported.");
+	    else console.log("Couldn't get any video.");
 	}
 
 	/* Parse HLS */
@@ -395,41 +333,28 @@
 	    };
 	    ytVideoList["Any Definition MP4"] = ytHLSVideos;
 	    if (ytHLSContent) {
-		var ytHLSVideo, ytVideoCodeParse, ytVideoCode, myVideoCode;
-		var ytHLSMatcher = new RegExp('(http.*?m3u8)', 'g');
-		ytHLSVideos = ytHLSContent.match(ytHLSMatcher);
-		if (ytHLSVideos) {
-		    for (var ytHLSVideo in ytHLSVideos) {
-			ytVideoCodeParse = ytHLSVideo.match(/\/itag\/(\d{1,3})\//);
-			ytVideoCode = (ytVideoCodeParse) ? ytVideoCodeParse[1] : null;
-			if (ytVideoCode) {
+		var ytHLSVideo, ytVideoCodeParse, myVideoCode;
+		if (ytHLSVideos = ytHLSContent.match(/(http.*?m3u8)/g))
+		    for (var ytHLSVideo in ytHLSVideos)
+			if (ytVideoCode = (ytHLSVideo.match(/\/itag\/(\d{1,3})\//) || [])[1]) {
 			    myVideoCode = ytHLSFormats[ytVideoCode];
-			    if (myVideoCode && ytHLSVideo) {
+			    if (myVideoCode && ytHLSVideo)
 				ytVideoList[myVideoCode] = ytHLSVideo;
-			    }
 			}
-		    }
-		}
 	    }
-
-	    /* DVL */
-	    ytVideoList['Direct Video Link'] = page.url;
-
 	    ytDefaultVideo = 'Any Definition MP4';
 	    ytPlayer();
 	}
 
 	/* Get Videos */
-	var ytVideoList = {};
+	var ytVideoList = {}, ytScriptURL;
 	if (ytVideosContent) {
 	    if (ytVideosContent.match(/&s=/) || ytVideosContent.match(/,s=/) || ytVideosContent.match(/u0026s=/)) {
-		var ytScriptURL = getMyContent(page.url, '"js":\\s*"(.*?)"', true)
-		    || getMyContent(page.url.replace(/watch.*?v=/, 'embed/').replace(/&.*$/, ''), '"js":\\s*"(.*?)"', true);
-		if (ytScriptURL) {
+		if (ytScriptURL = getMyContent(page.url, '"js":\\s*"(.*?)"', true)
+		    || getMyContent(page.url.replace(/watch.*?v=/, 'embed/').replace(/&.*$/, ''), '"js":\\s*"(.*?)"', true)) {
 		    ytScriptURL = page.win.location.protocol + ytScriptURL;
 		    try {
-			ytScriptSrc = getMyContent(ytScriptURL, 'TEXT', false);
-			if (ytScriptSrc) ytDecryptFunction();
+			if (ytScriptSrc = getMyContent(ytScriptURL, 'TEXT', false)) ytDecryptFunction();
 			ytVideos();
 		    }
 		    catch(e) {
@@ -456,34 +381,29 @@
 	    }
 	    else ytVideos();
 	}
-	else {
-	    if (ytHLSVideos) {
+	else if (ytHLSVideos) {
+	    try {
+		ytHLSContent = getMyContent(ytHLSVideos, 'TEXT', false);
+		ytHLS();
+	    }
+	    catch(e) {
 		try {
-		    ytHLSContent = getMyContent(ytHLSVideos, 'TEXT', false);
-		    ytHLS();
+		    var oReq = new XMLHttpRequest();
+		    oReq.open("GET", ytHLSVideos);
+		    oReq.onload = function(response) {
+			if (response.readyState === 4 && response.status === 200 && response.responseText)
+			    ytHLSContent = response.responseText;
+			ytHLS();
+		    };
+		    oReq.onerror = ytHLS;
+		    oReq.send();
 		}
 		catch(e) {
-		    try {
-			var oReq = new XMLHttpRequest();
-			oReq.open("GET", ytHLSVideos);
-			oReq.onload = function(response) {
-			    if (response.readyState === 4 && response.status === 200 && response.responseText) {
-				ytHLSContent = response.responseText;
-			    }
-			    ytHLS();
-			};
-			oReq.onerror = function() {
-			    ytHLS();
-			};
-			oReq.send();
-		    }
-		    catch(e) {
-			ytHLS();
-		    }
+		    ytHLS();
 		}
 	    }
-	    else console.log("Couldn't get the videos content.");
 	}
+	else console.log("Couldn't get the videos content.");
     }
 
 })();