Add BandCamp support

This commit is contained in:
Xaekai 2022-01-26 20:33:59 -08:00
parent c506ccf05b
commit 8da1d1c772
8 changed files with 52 additions and 6 deletions

View File

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

View File

@ -1,7 +1,7 @@
window.BitChutePlayer = class BitChutePlayer extends Player window.IframeChild = class IframeChild extends Player
constructor: (data) -> constructor: (data) ->
if not (this instanceof BitChutePlayer) if not (this instanceof IframeChild)
return new BitChutePlayer(data) return new IframeChild(data)
@load(data) @load(data)
@ -57,6 +57,7 @@ window.BitChutePlayer = class BitChutePlayer extends Player
iframe.contentWindow.document.querySelector('#ytapiplayer').classList.add('vjs-fluid') iframe.contentWindow.document.querySelector('#ytapiplayer').classList.add('vjs-fluid')
adapter = iframe.contentWindow.playerjs.VideoJSAdapter(iframe.contentWindow.PLAYER.player) adapter = iframe.contentWindow.playerjs.VideoJSAdapter(iframe.contentWindow.PLAYER.player)
adapter.ready() adapter.ready()
typeof data?.meta?.thumbnail == 'string' and iframe.contentWindow.PLAYER.player.poster(data.meta.thumbnail)
) )
play: -> play: ->

View File

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

View File

@ -30,6 +30,17 @@ const SOURCE_CONTENT_TYPES = new Set([
'video/webm' 'video/webm'
]); ]);
const LIVE_ONLY_CONTENT_TYPES = new Set([
'application/dash+xml'
]);
const AUDIO_ONLY_CONTENT_TYPES = new Set([
'audio/aac',
'audio/ogg',
'audio/mpeg',
'audio/opus'
]);
export function lookup(url, opts) { export function lookup(url, opts) {
if (!opts) opts = {}; if (!opts) opts = {};
if (!opts.hasOwnProperty('timeout')) opts.timeout = 10000; if (!opts.hasOwnProperty('timeout')) opts.timeout = 10000;
@ -179,7 +190,13 @@ function validateSources(sources) {
`unacceptable source contentType "${source.contentType}"` `unacceptable source contentType "${source.contentType}"`
); );
if (!SOURCE_QUALITIES.has(source.quality)) if (LIVE_ONLY_CONTENT_TYPES.has(source.contentType) && !data.live)
throw new ValidationError(
`contentType "${source.contentType}" requires live: true`
);
// TODO: This should be allowed
if (/*!AUDIO_ONLY_CONTENT_TYPES.has(source.contentType) && */!SOURCE_QUALITIES.has(source.quality))
throw new ValidationError(`unacceptable source quality "${source.quality}"`); throw new ValidationError(`unacceptable source quality "${source.quality}"`);
if (source.hasOwnProperty('bitrate')) { if (source.hasOwnProperty('bitrate')) {

View File

@ -8,6 +8,7 @@ const YouTube = require("@cytube/mediaquery/lib/provider/youtube");
const Vimeo = require("@cytube/mediaquery/lib/provider/vimeo"); const Vimeo = require("@cytube/mediaquery/lib/provider/vimeo");
const PeerTube = require("@cytube/mediaquery/lib/provider/peertube"); const PeerTube = require("@cytube/mediaquery/lib/provider/peertube");
const BitChute = require("@cytube/mediaquery/lib/provider/bitchute"); const BitChute = require("@cytube/mediaquery/lib/provider/bitchute");
const BandCamp = require("@cytube/mediaquery/lib/provider/bandcamp");
const Streamable = require("@cytube/mediaquery/lib/provider/streamable"); const Streamable = require("@cytube/mediaquery/lib/provider/streamable");
const TwitchVOD = require("@cytube/mediaquery/lib/provider/twitch-vod"); const TwitchVOD = require("@cytube/mediaquery/lib/provider/twitch-vod");
const TwitchClip = require("@cytube/mediaquery/lib/provider/twitch-clip"); const TwitchClip = require("@cytube/mediaquery/lib/provider/twitch-clip");
@ -396,6 +397,15 @@ var Getters = {
}); });
}, },
/* BandCamp */
bn: function (id, callback) {
BandCamp.lookup(id).then(video => {
video = new Media(video.id, video.title, video.duration, "bn", video.meta);
callback(null, video);
}).catch(error => {
callback(error.message || error);
});
}
}; };
module.exports = { module.exports = {

View File

@ -53,6 +53,11 @@ Media.prototype = {
result.meta.direct = this.meta.direct; result.meta.direct = this.meta.direct;
} }
// Only save thumbnails for items which can be audio track only
if (['bn','cm'].includes(this.type)) {
result.meta.thumbnail = this.meta.thumbnail;
}
return result; return result;
}, },

View File

@ -210,6 +210,9 @@
return `https://${domain}/videos/watch/${uuid}`; return `https://${domain}/videos/watch/${uuid}`;
case "bc": case "bc":
return `https://www.bitchute.com/video/${id}/`; return `https://www.bitchute.com/video/${id}/`;
case "bn":
const [artist,track] = id.split(';');
return `https://${artist}.bandcamp.com/track/${track}`;
default: default:
return ""; return "";
} }

View File

@ -61,6 +61,9 @@ function formatURL(data) {
} }
case "bc": case "bc":
return `https://www.bitchute.com/video/${data.id}/`; return `https://www.bitchute.com/video/${data.id}/`;
case "bn":
const [artist,track] = data.id.split(';');
return `https://${artist}.bandcamp.com/track/${track}`;
default: default:
return "#"; return "#";
} }
@ -1402,6 +1405,12 @@ function parseMediaLink(url) {
} }
if(data.hostname.endsWith('.bandcamp.com') && data.pathname.startsWith('/track/')){
const artist = data.hostname.replace('.bandcamp.com','')
const track = data.pathname.replace('/track/','')
return { type: 'bn', id: `${artist};${track}` }
}
/* PeerTubes */ /* PeerTubes */
if(data.pathname.match('^/w/|^/videos/watch/')){ if(data.pathname.match('^/w/|^/videos/watch/')){
const regLong = [8, 4, 4, 4, 12].map(x => `[0-9a-f]{${x}}`).join('-'); const regLong = [8, 4, 4, 4, 12].map(x => `[0-9a-f]{${x}}`).join('-');