Permalink
Browse files

Add initial userscript

  • Loading branch information...
1 parent d51722c commit 4feee02e33a3d3741b2d1cc605d061cc91d8e2db @calzoneman committed Aug 16, 2016
View
@@ -8,6 +8,7 @@ var order = [
'youtube.coffee',
'dailymotion.coffee',
'videojs.coffee',
+ 'gdrive-player.coffee',
'raw-file.coffee',
'soundcloud.coffee',
'embed.coffee',
@@ -0,0 +1,155 @@
+// ==UserScript==
+// @name Google Drive Video Player for {SITENAME}
+// @namespace gdcytube
+// @description Play Google Drive videos on {SITENAME}
+// {INCLUDE_BLOCK}
+// @grant unsafeWindow
+// @grant GM_xmlhttpRequest
+// @connect docs.google.com
+// @run-at document-end
+// @version 1.0.0
+// ==/UserScript==
+
+(function () {
+ if (!unsafeWindow.enableCyTubeGoogleDriveUserscript) {
+ return;
+ }
+
+ function debug(message) {
+ if (!unsafeWindow.enableCyTubeGoogleDriveUserscriptDebug) {
+ return;
+ }
+
+ unsafeWindow.console.log.apply(unsafeWindow.console, arguments);
+ }
+
+ var ITAG_QMAP = {
+ 37: 1080,
+ 46: 1080,
+ 22: 720,
+ 45: 720,
+ 59: 480,
+ 44: 480,
+ 35: 480,
+ 18: 360,
+ 43: 360,
+ 34: 360
+ };
+
+ var ITAG_CMAP = {
+ 43: 'video/webm',
+ 44: 'video/webm',
+ 45: 'video/webm',
+ 46: 'video/webm',
+ 18: 'video/mp4',
+ 22: 'video/mp4',
+ 37: 'video/mp4',
+ 59: 'video/mp4',
+ 35: 'video/flv',
+ 34: 'video/flv'
+ };
+
+ function getVideoInfo(id, cb) {
+ var url = 'https://docs.google.com/file/d/' + id + '/get_video_info';
+ debug('Fetching ' + url);
+
+ GM_xmlhttpRequest({
+ method: 'GET',
+ url: url,
+ onload: function (res) {
+ var data = {};
+ res.responseText.split('&').forEach(function (kv) {
+ var pair = kv.split('=');
+ data[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
+ });
+
+ if (data.status === 'fail') {
+ var error = new Error('Google Docs request failed: ' +
+ 'metadata indicated status=fail');
+ error.response = res.responseText;
+ error.reason = 'RESPONSE_STATUS_FAIL';
+ return cb(error);
+ }
+
+ if (!data.fmt_stream_map) {
+ var error = new Error('Google Docs request failed: ' +
+ 'metadata lookup returned no valid links');
+ error.response = res.responseText;
+ error.reason = 'MISSING_LINKS';
+ return cb(error);
+ }
+
+ data.links = {};
+ data.fmt_stream_map.split(',').forEach(function (item) {
+ var pair = item.split('|');
+ data.links[pair[0]] = pair[1];
+ });
+
+ cb(null, data);
+ },
+
+ onerror: function () {
+ var error = new Error('Google Docs request failed: ' +
+ 'metadata lookup HTTP request failed');
+ error.reason = 'HTTP_ONERROR';
+ return cb(error);
+ }
+ });
+ }
+
+ function mapLinks(links) {
+ var videos = {
+ 1080: [],
+ 720: [],
+ 480: [],
+ 360: []
+ };
+
+ Object.keys(links).forEach(function (itag) {
+ itag = parseInt(itag, 10);
+ if (!ITAG_QMAP.hasOwnProperty(itag)) {
+ return;
+ }
+
+ videos[ITAG_QMAP[itag]].push({
+ itag: itag,
+ contentType: ITAG_CMAP[itag],
+ link: links[itag]
+ });
+ });
+
+ return videos;
+ }
+
+ function GoogleDrivePlayer(data) {
+ if (!(this instanceof GoogleDrivePlayer)) {
+ return new GoogleDrivePlayer(data);
+ }
+
+ this.setMediaProperties(data);
+ this.load(data);
+ }
+
+ GoogleDrivePlayer.prototype = Object.create(unsafeWindow.VideoJSPlayer.prototype);
+
+ GoogleDrivePlayer.prototype.load = function (data) {
+ var self = this;
+ getVideoInfo(data.id, function (err, videoData) {
+ if (err) {
+ debug(err);
+ var alertBox = unsafeWindow.document.createElement('div');
+ alertBox.className = 'alert alert-danger';
+ alertBox.textContent = err.message;
+ document.getElementById('ytapiplayer').appendChild(alertBox);
+ return;
+ }
+
+ debug('Retrieved links: ' + JSON.stringify(videoData.links));
+ data.meta.direct = mapLinks(videoData.links);
+ unsafeWindow.VideoJSPlayer.prototype.loadPlayer.call(self, data);
+ });
+ };
+
+ unsafeWindow.GoogleDrivePlayer = GoogleDrivePlayer;
+ unsafeWindow.console.log('Initialized userscript Google Drive player');
+})();
@@ -0,0 +1,19 @@
+var fs = require('fs');
+var path = require('path');
+
+var sitename = process.argv[2];
+var includes = process.argv.slice(3).map(function (include) {
+ return '// @include ' + include;
+}).join('\n');
+
+var lines = String(fs.readFileSync(
+ path.resolve(__dirname, 'cytube-google-drive.user.js'))).split('\n');
+lines.forEach(function (line) {
+ if (line.match(/\{INCLUDE_BLOCK\}/)) {
+ console.log(includes);
+ } else if (line.match(/\{SITENAME\}/)) {
+ console.log(line.replace(/\{SITENAME\}/, sitename));
+ } else {
+ console.log(line);
+ }
+});
View
@@ -47,7 +47,8 @@
"build-player": "$npm_node_execpath build-player.js",
"build-server": "babel -D --source-maps --loose es6.destructuring,es6.forOf --out-dir lib/ src/",
"postinstall": "./postinstall.sh",
- "server-dev": "babel -D --watch --source-maps --loose es6.destructuring,es6.forOf --out-dir lib/ src/"
+ "server-dev": "babel -D --watch --source-maps --loose es6.destructuring,es6.forOf --out-dir lib/ src/",
+ "generate-userscript": "$npm_node_execpath gdrive-userscript/generate-userscript $@ > www/js/cytube-google-drive.user.js"
},
"devDependencies": {
"coffee-script": "^1.9.2"
@@ -0,0 +1,6 @@
+window.GoogleDrivePlayer = class GoogleDrivePlayer extends VideoJSPlayer
+ constructor: (data) ->
+ if not (this instanceof GoogleDrivePlayer)
+ return new GoogleDrivePlayer(data)
+
+ super(data)
@@ -2,7 +2,7 @@ TYPE_MAP =
yt: YouTubePlayer
vi: VimeoPlayer
dm: DailymotionPlayer
- gd: GoogleDriveYouTubePlayer
+ gd: GoogleDrivePlayer
gp: VideoJSPlayer
fi: FilePlayer
jw: FilePlayer
@@ -33,7 +33,7 @@ window.loadMediaPlayer = (data) ->
else if data.type is 'gd'
try
if data.meta.html5hack
- window.PLAYER = new VideoJSPlayer(data)
+ window.PLAYER = new window.GoogleDrivePlayer(data)
else
window.PLAYER = new GoogleDriveYouTubePlayer(data)
catch e
View
@@ -216,3 +216,6 @@ function eraseCookie(name) {
/* to be implemented in callbacks.js */
function setupCallbacks() { }
+
+window.enableCyTubeGoogleDriveUserscript = true;
+window.enableCyTubeGoogleDriveUserscriptDebug = true;
View
@@ -1,5 +1,5 @@
(function() {
- var CUSTOM_EMBED_WARNING, CustomEmbedPlayer, DEFAULT_ERROR, DailymotionPlayer, EmbedPlayer, FilePlayer, GoogleDriveYouTubePlayer, HITBOX_ERROR, HLSPlayer, HitboxPlayer, ImgurPlayer, LivestreamPlayer, Player, RTMPPlayer, SoundCloudPlayer, TYPE_MAP, TwitchPlayer, USTREAM_ERROR, UstreamPlayer, VideoJSPlayer, VimeoPlayer, YouTubePlayer, codecToMimeType, genParam, sortSources,
+ var CUSTOM_EMBED_WARNING, CustomEmbedPlayer, DEFAULT_ERROR, DailymotionPlayer, EmbedPlayer, FilePlayer, GoogleDrivePlayer, GoogleDriveYouTubePlayer, HITBOX_ERROR, HLSPlayer, HitboxPlayer, ImgurPlayer, LivestreamPlayer, Player, RTMPPlayer, SoundCloudPlayer, TYPE_MAP, TwitchPlayer, USTREAM_ERROR, UstreamPlayer, VideoJSPlayer, VimeoPlayer, YouTubePlayer, codecToMimeType, genParam, sortSources,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
@@ -666,6 +666,20 @@
})(Player);
+ window.GoogleDrivePlayer = GoogleDrivePlayer = (function(superClass) {
+ extend(GoogleDrivePlayer, superClass);
+
+ function GoogleDrivePlayer(data) {
+ if (!(this instanceof GoogleDrivePlayer)) {
+ return new GoogleDrivePlayer(data);
+ }
+ GoogleDrivePlayer.__super__.constructor.call(this, data);
+ }
+
+ return GoogleDrivePlayer;
+
+ })(VideoJSPlayer);
+
codecToMimeType = function(codec) {
switch (codec) {
case 'mov/h264':
@@ -1308,7 +1322,7 @@
yt: YouTubePlayer,
vi: VimeoPlayer,
dm: DailymotionPlayer,
- gd: GoogleDriveYouTubePlayer,
+ gd: GoogleDrivePlayer,
gp: VideoJSPlayer,
fi: FilePlayer,
jw: FilePlayer,
@@ -1345,7 +1359,7 @@
} else if (data.type === 'gd') {
try {
if (data.meta.html5hack) {
- return window.PLAYER = new VideoJSPlayer(data);
+ return window.PLAYER = new window.GoogleDrivePlayer(data);
} else {
return window.PLAYER = new GoogleDriveYouTubePlayer(data);
}

0 comments on commit 4feee02

Please sign in to comment.