Add a prompt explaining the situation as well as documentation

This commit is contained in:
Calvin Montgomery 2016-08-23 21:50:18 -07:00
parent 578d3fbb23
commit 5a81ab7ce7
10 changed files with 184 additions and 2 deletions

13
NEWS.md
View File

@ -1,3 +1,16 @@
2016-08-23
==========
A few weeks ago, the previous Google Drive player stopped working. This is
nothing new; Google Drive has consistently broken a few times a year ever since
support for it was added. However, it's becoming increasingly difficult and
complicated to provide good support for Google Drive, so I've made the decision
to phase out the native player and require a userscript for it, in order to
bypass CORS and allow each browser to request the video stream itself.
See [the updated documentation](docs/gdrive-userscript-serveradmins.md) for
details on how to enable this for your users.
2016-04-27 2016-04-27
========== ==========

View File

@ -0,0 +1,24 @@
# Google Drive Userscript Setup
In response to increasing difficulty and complexity of maintaining Google Drive
support, the native player is being phased out in favor of requiring a
userscript to allow each client to fetch the video stream links for themselves.
Users will be prompted with a link to `/google_drive_userscript`, which explains
the situation and instructs how to install the userscript.
As a server admin, you must generate the userscript from the template by using
the following command:
```sh
npm run generate-userscript <site name> <url> [<url>...]
```
The first argument is the site name as it will appear in the userscript title.
The remaining arguments are the URL patterns on which the script will run. For
example, for cytu.be I use:
```sh
npm run generate-userscript CyTube http://cytu.be/r/* https://cytu.be/r/*
```
This will generate `www/js/cytube-google-drive.user.js`.

View File

@ -2,7 +2,7 @@
"author": "Calvin Montgomery", "author": "Calvin Montgomery",
"name": "CyTube", "name": "CyTube",
"description": "Online media synchronizer and chat", "description": "Online media synchronizer and chat",
"version": "3.19.0", "version": "3.20.0",
"repository": { "repository": {
"url": "http://github.com/calzoneman/sync" "url": "http://github.com/calzoneman/sync"
}, },

View File

@ -7,6 +7,7 @@ window.GoogleDriveYouTubePlayer = class GoogleDriveYouTubePlayer extends Player
@init(data) @init(data)
init: (data) -> init: (data) ->
window.promptToInstallDriveUserscript()
embed = $('<embed />').attr( embed = $('<embed />').attr(
type: 'application/x-shockwave-flash' type: 'application/x-shockwave-flash'
src: "https://www.youtube.com/get_player?docid=#{data.id}&ps=docs\ src: "https://www.youtube.com/get_player?docid=#{data.id}&ps=docs\
@ -102,3 +103,30 @@ window.GoogleDriveYouTubePlayer = class GoogleDriveYouTubePlayer extends Player
cb(@yt.getVolume() / 100) cb(@yt.getVolume() / 100)
else else
cb(VOLUME) cb(VOLUME)
window.promptToInstallDriveUserscript = ->
if document.getElementById('prompt-install-drive-userscript')
return
alertBox = document.createElement('div')
alertBox.id = 'prompt-install-drive-userscript'
alertBox.className = 'alert alert-info'
alertBox.innerHTML = """
Due to continual breaking changes making it increasingly difficult to
maintain Google Drive support, you can now install a userscript that
simplifies the code and has better compatibility. In the future, the
old player will be removed."""
alertBox.appendChild(document.createElement('br'))
infoLink = document.createElement('a')
infoLink.className = 'btn btn-info'
infoLink.href = '/google_drive_userscript'
infoLink.textContent = 'Click here for details'
infoLink.target = '_blank'
alertBox.appendChild(infoLink)
closeButton = document.createElement('button')
closeButton.className = 'close pull-right'
closeButton.innerHTML = '&times;'
closeButton.onclick = ->
alertBox.parentNode.removeChild(alertBox)
alertBox.insertBefore(closeButton, alertBox.firstChild)
document.getElementById('videowrap').appendChild(alertBox)

View File

@ -93,6 +93,8 @@ window.VideoJSPlayer = class VideoJSPlayer extends Player
@player.src(@sources[@sourceIdx]) @player.src(@sources[@sourceIdx])
else else
console.error('Out of sources, video will not play') console.error('Out of sources, video will not play')
if @mediaType is 'gd' and not window.hasDriveUserscript
window.promptToInstallDriveUserscript()
) )
@setVolume(VOLUME) @setVolume(VOLUME)
@player.on('ended', -> @player.on('ended', ->

View File

@ -36,6 +36,9 @@ function getBaseUrl(res) {
* Renders and serves a pug template * Renders and serves a pug template
*/ */
function sendPug(res, view, locals) { function sendPug(res, view, locals) {
if (!locals) {
locals = {};
}
locals.loggedIn = locals.loggedIn || !!res.user; locals.loggedIn = locals.loggedIn || !!res.user;
locals.loginName = locals.loginName || res.user ? res.user.name : false; locals.loginName = locals.loginName || res.user ? res.user.name : false;
locals.superadmin = locals.superadmin || res.user ? res.user.global_rank >= 255 : false; locals.superadmin = locals.superadmin || res.user ? res.user.global_rank >= 255 : false;

View File

@ -0,0 +1,7 @@
import { sendPug } from '../pug';
export default function initialize(app) {
app.get('/google_drive_userscript', (req, res) => {
return sendPug(res, 'google_drive_userscript')
});
}

View File

@ -177,6 +177,7 @@ module.exports = {
require('./account').init(app); require('./account').init(app);
require('./acp').init(app); require('./acp').init(app);
require('../google2vtt').attach(app); require('../google2vtt').attach(app);
require('./routes/google_drive_userscript')(app);
app.use(serveStatic(path.join(__dirname, '..', '..', 'www'), { app.use(serveStatic(path.join(__dirname, '..', '..', 'www'), {
maxAge: webConfig.getCacheTTL() maxAge: webConfig.getCacheTTL()
})); }));

View File

@ -0,0 +1,74 @@
doctype html
html(lang="en")
head
include head
+head()
body
#wrap
nav.navbar.navbar-inverse.navbar-fixed-top(role="navigation")
include nav
+navheader()
#nav-collapsible.collapse.navbar-collapse
ul.nav.navbar-nav
+navdefaultlinks("/google_drive_userscript")
+navloginlogout("/google_drive_userscript")
section#mainpage
.container
.col-md-8.col-md-offset-2
h1 Google Drive Userscript
h2 Why?
p.
Since Google Drive support was launched in early 2014, it has broken
at least 4-5 times, requiring increasing effort to get it working again
and disrupting many channels. This is because there is no official API
for it like there is for YouTube videos, which means support for it
relies on undocumented tricks. In August 2016, the decision was made
to phase out the native support for Google Drive and instead require
users to install a userscript, which allows to bypass certain browser
restrictions and make the code easier, simpler, and less prone to failure
(it could still break due to future Google Drive changes, but is less
likely to be difficult to fix).
h2 How It Works
p.
The userscript is a short script that you can install using a browser
extension such as Greasemonkey or Tampermonkey that runs on the page
and provides additional functionality needed to play Google Drive
videos.
h2 Installation
ul
li
strong Chrome
| &mdash;Install <a href="https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo" target="_blank">Tampermonkey</a>.
li
strong Firefox
| &mdash;Install <a href="https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/" target="_blank">Tampermonkey</a>
| or <a href="https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/" target="_blank">Greasemonkey</a>.
li
strong Other Browsers
| &mdash;Install the appropriate userscript plugin for your browser.
| Tampermonkey supports many browsers besides Chrome.
p.
Once you have installed the userscript manager addon for your browser,
you can <a href="/js/cytube-google-drive.user.js?v=1.1" target="_blank">
install the userscript</a>. If this link 404s, it means the administrator
of this server hasn't generated it yet.
p.
You can find a guide with screenshots of the installation process
<a href="https://github.com/calzoneman/sync/wiki/Google-Drive-Userscript-Installation-Guide" target="_blank">on GitHub</a>.
include footer
+footer()
script(type="text/javascript").
function showEmail(btn, email, key) {
email = unescape(email);
key = unescape(key);
var dest = new Array(email.length);
for (var i = 0; i < email.length; i++) {
dest[i] = String.fromCharCode(email.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
email = dest.join("");
$("<a/>").attr("href", "mailto:" + email)
.text(email)
.insertBefore(btn);
$(btn).remove();
}

View File

@ -558,7 +558,10 @@
if (_this.sourceIdx < _this.sources.length) { if (_this.sourceIdx < _this.sources.length) {
return _this.player.src(_this.sources[_this.sourceIdx]); return _this.player.src(_this.sources[_this.sourceIdx]);
} else { } else {
return console.error('Out of sources, video will not play'); console.error('Out of sources, video will not play');
if (_this.mediaType === 'gd' && !window.hasDriveUserscript) {
return window.promptToInstallDriveUserscript();
}
} }
} }
}); });
@ -1179,6 +1182,7 @@
GoogleDriveYouTubePlayer.prototype.init = function(data) { GoogleDriveYouTubePlayer.prototype.init = function(data) {
var embed; var embed;
window.promptToInstallDriveUserscript();
embed = $('<embed />').attr({ embed = $('<embed />').attr({
type: 'application/x-shockwave-flash', type: 'application/x-shockwave-flash',
src: "https://www.youtube.com/get_player?docid=" + data.id + "&ps=docs&partnerid=30&enablejsapi=1&cc_load_policy=1&auth_timeout=86400000000", src: "https://www.youtube.com/get_player?docid=" + data.id + "&ps=docs&partnerid=30&enablejsapi=1&cc_load_policy=1&auth_timeout=86400000000",
@ -1308,6 +1312,32 @@
})(Player); })(Player);
window.promptToInstallDriveUserscript = function() {
var alertBox, closeButton, infoLink;
if (document.getElementById('prompt-install-drive-userscript')) {
return;
}
alertBox = document.createElement('div');
alertBox.id = 'prompt-install-drive-userscript';
alertBox.className = 'alert alert-info';
alertBox.innerHTML = "Due to continual breaking changes making it increasingly difficult to\nmaintain Google Drive support, you can now install a userscript that\nsimplifies the code and has better compatibility. In the future, the\nold player will be removed.";
alertBox.appendChild(document.createElement('br'));
infoLink = document.createElement('a');
infoLink.className = 'btn btn-info';
infoLink.href = '/google_drive_userscript';
infoLink.textContent = 'Click here for details';
infoLink.target = '_blank';
alertBox.appendChild(infoLink);
closeButton = document.createElement('button');
closeButton.className = 'close pull-right';
closeButton.innerHTML = '&times;';
closeButton.onclick = function() {
return alertBox.parentNode.removeChild(alertBox);
};
alertBox.insertBefore(closeButton, alertBox.firstChild);
return document.getElementById('videowrap').appendChild(alertBox);
};
window.HLSPlayer = HLSPlayer = (function(superClass) { window.HLSPlayer = HLSPlayer = (function(superClass) {
extend(HLSPlayer, superClass); extend(HLSPlayer, superClass);