Advertisement
Guest User

Untitled

a guest
Jan 26th, 2020
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.07 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Google Drive Video Player for CyTube
  3. // @namespace gdcytube
  4. // @description Play Google Drive videos on CyTube
  5. // @include http://cytu.be/r/*
  6. // @include https://cytu.be/r/*
  7. // @include https://agare.moe:8443/r/Agarestream
  8. // @include http://www.cytu.be/r/*
  9. // @include https://www.cytu.be/r/*
  10. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  11. // @grant unsafeWindow
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM.xmlHttpRequest
  14. // @connect docs.google.com
  15. // @run-at document-end
  16. // @version 1.4.0
  17. // ==/UserScript==
  18.  
  19. try {
  20. function debug(message) {
  21. if (!unsafeWindow.enableCyTubeGoogleDriveUserscriptDebug) {
  22. return;
  23. }
  24.  
  25. try {
  26. unsafeWindow.console.log(message);
  27. } catch (error) {
  28. unsafeWindow.console.error(error);
  29. }
  30. }
  31.  
  32. var ITAG_QMAP = {
  33. 37: 1080,
  34. 46: 1080,
  35. 22: 720,
  36. 45: 720,
  37. 59: 480,
  38. 44: 480,
  39. 35: 480,
  40. 18: 360,
  41. 43: 360,
  42. 34: 360
  43. };
  44.  
  45. var ITAG_CMAP = {
  46. 43: 'video/webm',
  47. 44: 'video/webm',
  48. 45: 'video/webm',
  49. 46: 'video/webm',
  50. 18: 'video/mp4',
  51. 22: 'video/mp4',
  52. 37: 'video/mp4',
  53. 59: 'video/mp4',
  54. 35: 'video/flv',
  55. 34: 'video/flv'
  56. };
  57.  
  58. function getVideoInfo(id, cb) {
  59. var url = 'https://docs.google.com/get_video_info?authuser='
  60. + '&docid=' + id
  61. + '&sle=true'
  62. + '&hl=en';
  63. debug('Fetching ' + url);
  64.  
  65. GM.xmlHttpRequest({
  66. method: 'GET',
  67. url: url,
  68. onload: function (res) {
  69. try {
  70. debug('Got response ' + res.responseText);
  71. var data = {};
  72. var error;
  73. res.responseText.split('&').forEach(function (kv) {
  74. var pair = kv.split('=');
  75. data[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
  76. });
  77.  
  78. if (data.status === 'fail') {
  79. var error = 'Google Docs request failed: ' +
  80. unescape(data.reason).replace(/\+/g, ' ');
  81. return cb(error);
  82. }
  83.  
  84. if (!data.fmt_stream_map) {
  85. var error = 'Google Docs request failed: ' +
  86. 'metadata lookup returned no valid links';
  87. return cb(error);
  88. }
  89.  
  90. data.links = {};
  91. data.fmt_stream_map.split(',').forEach(function (item) {
  92. var pair = item.split('|');
  93. data.links[pair[0]] = pair[1];
  94. });
  95. data.videoMap = mapLinks(data.links);
  96.  
  97. cb(null, data);
  98. } catch (error) {
  99. unsafeWindow.console.error(error);
  100. }
  101. },
  102.  
  103. onerror: function () {
  104. var error = 'Google Docs request failed: ' +
  105. 'metadata lookup HTTP request failed';
  106. error.reason = 'HTTP_ONERROR';
  107. return cb(error);
  108. }
  109. }).catch(function (error) {
  110. error.reason = 'GM.xmlHttpRequest error';
  111. return cb(error);
  112. });
  113. }
  114.  
  115. function mapLinks(links) {
  116. var videos = {
  117. 1080: [],
  118. 720: [],
  119. 480: [],
  120. 360: []
  121. };
  122.  
  123. Object.keys(links).forEach(function (itag) {
  124. itag = parseInt(itag, 10);
  125. if (!ITAG_QMAP.hasOwnProperty(itag)) {
  126. return;
  127. }
  128.  
  129. videos[ITAG_QMAP[itag]].push({
  130. itag: itag,
  131. contentType: ITAG_CMAP[itag],
  132. link: links[itag]
  133. });
  134. });
  135.  
  136. return videos;
  137. }
  138.  
  139. /*
  140. * Greasemonkey 2.0 has this wonderful sandbox that attempts
  141. * to prevent script developers from shooting themselves in
  142. * the foot by removing the trigger from the gun, i.e. it's
  143. * impossible to cross the boundary between the browser JS VM
  144. * and the privileged sandbox that can run GM_xmlhttpRequest().
  145. *
  146. * So in this case, we have to resort to polling a special
  147. * variable to see if getGoogleDriveMetadata needs to be called
  148. * and deliver the result into another special variable that is
  149. * being polled on the browser side.
  150. */
  151.  
  152. /*
  153. * Browser side function -- sets gdUserscript.pollID to the
  154. * ID of the Drive video to be queried and polls
  155. * gdUserscript.pollResult for the result.
  156. */
  157. function getGoogleDriveMetadata_GM(id, callback) {
  158. debug('Setting GD poll ID to ' + id);
  159. unsafeWindow.gdUserscript.pollID = id;
  160. var tries = 0;
  161. var i = setInterval(function () {
  162. if (unsafeWindow.gdUserscript.pollResult) {
  163. debug('Got result');
  164. clearInterval(i);
  165. var result = unsafeWindow.gdUserscript.pollResult;
  166. unsafeWindow.gdUserscript.pollResult = null;
  167. callback(result.error, result.result);
  168. } else if (++tries > 100) {
  169. // Took longer than 10 seconds, give up
  170. clearInterval(i);
  171. }
  172. }, 100);
  173. }
  174.  
  175. /*
  176. * Sandbox side function -- polls gdUserscript.pollID for
  177. * the ID of a Drive video to be queried, looks up the
  178. * metadata, and stores it in gdUserscript.pollResult
  179. */
  180. function setupGDPoll() {
  181. unsafeWindow.gdUserscript = cloneInto({}, unsafeWindow);
  182. var pollInterval = setInterval(function () {
  183. if (unsafeWindow.gdUserscript.pollID) {
  184. var id = unsafeWindow.gdUserscript.pollID;
  185. unsafeWindow.gdUserscript.pollID = null;
  186. debug('Polled and got ' + id);
  187. getVideoInfo(id, function (error, data) {
  188. unsafeWindow.gdUserscript.pollResult = cloneInto({
  189. error: error,
  190. result: data
  191. }, unsafeWindow);
  192. });
  193. }
  194. }, 1000);
  195. }
  196.  
  197. function isRunningTampermonkey() {
  198. try {
  199. return GM_info.scriptHandler === 'Tampermonkey';
  200. } catch (error) {
  201. return false;
  202. }
  203. }
  204.  
  205. if (isRunningTampermonkey()) {
  206. unsafeWindow.getGoogleDriveMetadata = getVideoInfo;
  207. } else {
  208. debug('Using non-TM polling workaround');
  209. unsafeWindow.getGoogleDriveMetadata = exportFunction(
  210. getGoogleDriveMetadata_GM, unsafeWindow);
  211. setupGDPoll();
  212. }
  213.  
  214. unsafeWindow.console.log('Initialized userscript Google Drive player');
  215. unsafeWindow.hasDriveUserscript = true;
  216. unsafeWindow.driveUserscriptVersion = '1.4';
  217. } catch (error) {
  218. unsafeWindow.console.error(error);
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement