diff --git a/channel.js b/channel.js index 3aba97ef..7243ecc9 100644 --- a/channel.js +++ b/channel.js @@ -467,6 +467,38 @@ Channel.prototype.enqueue = function(data) { }})(this, data.id); InfoGetter.getYTInfo(data.id, callback); } + // YouTube Playlist + else if(data.type == "yp") { + var callback = (function(chan, id) { return function(res, data) { + if(res != 200) { + return; + } + + try { + for(var i = 0; i < data.feed.entry.length; i++) { + var item = data.feed.entry[i]; + var title = item.title.$t; + var url = item.link[1].href; + var parts = url.split("/"); + var id = parts[parts.length - 1]; + var seconds = item.media$group.yt$duration.seconds; + var vid = new Media(id, title, seconds, "yt"); + chan.queue.splice(idx, 0, vid); + chan.sendAll("queue", { + media: vid.pack(), + pos: idx + }); + chan.addToLibrary(vid); + idx++; + } + } + catch(e) { + console.log("YTPlaylist Failed: id=", id); + console.log(e); + } + }})(this, data.id); + InfoGetter.getYTPlaylist(data.id, callback); + } // Set up twitch metadata else if(data.type == "tw") { var media = new Media(data.id, "Twitch ~ " + data.id, 0, "tw"); diff --git a/get-info.js b/get-info.js index 00cb2240..7cece832 100644 --- a/get-info.js +++ b/get-info.js @@ -71,6 +71,16 @@ exports.getYTInfo = function(id, callback) { timeout: 1000}, callback); } +exports.getYTPlaylist = function(id, callback) { + getJSON({ + host: "gdata.youtube.com", + port: 80, + path: "/feeds/api/playlists/" + id + "?v=2&alt=json", + method: "GET", + dataType: "jsonp", + timeout: 1000}, callback); +} + // Look up Soundcloud metadata // Whoever designed this should rethink it. I"ll submit a feedback // form on their website. diff --git a/www/assets/js/functions.js b/www/assets/js/functions.js index c778570d..e6fb62a6 100644 --- a/www/assets/js/functions.js +++ b/www/assets/js/functions.js @@ -449,8 +449,12 @@ function removeCurrentPlayer(){ function parseVideoURL(url){ if(typeof(url) != "string") return null; - if(url.indexOf("youtu.be") != -1 || url.indexOf("youtube.com") != -1) + if(url.indexOf("youtu.be") != -1 || url.indexOf("youtube.com") != -1) { + if(url.indexOf("playlist") != -1) { + return [parseYTPlaylist(url), "yp"]; + } return [parseYTURL(url), "yt"]; + } else if(url.indexOf("twitch.tv") != -1) return [parseTwitch(url), "tw"]; else if(url.indexOf("livestream.com") != -1) @@ -467,12 +471,12 @@ function parseYTURL(url) { url = url.replace("feature=player_embedded&", ""); if(url.indexOf("&list=") != -1) url = url.substring(0, url.indexOf("&list=")); - var m = url.match(/youtube\.com\/watch\\?v=([^&]*)/); + var m = url.match(/youtube\.com\/watch\?v=([^&]+)/); if(m) { // Extract ID return m[1]; } - var m = url.match(/youtu\.be\/([^&]*)/); + var m = url.match(/youtu\.be\/([^&]+)/); if(m) { // Extract ID return m[1]; @@ -486,8 +490,16 @@ function parseYTURL(url) { return null; } +function parseYTPlaylist(url) { + var m = url.match(/youtube\.com\/playlist\?list=([^&]+)/); + if(m) { + return m[1]; + } + return null; +} + function parseTwitch(url) { - var m = url.match(/twitch\.tv\/([a-zA-Z0-9]*)/); + var m = url.match(/twitch\.tv\/([a-zA-Z0-9]+)/); if(m) { // Extract channel name return m[1]; @@ -496,7 +508,7 @@ function parseTwitch(url) { } function parseLivestream(url) { - var m = url.match(/livestream\.com\/([a-zA-Z0-9]*)/); + var m = url.match(/livestream\.com\/([a-zA-Z0-9]+)/); if(m) { // Extract channel name return m[1];