Skip to content

Commit

Permalink
fix: gracefully fail with private videos
Browse files Browse the repository at this point in the history
  • Loading branch information
fent committed May 20, 2020
1 parent 3cc1e34 commit f778d84
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 11 deletions.
6 changes: 3 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ const createStream = options => {
const downloadFromInfoCallback = (stream, info, options) => {
options = options || {};

let playability = info.playerResponse.playabilityStatus;
if (playability && playability.status === 'UNPLAYABLE') {
stream.emit('error', Error(util.stripHTML(playability.reason)));
let err = util.playError(info, 'UNPLAYABLE');
if (err) {
stream.emit('error', err);
return;
}

Expand Down
10 changes: 7 additions & 3 deletions lib/info.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ exports.getBasicInfo = async(id, options) => {
throw Error(`Error parsing info: ${err.message}`);
}

let playability = info.playerResponse.playabilityStatus;
if (playability && playability.status === 'ERROR') {
throw Error(playability.reason);
let playErr = util.playError(info, 'ERROR');
if (playErr) {
throw playErr;
}

if (!info.player) {
Expand All @@ -63,6 +63,10 @@ exports.getBasicInfo = async(id, options) => {
} catch (err) {
throw Error(`Error parsing config: ${err.message}`);
}
playErr = util.playError(info, 'LOGIN_REQUIRED');
if (!config.args.player_response && !config.args.embedded_player_response && playErr) {
throw playErr;
}
info.player = config;
}
return gotConfig(id, options, info, body);
Expand Down
18 changes: 18 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ exports.stripHTML = html => html
.replace(/<.*?>/gi, '')
.trim();


/**
* Get a number from an abbreviated number string.
*
Expand All @@ -369,6 +370,7 @@ exports.parseAbbreviatedNumber = string => {
return null;
};


/**
* Match begin and end braces of input JSON, return only json
*
Expand Down Expand Up @@ -420,3 +422,19 @@ exports.cutAfterJSON = mixedJson => {
// We ran through the whole string and ended up with an unclosed bracket
throw Error("Can't cut unsupported JSON (no matching closing bracket found)");
};


/**
* Checks if there is a playability error.
*
* @param {Object} info
* @param {string} status
* @returns {!Error}
*/
exports.playError = (info, status) => {
let playability = info.playerResponse.playabilityStatus;
if (playability && playability.status === status) {
return Error(playability.reason || (playability.messages && playability.messages[0]));
}
return null;
};
6 changes: 5 additions & 1 deletion test/files/refresh.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ const videos = [
type: 'no-likes-or-dislikes',
skip: ['get_video_info', /player/],
},
{
id: 'z2jeHsa0UG0',
type: 'private',
},
];


Expand Down Expand Up @@ -333,7 +337,7 @@ const refreshVideo = async(video, noRequests) => {
writeTransforms(filename, body);
}
} catch (err) {
console.log('error retrieveing video info:', err.message);
console.log('error retrieving video info:', err.message);
console.log(err.stack);
}
}
Expand Down
15 changes: 15 additions & 0 deletions test/files/videos/private/embed.html

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions test/files/videos/private/watch.json

Large diffs are not rendered by default.

19 changes: 15 additions & 4 deletions test/info-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ const sinon = require('sinon');


describe('ytdl.getInfo()', () => {
let clock;
before(() => { clock = sinon.useFakeTimers({ toFake: ['setTimeout'] }); });
after(() => { clock.restore(); });

describe('From a regular video', () => {
const id = 'pJk0p-98Xzc';
let expectedInfo;
Expand Down Expand Up @@ -78,6 +74,9 @@ describe('ytdl.getInfo()', () => {

describe('Use `ytdl.downloadFromInfo()`', () => {
it('Retrieves video file', done => {
let clock = sinon.useFakeTimers({ toFake: ['setTimeout'] });
after(() => { clock.restore(); });

const stream = ytdl.downloadFromInfo(expectedInfo);
let scope;
stream.on('info', (info, format) => {
Expand Down Expand Up @@ -281,6 +280,18 @@ describe('ytdl.getInfo()', () => {
});
});

describe('With a private video', () => {
it('Fails gracefully', async() => {
const id = 'z2jeHsa0UG0';
const scope = nock(id, {
type: 'private',
embed: true,
});
await assert.rejects(ytdl.getInfo(id), /private video/);
scope.done();
});
});

it('Fails gracefully when unable to get watch page', async() => {
const id = '_HSylqgVYQI';
const scope = nock(id, {
Expand Down

0 comments on commit f778d84

Please sign in to comment.