New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

better-youtube-api

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

better-youtube-api - npm Package Compare versions

Comparing version 1.0.7 to 2.0.0

out/constants.js

0

CHANGELOG.md

@@ -0,0 +0,0 @@ ### 1.0.7

8

out/entities/index.js

@@ -6,7 +6,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./Video"));
__export(require("./Channel"));
__export(require("./Playlist"));
__export(require("./Comment"));
__export(require("./video"));
__export(require("./channel"));
__export(require("./playlist"));
__export(require("./comment"));
//# sourceMappingURL=index.js.map

@@ -18,2 +18,3 @@ "use strict";

const caching_1 = require("./util/caching");
const oauth_1 = require("./oauth");
__export(require("./entities"));

@@ -27,2 +28,3 @@ /**

* @param token Your YouTube Data API v3 token. Don't share this with anybody.
* It could be an API key or an OAuth 2.0 token.
* @param options Caching options. Recommended to change.

@@ -32,2 +34,3 @@ */

this.token = token;
this.oauth = new oauth_1.OAuth(this);
this._shouldCache = options.cache;

@@ -40,2 +43,9 @@ this._cacheSearches = options.cacheSearches;

}
get token() {
return this._token;
}
set token(val) {
this._token = val;
this.tokenType = val.startsWith('ya29') ? 'oauth' : 'key';
}
_cache(id, value) {

@@ -53,3 +63,3 @@ if (!this._shouldCache) {

searchVideos(searchTerm, maxResults = 10) {
return this.search('video', searchTerm, maxResults);
return this.search(entities_1.Video, searchTerm, maxResults);
}

@@ -62,3 +72,3 @@ /**

searchChannels(searchTerm, maxResults = 10) {
return this.search('channel', searchTerm, maxResults);
return this.search(entities_1.Channel, searchTerm, maxResults);
}

@@ -71,3 +81,3 @@ /**

searchPlaylists(searchTerm, maxResults = 10) {
return this.search('playlist', searchTerm, maxResults);
return this.search(entities_1.Playlist, searchTerm, maxResults);
}

@@ -79,3 +89,3 @@ /**

getVideo(id) {
return this.getItemById('video', id);
return this.getItemById(entities_1.Video, id);
}

@@ -87,3 +97,3 @@ /**

getChannel(id) {
return this.getItemById('channel', id);
return this.getItemById(entities_1.Channel, id);
}

@@ -95,3 +105,3 @@ /**

getPlaylist(id) {
return this.getItemById('playlist', id);
return this.getItemById(entities_1.Playlist, id);
}

@@ -103,3 +113,3 @@ /**

getComment(id) {
return this.getItemById('comment', id);
return this.getItemById(entities_1.YTComment, id);
}

@@ -115,3 +125,3 @@ /**

}
return this.getItemById('video', id.video);
return this.getItemById(entities_1.Video, id.video);
}

@@ -127,3 +137,3 @@ /**

}
return this.getItemById('channel', id.channel);
return this.getItemById(entities_1.Channel, id.channel);
}

@@ -139,3 +149,3 @@ /**

}
return this.getItemById('playlist', id.playlist);
return this.getItemById(entities_1.Playlist, id.playlist);
}

@@ -151,4 +161,3 @@ /**

/**
* Get `maxResults` comments on a video. Used mostly internally with `Video#fetchComments`.
* Can only get the last 100 comments on a video, due to a bug with the YouTube API.
* Get `maxResults` comments from a video. Used mostly internally with `Video#fetchComments`.
* @param videoId The ID of the video.

@@ -158,5 +167,13 @@ * @param maxResults The maximum amount of comments to get from the video. If <= 0 or not included, returns all comments on the video.

getVideoComments(videoId, maxResults = -1) {
return this.getPaginatedItems('commentThreads', videoId, maxResults);
return this.getPaginatedItems('commentThreads:video', videoId, maxResults);
}
/**
* Get `maxResults` comments from a channel's discussion tab. Used mostly internally with `Channel#fetchComments`.
* @param channelId The ID of the channel.
* @param maxResults The maximum amount of comments to get from the channel. If <= 0 or not included, returns all comments on the channel.
*/
getChannelComments(channelId, maxResults = -1) {
return this.getPaginatedItems('commentThreads:channel', channelId, maxResults);
}
/**
* Get `maxResults` replies to a comment. Used mostly internally with `Comment#fetchReplies`.

@@ -172,3 +189,3 @@ * @param commentId The ID of the comment to get replies from.

return __awaiter(this, void 0, void 0, function* () {
const cached = caching_1.Cache.get(`search://${type}/"${searchTerm}"/${maxResults}`);
const cached = caching_1.Cache.get(`search://${type.endpoint}/"${searchTerm}"/${maxResults}`);
if (this._shouldCache && cached) {

@@ -183,24 +200,11 @@ return cached;

maxResults,
key: this.token,
part: 'snippet',
type
});
type: type.endpoint.substring(0, type.endpoint.length - 1)
}, this.token, this.tokenType);
const items = [];
results.items.forEach(item => {
switch (type) {
case 'video':
items.push(new entities_1.Video(this, item));
break;
case 'channel':
items.push(new entities_1.Channel(this, item));
break;
case 'playlist':
items.push(new entities_1.Playlist(this, item));
break;
default:
return Promise.reject('Type must be a video, channel, or playlist');
}
items.push(new type(this, item));
});
if (this._shouldCache && this._cacheSearches) {
this._cache(`search://${type}/"${searchTerm}"/${maxResults}`, items);
this._cache(`search://${type.endpoint}/"${searchTerm}"/${maxResults}`, items);
}

@@ -213,57 +217,16 @@ return items;

return __awaiter(this, void 0, void 0, function* () {
const cached = caching_1.Cache.get(`get://${type}/${id}`);
if (!([entities_1.Video, entities_1.Channel, entities_1.Playlist, entities_1.YTComment].includes(type))) {
return Promise.reject('Type must be a video, channel, playlist, or comment.');
}
const cached = caching_1.Cache.get(`get://${type.endpoint}/${id}`);
if (this._shouldCache && cached) {
return cached;
}
let result;
if (type === 'video') {
result = yield util_1.request.api('videos', {
id,
part: 'snippet,contentDetails,statistics,status',
key: this.token
});
}
else if (type === 'channel') {
result = yield util_1.request.api('channels', {
id,
part: 'snippet,contentDetails,statistics,status',
key: this.token
});
}
else if (type === 'playlist') {
result = yield util_1.request.api('playlists', {
id,
part: 'snippet,contentDetails,player',
key: this.token
});
}
else if (type === 'comment') {
result = yield util_1.request.api('comments', {
id,
part: 'snippet',
key: this.token
});
}
const result = yield util_1.request.api(type.endpoint, { id, part: type.part }, this.token, this.tokenType);
if (result.items.length === 0) {
return Promise.reject('Item not found');
}
let endResult;
switch (type) {
case 'video':
endResult = new entities_1.Video(this, result.items[0]);
break;
case 'playlist':
endResult = new entities_1.Playlist(this, result.items[0]);
break;
case 'channel':
endResult = new entities_1.Channel(this, result.items[0]);
break;
case 'comment':
endResult = new entities_1.YTComment(this, result.items[0]);
break;
default:
return Promise.reject('Type must be a video, channel, playlist, or comment.');
}
let endResult = new type(this, result.items[0], result.items[0].snippet.channelId ? 'channel' : 'video');
if (this._shouldCache) {
this._cache(`get://${type}/${id}`, endResult);
this._cache(`get://${type.endpoint}/${id}`, endResult);
}

@@ -274,5 +237,5 @@ return endResult;

/* istanbul ignore next */
getPaginatedItems(type, id, maxResults = -1) {
getPaginatedItems(endpoint, id, maxResults = -1) {
return __awaiter(this, void 0, void 0, function* () {
const cached = caching_1.Cache.get(`get://${type}/${id}/${maxResults}`);
const cached = caching_1.Cache.get(`get://${endpoint}/${id}/${maxResults}`);
if (this._shouldCache && cached) {

@@ -289,88 +252,65 @@ return cached;

}
const options = {
part: 'snippet',
maxResults: 0
};
let max;
if (type === 'playlistItems') {
let clazz;
let commentType;
if (endpoint === 'playlistItems') {
max = 50;
clazz = entities_1.Video;
options.playlistId = id;
}
else if (type === 'commentThreads' || type === 'comments') {
else if (endpoint.startsWith('commentThreads')) {
max = 100;
clazz = entities_1.YTComment;
const [, type] = endpoint.split(':');
commentType = type ? type : 'video';
endpoint = 'commentThreads';
options[`${type}Id`] = id;
options.part += ',replies';
options.textFormat = 'plainText';
}
else if (endpoint === 'comments') {
max = 100;
clazz = entities_1.YTComment;
options.parentId = id;
}
else {
return Promise.reject('Unknown item type ' + type);
return Promise.reject('Unknown item type ' + endpoint);
}
if (maxResults > max) {
return Promise.reject(`Max results must be ${max} or below for ${type}`);
return Promise.reject(`Max results must be ${max} or below for ${endpoint}`);
}
const options = {
part: 'snippet',
key: this.token,
maxResults: full ? max : maxResults
};
switch (type) {
case 'playlistItems':
options.playlistId = id;
break;
case 'commentThreads':
options.videoId = id;
options.part += ',replies';
options.textFormat = 'plainText';
break;
case 'comments':
options.parentId = id;
break;
}
const results = yield util_1.request.api(type, options).catch(error => {
return Promise.reject('Items not found');
});
if (results.items.length === 0) {
return Promise.reject('Items not found');
}
const totalResults = results.pageInfo.totalResults;
const perPage = results.pageInfo.resultsPerPage;
const pages = Math.floor(totalResults / perPage);
results.items.forEach(item => {
let comment;
switch (type) {
case 'playlistItems':
items.push(new entities_1.Video(this, item));
break;
case 'commentThreads':
comment = new entities_1.YTComment(this, item.snippet.topLevelComment);
items.push(comment);
break;
case 'comments':
items.push(new entities_1.YTComment(this, item));
break;
options.maxResults = full ? max : maxResults;
let results;
let pages = null;
let shouldReturn = !full;
for (let i = 1; i < pages ? pages : 3; i++) {
results = yield util_1.request.api(endpoint, options, this.token, this.tokenType).catch(() => {
return Promise.reject('Items not found');
});
if (results.items.length === 0) {
return Promise.reject('Items not found');
}
if (item.replies) {
item.replies.comments.forEach(reply => {
const created = new entities_1.YTComment(this, reply);
comment.replies.push(created);
});
if (!pages) {
pages = results.pageInfo.totalResults / results.pageInfo.resultsPerPage;
if (pages <= 1) {
shouldReturn = true;
}
pages = Math.floor(pages);
}
});
if (!full || pages === 0) {
return items;
}
let oldRes = results;
options.pageToken = oldRes.nextPageToken;
for (let i = 1; i < pages; i++) {
const newResults = yield util_1.request.api(type, options);
oldRes = newResults;
newResults.items.forEach(item => {
results.items.forEach(item => {
let comment;
switch (type) {
case 'playlistItems':
items.push(new entities_1.Video(this, item));
break;
case 'commentThreads':
comment = new entities_1.YTComment(this, item.snippet.topLevelComment);
items.push(comment);
break;
case 'comments':
items.push(new entities_1.YTComment(this, item));
break;
if (item.snippet.topLevelComment) {
comment = new entities_1.YTComment(this, item.snippet.topLevelComment, commentType);
items.push(comment);
}
else {
items.push(new clazz(this, item, commentType));
}
if (item.replies) {
item.replies.comments.forEach(reply => {
const created = new entities_1.YTComment(this, reply);
const created = new entities_1.YTComment(this, reply, commentType);
comment.replies.push(created);

@@ -380,5 +320,11 @@ });

});
if (results.nextPageToken && !shouldReturn) {
options.pageToken = results.nextPageToken;
}
else {
return items;
}
}
if (this._shouldCache) {
this._cache(`get://${type}/${id}/${maxResults}`, items);
this._cache(`get://${endpoint}/${id}/${maxResults}`, items);
}

@@ -385,0 +331,0 @@ return items;

@@ -25,3 +25,3 @@ "use strict";

const time = new Date().getTime();
if (!item || item.t <= 0) {
if (item.t <= 0) {
return;

@@ -28,0 +28,0 @@ }

@@ -6,5 +6,20 @@ "use strict";

exports.request = {
api: (subUrl, params) => {
const url = 'https://www.googleapis.com/youtube/v3' + (subUrl.startsWith('/') ? subUrl : '/' + subUrl) + parseParams(params);
return get(url);
api: (subUrl, params, token, type) => {
/* istanbul ignore next */
const url = 'https://www.googleapis.com/youtube/v3' + (subUrl.startsWith('/') ? '' : '/') + subUrl + parseParams(params) +
(type === 'key' ? (params ? `&key=${token}` : `?key=${token}`) : '');
/* istanbul ignore next */
return get(url, type === 'oauth' ? token : undefined);
},
post: (subUrl, params, token, data) => {
/* istanbul ignore next */
const url = 'https://www.googleapis.com/youtube/v3' + (subUrl.startsWith('/') ? '' : '/') + subUrl + parseParams(params);
/* istanbul ignore next */
return post(url, data, token);
},
put: (subUrl, params, token, data) => {
/* istanbul ignore next */
const url = 'https://www.googleapis.com/youtube/v3' + (subUrl.startsWith('/') ? '' : '/') + subUrl + parseParams(params);
/* istanbul ignore next */
return put(url, data, token);
}

@@ -15,10 +30,9 @@ };

*/
function get(url) {
/* istanbul ignore next */
function get(url, token) {
const options = parseUrlToOptions(url, 'GET');
return req(options, req => {
req.on('error', error => {
throw error;
});
req.end();
});
if (token) {
options.headers['Authorization'] = `Bearer ${token}`;
}
return req(options, req => reqCallback(req));
}

@@ -28,2 +42,25 @@ /**

*/
/* istanbul ignore next */
function post(url, data, token) {
const options = parseUrlToOptions(url, 'POST');
if (token) {
options.headers['Authorization'] = `Bearer ${token}`;
}
return req(options, req => reqCallback(req, data));
}
/**
* @ignore
*/
/* istanbul ignore next */
function put(url, data, token) {
const options = parseUrlToOptions(url, 'PUT');
if (token) {
options.headers['Authorization'] = `Bearer ${token}`;
}
return req(options, req => reqCallback(req, data));
}
/**
* @ignore
*/
/* istanbul ignore next */
function parseUrlToOptions(url, type) {

@@ -44,2 +81,3 @@ const parsed = url_1.parse(url);

*/
/* istanbul ignore next */
function req(options, reqFunction) {

@@ -54,2 +92,5 @@ return new Promise((resolve, reject) => {

res.on('end', () => {
if (res.statusCode === 404) {
return reject(new Error('Not found'));
}
const parsed = JSON.parse(data);

@@ -71,2 +112,16 @@ if (parsed.error) {

*/
/* istanbul ignore next */
function reqCallback(req, data) {
req.on('error', error => {
throw error;
});
if (data) {
req.write(data);
}
req.end();
}
/**
* @ignore
*/
/* istanbul ignore next */
function parseParams(params) {

@@ -73,0 +128,0 @@ let url = '';

{
"name": "better-youtube-api",
"version": "1.0.7",
"version": "2.0.0",
"description": "A very easy to use promise-based Youtube Data v3 API.",

@@ -8,4 +8,4 @@ "main": "out/index.js",

"scripts": {
"test": "mocha --exit",
"coverage": "nyc mocha --exit && nyc report --reporter=text-lcov | coveralls",
"test": "mocha --exit --require ts-node/register --require source-map-support/register \"./test/!(oauth).spec.ts\"",
"coverage": "nyc yarn test && nyc report --reporter=text-lcov | coveralls",
"docs": "gulp typedoc",

@@ -12,0 +12,0 @@ "prepublishOnly": "gulp"

@@ -1,4 +0,4 @@

export * from './Video';
export * from './Channel';
export * from './Playlist';
export * from './Comment';
export * from './video';
export * from './channel';
export * from './playlist';
export * from './comment';
import { Video, Channel, Playlist, YTComment } from './entities';
import { OAuth } from './oauth';
export * from './entities';

@@ -11,6 +12,10 @@ export * from './types';

private _cacheTTL;
private _token;
token: string;
tokenType: 'key' | 'oauth';
oauth: OAuth;
/**
*
* @param token Your YouTube Data API v3 token. Don't share this with anybody.
* It could be an API key or an OAuth 2.0 token.
* @param options Caching options. Recommended to change.

@@ -80,4 +85,3 @@ */

/**
* Get `maxResults` comments on a video. Used mostly internally with `Video#fetchComments`.
* Can only get the last 100 comments on a video, due to a bug with the YouTube API.
* Get `maxResults` comments from a video. Used mostly internally with `Video#fetchComments`.
* @param videoId The ID of the video.

@@ -88,2 +92,8 @@ * @param maxResults The maximum amount of comments to get from the video. If <= 0 or not included, returns all comments on the video.

/**
* Get `maxResults` comments from a channel's discussion tab. Used mostly internally with `Channel#fetchComments`.
* @param channelId The ID of the channel.
* @param maxResults The maximum amount of comments to get from the channel. If <= 0 or not included, returns all comments on the channel.
*/
getChannelComments(channelId: string, maxResults?: number): Promise<YTComment[]>;
/**
* Get `maxResults` replies to a comment. Used mostly internally with `Comment#fetchReplies`.

@@ -90,0 +100,0 @@ * @param commentId The ID of the comment to get replies from.

export declare const request: {
api: (subUrl: string, params: Object) => Promise<any>;
api: (subUrl: string, params: Object, token: string, type: "oauth" | "key") => Promise<any>;
post: (subUrl: string, params: Object, token: string, data: any) => Promise<any>;
put: (subUrl: string, params: Object, token: string, data: any) => Promise<any>;
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc