commit
d017c4b65b
@ -13,9 +13,20 @@ interface SoundDataOptions {
|
|||||||
|
|
||||||
const pattern = /^(?:(https?):\/\/)?(?:(?:www|m)\.)?(api\.soundcloud\.com|soundcloud\.com|snd\.sc)\/(.*)$/;
|
const pattern = /^(?:(https?):\/\/)?(?:(?:www|m)\.)?(api\.soundcloud\.com|soundcloud\.com|snd\.sc)\/(.*)$/;
|
||||||
/**
|
/**
|
||||||
* Function to get info from a soundcloud url
|
* Gets info from a soundcloud url.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* let sound = await play.soundcloud('soundcloud url')
|
||||||
|
*
|
||||||
|
* // sound.type === "track" | "playlist" | "user"
|
||||||
|
*
|
||||||
|
* if (sound.type === "track") {
|
||||||
|
* spot = spot as play.SoundCloudTrack
|
||||||
|
* // Code with SoundCloud track class.
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
* @param url soundcloud url
|
* @param url soundcloud url
|
||||||
* @returns SoundCloud Track or SoundCloud Playlist
|
* @returns A {@link SoundCloudTrack} or {@link SoundCloudPlaylist}
|
||||||
*/
|
*/
|
||||||
export async function soundcloud(url: string): Promise<SoundCloud> {
|
export async function soundcloud(url: string): Promise<SoundCloud> {
|
||||||
if (!soundData) throw new Error('SoundCloud Data is missing\nDid you forgot to do authorization ?');
|
if (!soundData) throw new Error('SoundCloud Data is missing\nDid you forgot to do authorization ?');
|
||||||
@ -85,7 +96,17 @@ export async function stream(url: string, quality?: number): Promise<SoundCloudS
|
|||||||
return new SoundCloudStream(s_data.url, type);
|
return new SoundCloudStream(s_data.url, type);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function to get Free Client ID of soundcloud.
|
* Gets Free SoundCloud Client ID.
|
||||||
|
*
|
||||||
|
* Use this in beginning of your code to add SoundCloud support.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* play.getFreeClientID().then((clientID) => play.setToken({
|
||||||
|
* soundcloud : {
|
||||||
|
* client_id : clientID
|
||||||
|
* }
|
||||||
|
* }))
|
||||||
|
* ```
|
||||||
* @returns client ID
|
* @returns client ID
|
||||||
*/
|
*/
|
||||||
export async function getFreeClientID(): Promise<string> {
|
export async function getFreeClientID(): Promise<string> {
|
||||||
@ -133,12 +154,16 @@ export async function check_id(id: string): Promise<boolean> {
|
|||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function to validate for a soundcloud url
|
* Validates a soundcloud url
|
||||||
* @param url soundcloud url
|
* @param url soundcloud url
|
||||||
* @returns "false" | 'track' | 'playlist'
|
* @returns
|
||||||
|
* ```ts
|
||||||
|
* false | 'track' | 'playlist'
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
export async function so_validate(url: string): Promise<false | 'track' | 'playlist' | 'search'> {
|
export async function so_validate(url: string): Promise<false | 'track' | 'playlist' | 'search'> {
|
||||||
if (!url.match(pattern)) return 'search';
|
if (!url.startsWith('https')) return 'search';
|
||||||
|
if (!url.match(pattern)) return false;
|
||||||
const data = await request(
|
const data = await request(
|
||||||
`https://api-v2.soundcloud.com/resolve?url=${url}&client_id=${soundData.client_id}`
|
`https://api-v2.soundcloud.com/resolve?url=${url}&client_id=${soundData.client_id}`
|
||||||
).catch((err: Error) => err);
|
).catch((err: Error) => err);
|
||||||
@ -153,7 +178,7 @@ export async function so_validate(url: string): Promise<false | 'track' | 'playl
|
|||||||
/**
|
/**
|
||||||
* Function to select only hls streams from SoundCloud format array
|
* Function to select only hls streams from SoundCloud format array
|
||||||
* @param data SoundCloud Track Format data
|
* @param data SoundCloud Track Format data
|
||||||
* @returns a new array containing hls formats
|
* @returns HLS Formats Array
|
||||||
*/
|
*/
|
||||||
function parseHlsFormats(data: SoundCloudTrackFormat[]) {
|
function parseHlsFormats(data: SoundCloudTrackFormat[]) {
|
||||||
const result: SoundCloudTrackFormat[] = [];
|
const result: SoundCloudTrackFormat[] = [];
|
||||||
|
|||||||
@ -26,9 +26,20 @@ export interface SpotifyDataOptions {
|
|||||||
|
|
||||||
const pattern = /^((https:)?\/\/)?open.spotify.com\/(track|album|playlist)\//;
|
const pattern = /^((https:)?\/\/)?open.spotify.com\/(track|album|playlist)\//;
|
||||||
/**
|
/**
|
||||||
* Function to get Playlist | Album | Track
|
* Gets Spotify url details.
|
||||||
* @param url url of spotify from which you want info
|
*
|
||||||
* @returns Spotify type.
|
* ```ts
|
||||||
|
* let spot = await play.spotify('spotify url')
|
||||||
|
*
|
||||||
|
* // spot.type === "track" | "playlist" | "album"
|
||||||
|
*
|
||||||
|
* if (spot.type === "track") {
|
||||||
|
* spot = spot as play.SpotifyTrack
|
||||||
|
* // Code with spotify track class.
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @param url Spotify Url
|
||||||
|
* @returns A {@link SpotifyTrack} or {@link SpotifyPlaylist} or {@link SpotifyAlbum}
|
||||||
*/
|
*/
|
||||||
export async function spotify(url: string): Promise<Spotify> {
|
export async function spotify(url: string): Promise<Spotify> {
|
||||||
if (!spotifyData) throw new Error('Spotify Data is missing\nDid you forgot to do authorization ?');
|
if (!spotifyData) throw new Error('Spotify Data is missing\nDid you forgot to do authorization ?');
|
||||||
@ -72,12 +83,16 @@ export async function spotify(url: string): Promise<Spotify> {
|
|||||||
} else throw new Error('URL is out of scope for play-dl.');
|
} else throw new Error('URL is out of scope for play-dl.');
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function to validate Spotify url
|
* Validate Spotify url
|
||||||
* @param url url for validation
|
* @param url Spotify URL
|
||||||
* @returns type of url or false.
|
* @returns
|
||||||
|
* ```ts
|
||||||
|
* 'track' | 'playlist' | 'album' | 'search' | false
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
export function sp_validate(url: string): 'track' | 'playlist' | 'album' | 'search' | false {
|
export function sp_validate(url: string): 'track' | 'playlist' | 'album' | 'search' | false {
|
||||||
if (!url.match(pattern)) return 'search';
|
if (!url.startsWith('https')) return 'search';
|
||||||
|
if (!url.match(pattern)) return false;
|
||||||
if (url.indexOf('track/') !== -1) {
|
if (url.indexOf('track/') !== -1) {
|
||||||
return 'track';
|
return 'track';
|
||||||
} else if (url.indexOf('album/') !== -1) {
|
} else if (url.indexOf('album/') !== -1) {
|
||||||
@ -128,7 +143,14 @@ export async function SpotifyAuthorize(data: SpotifyDataOptions, file: boolean):
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function to check if authorization token is expired or not.
|
* Checks if spotify token is expired or not.
|
||||||
|
*
|
||||||
|
* Update token if returned false.
|
||||||
|
* ```ts
|
||||||
|
* if (!play.is_expired()) {
|
||||||
|
* await play.refreshToken()
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
* @returns boolean
|
* @returns boolean
|
||||||
*/
|
*/
|
||||||
export function is_expired(): boolean {
|
export function is_expired(): boolean {
|
||||||
@ -183,8 +205,14 @@ export async function sp_search(
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function to refresh Token
|
* Refreshes Token
|
||||||
* @returns boolean to check whether token is refreshed or not
|
*
|
||||||
|
* ```ts
|
||||||
|
* if (!play.is_expired()) {
|
||||||
|
* await play.refreshToken()
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @returns boolean
|
||||||
*/
|
*/
|
||||||
export async function refreshToken(): Promise<boolean> {
|
export async function refreshToken(): Promise<boolean> {
|
||||||
const response = await request(`https://accounts.spotify.com/api/token`, {
|
const response = await request(`https://accounts.spotify.com/api/token`, {
|
||||||
|
|||||||
@ -41,9 +41,9 @@ export class YouTubeChannel {
|
|||||||
*/
|
*/
|
||||||
url?: string;
|
url?: string;
|
||||||
/**
|
/**
|
||||||
* YouTube Channel Icon data.
|
* YouTube Channel Icons data.
|
||||||
*/
|
*/
|
||||||
icon?: ChannelIconInterface;
|
icons?: ChannelIconInterface[];
|
||||||
/**
|
/**
|
||||||
* YouTube Channel subscribers count.
|
* YouTube Channel subscribers count.
|
||||||
*/
|
*/
|
||||||
@ -60,7 +60,7 @@ export class YouTubeChannel {
|
|||||||
this.artist = !!data.artist || false;
|
this.artist = !!data.artist || false;
|
||||||
this.id = data.id || null;
|
this.id = data.id || null;
|
||||||
this.url = data.url || null;
|
this.url = data.url || null;
|
||||||
this.icon = data.icon || { url: null, width: 0, height: 0 };
|
this.icons = data.icon || [{ url: null, width: 0, height: 0 }];
|
||||||
this.subscribers = data.subscribers || null;
|
this.subscribers = data.subscribers || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,9 +71,9 @@ export class YouTubeChannel {
|
|||||||
*/
|
*/
|
||||||
iconURL(options = { size: 0 }): string | undefined {
|
iconURL(options = { size: 0 }): string | undefined {
|
||||||
if (typeof options.size !== 'number' || options.size < 0) throw new Error('invalid icon size');
|
if (typeof options.size !== 'number' || options.size < 0) throw new Error('invalid icon size');
|
||||||
if (!this.icon?.url) return undefined;
|
if (!this.icons?.[0]?.url) return undefined;
|
||||||
const def = this.icon.url.split('=s')[1].split('-c')[0];
|
const def = this.icons?.[0]?.url.split('=s')[1].split('-c')[0];
|
||||||
return this.icon.url.replace(`=s${def}-c`, `=s${options.size}-c`);
|
return this.icons?.[0]?.url.replace(`=s${def}-c`, `=s${options.size}-c`);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Converts Channel Class to channel name.
|
* Converts Channel Class to channel name.
|
||||||
@ -93,7 +93,7 @@ export class YouTubeChannel {
|
|||||||
artist: this.artist,
|
artist: this.artist,
|
||||||
id: this.id,
|
id: this.id,
|
||||||
url: this.url,
|
url: this.url,
|
||||||
icon: this.icon,
|
icons: this.icons,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
subscribers: this.subscribers
|
subscribers: this.subscribers
|
||||||
};
|
};
|
||||||
@ -128,7 +128,7 @@ interface ChannelJSON{
|
|||||||
/**
|
/**
|
||||||
* YouTube Channel Icon data.
|
* YouTube Channel Icon data.
|
||||||
*/
|
*/
|
||||||
icon?: ChannelIconInterface;
|
icons?: ChannelIconInterface[];
|
||||||
/**
|
/**
|
||||||
* YouTube Channel subscribers count.
|
* YouTube Channel subscribers count.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -46,12 +46,23 @@ export function setCookieToken(options: { cookie: string }) {
|
|||||||
youtubeData = { cookie };
|
youtubeData = { cookie };
|
||||||
youtubeData.file = false;
|
youtubeData.file = false;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
export function cookieHeaders(headCookie: string[]) {
|
* Updates cookies locally either in file or in memory.
|
||||||
|
*
|
||||||
|
* Example
|
||||||
|
* ```ts
|
||||||
|
* const response = ... // Any https package get function.
|
||||||
|
*
|
||||||
|
* play.cookieHeaders(response.headers['set-cookie'])
|
||||||
|
* ```
|
||||||
|
* @param headCookie response headers['set-cookie'] array
|
||||||
|
* @returns Nothing
|
||||||
|
*/
|
||||||
|
export function cookieHeaders(headCookie: string[]): void {
|
||||||
if (!youtubeData?.cookie) return;
|
if (!youtubeData?.cookie) return;
|
||||||
headCookie.forEach((x: string) => {
|
headCookie.forEach((x: string) => {
|
||||||
x.split(';').forEach((x) => {
|
x.split(';').forEach((z) => {
|
||||||
const arr = x.split('=');
|
const arr = z.split('=');
|
||||||
if (arr.length <= 1) return;
|
if (arr.length <= 1) return;
|
||||||
const key = arr.shift()?.trim() as string;
|
const key = arr.shift()?.trim() as string;
|
||||||
const value = arr.join('=').trim();
|
const value = arr.join('=').trim();
|
||||||
|
|||||||
@ -18,13 +18,25 @@ const video_id_pattern = /^[a-zA-Z\d_-]{11,12}$/;
|
|||||||
const playlist_id_pattern = /^(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{16,41}$/;
|
const playlist_id_pattern = /^(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{16,41}$/;
|
||||||
const DEFAULT_API_KEY = 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8';
|
const DEFAULT_API_KEY = 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8';
|
||||||
const video_pattern =
|
const video_pattern =
|
||||||
/^((?:https?:)?\/\/)?(?:(?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$/;
|
/^((?:https?:)?\/\/)?(?:(?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|shorts\/|embed\/|v\/)?)([\w\-]+)(\S+)?$/;
|
||||||
const playlist_pattern =
|
const playlist_pattern =
|
||||||
/^((?:https?:)?\/\/)?(?:(?:www|m)\.)?(youtube\.com)\/(?:(playlist|watch))(.*)?((\?|\&)list=)(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{16,41}(.*)?$/;
|
/^((?:https?:)?\/\/)?(?:(?:www|m)\.)?(youtube\.com)\/(?:(playlist|watch))(.*)?((\?|\&)list=)(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{16,41}(.*)?$/;
|
||||||
/**
|
/**
|
||||||
* Command to validate a YouTube url
|
* Validate YouTube URL or ID.
|
||||||
* @param url Url for validation
|
*
|
||||||
* @returns type of url or false.
|
* **CAUTION :** If your search word is 11-12 long, you might get it validated as video ID.
|
||||||
|
*
|
||||||
|
* To avoid above, add one more condition to yt_validate
|
||||||
|
* ```ts
|
||||||
|
* if (url.startsWith('https') && yt_validate(url) === 'video') {
|
||||||
|
* // YouTube Video Url.
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @param url YouTube URL OR ID
|
||||||
|
* @returns
|
||||||
|
* ```
|
||||||
|
* 'playlist' | 'video' | 'search' | false
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
export function yt_validate(url: string): 'playlist' | 'video' | 'search' | false {
|
export function yt_validate(url: string): 'playlist' | 'video' | 'search' | false {
|
||||||
if (url.indexOf('list=') === -1) {
|
if (url.indexOf('list=') === -1) {
|
||||||
@ -51,7 +63,7 @@ export function yt_validate(url: string): 'playlist' | 'video' | 'search' | fals
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function to extract ID of YouTube url.
|
* Extract ID of YouTube url.
|
||||||
* @param url ID or url of YouTube
|
* @param url ID or url of YouTube
|
||||||
* @returns ID of video or playlist.
|
* @returns ID of video or playlist.
|
||||||
*/
|
*/
|
||||||
@ -75,9 +87,32 @@ export function extractID(url: string): string {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Basic function to get data from a YouTube url or ID.
|
* Basic function to get data from a YouTube url or ID.
|
||||||
* @param url YouTube url or ID
|
*
|
||||||
* @param options cookie and proxy parameters to add
|
* Example
|
||||||
* @returns Data containing video_details, LiveStreamData and formats of video url.
|
* ```ts
|
||||||
|
* const video = await play.video_basic_info('youtube video url')
|
||||||
|
*
|
||||||
|
* const res = ... // Any https package get function.
|
||||||
|
* const video = await play.video_basic_info(res.body, { htmldata : true })
|
||||||
|
*
|
||||||
|
* const video = await play.video_basic_info('youtube video url', { proxy : [{
|
||||||
|
host : "IP or hostname",
|
||||||
|
port : 8080,
|
||||||
|
authentication: {
|
||||||
|
username: 'username';
|
||||||
|
password: 'very secret';
|
||||||
|
}
|
||||||
|
}] }) // Authentication is optional.
|
||||||
|
|
||||||
|
// OR
|
||||||
|
|
||||||
|
const video = await play.video_basic_info('youtube video url', { proxy : ['url'] })
|
||||||
|
* ```
|
||||||
|
* @param url YouTube url or ID or html body data
|
||||||
|
* @param options Video Info Options
|
||||||
|
* - `Proxy[]` proxy : sends data through a proxy
|
||||||
|
* - `boolean` htmldata : given data is html data or not
|
||||||
|
* @returns Video Basic Info {@link InfoData}.
|
||||||
*/
|
*/
|
||||||
export async function video_basic_info(url: string, options: InfoOptions = {}) : Promise<InfoData> {
|
export async function video_basic_info(url: string, options: InfoOptions = {}) : Promise<InfoData> {
|
||||||
let body: string;
|
let body: string;
|
||||||
@ -112,11 +147,11 @@ export async function video_basic_info(url: string, options: InfoOptions = {}) :
|
|||||||
player_response.playabilityStatus.errorScreen.playerKavRenderer?.reason.simpleText
|
player_response.playabilityStatus.errorScreen.playerKavRenderer?.reason.simpleText
|
||||||
}`
|
}`
|
||||||
);
|
);
|
||||||
|
const ownerInfo = initial_response.contents.twoColumnWatchNextResults.results?.results?.contents[1]?.videoSecondaryInfoRenderer
|
||||||
|
?.owner?.videoOwnerRenderer
|
||||||
const badge =
|
const badge =
|
||||||
initial_response.contents.twoColumnWatchNextResults.results?.results?.contents[1]?.videoSecondaryInfoRenderer
|
ownerInfo?.badges &&
|
||||||
?.owner?.videoOwnerRenderer?.badges &&
|
ownerInfo?.badges[0];
|
||||||
initial_response.contents.twoColumnWatchNextResults.results?.results?.contents[1]?.videoSecondaryInfoRenderer
|
|
||||||
?.owner?.videoOwnerRenderer?.badges[0];
|
|
||||||
const html5player = `https://www.youtube.com${body.split('"jsUrl":"')[1].split('"')[0]}`;
|
const html5player = `https://www.youtube.com${body.split('"jsUrl":"')[1].split('"')[0]}`;
|
||||||
const related: string[] = [];
|
const related: string[] = [];
|
||||||
initial_response.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results.forEach(
|
initial_response.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults.results.forEach(
|
||||||
@ -142,7 +177,8 @@ export async function video_basic_info(url: string, options: InfoOptions = {}) :
|
|||||||
id: vid.channelId,
|
id: vid.channelId,
|
||||||
url: `https://www.youtube.com/channel/${vid.channelId}`,
|
url: `https://www.youtube.com/channel/${vid.channelId}`,
|
||||||
verified: Boolean(badge?.metadataBadgeRenderer?.style?.toLowerCase().includes('verified')),
|
verified: Boolean(badge?.metadataBadgeRenderer?.style?.toLowerCase().includes('verified')),
|
||||||
artist: Boolean(badge?.metadataBadgeRenderer?.style?.toLowerCase().includes('artist'))
|
artist: Boolean(badge?.metadataBadgeRenderer?.style?.toLowerCase().includes('artist')),
|
||||||
|
icons : ownerInfo?.thumbnail?.thumbnails || undefined
|
||||||
},
|
},
|
||||||
views: vid.viewCount,
|
views: vid.viewCount,
|
||||||
tags: vid.keywords,
|
tags: vid.keywords,
|
||||||
@ -182,14 +218,40 @@ function parseSeconds(seconds: number): string {
|
|||||||
return hDisplay + mDisplay + sDisplay;
|
return hDisplay + mDisplay + sDisplay;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function which gets data from video_basic_info and deciphers it if it contains signatures.
|
* Gets data from YouTube url or ID or html body data and deciphers it.
|
||||||
* @param url YouTube Video URL
|
* ```
|
||||||
* @param options cookie and proxy parameters to add
|
* video_basic_info + decipher_info = video_info
|
||||||
* @returns Data containing video_details, LiveStreamData and formats of video url.
|
* ```
|
||||||
|
*
|
||||||
|
* Example
|
||||||
|
* ```ts
|
||||||
|
* const video = await play.video_info('youtube video url')
|
||||||
|
*
|
||||||
|
* const res = ... // Any https package get function.
|
||||||
|
* const video = await play.video_info(res.body, { htmldata : true })
|
||||||
|
*
|
||||||
|
* const video = await play.video_info('youtube video url', { proxy : [{
|
||||||
|
host : "IP or hostname",
|
||||||
|
port : 8080,
|
||||||
|
authentication: {
|
||||||
|
username: 'username';
|
||||||
|
password: 'very secret';
|
||||||
|
}
|
||||||
|
}] }) // Authentication is optional.
|
||||||
|
|
||||||
|
// OR
|
||||||
|
|
||||||
|
const video = await play.video_info('youtube video url', { proxy : ['url'] })
|
||||||
|
* ```
|
||||||
|
* @param url YouTube url or ID or html body data
|
||||||
|
* @param options Video Info Options
|
||||||
|
* - `Proxy[]` proxy : sends data through a proxy
|
||||||
|
* - `boolean` htmldata : given data is html data or not
|
||||||
|
* @returns Deciphered Video Info {@link InfoData}.
|
||||||
*/
|
*/
|
||||||
export async function video_info(url: string, options: InfoOptions = {}): Promise<InfoData> {
|
export async function video_info(url: string, options: InfoOptions = {}): Promise<InfoData> {
|
||||||
const data = await video_basic_info(url, options);
|
const data = await video_basic_info(url, options);
|
||||||
if (data.LiveStreamData.isLive === true && data.LiveStreamData.hlsManifestUrl !== null) {
|
if (data.LiveStreamData.isLive === true && data.LiveStreamData.dashManifestUrl !== null) {
|
||||||
return data;
|
return data;
|
||||||
} else if (data.format[0].signatureCipher || data.format[0].cipher) {
|
} else if (data.format[0].signatureCipher || data.format[0].cipher) {
|
||||||
data.format = await format_decipher(data.format, data.html5player);
|
data.format = await format_decipher(data.format, data.html5player);
|
||||||
@ -200,11 +262,11 @@ export async function video_info(url: string, options: InfoOptions = {}): Promis
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function uses data from video_basic_info and deciphers it if it contains signatures.
|
* Function uses data from video_basic_info and deciphers it if it contains signatures.
|
||||||
* @param data basic_video_info data
|
* @param data Data - {@link InfoData}
|
||||||
* @returns Data containing video_details, LiveStreamData and formats of video url.
|
* @returns Deciphered Video Info {@link InfoData}
|
||||||
*/
|
*/
|
||||||
export async function decipher_info(data: InfoData) {
|
export async function decipher_info(data: InfoData) {
|
||||||
if (data.LiveStreamData.isLive === true && data.LiveStreamData.hlsManifestUrl !== null) {
|
if (data.LiveStreamData.isLive === true && data.LiveStreamData.dashManifestUrl !== null) {
|
||||||
return data;
|
return data;
|
||||||
} else if (data.format[0].signatureCipher || data.format[0].cipher) {
|
} else if (data.format[0].signatureCipher || data.format[0].cipher) {
|
||||||
data.format = await format_decipher(data.format, data.html5player);
|
data.format = await format_decipher(data.format, data.html5player);
|
||||||
@ -214,9 +276,32 @@ export async function decipher_info(data: InfoData) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Function to get YouTube playlist info from a playlist url.
|
* Gets YouTube playlist info from a playlist url.
|
||||||
|
*
|
||||||
|
* Example
|
||||||
|
* ```ts
|
||||||
|
* const playlist = await play.playlist_info('youtube playlist url')
|
||||||
|
*
|
||||||
|
* const playlist = await play.playlist_info('youtube playlist url', { incomplete : true })
|
||||||
|
*
|
||||||
|
* const playlist = await play.playlist_info('youtube playlist url', { proxy : [{
|
||||||
|
host : "IP or hostname",
|
||||||
|
port : 8080,
|
||||||
|
authentication: {
|
||||||
|
username: 'username';
|
||||||
|
password: 'very secret';
|
||||||
|
}
|
||||||
|
}] }) // Authentication is optional.
|
||||||
|
|
||||||
|
// OR
|
||||||
|
|
||||||
|
const playlist = await play.playlist_info('youtube playlist url', { proxy : ['url'] })
|
||||||
|
* ```
|
||||||
* @param url Playlist URL
|
* @param url Playlist URL
|
||||||
* @param options incomplete and proxy to add.
|
* @param options Playlist Info Options
|
||||||
|
* - `boolean` incomplete : If set to true, parses playlist with hidden videos.
|
||||||
|
* - `Proxy[]` proxy : sends data through a proxy
|
||||||
|
*
|
||||||
* @returns YouTube Playlist
|
* @returns YouTube Playlist
|
||||||
*/
|
*/
|
||||||
export async function playlist_info(url: string, options: PlaylistOptions = {}): Promise<YouTubePlayList> {
|
export async function playlist_info(url: string, options: PlaylistOptions = {}): Promise<YouTubePlayList> {
|
||||||
|
|||||||
@ -134,14 +134,8 @@ export function parseVideo(data?: any): YouTubeVideo {
|
|||||||
data.videoRenderer.ownerText.runs[0].navigationEndpoint.browseEndpoint.canonicalBaseUrl ||
|
data.videoRenderer.ownerText.runs[0].navigationEndpoint.browseEndpoint.canonicalBaseUrl ||
|
||||||
data.videoRenderer.ownerText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url
|
data.videoRenderer.ownerText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url
|
||||||
}`,
|
}`,
|
||||||
icon: {
|
icons : data.videoRenderer.channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail
|
||||||
url: data.videoRenderer.channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail
|
.thumbnails,
|
||||||
.thumbnails[0].url,
|
|
||||||
width: data.videoRenderer.channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail
|
|
||||||
.thumbnails[0].width,
|
|
||||||
height: data.videoRenderer.channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail
|
|
||||||
.thumbnails[0].height
|
|
||||||
},
|
|
||||||
verified: Boolean(badge?.metadataBadgeRenderer?.style?.toLowerCase().includes('verified')),
|
verified: Boolean(badge?.metadataBadgeRenderer?.style?.toLowerCase().includes('verified')),
|
||||||
artist: Boolean(badge?.metadataBadgeRenderer?.style?.toLowerCase().includes('artist'))
|
artist: Boolean(badge?.metadataBadgeRenderer?.style?.toLowerCase().includes('artist'))
|
||||||
},
|
},
|
||||||
|
|||||||
@ -61,13 +61,13 @@ import { YouTubePlayList } from './YouTube/classes/Playlist';
|
|||||||
import { YouTubeChannel } from './YouTube/classes/Channel';
|
import { YouTubeChannel } from './YouTube/classes/Channel';
|
||||||
import { SpotifyAlbum, SpotifyPlaylist, SpotifyTrack } from './Spotify/classes';
|
import { SpotifyAlbum, SpotifyPlaylist, SpotifyTrack } from './Spotify/classes';
|
||||||
import { DeezerAlbum, DeezerPlaylist, DeezerTrack } from './Deezer/classes';
|
import { DeezerAlbum, DeezerPlaylist, DeezerTrack } from './Deezer/classes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main stream Command for streaming through various sources
|
* Main stream Command for streaming through various sources
|
||||||
* @param url The video / track url to make stream of
|
* @param url The video / track url to make stream of
|
||||||
* @param options contains quality, cookie and proxy to set for stream
|
* @param options contains quality, cookie and proxy to set for stream
|
||||||
* @returns YouTube / SoundCloud Stream to play
|
* @returns YouTube / SoundCloud Stream to play
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export async function stream(url: string, options: StreamOptions = {}): Promise<YouTubeStream | SoundCloudStream> {
|
export async function stream(url: string, options: StreamOptions = {}): Promise<YouTubeStream | SoundCloudStream> {
|
||||||
if (url.length === 0) throw new Error('Stream URL has a length of 0. Check your url again.');
|
if (url.length === 0) throw new Error('Stream URL has a length of 0. Check your url again.');
|
||||||
if (url.indexOf('spotify') !== -1) {
|
if (url.indexOf('spotify') !== -1) {
|
||||||
@ -91,7 +91,6 @@ export async function stream(url: string, options: StreamOptions = {}): Promise<
|
|||||||
* @returns Array of YouTube or Spotify or SoundCloud or Deezer
|
* @returns Array of YouTube or Spotify or SoundCloud or Deezer
|
||||||
deezer?: 'track' | 'playlist' | 'album';
|
deezer?: 'track' | 'playlist' | 'album';
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export async function search( query: string, options: { source : { deezer : "album" } } & SearchOptions) : Promise<DeezerAlbum[]>;
|
export async function search( query: string, options: { source : { deezer : "album" } } & SearchOptions) : Promise<DeezerAlbum[]>;
|
||||||
export async function search( query: string, options: { source : { deezer : "playlist" } } & SearchOptions) : Promise<DeezerPlaylist[]>;
|
export async function search( query: string, options: { source : { deezer : "playlist" } } & SearchOptions) : Promise<DeezerPlaylist[]>;
|
||||||
export async function search( query: string, options: { source : { deezer : "track" } } & SearchOptions) : Promise<DeezerTrack[]>;
|
export async function search( query: string, options: { source : { deezer : "track" } } & SearchOptions) : Promise<DeezerTrack[]>;
|
||||||
@ -104,6 +103,8 @@ export async function search( query: string, options: { source : { spotify : "tr
|
|||||||
export async function search( query: string, options: { source : { youtube : "channel" } } & SearchOptions) : Promise<YouTubeChannel[]>;
|
export async function search( query: string, options: { source : { youtube : "channel" } } & SearchOptions) : Promise<YouTubeChannel[]>;
|
||||||
export async function search( query: string, options: { source : { youtube : "playlist" } } & SearchOptions) : Promise<YouTubePlayList[]>;
|
export async function search( query: string, options: { source : { youtube : "playlist" } } & SearchOptions) : Promise<YouTubePlayList[]>;
|
||||||
export async function search( query: string, options: { source : { youtube : "video" } } & SearchOptions) : Promise<YouTubeVideo[]>;
|
export async function search( query: string, options: { source : { youtube : "video" } } & SearchOptions) : Promise<YouTubeVideo[]>;
|
||||||
|
export async function search( query: string, options: { limit : number } & SearchOptions ) : Promise<YouTubeVideo[]>;
|
||||||
|
export async function search( query: string, options? : SearchOptions) : Promise<YouTubeVideo[]>;
|
||||||
export async function search(
|
export async function search(
|
||||||
query: string,
|
query: string,
|
||||||
options: SearchOptions = {}
|
options: SearchOptions = {}
|
||||||
|
|||||||
@ -16,7 +16,18 @@ interface tokenOptions {
|
|||||||
cookie: string;
|
cookie: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Sets
|
||||||
|
*
|
||||||
|
* i> YouTube :- cookies.
|
||||||
|
*
|
||||||
|
* ii> SoundCloud :- client ID.
|
||||||
|
*
|
||||||
|
* iii> Spotify :- client ID, client secret, refresh token, market.
|
||||||
|
*
|
||||||
|
* locally in memory.
|
||||||
|
* @param options {@link tokenOptions}
|
||||||
|
*/
|
||||||
export function setToken(options: tokenOptions) {
|
export function setToken(options: tokenOptions) {
|
||||||
if (options.spotify) setSpotifyToken(options.spotify);
|
if (options.spotify) setSpotifyToken(options.spotify);
|
||||||
if (options.soundcloud) setSoundCloudToken(options.soundcloud);
|
if (options.soundcloud) setSoundCloudToken(options.soundcloud);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user