diff --git a/player/twitch.coffee b/player/twitch.coffee index 34a7d239..e95ef2af 100644 --- a/player/twitch.coffee +++ b/player/twitch.coffee @@ -12,17 +12,25 @@ window.TwitchPlayer = class TwitchPlayer extends Player init: (data) -> removeOld() - options = - channel: data.id + if data.type is 'tv' + # VOD + options = + video: data.id + else + # Livestream + options = + channel: data.id @twitch = new Twitch.Player('ytapiplayer', options) @twitch.addEventListener(Twitch.Player.READY, => @setVolume(VOLUME) @twitch.setQuality(@mapQuality(USEROPTS.default_quality)) @twitch.addEventListener(Twitch.Player.PLAY, => + @paused = false if CLIENT.leader sendVideoUpdate() ) @twitch.addEventListener(Twitch.Player.PAUSE, => + @paused = true if CLIENT.leader sendVideoUpdate() ) @@ -35,19 +43,26 @@ window.TwitchPlayer = class TwitchPlayer extends Player load: (data) -> @setMediaProperties(data) try - @twitch.setChannel(data.id) + if data.type is 'tv' + # VOD + @twitch.setVideo(data.id) + else + # Livestream + @twitch.setChannel(data.id) catch error console.error(error) pause: -> try @twitch.pause() + @paused = true catch error console.error(error) play: -> try @twitch.play() + @paused = false catch error console.error(error) @@ -59,7 +74,7 @@ window.TwitchPlayer = class TwitchPlayer extends Player getTime: (cb) -> try - cb(@twitch.getVolume()) + cb(@twitch.getCurrentTime()) catch error console.error(error) diff --git a/player/update.coffee b/player/update.coffee index 1dde4123..44eeb99a 100644 --- a/player/update.coffee +++ b/player/update.coffee @@ -9,6 +9,7 @@ TYPE_MAP = sc: SoundCloudPlayer li: LivestreamPlayer tw: TwitchPlayer + tv: TwitchPlayer cu: CustomEmbedPlayer rt: RTMPPlayer hb: HitboxPlayer diff --git a/src/get-info.js b/src/get-info.js index 08621176..0e12d3ee 100644 --- a/src/get-info.js +++ b/src/get-info.js @@ -13,6 +13,7 @@ var Vimeo = require("cytube-mediaquery/lib/provider/vimeo"); var Vidme = require("cytube-mediaquery/lib/provider/vidme"); var Streamable = require("cytube-mediaquery/lib/provider/streamable"); var GoogleDrive = require("cytube-mediaquery/lib/provider/googledrive"); +var TwitchVOD = require("cytube-mediaquery/lib/provider/twitch-vod"); /* * Preference map of quality => youtube formats. @@ -395,6 +396,25 @@ var Getters = { callback(false, media); }, + /* twitch VOD */ + tv: function (id, callback) { + var m = id.match(/([cv]\d+)/); + if (m) { + id = m[1]; + } else { + process.nextTick(callback, "Invalid Twitch VOD ID"); + return; + } + + TwitchVOD.lookup(id).then(video => { + const media = new Media(video.id, video.title, video.duration, + "tv", video.meta); + process.nextTick(callback, false, media); + }).catch(function (err) { + callback(err.message || err, null); + }); + }, + /* ustream.tv */ us: function (id, callback) { /** diff --git a/www/js/player.js b/www/js/player.js index 14c9e4da..1b2df99a 100644 --- a/www/js/player.js +++ b/www/js/player.js @@ -983,20 +983,28 @@ TwitchPlayer.prototype.init = function(data) { var options; removeOld(); - options = { - channel: data.id - }; + if (data.type === 'tv') { + options = { + video: data.id + }; + } else { + options = { + channel: data.id + }; + } this.twitch = new Twitch.Player('ytapiplayer', options); return this.twitch.addEventListener(Twitch.Player.READY, (function(_this) { return function() { _this.setVolume(VOLUME); _this.twitch.setQuality(_this.mapQuality(USEROPTS.default_quality)); _this.twitch.addEventListener(Twitch.Player.PLAY, function() { + _this.paused = false; if (CLIENT.leader) { return sendVideoUpdate(); } }); _this.twitch.addEventListener(Twitch.Player.PAUSE, function() { + _this.paused = true; if (CLIENT.leader) { return sendVideoUpdate(); } @@ -1014,7 +1022,11 @@ var error, error1; this.setMediaProperties(data); try { - return this.twitch.setChannel(data.id); + if (data.type === 'tv') { + return this.twitch.setVideo(data.id); + } else { + return this.twitch.setChannel(data.id); + } } catch (error1) { error = error1; return console.error(error); @@ -1024,7 +1036,8 @@ TwitchPlayer.prototype.pause = function() { var error, error1; try { - return this.twitch.pause(); + this.twitch.pause(); + return this.paused = true; } catch (error1) { error = error1; return console.error(error); @@ -1034,7 +1047,8 @@ TwitchPlayer.prototype.play = function() { var error, error1; try { - return this.twitch.play(); + this.twitch.play(); + return this.paused = false; } catch (error1) { error = error1; return console.error(error); @@ -1054,7 +1068,7 @@ TwitchPlayer.prototype.getTime = function(cb) { var error, error1; try { - return cb(this.twitch.getVolume()); + return cb(this.twitch.getCurrentTime()); } catch (error1) { error = error1; return console.error(error); @@ -1491,6 +1505,7 @@ sc: SoundCloudPlayer, li: LivestreamPlayer, tw: TwitchPlayer, + tv: TwitchPlayer, cu: CustomEmbedPlayer, rt: RTMPPlayer, hb: HitboxPlayer, diff --git a/www/js/util.js b/www/js/util.js index fa38aa54..985f3a4b 100644 --- a/www/js/util.js +++ b/www/js/util.js @@ -1299,7 +1299,14 @@ function parseMediaLink(url) { }; } - if((m = url.match(/twitch\.tv\/([^\?&#]+)/))) { + if((m = url.match(/twitch\.tv\/(?:.*?)\/([cv])\/(\d+)/))) { + return { + id: m[1] + m[2], + type: "tv" + }; + } + + if((m = url.match(/twitch\.tv\/([\w-]+)/))) { return { id: m[1], type: "tw"