Huge News!Announcing our $40M Series B led by Abstract Ventures.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 0.1.2 to 0.2.0

out/entities/Comment.js

1

out/entities/index.js

@@ -9,1 +9,2 @@ "use strict";

__export(require("./Playlist"));
__export(require("./Comment"));

@@ -43,5 +43,5 @@ "use strict";

*/
getVideos() {
fetchVideos(maxResults = -1) {
return __awaiter(this, void 0, void 0, function* () {
this.videos = yield this.youtube.getPlaylistItems(this.id);
this.videos = yield this.youtube.getPlaylistItems(this.id, maxResults);
return this.videos;

@@ -51,2 +51,9 @@ });

/**
* Deprecated, use Playlist#fetchVideos instead.
* @param maxResults Maximum number of videos to fetch.
*/
getVideos(maxResults = -1) {
return this.fetchVideos(maxResults);
}
/**
* Fetches this playlist and reassigns this object to the new playlist object.

@@ -53,0 +60,0 @@ * Only useful if `this.full` is false, or if you want updated playlist info.

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

this.id = data.snippet.resourceId.videoId;
this.private = data.snippet.title === 'Private video' ? true : false;
this.private = data.snippet.title === 'Private video';
}

@@ -62,3 +62,9 @@ else if (data.kind === 'youtube#searchResult') {

}
fetchComments(maxResults = -1) {
return __awaiter(this, void 0, void 0, function* () {
this.comments = yield this.youtube.getVideoComments(this.id, maxResults);
return this.comments;
});
}
}
exports.Video = Video;

@@ -1,3 +0,1 @@

import { youtube_v3 } from "googleapis"
/**

@@ -77,2 +75,16 @@ * The main class used to interact with the YouTube API. Use this.

public getPlaylistItems(playlistId: string, maxResults?: number): Promise<Video[]>
/**
* Get `maxResults` comments on a video. Used mostly internally with `Video#fetchComments`.
* @param videoId The ID of the video.
* @param maxResults The maximum amount of comments to get from the video. If <= 0 or not included, returns all comments on the video.
*/
public getVideoComments (videoId: string, maxResults: number): Promise<YTComment[]>
/**
* Get `maxResults` replies to a comment. Used mostly internally with `Comment#fetchReplies`.
* @param commentId The ID of the comment to get replies from.
* @param maxResults The maximum amount of replies to get. Gets all replies if <= 0 or not included.
*/
public getCommentReplies (commentId: string, maxResults: number): Promise<YTComment[]>
}

@@ -85,5 +97,5 @@

/**
* YouTube object that created the video.
*/
public youtube
* YouTube object that created the video.
*/
public youtube: YouTube

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

*/
public data: youtube_v3.Schema$Video | youtube_v3.Schema$PlaylistItem | youtube_v3.Schema$SearchResult
public data

@@ -119,3 +131,9 @@ /**

*/
public thumbnails: youtube_v3.Schema$ThumbnailDetails
public thumbnails: {
default?: Thumbnail,
high?: Thumbnail,
maxres?: Thumbnail
medium?: Thumbnail,
standard?: Thumbnail
}

@@ -132,2 +150,4 @@ /**

private _length: string
/**

@@ -176,4 +196,9 @@ * The minutes of the video.

constructor(youtube, data: youtube_v3.Schema$Video | youtube_v3.Schema$PlaylistItem | youtube_v3.Schema$SearchResult)
/**
* The video's comments. Only defined when Video#fetchComments is called.
*/
public comments: YTComment[]
constructor(youtube: YouTube, data)
/**

@@ -203,3 +228,3 @@ * Fetches this video and reassigns this object to the new video object.

*/
public data: youtube_v3.Schema$Channel | youtube_v3.Schema$SearchResult
public data: any

@@ -239,3 +264,9 @@ /**

*/
public profilePictures: youtube_v3.Schema$ThumbnailDetails
public profilePictures: {
default?: Thumbnail,
high?: Thumbnail,
maxres?: Thumbnail
medium?: Thumbnail,
standard?: Thumbnail
}

@@ -253,12 +284,2 @@ /**

/**
* This channel's statistics.
*/
public statistics: youtube_v3.Schema$ChannelStatistics
/**
* The status of this channel.
*/
public status: youtube_v3.Schema$ChannelStatus
/**
* This channel's view count.

@@ -283,3 +304,3 @@ */

constructor (youtube: YouTube, data: youtube_v3.Schema$Channel | youtube_v3.Schema$SearchResult)
constructor (youtube: YouTube, data)

@@ -310,3 +331,3 @@ /**

*/
public data: youtube_v3.Schema$Playlist | youtube_v3.Schema$SearchResult
public data: any

@@ -351,3 +372,9 @@ /**

*/
public thumbnails: youtube_v3.Schema$ThumbnailDetails
public thumbnails: {
default?: Thumbnail,
high?: Thumbnail,
maxres?: Thumbnail
medium?: Thumbnail,
standard?: Thumbnail
}

@@ -369,3 +396,3 @@ /**

constructor (youtube: YouTube, data: youtube_v3.Schema$Playlist | youtube_v3.Schema$SearchResult)
constructor (youtube: YouTube, data)

@@ -383,1 +410,110 @@ /**

}
export class YTComment {
/**
* The YouTube object used to create the comment.
*/
public youtube: YouTube
/**
* The raw data from the YouTube API of the comment.
*/
public data: any
/**
* The comment's unique YouTube ID.
*/
public id: string
/**
* The comment's author.
*/
public author: {
/**
* The author's YouTube username. May not be unique.
*/
username: string,
/**
* The author's avatar URL.
*/
avatar: string,
/**
* The author's channel ID.
*/
channelId: string,
/**
* The author's channel URL.
*/
channelUrl: string
}
/**
* The comment's content.
*/
public text: {
/**
* What YouTube displays to the user viewing the comment.
*/
displayed: string,
/**
* The comment's plain text.
*/
original: string
}
/**
* Whether or not you can like/dislike the comment.
*/
public rateable: boolean
/**
* Either YouTube thinks it's popular, or it has at least 100 likes.
*/
public popular: boolean
/**
* The number of likes the comment has gotten.
*/
public likes: number
/**
* The date the comment was published.
*/
public datePublished: Date
/**
* Either the date the comment was last edited, or the date it was
* posted.
*/
public dateEdited: Date
/**
* Either the ID of the video that it commented on, or the ID of the
* comment it is replying to.
*/
public parentId: string
/**
* Replies to the comment.
*/
public replies: YTComment[]
constructor (youtube: YouTube, data)
/**
* Fetches replies to the comment.
* @param maxResults The maximum amount of replies to fetch. Fetches all comments if not included
* or less than 0.
*/
public fetchReplies (maxResults?: number): Promise<YTComment[]>
}
export type Thumbnail = {
height?: number,
width?: number,
url?: string
}

@@ -83,2 +83,9 @@ "use strict";

}
else if (type === 'comment') {
result = yield util_1.request.api('comments', {
id,
part: 'snippet',
key: this.token
});
}
if (result.items.length === 0) {

@@ -148,2 +155,11 @@ return Promise.reject('Item not found');

/**
* Get a comment object from the ID of a comment.
* @param id The ID of the comment.
*/
getComment(id) {
return __awaiter(this, void 0, void 0, function* () {
return new entities_1.YTComment(this, yield this.getItemById('comment', id));
});
}
/**
* Get a video object from the url of a video.

@@ -188,3 +204,3 @@ * @param url The url of the video.

/**
* Get `maxResults` videos in a playlist. Used mostly internally with `Playlist#getVideos`.
* Get `maxResults` videos in a playlist. Used mostly internally with `Playlist#fetchVideos`.
* @param playlistId The ID of the playlist.

@@ -215,3 +231,3 @@ * @param maxResults The maximum amount of videos to get from the playlist. If <= 0 or not included, returns all videos in the playlist.

const totalResults = results.pageInfo.totalResults;
const perPage = 50;
const perPage = results.pageInfo.resultsPerPage;
const pages = Math.floor(totalResults / perPage);

@@ -241,3 +257,123 @@ results.items.forEach(item => {

}
/**
* Get `maxResults` comments on a video. Used mostly internally with `Video#fetchComments`.
* @param videoId The ID of the video.
* @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 __awaiter(this, void 0, void 0, function* () {
let full;
let comments = [];
if (maxResults <= 0) {
full = true;
}
else {
full = false;
}
if (maxResults > 100) {
return Promise.reject('Max results must be 100 or below');
}
const results = yield util_1.request.api('commentThreads', {
videoId,
part: 'snippet,replies',
key: this.token,
maxResults: full ? 100 : maxResults,
textFormat: 'plainText'
}).catch(() => {
return Promise.reject('Comment thread not found');
});
const totalResults = results.pageInfo.totalResults;
const perPage = results.pageInfo.resultsPerPage;
const pages = Math.floor(totalResults / perPage);
results.items.forEach(item => {
const comment = new entities_1.YTComment(this, item.snippet.topLevelComment);
comments.push(comment);
if (item.replies) {
item.replies.comments.forEach(reply => {
const created = new entities_1.YTComment(this, reply);
comment.replies.push(created);
});
}
});
if (!full || pages === 0) {
return comments;
}
let oldRes = results;
for (let i = 1; i < pages; i++) {
const newResults = yield util_1.request.api('commentThreads', {
videoId,
part: 'snippet',
key: this.token,
maxResults: 50,
pageToken: oldRes.nextPageToken,
textFormat: 'plainText'
});
oldRes = newResults;
newResults.items.forEach(item => {
const comment = new entities_1.YTComment(this, item.snippet.topLevelComment);
comments.push(comment);
if (item.replies) {
item.replies.comments.forEach(reply => {
const created = new entities_1.YTComment(this, reply);
comment.replies.push(created);
});
}
});
}
return comments;
});
}
/**
* Get `maxResults` replies to a comment. Used mostly internally with `Comment#fetchReplies`.
* @param commentId The ID of the comment to get replies from.
* @param maxResults The maximum amount of replies to get. Gets all replies if <= 0 or not included.
*/
getCommentReplies(commentId, maxResults = -1) {
return __awaiter(this, void 0, void 0, function* () {
let full;
let replies = [];
if (maxResults <= 0) {
full = true;
}
else {
full = false;
}
if (maxResults > 100) {
return Promise.reject('Max results must be 50 or below');
}
const results = yield util_1.request.api('comments', {
parentId: commentId,
part: 'snippet',
key: this.token,
maxResults: full ? 100 : maxResults
}).catch(() => {
return Promise.reject('Playlist not found');
});
const totalResults = results.pageInfo.totalResults;
const perPage = results.pageInfo.resultsPerPage;
const pages = Math.floor(totalResults / perPage);
results.items.forEach(item => {
replies.push(new entities_1.YTComment(this, item));
});
if (!full || pages === 0) {
return replies;
}
let oldRes = results;
for (let i = 1; i < pages; i++) {
const newResults = yield util_1.request.api('comments', {
parentId: commentId,
part: 'snippet',
key: this.token,
maxResults: 100,
pageToken: oldRes.nextPageToken
});
oldRes = newResults;
newResults.items.forEach(item => {
replies.push(new entities_1.YTComment(this, item));
});
}
return replies;
});
}
}
exports.YouTube = YouTube;

12

out/util/request.js

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

api: (subUrl, params) => {
let url = 'https://www.googleapis.com/youtube/v3' + (subUrl.startsWith('/') ? subUrl : '/' + subUrl);
for (let param in params) {
url += (!url.includes('?') ? '?' : '&') + param + '=' + params[param];
}
const url = 'https://www.googleapis.com/youtube/v3' + (subUrl.startsWith('/') ? subUrl : '/' + subUrl) + parseParams(params);
return get(url);

@@ -78,1 +75,8 @@ }

}
function parseParams(params) {
let url = '';
for (let param in params) {
url += (!url.includes('?') ? '?' : '&') + param + '=' + params[param];
}
return url;
}
{
"name": "better-youtube-api",
"version": "0.1.2",
"description": "A very easy to use Youtube Data v3 API.",
"version": "0.2.0",
"description": "A very easy to use promise-based Youtube Data v3 API.",
"main": "out/index.js",

@@ -16,3 +16,6 @@ "scripts": {

"youtube api",
"youtube videos"
"youtube videos",
"promise",
"promise based",
"no dependencies"
],

@@ -23,7 +26,7 @@ "devDependencies": {

"@types/node": "^10.5.6",
"tslint": "^5.11.0",
"tslint-config-standard": "^7.1.0",
"chai": "^4.1.2",
"mocha": "^5.2.0",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"tslint-config-standard": "^7.1.0",
"typescript": "^3.0.1"

@@ -30,0 +33,0 @@ },

# Better YouTube API
Want to access data from the YouTube Data v3 API? Want a Node.js YouTube API wrapper with typings? No problem! We've got ya covered. `npm i better-youtube-api`
Want to access data from the YouTube Data v3 API? Want a Node.js YouTube API wrapper with typings and promises? No problem! We've got ya covered. `npm i better-youtube-api`

@@ -28,2 +28,2 @@ # Examples

You can do the same thing with playlists and channels by replacing `Video` with either one.
You can do the same thing with playlists, channels, and comments by replacing `Video` with either one.
import { YouTube } from '..'
import { youtube_v3 } from 'googleapis'
import { Playlist } from '.'
import { Thumbnail } from '../types'

@@ -22,3 +22,3 @@ /**

*/
public data: youtube_v3.Schema$Channel | youtube_v3.Schema$SearchResult
public data: any

@@ -58,3 +58,9 @@ /**

*/
public profilePictures: youtube_v3.Schema$ThumbnailDetails
public profilePictures: {
default?: Thumbnail,
high?: Thumbnail,
maxres?: Thumbnail
medium?: Thumbnail,
standard?: Thumbnail
}

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

constructor (youtube: YouTube, data: youtube_v3.Schema$Channel | youtube_v3.Schema$SearchResult) {
constructor (youtube: YouTube, data) {
this.youtube = youtube

@@ -99,6 +105,6 @@ this.data = data

private _init (data: youtube_v3.Schema$Channel | youtube_v3.Schema$SearchResult) {
private _init (data) {
if (data.kind === 'youtube#channel' && (data as youtube_v3.Schema$Channel).status.isLinked) {
const channel = data as youtube_v3.Schema$Channel
if (data.kind === 'youtube#channel' && data.status.isLinked) {
const channel = data

@@ -116,3 +122,3 @@ this.id = channel.id

} else if (data.kind === 'youtube#searchResult') {
this.id = (data as youtube_v3.Schema$SearchResult).id.channelId
this.id = data.id.channelId
} else {

@@ -143,7 +149,7 @@ throw new Error(`Invalid channel type: ${data.kind}`)

public async fetchVideos () {
if (!((this.data as youtube_v3.Schema$Channel).contentDetails)) {
if (!(this.data.contentDetails)) {
await this.fetch()
}
const videos = await this.youtube.getPlaylist((this.data as youtube_v3.Schema$Channel).contentDetails.relatedPlaylists.uploads)
const videos = await this.youtube.getPlaylist(this.data.contentDetails.relatedPlaylists.uploads)
this.videos = videos

@@ -150,0 +156,0 @@

export * from './Video'
export * from './Channel'
export * from './Playlist'
export * from './Comment'
import { YouTube } from '..'
import { youtube_v3 } from 'googleapis'
import { Video } from '.'
import { Thumbnail } from '../types'

@@ -17,3 +17,3 @@ /**

*/
public data: youtube_v3.Schema$Playlist | youtube_v3.Schema$SearchResult
public data: any

@@ -58,3 +58,9 @@ /**

*/
public thumbnails: youtube_v3.Schema$ThumbnailDetails
public thumbnails: {
default?: Thumbnail,
high?: Thumbnail,
maxres?: Thumbnail
medium?: Thumbnail,
standard?: Thumbnail
}

@@ -76,3 +82,3 @@ /**

constructor (youtube: YouTube, data: youtube_v3.Schema$Playlist | youtube_v3.Schema$SearchResult) {
constructor (youtube: YouTube, data) {
this.youtube = youtube

@@ -84,5 +90,5 @@ this.data = data

private _init (data: youtube_v3.Schema$Playlist | youtube_v3.Schema$SearchResult) {
private _init (data) {
if (data.kind === 'youtube#playlist') {
const playlist = data as youtube_v3.Schema$Playlist
const playlist = data

@@ -94,3 +100,3 @@ this.id = playlist.id

} else if (data.kind === 'youtube#searchResult') {
this.id = (data as youtube_v3.Schema$SearchResult).id.playlistId
this.id = data.id.playlistId
} else {

@@ -110,4 +116,4 @@ throw new Error(`Invalid playlist type: ${data.kind}`)

*/
public async getVideos () {
this.videos = await this.youtube.getPlaylistItems(this.id)
public async fetchVideos (maxResults: number = -1) {
this.videos = await this.youtube.getPlaylistItems(this.id, maxResults)
return this.videos

@@ -117,2 +123,10 @@ }

/**
* Deprecated, use Playlist#fetchVideos instead.
* @param maxResults Maximum number of videos to fetch.
*/
public getVideos (maxResults: number = -1) {
return this.fetchVideos(maxResults)
}
/**
* Fetches this playlist and reassigns this object to the new playlist object.

@@ -119,0 +133,0 @@ * Only useful if `this.full` is false, or if you want updated playlist info.

import { YouTube } from '..'
import { youtube_v3 } from 'googleapis'
import { Thumbnail } from '../types'
import { YTComment } from './Comment'

@@ -16,3 +17,3 @@ /**

*/
public data: youtube_v3.Schema$Video | youtube_v3.Schema$PlaylistItem | youtube_v3.Schema$SearchResult
public data

@@ -42,3 +43,9 @@ /**

*/
public thumbnails: youtube_v3.Schema$ThumbnailDetails
public thumbnails: {
default?: Thumbnail,
high?: Thumbnail,
maxres?: Thumbnail
medium?: Thumbnail,
standard?: Thumbnail
}

@@ -100,3 +107,8 @@ /**

constructor (youtube: YouTube, data: youtube_v3.Schema$Video | youtube_v3.Schema$PlaylistItem | youtube_v3.Schema$SearchResult) {
/**
* The video's comments. Only defined when Video#fetchComments is called.
*/
public comments: YTComment[]
constructor (youtube: YouTube, data) {
this.youtube = youtube

@@ -108,5 +120,5 @@ this.data = data

private _init (data: youtube_v3.Schema$Video | youtube_v3.Schema$PlaylistItem | youtube_v3.Schema$SearchResult) {
private _init (data) {
if (data.kind === 'youtube#video') {
const video = data as youtube_v3.Schema$Video
const video = data

@@ -122,6 +134,6 @@ this._length = video.contentDetails.duration

} else if (data.kind === 'youtube#playlistItem') {
this.id = (data.snippet as youtube_v3.Schema$PlaylistItemSnippet).resourceId.videoId
this.private = data.snippet.title === 'Private video' ? true : false
this.id = data.snippet.resourceId.videoId
this.private = data.snippet.title === 'Private video'
} else if (data.kind === 'youtube#searchResult') {
this.id = (data.id as youtube_v3.Schema$ResourceId).videoId
this.id = data.id.videoId
} else {

@@ -151,2 +163,7 @@ throw new Error(`Invalid video type: ${data.kind}.`)

}
public async fetchComments (maxResults: number = -1) {
this.comments = await this.youtube.getVideoComments(this.id, maxResults)
return this.comments
}
}

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

import { Video, Channel, Playlist } from './entities'
import { Video, Channel, Playlist, YTComment } from './entities'
import { parseUrl, request } from './util'
export * from './entities'
export * from './types'

@@ -53,3 +54,3 @@ /**

private async getItemById (type: 'video' | 'channel' | 'playlist', id: string) {
private async getItemById (type: 'video' | 'channel' | 'playlist' | 'comment', id: string) {
let result

@@ -75,2 +76,8 @@

})
} else if (type === 'comment') {
result = await request.api('comments', {
id,
part: 'snippet',
key: this.token
})
}

@@ -137,2 +144,10 @@

/**
* Get a comment object from the ID of a comment.
* @param id The ID of the comment.
*/
public async getComment (id: string) {
return new YTComment(this, await this.getItemById('comment', id))
}
/**
* Get a video object from the url of a video.

@@ -180,3 +195,3 @@ * @param url The url of the video.

/**
* Get `maxResults` videos in a playlist. Used mostly internally with `Playlist#getVideos`.
* Get `maxResults` videos in a playlist. Used mostly internally with `Playlist#fetchVideos`.
* @param playlistId The ID of the playlist.

@@ -209,3 +224,3 @@ * @param maxResults The maximum amount of videos to get from the playlist. If <= 0 or not included, returns all videos in the playlist.

const totalResults = results.pageInfo.totalResults
const perPage = 50
const perPage = results.pageInfo.resultsPerPage
const pages = Math.floor(totalResults / perPage)

@@ -240,2 +255,140 @@

}
/**
* Get `maxResults` comments on a video. Used mostly internally with `Video#fetchComments`.
* @param videoId The ID of the video.
* @param maxResults The maximum amount of comments to get from the video. If <= 0 or not included, returns all comments on the video.
*/
public async getVideoComments (videoId: string, maxResults: number = -1) {
let full
let comments: YTComment[] = []
if (maxResults <= 0) {
full = true
} else {
full = false
}
if (maxResults > 100) {
return Promise.reject('Max results must be 100 or below')
}
const results = await request.api('commentThreads', {
videoId,
part: 'snippet,replies',
key: this.token,
maxResults: full ? 100 : maxResults,
textFormat: 'plainText'
}).catch(() => {
return Promise.reject('Comment thread not found')
})
const totalResults = results.pageInfo.totalResults
const perPage = results.pageInfo.resultsPerPage
const pages = Math.floor(totalResults / perPage)
results.items.forEach(item => {
const comment = new YTComment(this, item.snippet.topLevelComment)
comments.push(comment)
if (item.replies) {
item.replies.comments.forEach(reply => {
const created = new YTComment(this, reply)
comment.replies.push(created)
})
}
})
if (!full || pages === 0) {
return comments
}
let oldRes = results
for (let i = 1; i < pages; i++) {
const newResults = await request.api('commentThreads', {
videoId,
part: 'snippet',
key: this.token,
maxResults: 50,
pageToken: oldRes.nextPageToken,
textFormat: 'plainText'
})
oldRes = newResults
newResults.items.forEach(item => {
const comment = new YTComment(this, item.snippet.topLevelComment)
comments.push(comment)
if (item.replies) {
item.replies.comments.forEach(reply => {
const created = new YTComment(this, reply)
comment.replies.push(created)
})
}
})
}
return comments
}
/**
* Get `maxResults` replies to a comment. Used mostly internally with `Comment#fetchReplies`.
* @param commentId The ID of the comment to get replies from.
* @param maxResults The maximum amount of replies to get. Gets all replies if <= 0 or not included.
*/
public async getCommentReplies (commentId: string, maxResults: number = -1) {
let full
let replies: YTComment[] = []
if (maxResults <= 0) {
full = true
} else {
full = false
}
if (maxResults > 100) {
return Promise.reject('Max results must be 50 or below')
}
const results = await request.api('comments', {
parentId: commentId,
part: 'snippet',
key: this.token,
maxResults: full ? 100 : maxResults
}).catch(() => {
return Promise.reject('Playlist not found')
})
const totalResults = results.pageInfo.totalResults
const perPage = results.pageInfo.resultsPerPage
const pages = Math.floor(totalResults / perPage)
results.items.forEach(item => {
replies.push(new YTComment(this, item))
})
if (!full || pages === 0) {
return replies
}
let oldRes = results
for (let i = 1; i < pages; i++) {
const newResults = await request.api('comments', {
parentId: commentId,
part: 'snippet',
key: this.token,
maxResults: 100,
pageToken: oldRes.nextPageToken
})
oldRes = newResults
newResults.items.forEach(item => {
replies.push(new YTComment(this, item))
})
}
return replies
}
}

@@ -7,8 +7,3 @@ import { request as https } from 'https'

api: (subUrl: string, params: Object): Promise<any> => {
let url = 'https://www.googleapis.com/youtube/v3' + (subUrl.startsWith('/') ? subUrl : '/' + subUrl)
for (let param in params) {
url += (!url.includes('?') ? '?' : '&') + param + '=' + params[param]
}
const url = 'https://www.googleapis.com/youtube/v3' + (subUrl.startsWith('/') ? subUrl : '/' + subUrl) + parseParams(params)
return get(url)

@@ -99,1 +94,11 @@ }

}
function parseParams (params: Object) {
let url = ''
for (let param in params) {
url += (!url.includes('?') ? '?' : '&') + param + '=' + params[param]
}
return url
}
import 'mocha'
import { expect } from 'chai'
import { YouTube, Video, Playlist } from '../src'
import { YouTube, Video, YTComment, Playlist } from '../src'
import { apiKey } from './config'

@@ -43,3 +43,2 @@ import { parseUrl } from '../src/util'

const youtube = new YouTube(apiKey)
expect(await youtube.getVideo('dQw4w9WgXcQ')).to.be.instanceOf(Video)

@@ -59,2 +58,17 @@ })

it('should work with comments', async () => {
const youtube = new YouTube(apiKey)
expect(await youtube.getComment('UgyNb5InfceN2n5WhG94AaABAg')).to.be.instanceOf(YTComment)
})
it('should work with replies', async () => {
const youtube = new YouTube(apiKey)
expect((await (await youtube.getComment('UgyNb5InfceN2n5WhG94AaABAg')).fetchReplies()).length).to.be.greaterThan(0)
})
it('should work with playlists', async () => {
const youtube = new YouTube(apiKey)
expect(await youtube.getPlaylist('PLMC9KNkIncKvYin_USF1qoJQnIyMAfRxl')).to.be.instanceOf(Playlist)
})
describe('Playlist items', () => {

@@ -81,2 +95,27 @@ it('should reject if the playlist isn\'t found', async () => {

})
describe('Video comments', () => {
it('should work with valid videos with comments and replies', async () => {
const youtube = new YouTube(apiKey)
const comments = await youtube.getVideoComments('Lq1D8PFnjWY')
expect(comments.find(comment => comment.text.displayed.startsWith('comment'))).to.be.instanceOf(YTComment)
expect(comments.find(comment => comment.text.displayed.startsWith('comment')).replies[0]).to.be.instanceOf(YTComment)
})
it('should not work with valid videos with comments disabled', async () => {
const youtube = new YouTube(apiKey)
expect(await youtube.getVideoComments('24EWkH5ipdw').catch(error => { return error })).to.equal('Comment thread not found')
})
it('should not work with invalid videos', async () => {
const youtube = new YouTube(apiKey)
expect(await youtube.getVideoComments('0').catch(error => { return error })).to.equal('Comment thread not found')
})
it('should return an array with a length of <= maxResults', async () => {
const youtube = new YouTube(apiKey)
expect((await youtube.getVideoComments('Lq1D8PFnjWY', 1)).length).to.be.lessThan(2)
})
})
})
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