-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathRequest.js
101 lines (91 loc) · 3.54 KB
/
Request.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
const fetch = require('node-fetch');
const Constants = require('./util/Constants');
class Request {
constructor(youtube) {
this.youtube = youtube;
}
/**
* Make a request to the YouTube API
* @param {string} endpoint The endpoint to query
* @param {object} [qs={}] Query strings
* @returns {Promise<object>}
*/
make(endpoint, qs = {}) {
qs = Object.assign({ key: this.youtube.key }, qs);
const params = Object.keys(qs).filter(k => qs[k]).map(k => `${k}=${qs[k]}`);
return fetch(encodeURI(`https://www.googleapis.com/youtube/v3/${endpoint}${params.length ? `?${params.join('&')}` : ''}`))
.then(result => result.json())
.then(result => {
if (result.error) return Promise.reject(result.error);
return result;
});
}
/**
* Get a resource from the YouTube API
* @param {string} type The type of resource to get
* @param {object} [qs={}] Any other query options
* @returns {Promise<object>}
*/
getResource(type, qs = {}) {
qs = Object.assign({ part: Constants.PARTS[type] }, qs);
return this.make(Constants.ENDPOINTS[type], qs).then(result =>
result.items.length ? result.items[0] : Promise.reject(new Error(`resource ${result.kind} not found`))
);
}
/**
* Get a resource from the YouTube API, by ID
* @param {string} type The type of resource to get
* @param {string} id The ID of the resource to get
* @param {object} [qs={}] Any other query options
* @returns {Promise<object>}
*/
getResourceByID(type, id, qs = {}) {
return this.getResource(type, Object.assign(qs, { id }));
}
/**
* Get a video from the YouTube API
* @param {string} id The video to get
* @param {object} [options] Any request options
* @returns {Promise<object>}
*/
getVideo(id, options) {
return this.getResourceByID('Videos', id, options);
}
/**
* Get a playlist from the YouTube API
* @param {string} id The playlist to get
* @param {object} [options] Any request options
* @returns {Promise<object>}
*/
getPlaylist(id, options) {
return this.getResourceByID('Playlists', id, options);
}
/**
* Get a channel from the YouTube API
* @param {string} id The channel to get
* @param {object} [options] Any request options
* @returns {Promise<object>}
*/
getChannel(id, options) {
return this.getResourceByID('Channels', id, options);
}
/**
* Fetch a paginated resource.
* @param {string} endpoint The endpoint to query.
* @param {number} [count=Infinity] How many results to retrieve.
* @param {Object} [options={}] Additional options to send.
* @param {Array} [fetched=[]] Previously fetched resources.
* @param {?string} [pageToken] The page token to retrieve.
* @returns {Promise<Array<object>>}
*/
getPaginated(endpoint, count = Infinity, options = {}, fetched = [], pageToken = null) {
if(count < 1) return Promise.reject('Cannot fetch less than 1.');
const limit = count > 50 ? 50 : count;
return this.make(endpoint, Object.assign(options, { pageToken, maxResults: limit })).then(result => {
const results = fetched.concat(result.items);
if(result.nextPageToken && limit !== count) return this.getPaginated(endpoint, count - limit, options, results, result.nextPageToken);
return results;
});
}
}
module.exports = Request;