Merge pull request #487 from calzoneman/remove-yt2
Remove YouTube v2 API fallback since v2 is dead
This commit is contained in:
commit
3f79e9f858
|
@ -120,10 +120,14 @@ mail:
|
|||
|
||||
# YouTube v3 API key
|
||||
# See https://developers.google.com/youtube/registering_an_application
|
||||
# Google is closing the v2 API (which allowed anonymous requests) on
|
||||
# April 20, 2015 so you must register a v3 API key now.
|
||||
# NOTE: You must generate a Server key under Public API access, NOT a
|
||||
# browser key.
|
||||
# YouTube links will not work without this!
|
||||
# Instructions:
|
||||
# 1. Go to https://console.developers.google.com/project
|
||||
# 2. Create a new API project
|
||||
# 3. On the left sidebar, click "Credentials" under "APIs & auth"
|
||||
# 4. Click "Create new Key" under "Public API access"
|
||||
# 5. Click "Server key"
|
||||
# 6. Under "APIs & auth" click "YouTube Data API" and then click "Enable API"
|
||||
youtube-v3-key: ''
|
||||
# Minutes between saving channel state to disk
|
||||
channel-save-interval: 5
|
||||
|
|
|
@ -352,9 +352,8 @@ function preprocessConfig(cfg) {
|
|||
require("cytube-mediaquery/lib/provider/youtube").setApiKey(
|
||||
cfg["youtube-v3-key"]);
|
||||
} else {
|
||||
Logger.errlog.log("Warning: No YouTube v3 API key set. YouTube lookups will " +
|
||||
"fall back to the v2 API, which is scheduled for closure soon after " +
|
||||
"April 20, 2015. See " +
|
||||
Logger.errlog.log("Warning: No YouTube v3 API key set. YouTube links will " +
|
||||
"not work. See youtube-v3-key in config.template.yaml and " +
|
||||
"https://developers.google.com/youtube/registering_an_application for " +
|
||||
"information on registering an API key.");
|
||||
}
|
||||
|
|
257
lib/get-info.js
257
lib/get-info.js
|
@ -66,7 +66,8 @@ var Getters = {
|
|||
/* youtube.com */
|
||||
yt: function (id, callback) {
|
||||
if (!Config.get("youtube-v3-key")) {
|
||||
return Getters.yt2(id, callback);
|
||||
return callback("The YouTube API now requires an API key. Please see the " +
|
||||
"documentation for youtube-v3-key in config.template.yaml");
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,7 +87,8 @@ var Getters = {
|
|||
/* youtube.com playlists */
|
||||
yp: function (id, callback) {
|
||||
if (!Config.get("youtube-v3-key")) {
|
||||
return Getters.yp2(id, callback);
|
||||
return callback("The YouTube API now requires an API key. Please see the " +
|
||||
"documentation for youtube-v3-key in config.template.yaml");
|
||||
}
|
||||
|
||||
YouTube.lookupPlaylist(id).then(function (videos) {
|
||||
|
@ -108,7 +110,8 @@ var Getters = {
|
|||
/* youtube.com search */
|
||||
ytSearch: function (query, callback) {
|
||||
if (!Config.get("youtube-v3-key")) {
|
||||
return Getters.ytSearch2(query.split(" "), callback);
|
||||
return callback("The YouTube API now requires an API key. Please see the " +
|
||||
"documentation for youtube-v3-key in config.template.yaml");
|
||||
}
|
||||
|
||||
YouTube.search(query).then(function (res) {
|
||||
|
@ -730,254 +733,6 @@ var Getters = {
|
|||
var media = new Media(id, title, "--:--", "hb");
|
||||
callback(false, media);
|
||||
},
|
||||
|
||||
/* youtube.com - old v2 API */
|
||||
yt2: function (id, callback) {
|
||||
var sv = Server.getServer();
|
||||
|
||||
var m = id.match(/([\w-]{11})/);
|
||||
if (m) {
|
||||
id = m[1];
|
||||
} else {
|
||||
callback("Invalid ID", null);
|
||||
return;
|
||||
}
|
||||
|
||||
var options = {
|
||||
host: "gdata.youtube.com",
|
||||
port: 443,
|
||||
path: "/feeds/api/videos/" + id + "?v=2&alt=json",
|
||||
method: "GET",
|
||||
dataType: "jsonp",
|
||||
timeout: 1000
|
||||
};
|
||||
|
||||
if (Config.get("youtube-v2-key")) {
|
||||
options.headers = {
|
||||
"X-Gdata-Key": "key=" + Config.get("youtube-v2-key")
|
||||
};
|
||||
}
|
||||
|
||||
urlRetrieve(https, options, function (status, data) {
|
||||
switch (status) {
|
||||
case 200:
|
||||
break; /* Request is OK, skip to handling data */
|
||||
case 400:
|
||||
return callback("Invalid request", null);
|
||||
case 403:
|
||||
return callback("Private video", null);
|
||||
case 404:
|
||||
return callback("Video not found", null);
|
||||
case 500:
|
||||
case 503:
|
||||
return callback("Service unavailable", null);
|
||||
default:
|
||||
return callback("HTTP " + status, null);
|
||||
}
|
||||
|
||||
var buffer = data;
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
/* Check for embedding restrictions */
|
||||
if (data.entry.yt$accessControl) {
|
||||
var ac = data.entry.yt$accessControl;
|
||||
for (var i = 0; i < ac.length; i++) {
|
||||
if (ac[i].action === "embed") {
|
||||
if (ac[i].permission === "denied") {
|
||||
callback("Embedding disabled", null);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var seconds = data.entry.media$group.yt$duration.seconds;
|
||||
var title = data.entry.title.$t;
|
||||
var meta = {};
|
||||
/* Check for country restrictions */
|
||||
if (data.entry.media$group.media$restriction) {
|
||||
var rest = data.entry.media$group.media$restriction;
|
||||
if (rest.length > 0) {
|
||||
if (rest[0].relationship === "deny") {
|
||||
meta.restricted = rest[0].$t;
|
||||
}
|
||||
}
|
||||
}
|
||||
var media = new Media(id, title, seconds, "yt", meta);
|
||||
callback(false, media);
|
||||
} catch (e) {
|
||||
// Gdata version 2 has the rather silly habit of
|
||||
// returning error codes in XML when I explicitly asked
|
||||
// for JSON
|
||||
var m = buffer.match(/<internalReason>([^<]+)<\/internalReason>/);
|
||||
if (m === null)
|
||||
m = buffer.match(/<code>([^<]+)<\/code>/);
|
||||
|
||||
var err = e;
|
||||
if (m) {
|
||||
if(m[1] === "too_many_recent_calls") {
|
||||
err = "YouTube is throttling the server right "+
|
||||
"now for making too many requests. "+
|
||||
"Please try again in a moment.";
|
||||
} else {
|
||||
err = m[1];
|
||||
}
|
||||
}
|
||||
|
||||
callback(err, null);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/* youtube.com playlists - old v2 api */
|
||||
yp2: function (id, callback, url) {
|
||||
/**
|
||||
* NOTE: callback may be called multiple times, once for each <= 25 video
|
||||
* batch of videos in the list. It will be called in order.
|
||||
*/
|
||||
var m = id.match(/([\w-]+)/);
|
||||
if (m) {
|
||||
id = m[1];
|
||||
} else {
|
||||
callback("Invalid ID", null);
|
||||
return;
|
||||
}
|
||||
var path = "/feeds/api/playlists/" + id + "?v=2&alt=json";
|
||||
/**
|
||||
* NOTE: the third parameter, url, is used to chain this retriever
|
||||
* multiple times to get all the videos from a playlist, as each
|
||||
* request only returns 25 videos.
|
||||
*/
|
||||
if (url !== undefined) {
|
||||
path = "/" + url.split("gdata.youtube.com")[1];
|
||||
}
|
||||
|
||||
var options = {
|
||||
host: "gdata.youtube.com",
|
||||
port: 443,
|
||||
path: path,
|
||||
method: "GET",
|
||||
dataType: "jsonp",
|
||||
timeout: 1000
|
||||
};
|
||||
|
||||
if (Config.get("youtube-v2-key")) {
|
||||
options.headers = {
|
||||
"X-Gdata-Key": "key=" + Config.get("youtube-v2-key")
|
||||
};
|
||||
}
|
||||
|
||||
urlRetrieve(https, options, function (status, data) {
|
||||
switch (status) {
|
||||
case 200:
|
||||
break; /* Request is OK, skip to handling data */
|
||||
case 400:
|
||||
return callback("Invalid request", null);
|
||||
case 403:
|
||||
return callback("Private playlist", null);
|
||||
case 404:
|
||||
return callback("Playlist not found", null);
|
||||
case 500:
|
||||
case 503:
|
||||
return callback("Service unavailable", null);
|
||||
default:
|
||||
return callback("HTTP " + status, null);
|
||||
}
|
||||
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
var vids = [];
|
||||
for(var i in data.feed.entry) {
|
||||
try {
|
||||
/**
|
||||
* FIXME: This should probably check for embed restrictions
|
||||
* and country restrictions on each video in the list
|
||||
*/
|
||||
var item = data.feed.entry[i];
|
||||
var id = item.media$group.yt$videoid.$t;
|
||||
var title = item.title.$t;
|
||||
var seconds = item.media$group.yt$duration.seconds;
|
||||
var media = new Media(id, title, seconds, "yt");
|
||||
vids.push(media);
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
|
||||
callback(false, vids);
|
||||
|
||||
var links = data.feed.link;
|
||||
for (var i in links) {
|
||||
if (links[i].rel === "next") {
|
||||
/* Look up the next batch of videos from the list */
|
||||
Getters["yp2"](id, callback, links[i].href);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
callback(e, null);
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
/* youtube.com search - old v2 api */
|
||||
ytSearch2: function (terms, callback) {
|
||||
/**
|
||||
* terms is a list of words from the search query. Each word must be
|
||||
* encoded properly for use in the request URI
|
||||
*/
|
||||
for (var i in terms) {
|
||||
terms[i] = encodeURIComponent(terms[i]);
|
||||
}
|
||||
var query = terms.join("+");
|
||||
|
||||
var options = {
|
||||
host: "gdata.youtube.com",
|
||||
port: 443,
|
||||
path: "/feeds/api/videos/?q=" + query + "&v=2&alt=json",
|
||||
method: "GET",
|
||||
dataType: "jsonp",
|
||||
timeout: 1000
|
||||
};
|
||||
|
||||
if (Config.get("youtube-v2-key")) {
|
||||
options.headers = {
|
||||
"X-Gdata-Key": "key=" + Config.get("youtube-v2-key")
|
||||
};
|
||||
}
|
||||
|
||||
urlRetrieve(https, options, function (status, data) {
|
||||
if (status !== 200) {
|
||||
callback("YouTube search: HTTP " + status, null);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
var vids = [];
|
||||
for(var i in data.feed.entry) {
|
||||
try {
|
||||
/**
|
||||
* FIXME: This should probably check for embed restrictions
|
||||
* and country restrictions on each video in the list
|
||||
*/
|
||||
var item = data.feed.entry[i];
|
||||
var id = item.media$group.yt$videoid.$t;
|
||||
var title = item.title.$t;
|
||||
var seconds = item.media$group.yt$duration.seconds;
|
||||
var media = new Media(id, title, seconds, "yt");
|
||||
media.thumb = item.media$group.media$thumbnail[0];
|
||||
vids.push(media);
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
|
||||
callback(false, vids);
|
||||
} catch(e) {
|
||||
callback(e, null);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue