Merge pull request #167 from play-dl/developer

1.3.6
This commit is contained in:
Killer069 2021-11-23 11:24:35 +05:30 committed by GitHub
commit ba4979dd94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 783 additions and 597 deletions

View File

@ -29,4 +29,6 @@ import * as play from 'play-dl' // ES-6 import or TS import
const play = require('play-dl') //JS importing const play = require('play-dl') //JS importing
``` ```
## [Documentation](https://play-dl.github.io/modules.html) ### [Documentation](https://play-dl.github.io/modules.html)
### [Examples](./examples)
### [Instructions](./instructions)

View File

@ -1,56 +0,0 @@
const https = require('https')
const play = require('play-dl');
(async() => {
let data = await request('https://soundcloud.com/')
let splitted = data.split('<script crossorigin src="')
let urls = []
splitted.forEach((r) => {
if(r.startsWith('https')) {
urls.push(r.split('"')[0])
}
})
let data2 = await request(urls[urls.length - 1])
let client_id = data2.split(',client_id:"')[1].split('"')[0]
console.log('Free SoundCloud Client ID : ' + client_id)
play.authorization()
})();
function https_getter(req_url, options = {}) {
return new Promise((resolve, reject) => {
const s = new URL(req_url);
options.method ??= 'GET';
const req_options = {
host: s.hostname,
path: s.pathname + s.search,
headers: options.headers ?? {},
method: options.method
};
const req = https.request(req_options, resolve);
req.on('error', (err) => {
reject(err);
});
if (options.method === 'POST') req.write(options.body);
req.end();
});
}
async function request(url, options){
return new Promise(async (resolve, reject) => {
let data = '';
let res = await https_getter(url, options).catch((err) => err);
if (res instanceof Error) {
reject(res);
return;
}
if (Number(res.statusCode) >= 300 && Number(res.statusCode) < 400) {
res = await https_getter(res.headers.location, options);
} else if (Number(res.statusCode) > 400) {
reject(new Error(`Got ${res.statusCode} from the request`));
}
res.setEncoding('utf-8');
res.on('data', (c) => (data += c));
res.on('end', () => resolve(data));
});
}

View File

@ -1,3 +0,0 @@
const { authorization } = require('play-dl');
authorization()

78
instructions/README.md Normal file
View File

@ -0,0 +1,78 @@
## YouTube Cookies
Steps : -
- Open your browser, then open dev-tools [ Option + ⌘ + J (on macOS), or Shift + CTRL + J (on Windows/Linux). ]
- Then go to Network Tab
![image](https://user-images.githubusercontent.com/65385476/131779512-0f5773a2-f7b5-4f9d-afcb-a6d5cd97931c.png)
- Go to any YouTube URL and find the first request and open it
First Request :-
![image](https://user-images.githubusercontent.com/65385476/131779664-9b63bca0-7036-4405-9945-a51049303665.png)
**The first request would be watch?v="Your video ID"**
- Now go to Request Headers
![image](https://user-images.githubusercontent.com/65385476/131779800-adc6f5b9-23e8-4252-aee5-f492d0916baa.png)
- find cookie in request headers
![image](https://user-images.githubusercontent.com/65385476/131779829-30ffce93-536a-43c2-9266-419c7b9b745b.png)
- Now just create a new file with this code :
```ts
const play = require('play-dl');
play.authorization();
```
And run this file. You will get a interface asking some question.
## Spotify
1. Go to [ Spotify Dashboard ](https://developer.spotify.com/dashboard/login) and create a new application or use old one.
![image](https://user-images.githubusercontent.com/65385476/132643880-a6831ee6-d8f7-4404-b749-0e3f3d611a64.png)
2. Open that application. You will be given 2 things [ Client ID and Client Secret ( click on `Show Client Secret` to get info ) ]. Note these 2 things somewhere.
3. Click on Edit Settings and go to Redirect URIs
![image](https://user-images.githubusercontent.com/65385476/132644797-d66b07dc-58cc-4fbd-80a9-6b938be138a9.png)
4. Add this Redirect URI : `http://127.0.0.1/index.html` or any url according to you. [ Also note this somewhere ]
5. Now create a `authorize.js` file and add this code :
```ts
const play = require('play-dl');
play.authorization();
```
and run it `node authorize.js`
6. You will be asked :-
- Saving INFO in file or not. [ If selected no, you will have to use `setToken` function after you get refresh-Token ]
- Client ID
- Client Secret
- Redirect URI or Redirect URL
- Market [ Choose 2 letter code on left side of your country name from [url](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) ]
- You will be given a link for authorizing. Just paste it in your browser and click on authorize and copy the link that you are redirected to. [ Redirected Link should start with Redirect URI / Redirect URL that you have provided ]
- Paste the url in Redirected URL
7. You have completed Authorization part. Now you can delete authorize js file.
You will notice that a folder named `.data` has been created. **Do not delete this**, this contains all your spotify data. [ Only applicable if save in file is set to yes. ]
## SoundCloud
## Getting Free Client ID
``` ts
const play = require('play-dl')
play.getFreeClientID().then((clientID) => {
play.setToken({
soundcloud : {
client_id : clientID
}
})
})
```

View File

@ -256,4 +256,4 @@ export async function dz_advanced_track_search(options: DeezerAdvancedSearchOpti
return results; return results;
} }
export { DeezerTrack, DeezerAlbum, DeezerPlaylist } export { DeezerTrack, DeezerAlbum, DeezerPlaylist };

View File

@ -182,7 +182,7 @@ export class SoundCloudTrack {
* Converts class to JSON * Converts class to JSON
* @returns JSON parsed Data * @returns JSON parsed Data
*/ */
toJSON() : SoundTrackJSON { toJSON(): SoundTrackJSON {
return { return {
name: this.name, name: this.name,
id: this.id, id: this.id,

View File

@ -1,6 +1,6 @@
import { SoundCloudTrack, SoundCloudTrackDeprecated, SoundCloudTrackFormat, SoundCloudUser } from "./classes"; import { SoundCloudTrack, SoundCloudTrackDeprecated, SoundCloudTrackFormat, SoundCloudUser } from './classes';
export interface SoundTrackJSON{ export interface SoundTrackJSON {
/** /**
* SoundCloud Track Name * SoundCloud Track Name
*/ */
@ -49,7 +49,7 @@ export interface SoundTrackJSON{
user: SoundCloudUser; user: SoundCloudUser;
} }
export interface PlaylistJSON{ export interface PlaylistJSON {
/** /**
* SoundCloud Playlist Name * SoundCloud Playlist Name
*/ */

View File

@ -192,4 +192,4 @@ export function setSoundCloudToken(options: SoundDataOptions) {
soundData = options; soundData = options;
} }
export { SoundCloudTrack, SoundCloudPlaylist, SoundCloudStream } export { SoundCloudTrack, SoundCloudPlaylist, SoundCloudStream };

View File

@ -149,7 +149,7 @@ export class SpotifyTrack {
else this.thumbnail = data.album.images[0]; else this.thumbnail = data.album.images[0];
} }
toJSON() : TrackJSON { toJSON(): TrackJSON {
return { return {
name: this.name, name: this.name,
id: this.id, id: this.id,
@ -332,7 +332,7 @@ export class SpotifyPlaylist {
* Converts Class to JSON * Converts Class to JSON
* @returns JSON data * @returns JSON data
*/ */
toJSON() : PlaylistJSON{ toJSON(): PlaylistJSON {
return { return {
name: this.name, name: this.name,
collaborative: this.collaborative, collaborative: this.collaborative,
@ -341,7 +341,7 @@ export class SpotifyPlaylist {
id: this.id, id: this.id,
thumbnail: this.thumbnail, thumbnail: this.thumbnail,
owner: this.owner, owner: this.owner,
tracksCount : this.tracksCount tracksCount: this.tracksCount
}; };
} }
} }
@ -520,10 +520,10 @@ export class SpotifyAlbum {
return (page_number - 1) * 100 + (this.fetched_tracks.get(`${page_number}`) as SpotifyTrack[]).length; return (page_number - 1) * 100 + (this.fetched_tracks.get(`${page_number}`) as SpotifyTrack[]).length;
} }
toJSON() : AlbumJSON { toJSON(): AlbumJSON {
return { return {
name: this.name, name: this.name,
id : this.id, id: this.id,
type: this.type, type: this.type,
url: this.url, url: this.url,
thumbnail: this.thumbnail, thumbnail: this.thumbnail,
@ -531,7 +531,7 @@ export class SpotifyAlbum {
copyrights: this.copyrights, copyrights: this.copyrights,
release_date: this.release_date, release_date: this.release_date,
release_date_precision: this.release_date_precision, release_date_precision: this.release_date_precision,
tracksCount : this.tracksCount tracksCount: this.tracksCount
}; };
} }
} }

View File

@ -1,6 +1,6 @@
import { SpotifyArtists, SpotifyCopyright, SpotifyThumbnail, SpotifyTrackAlbum } from './classes' import { SpotifyArtists, SpotifyCopyright, SpotifyThumbnail, SpotifyTrackAlbum } from './classes';
export interface TrackJSON{ export interface TrackJSON {
/** /**
* Spotify Track Name * Spotify Track Name
*/ */
@ -74,7 +74,7 @@ export interface PlaylistJSON {
tracksCount: number; tracksCount: number;
} }
export interface AlbumJSON{ export interface AlbumJSON {
/** /**
* Spotify Album Name * Spotify Album Name
*/ */

View File

@ -243,4 +243,4 @@ export function setSpotifyToken(options: SpotifyDataOptions) {
refreshToken(); refreshToken();
} }
export { SpotifyTrack, SpotifyAlbum, SpotifyPlaylist } export { SpotifyTrack, SpotifyAlbum, SpotifyPlaylist };

View File

@ -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.icons = data.icon || [{ url: null, width: 0, height: 0 }]; this.icons = data.icons || [{ url: null, width: 0, height: 0 }];
this.subscribers = data.subscribers || null; this.subscribers = data.subscribers || null;
} }
@ -86,7 +86,7 @@ export class YouTubeChannel {
* Converts Channel Class to JSON format * Converts Channel Class to JSON format
* @returns json data of the channel * @returns json data of the channel
*/ */
toJSON() : ChannelJSON { toJSON(): ChannelJSON {
return { return {
name: this.name, name: this.name,
verified: this.verified, verified: this.verified,
@ -100,7 +100,7 @@ export class YouTubeChannel {
} }
} }
interface ChannelJSON{ interface ChannelJSON {
/** /**
* YouTube Channel Title * YouTube Channel Title
*/ */

View File

@ -47,7 +47,7 @@ export class YouTubePlayList {
/** /**
* YouTube Playlist thumbnail Data * YouTube Playlist thumbnail Data
*/ */
thumbnail?: YouTubeThumbnail thumbnail?: YouTubeThumbnail;
/** /**
* Videos array containing data of first 100 videos * Videos array containing data of first 100 videos
*/ */
@ -173,7 +173,7 @@ export class YouTubePlayList {
this.__count++; this.__count++;
const res = await this.next(); const res = await this.next();
max -= res.length; max -= res.length;
if(max <= 0) break; if (max <= 0) break;
if (!res.length) break; if (!res.length) break;
} }
@ -232,7 +232,7 @@ export class YouTubePlayList {
* Converts Playlist Class to a json parsed data. * Converts Playlist Class to a json parsed data.
* @returns * @returns
*/ */
toJSON() : PlaylistJSON { toJSON(): PlaylistJSON {
return { return {
id: this.id, id: this.id,
title: this.title, title: this.title,
@ -244,7 +244,7 @@ export class YouTubePlayList {
} }
} }
interface PlaylistJSON{ interface PlaylistJSON {
/** /**
* YouTube Playlist ID * YouTube Playlist ID
*/ */
@ -289,5 +289,5 @@ interface PlaylistJSON{
/** /**
* first 100 videos in that playlist * first 100 videos in that playlist
*/ */
videos? : YouTubeVideo[] videos?: YouTubeVideo[];
} }

View File

@ -1,22 +1,22 @@
export class YouTubeThumbnail { export class YouTubeThumbnail {
id : string; id: string;
url : string; url: string;
width : number; width: number;
height : number; height: number;
constructor(data : any){ constructor(data: any) {
this.id = data.id this.id = data.id;
this.url = data.url this.url = data.url;
this.width = data.width this.width = data.width;
this.height = data.height this.height = data.height;
} }
toJSON(){ toJSON() {
return { return {
id : this.id, id: this.id,
url : this.url, url: this.url,
width : this.width, width: this.width,
height : this.height height: this.height
} };
} }
} }

View File

@ -1,7 +1,6 @@
export { stream, stream_from_info, YouTubeStream } from './stream'; export { stream, stream_from_info, YouTubeStream } from './stream';
export * from './utils'; export * from './utils';
export { YouTube } from './search'; export { YouTube } from './search';
export { cookieHeaders } from './utils/cookie'; export { YouTubeVideo } from './classes/Video';
export { YouTubeVideo } from './classes/Video' export { YouTubePlayList } from './classes/Playlist';
export { YouTubePlayList } from './classes/Playlist' export { YouTubeChannel } from './classes/Channel';
export { YouTubeChannel } from './classes/Channel'

View File

@ -1,39 +1,39 @@
import { YouTubeVideo } from "../classes/Video"; import { YouTubeVideo } from '../classes/Video';
export interface LiveStreamData { export interface LiveStreamData {
isLive: boolean; isLive: boolean;
dashManifestUrl: string | null dashManifestUrl: string | null;
hlsManifestUrl: string | null hlsManifestUrl: string | null;
} }
export interface formatData { export interface formatData {
itag: number; itag: number;
mimeType: string mimeType: string;
bitrate: number bitrate: number;
width: number width: number;
height: number height: number;
lastModified: string lastModified: string;
contentLength: string contentLength: string;
quality: string quality: string;
fps: number fps: number;
qualityLabel: string qualityLabel: string;
projectionType: string projectionType: string;
averageBitrate: number averageBitrate: number;
audioQuality: string audioQuality: string;
approxDurationMs: string approxDurationMs: string;
audioSampleRate: string audioSampleRate: string;
audioChannels: number audioChannels: number;
url : string url: string;
signatureCipher : string; signatureCipher: string;
cipher : string; cipher: string;
loudnessDb : number; loudnessDb: number;
targetDurationSec : number; targetDurationSec: number;
} }
export interface InfoData{ export interface InfoData {
LiveStreamData : LiveStreamData LiveStreamData: LiveStreamData;
html5player : string html5player: string;
format : Partial<formatData>[] format: Partial<formatData>[];
video_details : YouTubeVideo video_details: YouTubeVideo;
related_videos: string[] related_videos: string[];
} }

View File

@ -46,6 +46,7 @@ export function setCookieToken(options: { cookie: string }) {
youtubeData = { cookie }; youtubeData = { cookie };
youtubeData.file = false; youtubeData.file = false;
} }
/** /**
* Updates cookies locally either in file or in memory. * Updates cookies locally either in file or in memory.
* *
@ -58,7 +59,7 @@ export function setCookieToken(options: { cookie: string }) {
* @param headCookie response headers['set-cookie'] array * @param headCookie response headers['set-cookie'] array
* @returns Nothing * @returns Nothing
*/ */
export function cookieHeaders(headCookie: string[]): void { 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((z) => { x.split(';').forEach((z) => {

View File

@ -114,7 +114,7 @@ export function extractID(url: string): string {
* - `boolean` htmldata : given data is html data or not * - `boolean` htmldata : given data is html data or not
* @returns Video Basic Info {@link InfoData}. * @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;
if (options.htmldata) { if (options.htmldata) {
body = url; body = url;
@ -147,11 +147,10 @@ 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 const ownerInfo =
?.owner?.videoOwnerRenderer initial_response.contents.twoColumnWatchNextResults.results?.results?.contents[1]?.videoSecondaryInfoRenderer
const badge = ?.owner?.videoOwnerRenderer;
ownerInfo?.badges && const badge = ownerInfo?.badges && ownerInfo?.badges[0];
ownerInfo?.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(
@ -178,7 +177,7 @@ export async function video_basic_info(url: string, options: InfoOptions = {}) :
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 icons: ownerInfo?.thumbnail?.thumbnails || undefined
}, },
views: vid.viewCount, views: vid.viewCount,
tags: vid.keywords, tags: vid.keywords,

View File

@ -134,7 +134,7 @@ 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
}`, }`,
icons : data.videoRenderer.channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail icons: data.videoRenderer.channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail
.thumbnails, .thumbnails,
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'))

View File

@ -7,14 +7,38 @@ export {
extractID, extractID,
YouTube, YouTube,
YouTubeStream, YouTubeStream,
cookieHeaders,
YouTubeChannel, YouTubeChannel,
YouTubePlayList, YouTubePlayList,
YouTubeVideo YouTubeVideo
} from './YouTube'; } from './YouTube';
export { spotify, sp_validate, refreshToken, is_expired, SpotifyAlbum, SpotifyPlaylist, SpotifyTrack, Spotify } from './Spotify'; export {
export { soundcloud, so_validate, SoundCloud, SoundCloudStream, getFreeClientID, SoundCloudPlaylist, SoundCloudTrack } from './SoundCloud'; spotify,
export { deezer, dz_validate, dz_advanced_track_search, Deezer, DeezerTrack, DeezerPlaylist, DeezerAlbum } from './Deezer'; sp_validate,
refreshToken,
is_expired,
SpotifyAlbum,
SpotifyPlaylist,
SpotifyTrack,
Spotify
} from './Spotify';
export {
soundcloud,
so_validate,
SoundCloud,
SoundCloudStream,
getFreeClientID,
SoundCloudPlaylist,
SoundCloudTrack
} from './SoundCloud';
export {
deezer,
dz_validate,
dz_advanced_track_search,
Deezer,
DeezerTrack,
DeezerPlaylist,
DeezerAlbum
} from './Deezer';
export { setToken } from './token'; export { setToken } from './token';
enum AudioPlayerStatus { enum AudioPlayerStatus {
@ -63,10 +87,25 @@ 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 * Creates a Stream [ YouTube or SoundCloud ] class from a url for playing.
* @param url The video / track url to make stream of *
* @param options contains quality, cookie and proxy to set for stream * Example
* @returns YouTube / SoundCloud Stream to play * ```ts
* const source = await play.stream('youtube video URL') // YouTube Video Stream
*
* const source = await play.stream('soundcloud track URL') // SoundCloud Track Stream
*
* const resource = createAudioResource(source.stream, {
* inputType : source.type
* }) // Use discordjs voice createAudioResource function.
* ```
* @param url Video / Track URL
* @param options
*
* - `number` quality : Quality number. [ 0 = Lowest, 1 = Medium, 2 = Highest ]
* - `Proxy[]` proxy : sends data through a proxy
* - `boolean` htmldata : given data is html data or not
* @returns A {@link YouTubeStream} or {@link SoundCloudStream} 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.');
@ -85,26 +124,113 @@ export async function stream(url: string, options: StreamOptions = {}): Promise<
} }
/** /**
* Main Search Command for searching through various sources * Searches through a particular source and gives respective info.
*
* Example
* ```ts
* const searched = await play.search('Rick Roll', { source : { youtube : "video" } }) // YouTube Video Search
*
* const searched = await play.search('Rick Roll', { limit : 1 }) // YouTube Video Search but returns only 1 video.
*
* const searched = await play.search('Rick Roll', { source : { spotify : "track" } }) // Spotify Track Search
*
* const searched = await play.search('Rick Roll', { source : { soundcloud : "tracks" } }) // SoundCloud Track Search
*
* const searched = await play.search('Rick Roll', { source : { deezer : "track" } }) // Deezer Track Search
* ```
* @param query string to search. * @param query string to search.
* @param options contains limit and source to choose. * @param options
* @returns Array of YouTube or Spotify or SoundCloud or Deezer *
deezer?: 'track' | 'playlist' | 'album'; * - `number` limit : No of searches you want to have.
* - `boolean` fuzzy : Whether the search should be fuzzy or only return exact matches. Defaults to `true`. [ for `Deezer` Only ]
* - `Object` source : Contains type of source and type of result you want to have
* ```ts
* - youtube : 'video' | 'playlist' | 'channel';
- spotify : 'album' | 'playlist' | 'track';
- soundcloud : 'tracks' | 'playlists' | 'albums';
- deezer : 'track' | 'playlist' | 'album';
```
* @returns Array of {@link YouTube} or {@link Spotify} or {@link SoundCloud} or {@link Deezer} type
*/
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: 'track' } } & SearchOptions
): Promise<DeezerTrack[]>;
export async function search(
query: string,
options: { source: { soundcloud: 'albums' } } & SearchOptions
): Promise<SoundCloudPlaylist[]>;
export async function search(
query: string,
options: { source: { soundcloud: 'playlists' } } & SearchOptions
): Promise<SoundCloudPlaylist[]>;
export async function search(
query: string,
options: { source: { soundcloud: 'tracks' } } & SearchOptions
): Promise<SoundCloudTrack[]>;
export async function search(
query: string,
options: { source: { spotify: 'album' } } & SearchOptions
): Promise<SpotifyAlbum[]>;
export async function search(
query: string,
options: { source: { spotify: 'playlist' } } & SearchOptions
): Promise<SpotifyPlaylist[]>;
export async function search(
query: string,
options: { source: { spotify: 'track' } } & SearchOptions
): Promise<SpotifyTrack[]>;
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: '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[]>;
/**
* Searches through a particular source and gives respective info.
*
* Example
* ```ts
* const searched = await play.search('Rick Roll', { source : { youtube : "video" } }) // YouTube Video Search
*
* const searched = await play.search('Rick Roll', { limit : 1 }) // YouTube Video Search but returns only 1 video.
*
* const searched = await play.search('Rick Roll', { source : { spotify : "track" } }) // Spotify Track Search
*
* const searched = await play.search('Rick Roll', { source : { soundcloud : "tracks" } }) // SoundCloud Track Search
*
* const searched = await play.search('Rick Roll', { source : { deezer : "track" } }) // Deezer Track Search
* ```
* @param query string to search.
* @param options
*
* - `number` limit : No of searches you want to have.
* - `boolean` fuzzy : Whether the search should be fuzzy or only return exact matches. Defaults to `true`. [ for `Deezer` Only ]
* - `Object` source : Contains type of source and type of result you want to have
* ```ts
* - youtube : 'video' | 'playlist' | 'channel';
- spotify : 'album' | 'playlist' | 'track';
- soundcloud : 'tracks' | 'playlists' | 'albums';
- deezer : 'track' | 'playlist' | 'album';
```
* @returns Array of {@link YouTube} or {@link Spotify} or {@link SoundCloud} or {@link Deezer} type
*/ */
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 : "track" } } & SearchOptions) : Promise<DeezerTrack[]>;
export async function search( query: string, options: { source : { soundcloud : "albums" } } & SearchOptions) : Promise<SoundCloudPlaylist[]>;
export async function search( query: string, options: { source : { soundcloud : "playlists" } } & SearchOptions) : Promise<SoundCloudPlaylist[]>;
export async function search( query: string, options: { source : { soundcloud : "tracks" } } & SearchOptions) : Promise<SoundCloudTrack[]>;
export async function search( query: string, options: { source : { spotify : "album" } } & SearchOptions) : Promise<SpotifyAlbum[]>;
export async function search( query: string, options: { source : { spotify : "playlist" } } & SearchOptions) : Promise<SpotifyPlaylist[]>;
export async function search( query: string, options: { source : { spotify : "track" } } & SearchOptions) : Promise<SpotifyTrack[]>;
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 : "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 = {}
@ -115,16 +241,32 @@ export async function search(
else if (options.source.spotify) return await sp_search(query, options.source.spotify, options.limit); else if (options.source.spotify) return await sp_search(query, options.source.spotify, options.limit);
else if (options.source.soundcloud) return await so_search(query, options.source.soundcloud, options.limit); else if (options.source.soundcloud) return await so_search(query, options.source.soundcloud, options.limit);
else if (options.source.deezer) else if (options.source.deezer)
return await dz_search(query, { limit: options.limit, type: options.source.deezer, fuzzy : options.fuzzy }); return await dz_search(query, { limit: options.limit, type: options.source.deezer, fuzzy: options.fuzzy });
else throw new Error('Not possible to reach Here LOL. Easter Egg of play-dl if someone get this.'); else throw new Error('Not possible to reach Here LOL. Easter Egg of play-dl if someone get this.');
} }
/** /**
* stream Command for streaming through various sources using data from video_info or soundcloud * Creates a Stream [ YouTube or SoundCloud ] class from video or track info for playing.
* SoundCloud Track is only supported *
* @param info video_info data or SoundCloud Track data. * Example
* @param options contains quality, cookie and proxy to set for stream * ```ts
* @returns YouTube / SoundCloud Stream to play * const info = await video_info('youtube URL')
* const source = await play.stream_from_info(info) // YouTube Video Stream
*
* const soundInfo = await play.soundcloud('SoundCloud URL')
* const source = await play.stream_from_info(soundInfo) // SoundCloud Track Stream
*
* const resource = createAudioResource(source.stream, {
* inputType : source.type
* }) // Use discordjs voice createAudioResource function.
* ```
* @param info YouTube video info OR SoundCloud track Class
* @param options
*
* - `number` quality : Quality number. [ 0 = Lowest, 1 = Medium, 2 = Highest ]
* - `Proxy[]` proxy : sends data through a proxy
* - `boolean` htmldata : given data is html data or not
* @returns A {@link YouTubeStream} or {@link SoundCloudStream} Stream to play
*/ */
export async function stream_from_info( export async function stream_from_info(
info: InfoData | SoundCloudTrack, info: InfoData | SoundCloudTrack,
@ -134,9 +276,17 @@ export async function stream_from_info(
else return await yt_stream_info(info, options); else return await yt_stream_info(info, options);
} }
/** /**
* Command to validate the provided url. It checks whether it supports play-dl or not. * Validates url that play-dl supports.
* @param url url to validate *
* @returns On failure, returns false else type of url. * - `so` - SoundCloud
* - `sp` - Spotify
* - `dz` - Deezer
* - `yt` - YouTube
* @param url URL
* @returns
* ```ts
* 'so_playlist' / 'so_track' | 'sp_track' | 'sp_album' | 'sp_playlist' | 'dz_track' | 'dz_playlist' | 'dz_album' | 'yt_video' | 'yt_playlist' | 'search' | false
* ```
*/ */
export async function validate( export async function validate(
url: string url: string
@ -171,7 +321,17 @@ export async function validate(
} }
} }
/** /**
* Authorization interface for Spotify and SoundCloud. * Authorization interface for Spotify, SoundCloud and YouTube.
*
* Either stores info in `.data` folder or shows relevant data to be used in `setToken` function.
*
* ```ts
* const play = require('play-dl')
*
* play.authorization()
* ```
*
* Just run the above command and you will get a interface asking some questions.
*/ */
export function authorization(): void { export function authorization(): void {
const ask = readline.createInterface({ const ask = readline.createInterface({
@ -285,7 +445,13 @@ export function authorization(): void {
}); });
}); });
} }
/**
* Attaches paused, playing, autoPaused Listeners to discordjs voice AudioPlayer.
*
* Useful if you don't want extra data to be downloaded by play-dl.
* @param player discordjs voice AudioPlayer
* @param resource A {@link YouTubeStream} or {@link SoundCloudStream}
*/
export function attachListeners(player: EventEmitter, resource: YouTubeStream | SoundCloudStream) { export function attachListeners(player: EventEmitter, resource: YouTubeStream | SoundCloudStream) {
const pauseListener = () => resource.pause(); const pauseListener = () => resource.pause();
const resumeListener = () => resource.resume(); const resumeListener = () => resource.resume();