SHARE
TWEET

Untitled

a guest Sep 18th, 2019 161 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name Google Drive Video Player for CyTube
  3. // @namespace gdcytube
  4. // @description Play Google Drive videos on CyTube
  5. // @include https://cytu.be/r/*
  6. // @include https://www.cytu.be/r/*
  7. // @include http://idoltube.fun/r/*
  8. // @include https://idoltube.fun/r/*
  9. // @include http://www.idoltube.fun/r/*
  10. // @include https://www.idoltube.fun/r/*
  11. // @grant unsafeWindow
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM.xmlHttpRequest
  14. // @connect docs.google.com
  15. // @run-at document-end
  16. // @version 1.7.0
  17. // ==/UserScript==
  18.  
  19. try {
  20.     function debug(message) {
  21.         try {
  22.             unsafeWindow.console.log('[Drive]', message);
  23.         } catch (error) {
  24.             unsafeWindow.console.error(error);
  25.         }
  26.     }
  27.  
  28.     function httpRequest(opts) {
  29.         if (typeof GM_xmlhttpRequest === 'undefined') {
  30.             // Assume GM4.0
  31.             debug('Using GM4.0 GM.xmlHttpRequest');
  32.             GM.xmlHttpRequest(opts);
  33.         } else {
  34.             debug('Using old-style GM_xmlhttpRequest');
  35.             GM_xmlhttpRequest(opts);
  36.         }
  37.     }
  38.  
  39.     var ITAG_QMAP = {
  40.         37: 1080,
  41.         46: 1080,
  42.         22: 720,
  43.         45: 720,
  44.         59: 480,
  45.         44: 480,
  46.         35: 480,
  47.         18: 360,
  48.         43: 360,
  49.         34: 360
  50.     };
  51.  
  52.     var ITAG_CMAP = {
  53.         43: 'video/webm',
  54.         44: 'video/webm',
  55.         45: 'video/webm',
  56.         46: 'video/webm',
  57.         18: 'video/mp4',
  58.         22: 'video/mp4',
  59.         37: 'video/mp4',
  60.         59: 'video/mp4',
  61.         35: 'video/flv',
  62.         34: 'video/flv'
  63.     };
  64.  
  65.     function getVideoInfo(id, cb) {
  66.         var url = 'https://docs.google.com/get_video_info?authuser='
  67.                 + '&docid=' + id
  68.                 + '&sle=true'
  69.                 + '&hl=en';
  70.         debug('Fetching ' + url);
  71.  
  72.         httpRequest({
  73.             method: 'GET',
  74.             url: url,
  75.             onload: function (res) {
  76.                 try {
  77.                     debug('Got response ' + res.responseText);
  78.  
  79.                     if (res.status !== 200) {
  80.                         debug('Response status not 200: ' + res.status);
  81.                         return cb(
  82.                             'Google Drive request failed: HTTP ' + res.status
  83.                         );
  84.                     }
  85.  
  86.                     var data = {};
  87.                     var error;
  88.                     // Google Santa sometimes eats login cookies and gets mad if there aren't any.
  89.                     if(/accounts\.google\.com\/ServiceLogin/.test(res.responseText)){
  90.                         error = 'Google Docs request failed: ' +
  91.                                 'This video requires you be logged into a Google account. ' +
  92.                                 'Open your Gmail in another tab and then refresh video.';
  93.                         return cb(error);
  94.                     }
  95.  
  96.                     res.responseText.split('&').forEach(function (kv) {
  97.                         var pair = kv.split('=');
  98.                         data[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
  99.                     });
  100.  
  101.                     if (data.status === 'fail') {
  102.                         error = 'Google Drive request failed: ' +
  103.                                 unescape(data.reason).replace(/\+/g, ' ');
  104.                         return cb(error);
  105.                     }
  106.  
  107.                     if (!data.fmt_stream_map) {
  108.                         error = (
  109.                             'Google has removed the video streams associated' +
  110.                             ' with this item.  It can no longer be played.'
  111.                         );
  112.  
  113.                         return cb(error);
  114.                     }
  115.  
  116.                     data.links = {};
  117.                     data.fmt_stream_map.split(',').forEach(function (item) {
  118.                         var pair = item.split('|');
  119.                         data.links[pair[0]] = pair[1];
  120.                     });
  121.                     data.videoMap = mapLinks(data.links);
  122.  
  123.                     cb(null, data);
  124.                 } catch (error) {
  125.                     unsafeWindow.console.error(error);
  126.                 }
  127.             },
  128.  
  129.             onerror: function () {
  130.                 var error = 'Google Drive request failed: ' +
  131.                             'metadata lookup HTTP request failed';
  132.                 error.reason = 'HTTP_ONERROR';
  133.                 return cb(error);
  134.             }
  135.         });
  136.     }
  137.  
  138.     function mapLinks(links) {
  139.         var videos = {
  140.             1080: [],
  141.             720: [],
  142.             480: [],
  143.             360: []
  144.         };
  145.  
  146.         Object.keys(links).forEach(function (itag) {
  147.             itag = parseInt(itag, 10);
  148.             if (!ITAG_QMAP.hasOwnProperty(itag)) {
  149.                 return;
  150.             }
  151.  
  152.             videos[ITAG_QMAP[itag]].push({
  153.                 itag: itag,
  154.                 contentType: ITAG_CMAP[itag],
  155.                 link: links[itag]
  156.             });
  157.         });
  158.  
  159.         return videos;
  160.     }
  161.  
  162.     /*
  163.      * Greasemonkey 2.0 has this wonderful sandbox that attempts
  164.      * to prevent script developers from shooting themselves in
  165.      * the foot by removing the trigger from the gun, i.e. it's
  166.      * impossible to cross the boundary between the browser JS VM
  167.      * and the privileged sandbox that can run GM_xmlhttpRequest().
  168.      *
  169.      * So in this case, we have to resort to polling a special
  170.      * variable to see if getGoogleDriveMetadata needs to be called
  171.      * and deliver the result into another special variable that is
  172.      * being polled on the browser side.
  173.      */
  174.  
  175.     /*
  176.      * Browser side function -- sets gdUserscript.pollID to the
  177.      * ID of the Drive video to be queried and polls
  178.      * gdUserscript.pollResult for the result.
  179.      */
  180.     function getGoogleDriveMetadata_GM(id, callback) {
  181.         debug('Setting GD poll ID to ' + id);
  182.         unsafeWindow.gdUserscript.pollID = id;
  183.         var tries = 0;
  184.         var i = setInterval(function () {
  185.             if (unsafeWindow.gdUserscript.pollResult) {
  186.                 debug('Got result');
  187.                 clearInterval(i);
  188.                 var result = unsafeWindow.gdUserscript.pollResult;
  189.                 unsafeWindow.gdUserscript.pollResult = null;
  190.                 callback(result.error, result.result);
  191.             } else if (++tries > 100) {
  192.                 // Took longer than 10 seconds, give up
  193.                 clearInterval(i);
  194.             }
  195.         }, 100);
  196.     }
  197.  
  198.     /*
  199.      * Sandbox side function -- polls gdUserscript.pollID for
  200.      * the ID of a Drive video to be queried, looks up the
  201.      * metadata, and stores it in gdUserscript.pollResult
  202.      */
  203.     function setupGDPoll() {
  204.         unsafeWindow.gdUserscript = cloneInto({}, unsafeWindow);
  205.         var pollInterval = setInterval(function () {
  206.             if (unsafeWindow.gdUserscript.pollID) {
  207.                 var id = unsafeWindow.gdUserscript.pollID;
  208.                 unsafeWindow.gdUserscript.pollID = null;
  209.                 debug('Polled and got ' + id);
  210.                 getVideoInfo(id, function (error, data) {
  211.                     unsafeWindow.gdUserscript.pollResult = cloneInto({
  212.                         error: error,
  213.                         result: data
  214.                     }, unsafeWindow);
  215.                 });
  216.             }
  217.         }, 1000);
  218.     }
  219.  
  220.     var TM_COMPATIBLES = [
  221.         'Tampermonkey',
  222.         'Violentmonkey' // https://github.com/calzoneman/sync/issues/713
  223.     ];
  224.  
  225.     function isTampermonkeyCompatible() {
  226.         try {
  227.             return TM_COMPATIBLES.indexOf(GM_info.scriptHandler) >= 0;
  228.         } catch (error) {
  229.             return false;
  230.         }
  231.     }
  232.  
  233.     if (isTampermonkeyCompatible()) {
  234.         unsafeWindow.getGoogleDriveMetadata = getVideoInfo;
  235.     } else {
  236.         debug('Using non-TM polling workaround');
  237.         unsafeWindow.getGoogleDriveMetadata = exportFunction(
  238.                 getGoogleDriveMetadata_GM, unsafeWindow);
  239.         setupGDPoll();
  240.     }
  241.  
  242.     unsafeWindow.console.log('Initialized userscript Google Drive player');
  243.     unsafeWindow.hasDriveUserscript = true;
  244.     // Checked against GS_VERSION from data.js
  245.     unsafeWindow.driveUserscriptVersion = '1.7';
  246. } catch (error) {
  247.     unsafeWindow.console.error(error);
  248. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top