Youtube Multiscript

Returns youtube's old layout and adds a download button.

  1. // ==UserScript==
  2. // @name Youtube Multiscript
  3. // @description Returns youtube's old layout and adds a download button.
  4. // @author sk1pp3rFTW
  5. // @namespace https://pelican.gq/
  6. // @include http://www.youtube.com/*
  7. // @include https://www.youtube.com/*
  8. // @exclude http://www.youtube.com/embed/*
  9. // @exclude https://www.youtube.com/embed/*
  10. // @match http://www.youtube.com/*
  11. // @match https://www.youtube.com/*
  12. // @match http://s.ytimg.com/yts/jsbin/*
  13. // @match https://s.ytimg.com/yts/jsbin/*
  14. // @match http://manifest.googlevideo.com/*
  15. // @match https://manifest.googlevideo.com/*
  16. // @match http://*.googlevideo.com/videoplayback*
  17. // @match https://*.googlevideo.com/videoplayback*
  18. // @match http://*.youtube.com/videoplayback*
  19. // @match https://*.youtube.com/videoplayback*
  20. // @connect googlevideo.com
  21. // @connect ytimg.com
  22. // @grant GM_xmlhttpRequest
  23. // @grant GM_getValue
  24. // @grant GM_setValue
  25. // @run-at document-start
  26. // @license MIT License
  27. // @icon data:image/png;base64,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
  28. // @version 1.0.69
  29. // ==/UserScript==
  30. var url = window.location.href;
  31. if (url.indexOf("disable_polymer") === -1) {
  32. if (url.indexOf("?") > 0) {
  33. url += "&";
  34. } else {
  35. url += "?";
  36. }
  37. url += "disable_polymer=1";
  38. window.location.href = url;
  39. }
  40.  
  41. (function () {
  42. var FORMAT_LABEL={'18':'MP4 360p','22':'MP4 720p','43':'WebM 360p','44':'WebM 480p','45':'WebM 720p','46':'WebM 1080p','135':'MP4 480p - no audio','137':'MP4 1080p - no audio','138':'MP4 2160p - no audio','140':'M4A 128kbps - audio','264':'MP4 1440p - no audio','266':'MP4 2160p - no audio','298':'MP4 720p60 - no audio','299':'MP4 1080p60 - no audio'};
  43. var FORMAT_TYPE={'18':'mp4','22':'mp4','43':'webm','44':'webm','45':'webm','46':'webm','135':'mp4','137':'mp4','138':'mp4','140':'m4a','264':'mp4','266':'mp4','298':'mp4','299':'mp4'};
  44. var FORMAT_ORDER=['18','43','135','44','22','298','45','137','299','46','264','138','266','140'];
  45. var FORMAT_RULE={'mp4':'all','webm':'none','m4a':'all'};
  46. // all=display all versions, max=only highest quality version, none=no version
  47. // the default settings show all MP4 videos
  48. var SHOW_DASH_FORMATS=false;
  49. var BUTTON_TEXT={'ar':'تنزيل','cs':'Stáhnout','de':'Herunterladen','en':'Download','es':'Descargar','fr':'Télécharger','hi':'डाउनलोड','hu':'Letöltés','id':'Unduh','it':'Scarica','ja':'ダウンロード','ko':'내려받기','pl':'Pobierz','pt':'Baixar','ro':'Descărcați','ru':'Скачать','tr':'İndir','zh':'下载','zh-TW':'下載'};
  50. var BUTTON_TOOLTIP={'ar':'تنزيل هذا الفيديو','cs':'Stáhnout toto video','de':'Dieses Video herunterladen','en':'Download this video','es':'Descargar este vídeo','fr':'Télécharger cette vidéo','hi':'वीडियो डाउनलोड करें','hu':'Videó letöltése','id':'Unduh video ini','it':'Scarica questo video','ja':'このビデオをダウンロードする','ko':'이 비디오를 내려받기','pl':'Pobierz plik wideo','pt':'Baixar este vídeo','ro':'Descărcați acest videoclip','ru':'Скачать это видео','tr': 'Bu videoyu indir','zh':'下载此视频','zh-TW':'下載此影片'};
  51. var DECODE_RULE=[];
  52. var RANDOM=7489235179; // Math.floor(Math.random()*1234567890);
  53. var CONTAINER_ID='download-youtube-video'+RANDOM;
  54. var LISTITEM_ID='download-youtube-video-fmt'+RANDOM;
  55. var BUTTON_ID='download-youtube-video-button'+RANDOM;
  56. var DEBUG_ID='download-youtube-video-debug-info';
  57. var STORAGE_URL='download-youtube-script-url';
  58. var STORAGE_CODE='download-youtube-signature-code';
  59. var STORAGE_DASH='download-youtube-dash-enabled';
  60. var isDecodeRuleUpdated=false;
  61.  
  62. start();
  63.  
  64. function start() {
  65. var pagecontainer=document.getElementById('page-container');
  66. if (!pagecontainer) return;
  67. if (/^https?:\/\/www\.youtube.com\/watch\?/.test(window.location.href)) run();
  68. var isAjax=/class[\w\s"'-=]+spf\-link/.test(pagecontainer.innerHTML);
  69. var logocontainer=document.getElementById('logo-container');
  70. if (logocontainer && !isAjax) { // fix for blocked videos
  71. isAjax=(' '+logocontainer.className+' ').indexOf(' spf-link ')>=0;
  72. }
  73. var content=document.getElementById('content');
  74. if (isAjax && content) { // Ajax UI
  75. var mo=window.MutationObserver||window.WebKitMutationObserver;
  76. if(typeof mo!=='undefined') {
  77. var observer=new mo(function(mutations) {
  78. mutations.forEach(function(mutation) {
  79. if(mutation.addedNodes!==null) {
  80. for (var i=0; i<mutation.addedNodes.length; i++) {
  81. if (mutation.addedNodes[i].id=='watch7-main-container') { // || id=='watch7-container'
  82. run();
  83. break;
  84. }
  85. }
  86. }
  87. });
  88. });
  89. observer.observe(content, {childList: true, subtree: true}); // old value: pagecontainer
  90. } else { // MutationObserver fallback for old browsers
  91. pagecontainer.addEventListener('DOMNodeInserted', onNodeInserted, false);
  92. }
  93. }
  94. }
  95.  
  96. function onNodeInserted(e) {
  97. if (e && e.target && (e.target.id=='watch7-main-container')) { // || id=='watch7-container'
  98. run();
  99. }
  100. }
  101.  
  102. function run() {
  103. if (document.getElementById(CONTAINER_ID)) return; // check download container
  104.  
  105. var videoID, videoFormats, videoAdaptFormats, videoManifestURL, scriptURL=null;
  106. var isSignatureUpdatingStarted=false;
  107. var operaTable=new Array();
  108. var language=document.documentElement.getAttribute('lang');
  109. var textDirection='left';
  110. if (document.body.getAttribute('dir')=='rtl') {
  111. textDirection='right';
  112. }
  113. if (document.getElementById('watch7-action-buttons')) { // old UI
  114. fixTranslations(language, textDirection);
  115. }
  116.  
  117. // obtain video ID, formats map
  118.  
  119. var args=null;
  120. var usw=(typeof this.unsafeWindow !== 'undefined')?this.unsafeWindow:window; // Firefox, Opera<15
  121. if (usw.ytplayer && usw.ytplayer.config && usw.ytplayer.config.args) {
  122. args=usw.ytplayer.config.args;
  123. }
  124. if (args) {
  125. videoID=args['video_id'];
  126. videoFormats=args['url_encoded_fmt_stream_map'];
  127. videoAdaptFormats=args['adaptive_fmts'];
  128. videoManifestURL=args['dashmpd'];
  129. debug('DYVAM - Info: Standard mode. videoID '+(videoID?videoID:'none')+'; ');
  130. }
  131. if (usw.ytplayer && usw.ytplayer.config && usw.ytplayer.config.assets) {
  132. scriptURL=usw.ytplayer.config.assets.js;
  133. }
  134.  
  135. if (videoID==null) { // unsafeWindow workaround (Chrome, Opera 15+)
  136. var buffer=document.getElementById(DEBUG_ID+'2');
  137. if (buffer) {
  138. while (buffer.firstChild) {
  139. buffer.removeChild(buffer.firstChild);
  140. }
  141. } else {
  142. buffer=createHiddenElem('pre', DEBUG_ID+'2');
  143. }
  144. injectScript ('if(ytplayer&&ytplayer.config&&ytplayer.config.args){document.getElementById("'+DEBUG_ID+'2").appendChild(document.createTextNode(\'"video_id":"\'+ytplayer.config.args.video_id+\'", "js":"\'+ytplayer.config.assets.js+\'", "dashmpd":"\'+ytplayer.config.args.dashmpd+\'", "url_encoded_fmt_stream_map":"\'+ytplayer.config.args.url_encoded_fmt_stream_map+\'", "adaptive_fmts":"\'+ytplayer.config.args.adaptive_fmts+\'"\'));}');
  145. var code=buffer.innerHTML;
  146. if (code) {
  147. videoID=findMatch(code, /\"video_id\":\s*\"([^\"]+)\"/);
  148. videoFormats=findMatch(code, /\"url_encoded_fmt_stream_map\":\s*\"([^\"]+)\"/);
  149. videoFormats=videoFormats.replace(/&amp;/g,'\\u0026');
  150. videoAdaptFormats=findMatch(code, /\"adaptive_fmts\":\s*\"([^\"]+)\"/);
  151. videoAdaptFormats=videoAdaptFormats.replace(/&amp;/g,'\\u0026');
  152. videoManifestURL=findMatch(code, /\"dashmpd\":\s*\"([^\"]+)\"/);
  153. scriptURL=findMatch(code, /\"js\":\s*\"([^\"]+)\"/);
  154. }
  155. debug('DYVAM - Info: Injection mode. videoID '+(videoID?videoID:'none')+'; ');
  156. }
  157.  
  158. if (videoID==null) { // if all else fails
  159. var bodyContent=document.body.innerHTML;
  160. if (bodyContent!=null) {
  161. videoID=findMatch(bodyContent, /\"video_id\":\s*\"([^\"]+)\"/);
  162. videoFormats=findMatch(bodyContent, /\"url_encoded_fmt_stream_map\":\s*\"([^\"]+)\"/);
  163. videoAdaptFormats=findMatch(bodyContent, /\"adaptive_fmts\":\s*\"([^\"]+)\"/);
  164. videoManifestURL=findMatch(bodyContent, /\"dashmpd\":\s*\"([^\"]+)\"/);
  165. if (scriptURL==null) {
  166. scriptURL=findMatch(bodyContent, /\"js\":\s*\"([^\"]+)\"/);
  167. if (scriptURL) {
  168. scriptURL=scriptURL.replace(/\\/g,'');
  169. }
  170. }
  171. }
  172. debug('DYVAM - Info: Brute mode. videoID '+(videoID?videoID:'none')+'; ');
  173. }
  174.  
  175. debug('DYVAM - Info: url '+window.location.href+'; useragent '+window.navigator.userAgent);
  176.  
  177. if (videoID==null || videoFormats==null || videoID.length==0 || videoFormats.length==0) {
  178. debug('DYVAM - Error: No config information found. YouTube must have changed the code.');
  179. return;
  180. }
  181.  
  182. // Opera 12 extension message handler
  183. if (typeof window.opera !== 'undefined' && window.opera && typeof opera.extension !== 'undefined') {
  184. opera.extension.onmessage = function(event) {
  185. var index=findMatch(event.data.action, /xhr\-([0-9]+)\-response/);
  186. if (index && operaTable[parseInt(index,10)]) {
  187. index=parseInt(index,10);
  188. var trigger=(operaTable[index])['onload'];
  189. if (typeof trigger === 'function' && event.data.readyState == 4) {
  190. if (trigger) {
  191. trigger(event.data);
  192. }
  193. }
  194. }
  195. }
  196. }
  197.  
  198. if (!isDecodeRuleUpdated) {
  199. DECODE_RULE=getDecodeRules(DECODE_RULE);
  200. isDecodeRuleUpdated=true;
  201. }
  202. if (scriptURL) {
  203. scriptURL = absoluteURL(scriptURL);
  204. debug('DYVAM - Info: Full script URL: '+scriptURL);
  205. fetchSignatureScript(scriptURL);
  206. }
  207.  
  208. // video title
  209. var videoTitle=document.title || 'video';
  210. videoTitle=videoTitle.replace(/\s*\-\s*YouTube$/i, '').replace(/'/g, '\'').replace(/^\s+|\s+$/g, '').replace(/\.+$/g, '');
  211. videoTitle=videoTitle.replace(/[:"\?\*]/g, '').replace(/[\|\\\/]/g, '_'); // Mac, Linux, Windows
  212. if (((window.navigator.userAgent || '').toLowerCase()).indexOf('windows') >= 0) {
  213. videoTitle=videoTitle.replace(/#/g, '').replace(/&/g, '_'); // Windows
  214. } else {
  215. videoTitle=videoTitle.replace(/#/g, '%23').replace(/&/g, '%26'); // Mac, Linux
  216. }
  217.  
  218. // parse the formats map
  219. var sep1='%2C', sep2='%26', sep3='%3D';
  220. if (videoFormats.indexOf(',')>-1||videoFormats.indexOf('&')>-1||videoFormats.indexOf('\\u0026')>-1) {
  221. sep1=',';
  222. sep2=(videoFormats.indexOf('&')>-1)?'&':'\\u0026';
  223. sep3='=';
  224. }
  225. var videoURL=new Array();
  226. var videoSignature=new Array();
  227. if (videoAdaptFormats) {
  228. videoFormats=videoFormats+sep1+videoAdaptFormats;
  229. }
  230. var videoFormatsGroup=videoFormats.split(sep1);
  231. for (var i=0;i<videoFormatsGroup.length;i++) {
  232. var videoFormatsElem=videoFormatsGroup[i].split(sep2);
  233. var videoFormatsPair=new Array();
  234. for (var j=0;j<videoFormatsElem.length;j++) {
  235. var pair=videoFormatsElem[j].split(sep3);
  236. if (pair.length==2) {
  237. videoFormatsPair[pair[0]]=pair[1];
  238. }
  239. }
  240. if (videoFormatsPair['url']==null) continue;
  241. var url=unescape(unescape(videoFormatsPair['url'])).replace(/\\\//g,'/').replace(/\\u0026/g,'&');
  242. if (videoFormatsPair['itag']==null) continue;
  243. var itag=videoFormatsPair['itag'];
  244. var sig=videoFormatsPair['sig']||videoFormatsPair['signature'];
  245. if (sig) {
  246. url=url+'&signature='+sig;
  247. videoSignature[itag]=null;
  248. } else if (videoFormatsPair['s']) {
  249. url=url+'&signature='+decryptSignature(videoFormatsPair['s']);
  250. videoSignature[itag]=videoFormatsPair['s'];
  251. }
  252. if (url.toLowerCase().indexOf('ratebypass')==-1) { // speed up download for dash
  253. url=url+'&ratebypass=yes';
  254. }
  255. if (url.toLowerCase().indexOf('http')==0) { // validate URL
  256. videoURL[itag]=url+'&title='+videoTitle;
  257. }
  258. }
  259.  
  260. var showFormat=new Array();
  261. for (var category in FORMAT_RULE) {
  262. var rule=FORMAT_RULE[category];
  263. for (var index in FORMAT_TYPE){
  264. if (FORMAT_TYPE[index]==category) {
  265. showFormat[index]=(rule=='all');
  266. }
  267. }
  268. if (rule=='max') {
  269. for (var i=FORMAT_ORDER.length-1;i>=0;i--) {
  270. var format=FORMAT_ORDER[i];
  271. if (FORMAT_TYPE[format]==category && videoURL[format]!=undefined) {
  272. showFormat[format]=true;
  273. break;
  274. }
  275. }
  276. }
  277. }
  278.  
  279. var dashPref=getPref(STORAGE_DASH);
  280. if (dashPref=='1') {
  281. SHOW_DASH_FORMATS=true;
  282. } else if (dashPref!='0') {
  283. setPref(STORAGE_DASH,'0');
  284. }
  285.  
  286. var downloadCodeList=[];
  287. for (var i=0;i<FORMAT_ORDER.length;i++) {
  288. var format=FORMAT_ORDER[i];
  289. if (format=='37' && videoURL[format]==undefined) { // hack for dash 1080p
  290. if (videoURL['137']) {
  291. format='137';
  292. }
  293. showFormat[format]=showFormat['37'];
  294. } else if (format=='38' && videoURL[format]==undefined) { // hack for dash 4K
  295. if (videoURL['138'] && !videoURL['266']) {
  296. format='138';
  297. }
  298. showFormat[format]=showFormat['38'];
  299. }
  300. if (!SHOW_DASH_FORMATS && format.length>2) continue;
  301. if (videoURL[format]!=undefined && FORMAT_LABEL[format]!=undefined && showFormat[format]) {
  302. downloadCodeList.push({url:videoURL[format],sig:videoSignature[format],format:format,label:FORMAT_LABEL[format]});
  303. debug('DYVAM - Info: itag'+format+' url:'+videoURL[format]);
  304. }
  305. }
  306.  
  307. if (downloadCodeList.length==0) {
  308. debug('DYVAM - Error: No download URL found. Probably YouTube uses encrypted streams.');
  309. return; // no format
  310. }
  311.  
  312. // find parent container
  313. var newWatchPage=false;
  314. var parentElement=document.getElementById('watch7-action-buttons');
  315. if (parentElement==null) {
  316. parentElement=document.getElementById('watch8-secondary-actions');
  317. if (parentElement==null) {
  318. debug('DYVAM Error - No container for adding the download button. YouTube must have changed the code.');
  319. return;
  320. } else {
  321. newWatchPage=true;
  322. }
  323. }
  324.  
  325. // get button labels
  326. var buttonText=(BUTTON_TEXT[language])?BUTTON_TEXT[language]:BUTTON_TEXT['en'];
  327. var buttonLabel=(BUTTON_TOOLTIP[language])?BUTTON_TOOLTIP[language]:BUTTON_TOOLTIP['en'];
  328.  
  329. // generate download code for regular interface
  330. var mainSpan=document.createElement('span');
  331.  
  332. if (newWatchPage) {
  333. var spanIcon=document.createElement('span');
  334. spanIcon.setAttribute('class', 'yt-uix-button-icon-wrapper');
  335. var imageIcon=document.createElement('img');
  336. imageIcon.setAttribute('src', '//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif');
  337. imageIcon.setAttribute('class', 'yt-uix-button-icon');
  338. imageIcon.setAttribute('style', 'width:20px;height:20px;background-size:20px 20px;background-repeat:no-repeat;background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABG0lEQVRYR+2W0Q3CMAxE2wkYAdiEEWADmIxuACMwCmzABpCTEmRSO7YTQX+ChECV43t2nF7GYeHPuLD+0AKwC/DnWMAp/N5qimkBuAfBdRTF/+2/AV6ZYFUxVYuicAfoHegd6B3oHfhZB+ByF+JyV8FkrAB74pqH3DU5L3iGoBURhdVODIQF4EjEkWLmmhYALOQgNIBcHHke4buhxXAAaFnaAhqbQ5QAOHHkwhZ8balkx1ICCiEBWNZ+CivdB7REHIC2ZjZK2oWklDDdB1NSdCd/Js2PqQMpSIKYVcM8kE6QCwDBNRCqOBJrW0CL8kCYxL0A1k6YxWsANAiXeC2ABOEWbwHAWrwxpzgkmA/JtIqnxTOElmPnjlkc4A3FykAhA42AxwAAAABJRU5ErkJggg==);');
  339. spanIcon.appendChild(imageIcon);
  340. mainSpan.appendChild(spanIcon);
  341. }
  342.  
  343. var spanButton=document.createElement('span');
  344. spanButton.setAttribute('class', 'yt-uix-button-content');
  345. spanButton.appendChild(document.createTextNode(buttonText+' '));
  346. mainSpan.appendChild(spanButton);
  347.  
  348. if (!newWatchPage) { // old UI
  349. var imgButton=document.createElement('img');
  350. imgButton.setAttribute('class', 'yt-uix-button-arrow');
  351. imgButton.setAttribute('src', '//s.ytimg.com/yt/img/pixel-vfl3z5WfW.gif');
  352. mainSpan.appendChild(imgButton);
  353. }
  354.  
  355. var listItems=document.createElement('ol');
  356. listItems.setAttribute('style', 'display:none;');
  357. listItems.setAttribute('class', 'yt-uix-button-menu');
  358. for (var i=0;i<downloadCodeList.length;i++) {
  359. var listItem=document.createElement('li');
  360. var listLink=document.createElement('a');
  361. listLink.setAttribute('style', 'text-decoration:none;');
  362. listLink.setAttribute('href', downloadCodeList[i].url);
  363. listLink.setAttribute('download', videoTitle+'.'+FORMAT_TYPE[downloadCodeList[i].format]);
  364. var listButton=document.createElement('span');
  365. listButton.setAttribute('class', 'yt-uix-button-menu-item');
  366. listButton.setAttribute('loop', i+'');
  367. listButton.setAttribute('id', LISTITEM_ID+downloadCodeList[i].format);
  368. listButton.appendChild(document.createTextNode(downloadCodeList[i].label));
  369. listLink.appendChild(listButton);
  370. listItem.appendChild(listLink);
  371. listItems.appendChild(listItem);
  372. }
  373. mainSpan.appendChild(listItems);
  374. var buttonElement=document.createElement('button');
  375. buttonElement.setAttribute('id', BUTTON_ID);
  376. if (newWatchPage) {
  377. buttonElement.setAttribute('class', 'yt-uix-button yt-uix-button-size-default yt-uix-button-opacity yt-uix-tooltip');
  378. } else { // old UI
  379. buttonElement.setAttribute('class', 'yt-uix-button yt-uix-tooltip yt-uix-button-empty yt-uix-button-text');
  380. buttonElement.setAttribute('style', 'margin-top:4px; margin-left:'+((textDirection=='left')?5:10)+'px;');
  381. }
  382. buttonElement.setAttribute('data-tooltip-text', buttonLabel);
  383. buttonElement.setAttribute('type', 'button');
  384. buttonElement.setAttribute('role', 'button');
  385. buttonElement.addEventListener('click', function(){return false;}, false);
  386. buttonElement.appendChild(mainSpan);
  387. var containerSpan=document.createElement('span');
  388. containerSpan.setAttribute('id', CONTAINER_ID);
  389. containerSpan.appendChild(document.createTextNode(' '));
  390. containerSpan.appendChild(buttonElement);
  391.  
  392. // add the button
  393. if (!newWatchPage) { // watch7
  394. parentElement.appendChild(containerSpan);
  395. } else { // watch8
  396. parentElement.insertBefore(containerSpan, parentElement.firstChild);
  397. }
  398.  
  399. // REPLACEWITH if (!isSignatureUpdatingStarted) {
  400. for (var i=0;i<downloadCodeList.length;i++) {
  401. addFileSize(downloadCodeList[i].url, downloadCodeList[i].format);
  402. }
  403. // }
  404.  
  405. if (typeof GM_download !== 'undefined') {
  406. for (var i=0;i<downloadCodeList.length;i++) {
  407. var downloadFMT=document.getElementById(LISTITEM_ID+downloadCodeList[i].format);
  408. var url=(downloadCodeList[i].url).toLowerCase();
  409. if (url.indexOf('clen=')>0 && url.indexOf('dur=')>0 && url.indexOf('gir=')>0
  410. && url.indexOf('lmt=')>0) {
  411. downloadFMT.addEventListener('click', downloadVideoNatively, false);
  412. }
  413. }
  414. }
  415.  
  416. addFromManifest();
  417.  
  418. function downloadVideoNatively(e) {
  419. var elem=e.currentTarget;
  420. e.returnValue=false;
  421. if (e.preventDefault) {
  422. e.preventDefault();
  423. }
  424. var loop=elem.getAttribute('loop');
  425. if (loop) {
  426. GM_download(downloadCodeList[loop].url, videoTitle+'.'+FORMAT_TYPE[downloadCodeList[loop].format]);
  427. }
  428. return false;
  429. }
  430.  
  431. function addFromManifest() { // add Dash URLs from manifest file
  432. var formats=['137', '138', '140']; // 137=1080p, 138=4k, 140=m4a
  433. var isNecessary=true;
  434. for (var i=0;i<formats.length;i++) {
  435. if (videoURL[formats[i]]) {
  436. isNecessary=false;
  437. break;
  438. }
  439. }
  440. if (videoManifestURL && SHOW_DASH_FORMATS && isNecessary) {
  441. var matchSig=findMatch(videoManifestURL, /\/s\/([a-zA-Z0-9\.]+)\//i);
  442. if (matchSig) {
  443. var decryptedSig=decryptSignature(matchSig);
  444. if (decryptedSig) {
  445. videoManifestURL=videoManifestURL.replace('/s/'+matchSig+'/','/signature/'+decryptedSig+'/');
  446. }
  447. }
  448. videoManifestURL=absoluteURL(videoManifestURL);
  449. debug('DYVAM - Info: manifestURL '+videoManifestURL);
  450. crossXmlHttpRequest({
  451. method:'GET',
  452. url:videoManifestURL, // check if URL exists
  453. onload:function(response) {
  454. if (response.readyState === 4 && response.status === 200 && response.responseText) {
  455. debug('DYVAM - Info: maniestFileContents '+response.responseText);
  456. var lastFormatFromList=downloadCodeList[downloadCodeList.length-1].format;
  457. debug('DYVAM - Info: lastformat: '+lastFormatFromList);
  458. for (var i=0;i<formats.length;i++) {
  459. k=formats[i];
  460. if (videoURL[k] || showFormat[k]==false) continue;
  461. var regexp = new RegExp('<BaseURL>(http[^<]+itag\\/'+k+'[^<]+)<\\/BaseURL>','i');
  462. var matchURL=findMatch(response.responseText, regexp);
  463. debug('DYVAM - Info: matchURL itag= '+k+' url= '+matchURL);
  464. if (!matchURL) continue;
  465. matchURL=matchURL.replace(/&amp\;/g,'&');
  466. // ...
  467. downloadCodeList.push(
  468. {url:matchURL,sig:videoSignature[k],format:k,label:FORMAT_LABEL[k]});
  469. var downloadFMT=document.getElementById(LISTITEM_ID+lastFormatFromList);
  470. var clone=downloadFMT.parentNode.parentNode.cloneNode(true);
  471. clone.firstChild.firstChild.setAttribute('id', LISTITEM_ID+k);
  472. clone.firstChild.setAttribute('href', matchURL);
  473. downloadFMT.parentNode.parentNode.parentNode.appendChild(clone);
  474. downloadFMT=document.getElementById(LISTITEM_ID+k);
  475. downloadFMT.firstChild.nodeValue=FORMAT_LABEL[k];
  476. addFileSize(matchURL, k);
  477. lastFormatFromList=k;
  478. }
  479. }
  480. }
  481. });
  482. }
  483. }
  484.  
  485. function injectStyle(code) {
  486. var style=document.createElement('style');
  487. style.type='text/css';
  488. style.appendChild(document.createTextNode(code));
  489. document.getElementsByTagName('head')[0].appendChild(style);
  490. }
  491.  
  492. function injectScript(code) {
  493. var script=document.createElement('script');
  494. script.type='application/javascript';
  495. script.textContent=code;
  496. document.body.appendChild(script);
  497. document.body.removeChild(script);
  498. }
  499.  
  500. function debug(str) {
  501. var debugElem=document.getElementById(DEBUG_ID);
  502. if (!debugElem) {
  503. debugElem=createHiddenElem('div', DEBUG_ID);
  504. }
  505. debugElem.appendChild(document.createTextNode(str+' '));
  506. }
  507.  
  508. function createHiddenElem(tag, id) {
  509. var elem=document.createElement(tag);
  510. elem.setAttribute('id', id);
  511. elem.setAttribute('style', 'display:none;');
  512. document.body.appendChild(elem);
  513. return elem;
  514. }
  515.  
  516. function fixTranslations(language, textDirection) {
  517. if (/^af|bg|bn|ca|cs|de|el|es|et|eu|fa|fi|fil|fr|gl|hi|hr|hu|id|it|iw|kn|lv|lt|ml|mr|ms|nl|pl|ro|ru|sl|sk|sr|sw|ta|te|th|uk|ur|vi|zu$/.test(language)) { // fix international UI
  518. var likeButton=document.getElementById('watch-like');
  519. if (likeButton) {
  520. var spanElements=likeButton.getElementsByClassName('yt-uix-button-content');
  521. if (spanElements) {
  522. spanElements[0].style.display='none'; // hide like text
  523. }
  524. }
  525. var marginPixels=10;
  526. if (/^bg|ca|cs|el|eu|hr|it|ml|ms|pl|sl|sw|te$/.test(language)) {
  527. marginPixels=1;
  528. }
  529. injectStyle('#watch7-secondary-actions .yt-uix-button{margin-'+textDirection+':'+marginPixels+'px!important}');
  530. }
  531. }
  532.  
  533. function findMatch(text, regexp) {
  534. var matches=text.match(regexp);
  535. return (matches)?matches[1]:null;
  536. }
  537.  
  538. function isString(s) {
  539. return (typeof s==='string' || s instanceof String);
  540. }
  541.  
  542. function isInteger(n) {
  543. return (typeof n==='number' && n%1==0);
  544. }
  545.  
  546. function absoluteURL(url) {
  547. var link = document.createElement('a');
  548. link.href = url;
  549. return link.href;
  550. }
  551.  
  552. function getPref(name) { // cross-browser GM_getValue
  553. var a='', b='';
  554. try {a=typeof GM_getValue.toString; b=GM_getValue.toString()} catch(e){}
  555. if (typeof GM_getValue === 'function' &&
  556. (a === 'undefined' || b.indexOf('not supported') === -1)) {
  557. return GM_getValue(name, null); // Greasemonkey, Tampermonkey, Firefox extension
  558. } else {
  559. var ls=null;
  560. try {ls=window.localStorage||null} catch(e){}
  561. if (ls) {
  562. return ls.getItem(name); // Chrome script, Opera extensions
  563. }
  564. }
  565. return;
  566. }
  567.  
  568. function setPref(name, value) { // cross-browser GM_setValue
  569. var a='', b='';
  570. try {a=typeof GM_setValue.toString; b=GM_setValue.toString()} catch(e){}
  571. if (typeof GM_setValue === 'function' &&
  572. (a === 'undefined' || b.indexOf('not supported') === -1)) {
  573. GM_setValue(name, value); // Greasemonkey, Tampermonkey, Firefox extension
  574. } else {
  575. var ls=null;
  576. try {ls=window.localStorage||null} catch(e){}
  577. if (ls) {
  578. return ls.setItem(name, value); // Chrome script, Opera extensions
  579. }
  580. }
  581. }
  582.  
  583. function crossXmlHttpRequest(details) { // cross-browser GM_xmlhttpRequest
  584. if (typeof GM_xmlhttpRequest === 'function') { // Greasemonkey, Tampermonkey, Firefox extension, Chrome script
  585. GM_xmlhttpRequest(details);
  586. } else if (typeof window.opera !== 'undefined' && window.opera && typeof opera.extension !== 'undefined' &&
  587. typeof opera.extension.postMessage !== 'undefined') { // Opera 12 extension
  588. var index=operaTable.length;
  589. opera.extension.postMessage({'action':'xhr-'+index, 'url':details.url, 'method':details.method});
  590. operaTable[index]=details;
  591. } else if (typeof window.opera === 'undefined' && typeof XMLHttpRequest === 'function') { // Opera 15+ extension
  592. var xhr=new XMLHttpRequest();
  593. xhr.onreadystatechange = function() {
  594. if (xhr.readyState == 4) {
  595. if (details['onload']) {
  596. details['onload'](xhr);
  597. }
  598. }
  599. }
  600. xhr.open(details.method, details.url, true);
  601. xhr.send();
  602. }
  603. }
  604.  
  605. function addFileSize(url, format) {
  606.  
  607. function updateVideoLabel(size, format) {
  608. var elem=document.getElementById(LISTITEM_ID+format);
  609. if (elem) {
  610. size=parseInt(size,10);
  611. if (size>=1073741824) {
  612. size=parseFloat((size/1073741824).toFixed(1))+' GB';
  613. } else if (size>=1048576) {
  614. size=parseFloat((size/1048576).toFixed(1))+' MB';
  615. } else {
  616. size=parseFloat((size/1024).toFixed(1))+' KB';
  617. }
  618. if (elem.childNodes.length>1) {
  619. elem.lastChild.nodeValue=' ('+size+')';
  620. } else if (elem.childNodes.length==1) {
  621. elem.appendChild(document.createTextNode(' ('+size+')'));
  622. }
  623. }
  624. }
  625.  
  626. var matchSize=findMatch(url, /[&\?]clen=([0-9]+)&/i);
  627. if (matchSize) {
  628. updateVideoLabel(matchSize, format);
  629. } else {
  630. try {
  631. crossXmlHttpRequest({
  632. method:'HEAD',
  633. url:url,
  634. onload:function(response) {
  635. if (response.readyState == 4 && response.status == 200) { // add size
  636. var size=0;
  637. if (typeof response.getResponseHeader === 'function') {
  638. size=response.getResponseHeader('Content-length');
  639. } else if (response.responseHeaders) {
  640. var regexp = new RegExp('^Content\-length: (.*)$','im');
  641. var match = regexp.exec(response.responseHeaders);
  642. if (match) {
  643. size=match[1];
  644. }
  645. }
  646. if (size) {
  647. updateVideoLabel(size, format);
  648. }
  649. }
  650. }
  651. });
  652. } catch(e) { }
  653. }
  654. }
  655.  
  656. function findSignatureCode(sourceCode) {
  657. debug('DYVAM - Info: signature start '+getPref(STORAGE_CODE));
  658. var signatureFunctionName =
  659. findMatch(sourceCode,
  660. /\.set\s*\("signature"\s*,\s*([a-zA-Z0-9_$][\w$]*)\(/)
  661. || findMatch(sourceCode,
  662. /\.sig\s*\|\|\s*([a-zA-Z0-9_$][\w$]*)\(/)
  663. || findMatch(sourceCode,
  664. /\.signature\s*=\s*([a-zA-Z_$][\w$]*)\([a-zA-Z_$][\w$]*\)/); //old
  665. if (signatureFunctionName == null) return setPref(STORAGE_CODE, 'error');
  666. signatureFunctionName=signatureFunctionName.replace('$','\\$');
  667. var regCode = new RegExp(signatureFunctionName + '\\s*=\\s*function' +
  668. '\\s*\\([\\w$]*\\)\\s*{[\\w$]*=[\\w$]*\\.split\\(""\\);\n*(.+);return [\\w$]*\\.join');
  669. var regCode2 = new RegExp('function \\s*' + signatureFunctionName +
  670. '\\s*\\([\\w$]*\\)\\s*{[\\w$]*=[\\w$]*\\.split\\(""\\);\n*(.+);return [\\w$]*\\.join');
  671. var functionCode = findMatch(sourceCode, regCode) || findMatch(sourceCode, regCode2);
  672. debug('DYVAM - Info: signaturefunction ' + signatureFunctionName + ' -- ' + functionCode);
  673. if (functionCode == null) return setPref(STORAGE_CODE, 'error');
  674.  
  675. var reverseFunctionName = findMatch(sourceCode,
  676. /([\w$]*)\s*:\s*function\s*\(\s*[\w$]*\s*\)\s*{\s*(?:return\s*)?[\w$]*\.reverse\s*\(\s*\)\s*}/);
  677. debug('DYVAM - Info: reversefunction ' + reverseFunctionName);
  678. if (reverseFunctionName) reverseFunctionName=reverseFunctionName.replace('$','\\$');
  679. var sliceFunctionName = findMatch(sourceCode,
  680. /([\w$]*)\s*:\s*function\s*\(\s*[\w$]*\s*,\s*[\w$]*\s*\)\s*{\s*(?:return\s*)?[\w$]*\.(?:slice|splice)\(.+\)\s*}/);
  681. debug('DYVAM - Info: slicefunction ' + sliceFunctionName);
  682. if (sliceFunctionName) sliceFunctionName=sliceFunctionName.replace('$','\\$');
  683.  
  684. var regSlice = new RegExp('\\.(?:'+'slice'+(sliceFunctionName?'|'+sliceFunctionName:'')+
  685. ')\\s*\\(\\s*(?:[a-zA-Z_$][\\w$]*\\s*,)?\\s*([0-9]+)\\s*\\)'); // .slice(5) sau .Hf(a,5)
  686. var regReverse = new RegExp('\\.(?:'+'reverse'+(reverseFunctionName?'|'+reverseFunctionName:'')+
  687. ')\\s*\\([^\\)]*\\)'); // .reverse() sau .Gf(a,45)
  688. var regSwap = new RegExp('[\\w$]+\\s*\\(\\s*[\\w$]+\\s*,\\s*([0-9]+)\\s*\\)');
  689. var regInline = new RegExp('[\\w$]+\\[0\\]\\s*=\\s*[\\w$]+\\[([0-9]+)\\s*%\\s*[\\w$]+\\.length\\]');
  690. var functionCodePieces=functionCode.split(';');
  691. var decodeArray=[];
  692. for (var i=0; i<functionCodePieces.length; i++) {
  693. functionCodePieces[i]=functionCodePieces[i].trim();
  694. var codeLine=functionCodePieces[i];
  695. if (codeLine.length>0) {
  696. var arrSlice=codeLine.match(regSlice);
  697. var arrReverse=codeLine.match(regReverse);
  698. debug(i+': '+codeLine+' --'+(arrSlice?' slice length '+arrSlice.length:'') +' '+(arrReverse?'reverse':''));
  699. if (arrSlice && arrSlice.length >= 2) { // slice
  700. var slice=parseInt(arrSlice[1], 10);
  701. if (isInteger(slice)){
  702. decodeArray.push(-slice);
  703. } else return setPref(STORAGE_CODE, 'error');
  704. } else if (arrReverse && arrReverse.length >= 1) { // reverse
  705. decodeArray.push(0);
  706. } else if (codeLine.indexOf('[0]') >= 0) { // inline swap
  707. if (i+2<functionCodePieces.length &&
  708. functionCodePieces[i+1].indexOf('.length') >= 0 &&
  709. functionCodePieces[i+1].indexOf('[0]') >= 0) {
  710. var inline=findMatch(functionCodePieces[i+1], regInline);
  711. inline=parseInt(inline, 10);
  712. decodeArray.push(inline);
  713. i+=2;
  714. } else return setPref(STORAGE_CODE, 'error');
  715. } else if (codeLine.indexOf(',') >= 0) { // swap
  716. var swap=findMatch(codeLine, regSwap);
  717. swap=parseInt(swap, 10);
  718. if (isInteger(swap) && swap>0){
  719. decodeArray.push(swap);
  720. } else return setPref(STORAGE_CODE, 'error');
  721. } else return setPref(STORAGE_CODE, 'error');
  722. }
  723. }
  724.  
  725. if (decodeArray) {
  726. setPref(STORAGE_URL, scriptURL);
  727. setPref(STORAGE_CODE, decodeArray.toString());
  728. DECODE_RULE=decodeArray;
  729. debug('DYVAM - Info: signature '+decodeArray.toString()+' '+scriptURL);
  730. // update download links and add file sizes
  731. for (var i=0;i<downloadCodeList.length;i++) {
  732. var elem=document.getElementById(LISTITEM_ID+downloadCodeList[i].format);
  733. var url=downloadCodeList[i].url;
  734. var sig=downloadCodeList[i].sig;
  735. if (elem && url && sig) {
  736. url=url.replace(/\&signature=[\w\.]+/, '&signature='+decryptSignature(sig));
  737. elem.parentNode.setAttribute('href', url);
  738. addFileSize(url, downloadCodeList[i].format);
  739. }
  740. }
  741. }
  742. }
  743.  
  744. function isValidSignatureCode(arr) { // valid values: '5,-3,0,2,5', 'error'
  745. if (!arr) return false;
  746. if (arr=='error') return true;
  747. arr=arr.split(',');
  748. for (var i=0;i<arr.length;i++) {
  749. if (!isInteger(parseInt(arr[i],10))) return false;
  750. }
  751. return true;
  752. }
  753.  
  754. function fetchSignatureScript(scriptURL) {
  755. var storageURL=getPref(STORAGE_URL);
  756. var storageCode=getPref(STORAGE_CODE);
  757. if (!(/,0,|^0,|,0$|\-/.test(storageCode))) storageCode=null; // hack for only positive items
  758. if (storageCode && isValidSignatureCode(storageCode) && storageURL &&
  759. scriptURL==absoluteURL(storageURL)) return;
  760. try {
  761. debug('DYVAM fetch '+scriptURL);
  762. isSignatureUpdatingStarted=true;
  763. crossXmlHttpRequest({
  764. method:'GET',
  765. url:scriptURL,
  766. onload:function(response) {
  767. debug('DYVAM fetch status '+response.status);
  768. if (response.readyState === 4 && response.status === 200 && response.responseText) {
  769. findSignatureCode(response.responseText);
  770. }
  771. }
  772. });
  773. } catch(e) { }
  774. }
  775.  
  776. function getDecodeRules(rules) {
  777. var storageCode=getPref(STORAGE_CODE);
  778. if (storageCode && storageCode!='error' && isValidSignatureCode(storageCode)) {
  779. var arr=storageCode.split(',');
  780. for (var i=0; i<arr.length; i++) {
  781. arr[i]=parseInt(arr[i], 10);
  782. }
  783. rules=arr;
  784. debug('DYVAM - Info: signature '+arr.toString()+' '+scriptURL);
  785. }
  786. return rules;
  787. }
  788.  
  789. function decryptSignature(sig) {
  790. function swap(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c;return a};
  791. function decode(sig, arr) { // encoded decryption
  792. if (!isString(sig)) return null;
  793. var sigA=sig.split('');
  794. for (var i=0;i<arr.length;i++) {
  795. var act=arr[i];
  796. if (!isInteger(act)) return null;
  797. sigA=(act>0)?swap(sigA, act):((act==0)?sigA.reverse():sigA.slice(-act));
  798. }
  799. var result=sigA.join('');
  800. return result;
  801. }
  802.  
  803. if (sig==null) return '';
  804. var arr=DECODE_RULE;
  805. if (arr) {
  806. var sig2=decode(sig, arr);
  807. if (sig2) return sig2;
  808. } else {
  809. setPref(STORAGE_URL, '');
  810. setPref(STORAGE_CODE, '');
  811. }
  812. return sig;
  813. }
  814.  
  815. }
  816.  
  817. })();
  818.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址