Use child iframe for BitChute

By using an iframe we can take advantage of the referrer meta tag,
while still being able to scaffold everything relatively easily because it's same-origin
This commit is contained in:
Xaekai 2022-01-26 15:59:39 -08:00
parent 6a0119fa17
commit 8dde08ac6d
6 changed files with 138 additions and 1 deletions

View file

@ -23,6 +23,7 @@ var order = [
'hls.coffee',
'twitchclip.coffee',
'peertube.coffee',
'bitchute.coffee',
'update.coffee'
];

92
player/bitchute.coffee Normal file
View file

@ -0,0 +1,92 @@
window.BitChutePlayer = class BitChutePlayer extends Player
constructor: (data) ->
if not (this instanceof BitChutePlayer)
return new BitChutePlayer(data)
@load(data)
load: (data) ->
@setMediaProperties(data)
@ready = false
waitUntilDefined(window, 'playerjs', =>
iframe = $('<iframe/>')
.attr(
src: '/iframe'
allow: 'autoplay; fullscreen'
)
removeOld(iframe)
@setupframe(iframe[0], data)
@player = new playerjs.Player(iframe[0])
@player.on('ready', =>
@player.on('error', (error) =>
console.error('PlayerJS error', error.stack)
)
@player.on('ended', ->
# Streamable seems to not implement this since it loops
# gotta use the timeupdate hack below
if CLIENT.leader
socket.emit('playNext')
)
@player.on('play', ->
@paused = false
if CLIENT.leader
sendVideoUpdate()
)
@player.on('pause', ->
@paused = true
if CLIENT.leader
sendVideoUpdate()
)
@player.setVolume(VOLUME * 100)
if not @paused
@player.play()
@ready = true
)
)
setupframe: (iframe, data) ->
iframe.addEventListener('load', =>
iframe.contentWindow.VOLUME = VOLUME;
iframe.contentWindow.loadMediaPlayer(Object.assign({}, data, { type: 'cm' } ))
iframe.contentWindow.document.querySelector('#ytapiplayer').classList.add('vjs-fluid')
adapter = iframe.contentWindow.playerjs.VideoJSAdapter(iframe.contentWindow.PLAYER.player)
adapter.ready()
)
play: ->
@paused = false
if @player and @ready
@player.play()
pause: ->
@paused = true
if @player and @ready
@player.pause()
seekTo: (time) ->
if @player and @ready
@player.setCurrentTime(time)
setVolume: (volume) ->
if @player and @ready
@player.setVolume(volume * 100)
getTime: (cb) ->
if @player and @ready
@player.getCurrentTime(cb)
else
cb(0)
getVolume: (cb) ->
if @player and @ready
@player.getVolume((volume) ->
cb(volume / 100)
)
else
cb(VOLUME)

View file

@ -14,7 +14,7 @@ TYPE_MAP =
sb: StreamablePlayer
tc: TwitchClipPlayer
cm: VideoJSPlayer
bc: VideoJSPlayer
bc: BitChutePlayer
pt: PeerPlayer
window.loadMediaPlayer = (data) ->

7
src/web/routes/iframe.js Normal file
View file

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

View file

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

36
templates/iframe.pug Normal file
View file

@ -0,0 +1,36 @@
doctype html
html(lang="en")
head
meta(charset="utf-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
meta(name="referrer", content="same-origin")
link(rel="stylesheet", href="/css/video-js.css")
link(rel="stylesheet", href="/css/videojs-resolution-switcher.css")
style.
body { overflow-y: hidden }
body
#wrap
#videowrap
#ytapiplayer
script.
const USEROPTS = {
default_quality: 'auto'
}
const CLIENT = {
leader: false
}
let VOLUME = 0;
function waitUntilDefined(obj, key, fn) {
if(typeof obj[key] === "undefined") {
setTimeout(function () {
waitUntilDefined(obj, key, fn);
}, 100);
return;
}
fn();
}
script(src="/js/jquery-1.12.4.min.js")
script(src="/js/video.js")
script(src="/js/videojs-resolution-switcher.js")
script(src="/js/playerjs-0.0.12.js")
script(src="/js/player.js")