Skip to content

Commit b2df83c

Browse files
feat: Access to the various getInfo miniget requests. (#901)
* Add files via upload * Add files via upload * Update info.js * Update info.js * Add files via upload * Update README.md * Update info.js * Update README.md * Add files via upload * Add files via upload * rework callback * linting * Update index.d.ts Co-authored-by: TimeForANinja <[email protected]> Co-authored-by: TimeForANinja <[email protected]>
1 parent 6f4907d commit b2df83c

File tree

6 files changed

+74
-8
lines changed

6 files changed

+74
-8
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Gets metainfo from a video. Includes additional formats, and ready to download d
6969
`options` can have the following
7070

7171
* `requestOptions` - Anything to merge into the request options which [miniget](https://github.com/fent/node-miniget) is called with, such as `headers`.
72+
* `requestCallback` - Provide a callback function that receives miniget request stream objects used while fetching metainfo.
7273
* `lang` - The 2 character symbol of a language. Default is `en`.
7374

7475
### ytdl.downloadFromInfo(info, options)

lib/info.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,14 @@ const isNotYetBroadcasted = player_response => {
120120
const getWatchHTMLURL = (id, options) => `${BASE_URL + id}&hl=${options.lang || 'en'}`;
121121
const getWatchHTMLPageBody = (id, options) => {
122122
const url = getWatchHTMLURL(id, options);
123-
return exports.watchPageCache.getOrSet(url, () => miniget(url, options.requestOptions).text());
123+
return exports.watchPageCache.getOrSet(url, () => utils.exposedMiniget(url, options).text());
124124
};
125125

126126

127127
const EMBED_URL = 'https://www.youtube.com/embed/';
128128
const getEmbedPageBody = (id, options) => {
129129
const embedUrl = `${EMBED_URL + id}?hl=${options.lang || 'en'}`;
130-
return miniget(embedUrl, options.requestOptions).text();
130+
return utils.exposedMiniget(embedUrl, options).text();
131131
};
132132

133133

@@ -288,7 +288,7 @@ const getWatchJSONPage = async(id, options) => {
288288
}
289289

290290
const jsonUrl = getWatchJSONURL(id, options);
291-
let body = await miniget(jsonUrl, reqOptions).text();
291+
const body = await utils.exposedMiniget(jsonUrl, options, reqOptions).text();
292292
let parsedBody = parseJSON('watch.json', 'body', body);
293293
if (parsedBody.reload === 'now') {
294294
await setIdentityToken('browser', false);
@@ -330,7 +330,7 @@ const getVideoInfoPage = async(id, options) => {
330330
url.searchParams.set('ps', 'default');
331331
url.searchParams.set('gl', 'US');
332332
url.searchParams.set('hl', options.lang || 'en');
333-
let body = await miniget(url.toString(), options.requestOptions).text();
333+
const body = await utils.exposedMiniget(url.toString(), options).text();
334334
let info = querystring.parse(body);
335335
info.player_response = findPlayerResponse('get_video_info', info);
336336
return info;
@@ -427,7 +427,7 @@ const getDashManifest = (url, options) => new Promise((resolve, reject) => {
427427
}
428428
};
429429
parser.onend = () => { resolve(formats); };
430-
const req = miniget(new URL(url, BASE_URL).toString(), options.requestOptions);
430+
const req = utils.exposedMiniget(new URL(url, BASE_URL).toString(), options);
431431
req.setEncoding('utf8');
432432
req.on('error', reject);
433433
req.on('data', chunk => { parser.write(chunk); });
@@ -444,7 +444,7 @@ const getDashManifest = (url, options) => new Promise((resolve, reject) => {
444444
*/
445445
const getM3U8 = async(url, options) => {
446446
url = new URL(url, BASE_URL);
447-
let body = await miniget(url.toString(), options.requestOptions).text();
447+
const body = await utils.exposedMiniget(url.toString(), options).text();
448448
let formats = {};
449449
body
450450
.split('\n')

lib/sig.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const { URL } = require('url');
2-
const miniget = require('miniget');
32
const querystring = require('querystring');
43
const Cache = require('./cache');
4+
const utils = require('./utils');
55

66

77
// A shared cache to keep track of html5player.js tokens.
@@ -16,7 +16,7 @@ exports.cache = new Cache();
1616
* @returns {Promise<Array.<string>>}
1717
*/
1818
exports.getTokens = (html5playerfile, options) => exports.cache.getOrSet(html5playerfile, async() => {
19-
let body = await miniget(html5playerfile, options.requestOptions).text();
19+
const body = await utils.exposedMiniget(html5playerfile, options).text();
2020
const tokens = exports.extractActions(body);
2121
if (!tokens || !tokens.length) {
2222
throw Error('Could not extract signature deciphering actions');

lib/utils.js

+13
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,19 @@ exports.playError = (player_response, statuses, ErrorType = Error) => {
126126
return null;
127127
};
128128

129+
/**
130+
* Does a miniget request and calls options.requestCallback if present
131+
*
132+
* @param {string} url the request url
133+
* @param {Object} options an object with optional requestOptions and requestCallback parameters
134+
* @param {Object} requestOptionsOverwrite overwrite of options.requestOptions
135+
* @returns {miniget.Stream}
136+
*/
137+
exports.exposedMiniget = (url, options = {}, requestOptionsOverwrite) => {
138+
const req = miniget(url, requestOptionsOverwrite || options.requestOptions);
139+
if (typeof options.requestCallback === 'function') options.requestCallback(req);
140+
return req;
141+
};
129142

130143
/**
131144
* Temporary helper to help deprecating a few properties.

test/utils-test.js

+51
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,54 @@ describe('utils.checkForUpdates', () => {
180180
});
181181
});
182182
});
183+
184+
describe('utils.exposedMiniget', () => {
185+
it('does not error with undefined requestOptionsOverwrite', async() => {
186+
const scope = nock('https://test.com').get('/').reply(200, 'nice');
187+
const req = utils.exposedMiniget('https://test.com/', {});
188+
await req.text();
189+
scope.done();
190+
});
191+
192+
it('does not error without options', async() => {
193+
const scope = nock('https://test.com').get('/').reply(200, 'nice');
194+
const req = utils.exposedMiniget('https://test.com/');
195+
await req.text();
196+
scope.done();
197+
});
198+
199+
it('does not error without options', async() => {
200+
const scope = nock('https://test.com').get('/').reply(200, 'nice');
201+
const req = utils.exposedMiniget('https://test.com/');
202+
assert.equal(await req.text(), 'nice');
203+
scope.done();
204+
});
205+
206+
it('calls a provided callback with the req object', async() => {
207+
const scope = nock('https://test.com').get('/').reply(200, 'nice');
208+
let cbReq;
209+
const requestCallback = r => cbReq = r;
210+
const req = utils.exposedMiniget('https://test.com/', { requestCallback });
211+
await req.text();
212+
assert.equal(cbReq, req);
213+
scope.done();
214+
});
215+
216+
it('it uses requestOptions', async() => {
217+
const scope = nock('https://test.com', { reqheaders: { auth: 'a' } }).get('/').reply(200, 'nice');
218+
const req = utils.exposedMiniget('https://test.com/', { requestOptions: { headers: { auth: 'a' } } });
219+
await req.text();
220+
scope.done();
221+
});
222+
223+
it('it prefers requestOptionsOverwrite over requestOptions', async() => {
224+
const scope = nock('https://test.com', { reqheaders: { auth: 'b' } }).get('/').reply(200, 'nice');
225+
const req = utils.exposedMiniget(
226+
'https://test.com/',
227+
{ requestOptions: { headers: { auth: 'a' } } },
228+
{ headers: { auth: 'b' } },
229+
);
230+
await req.text();
231+
scope.done();
232+
});
233+
});

typings/index.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ declare module 'ytdl-core' {
77

88
interface getInfoOptions {
99
lang?: string;
10+
requestCallback?: () => {};
1011
requestOptions?: {};
1112
}
1213

0 commit comments

Comments
 (0)