Add PeerTube support

This commit is contained in:
Xaekai 2022-01-19 06:30:00 -08:00 committed by Calvin Montgomery
parent 3668c1b3da
commit d516c5ebfc
8 changed files with 150 additions and 0 deletions

View file

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

113
player/peertube.coffee Normal file
View file

@ -0,0 +1,113 @@
PEERTUBE_EMBED_WARNING = 'This channel is embedding PeerTube content from %link%.
PeerTube instances may use P2P technology that will expose your IP address to third parties, including but not
limited to other users in this channel. It is also conceivable that if the content in question is in violation of
copyright laws your IP address could be potentially be observed by legal authorities monitoring the tracker of
this PeerTube instance. The operators of %site% are not responsible for the data sent by the embedded player to
third parties on your behalf.<br><br> If you understand the risks, wish to assume all liability, and continue to
the content, click "Embed" below to allow the content to be embedded.<hr>'
window.PeerPlayer = class PeerPlayer extends Player
constructor: (data) ->
if not (this instanceof PeerPlayer)
return new PeerPlayer(data)
@warn(data)
warn: (data) ->
site = new URL(document.URL).hostname
embedSrc = data.meta.embed.domain
link = "<a href=\"http://#{embedSrc}\" target=\"_blank\"><strong>#{embedSrc}</strong></a>"
alert = makeAlert('Privacy Advisory', PEERTUBE_EMBED_WARNING.replace('%link%', link).replace('%site%', site),
'alert-warning')
.removeClass('col-md-12')
$('<button/>').addClass('btn btn-default')
.text('Embed')
.on('click', =>
@load(data)
)
.appendTo(alert.find('.alert'))
removeOld(alert)
load: (data) ->
@setMediaProperties(data)
waitUntilDefined(window, 'PeerTubePlayer', =>
video = $('<iframe/>')
removeOld(video)
video.attr(
src: "https://#{data.meta.embed.domain}/videos/embed/#{data.meta.embed.uuid}?api=1"
allow: 'autoplay; fullscreen'
)
if USEROPTS.wmode_transparent
video.attr('wmode', 'transparent')
@peertube = new PeerTubePlayer(video[0])
@peertube.addEventListener('playbackStatusChange', (status) =>
@paused = status == 'paused'
if CLIENT.leader
sendVideoUpdate()
)
@peertube.addEventListener('playbackStatusUpdate', (status) =>
@peertube.currentTime = status.position
if status.playbackState == "ended" and CLIENT.leader
socket.emit('playNext')
)
@peertube.addEventListener('volumeChange', (volume) =>
VOLUME = volume
setOpt("volume", VOLUME)
)
@play()
@setVolume(VOLUME)
)
play: ->
@paused = false
if @peertube and @peertube.ready
@peertube.play().catch((error) ->
console.error('PeerTube::play():', error)
)
pause: ->
@paused = true
if @peertube and @peertube.ready
@peertube.pause().catch((error) ->
console.error('PeerTube::pause():', error)
)
seekTo: (time) ->
if @peertube and @peertube.ready
@peertube.seek(time)
getVolume: (cb) ->
if @peertube and @peertube.ready
@peertube.getVolume().then((volume) ->
cb(parseFloat(volume))
).catch((error) ->
console.error('PeerTube::getVolume():', error)
)
else
cb(VOLUME)
setVolume: (volume) ->
if @peertube and @peertube.ready
@peertube.setVolume(volume).catch((error) ->
console.error('PeerTube::setVolume():', error)
)
getTime: (cb) ->
if @peertube and @peertube.ready
cb(@peertube.currentTime)
else
cb(0)
setQuality: (quality) ->
# USEROPTS.default_quality
# @peertube.getResolutions()
# @peertube.setResolution(resolutionId : number)

View file

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

View file

@ -6,6 +6,7 @@ const ffmpeg = require("./ffmpeg");
const mediaquery = require("@cytube/mediaquery");
const YouTube = require("@cytube/mediaquery/lib/provider/youtube");
const Vimeo = require("@cytube/mediaquery/lib/provider/vimeo");
const PeerTube = require("@cytube/mediaquery/lib/provider/peertube");
const Streamable = require("@cytube/mediaquery/lib/provider/streamable");
const TwitchVOD = require("@cytube/mediaquery/lib/provider/twitch-vod");
const TwitchClip = require("@cytube/mediaquery/lib/provider/twitch-clip");
@ -366,6 +367,16 @@ var Getters = {
});
},
/* PeerTube network */
pt: function (id, callback) {
PeerTube.lookup(id).then(video => {
video = new Media(video.id, video.title, video.duration, "pt", video.meta);
callback(null, video);
}).catch(error => {
callback(error.message || error);
});
},
/* custom media - https://github.com/calzoneman/sync/issues/655 */
cm: async function (id, callback) {
try {

View file

@ -205,6 +205,9 @@
return "https://clips.twitch.tv/" + id;
case "cm":
return id;
case "pt":
const [domain,uuid] = id.split(';');
return `https://${domain}/videos/watch/${uuid}`;
default:
return "";
}

View file

@ -252,6 +252,7 @@ html(lang="en")
script(defer, src="https://www.youtube.com/iframe_api")
script(defer, src="https://api.dmcdn.net/all.js")
script(defer, src="https://player.vimeo.com/api/player.js")
script(defer, src="/js/peertube.js")
script(defer, src="/js/sc.js")
script(defer, src="/js/video.js")
script(defer, src="/js/videojs-contrib-hls.min.js")

1
www/js/peertube.js Normal file

File diff suppressed because one or more lines are too long

View file

@ -52,6 +52,12 @@ function formatURL(data) {
return data.id;
case "cu":
return data.meta.embed.src;
case "pt":
if(data.meta.embed.onlyLong){
return `https://${data.meta.embed.domain}/videos/watch/${data.meta.embed.uuid}`;
} else {
return `https://${data.meta.embed.domain}/w/${data.meta.embed.short}`;
}
default:
return "#";
}
@ -1385,6 +1391,19 @@ function parseMediaLink(url) {
}
}
/* PeerTubes */
if(data.pathname.match('^/w/|^/videos/watch/')){
const regLong = [8, 4, 4, 4, 12].map(x => `[0-9a-f]{${x}}`).join('-');
const regShort = '[a-zA-Z0-9]{22}';
const pattern = new RegExp(`(?:/w/|/videos/watch/)(?:(?<short>${regShort})|(?<long>${regLong}))`);
if((m = data.pathname.match(pattern))) {
return {
id: `${data.hostname};${m.groups.short || m.groups.long}`,
type: "pt"
};
}
}
/* Raw file (server will check) */
if (data.protocol.match(/^http/)) {
return {