From 4179557fde7effd63edc43dc4f0c8344927d4e82 Mon Sep 17 00:00:00 2001 From: killer069 <65385476+killer069@users.noreply.github.com> Date: Sun, 5 Sep 2021 18:50:57 +0530 Subject: [PATCH 1/5] Spotify support added --- README.md | 176 +------------- docs/README.md | 25 ++ docs/Spotify/README.md | 24 ++ docs/YouTube/README.md | 189 +++++++++++++++ examples/Spotify/play.js | 42 ++++ examples/{ => YouTube}/play - cookies.js | 8 +- .../play - search.js} | 6 +- .../{play(url).js => YouTube/play - url.js} | 8 +- play-dl/Spotify/classes.ts | 221 ++++++++++++++++++ play-dl/Spotify/index.ts | 56 +++++ play-dl/YouTube/stream.ts | 9 +- play-dl/YouTube/utils/extractor.ts | 23 +- play-dl/YouTube/utils/index.ts | 2 +- play-dl/index.ts | 23 +- 14 files changed, 609 insertions(+), 203 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/Spotify/README.md create mode 100644 docs/YouTube/README.md create mode 100644 examples/Spotify/play.js rename examples/{ => YouTube}/play - cookies.js (88%) rename examples/{play(search).js => YouTube/play - search.js} (90%) rename examples/{play(url).js => YouTube/play - url.js} (88%) create mode 100644 play-dl/Spotify/classes.ts create mode 100644 play-dl/Spotify/index.ts diff --git a/README.md b/README.md index 27bba6f..0d5e373 100644 --- a/README.md +++ b/README.md @@ -20,176 +20,8 @@ npm install play-dl@latest For pre-made examples, head over to [/examples](https://github.com/play-dl/play-dl/tree/main/examples) folder. +### Docs -# Basic Usage - -```js -const youtube = require('play-dl'); -// ES6: import youtube from 'play-dl'; -const options = { - limit : 1 -} -const results = await youtube.search('post malone sunflower', options); -``` - -# Validate - -### validate( url : `string` ) - *Much faster and easier way to validate url.* -```js -if(validate(url)) // Will return true if url is a YouTube url -``` - -### validate_playlist( url : `string` ) - *Much faster and easier way to validate url.* -```js -if(validate_playlist(url)) // Will return true if url is a YouTube Playlist url -``` - - > Want to Check both, use this - ```js -if(validate(url) || validate_playlist(url)) // This will check both and if anyone is true, it will execute the below function - ``` - -# Stream - -### stream(url : `string`, cookie? : `string`) -*This is basic to create a youtube stream from a url.* - -**[Cookies](https://github.com/play-dl/play-dl/discussions/34) are optional and are required for playing age restricted videos.** - -```js - let source = await stream("url") // This will create a stream Class which contains type and stream to be played. - let resource = createAudioResource(source.stream, { - inputType : source.type - }) // This creates resource for playing -``` - -### stream_from_info(info : `infoData`) -*This is basic to create a youtube stream from a info [ from [video_info](https://github.com/play-dl/play-dl#video_infourl--string) function ].* -```js -let info = await video_info("url") - let source = await stream_from_info(info) // This will create a stream Class which contains type and stream to be played. - let resource = createAudioResource(source.stream, { - inputType : source.type - }) // This creates resource for playing -``` - -# Search - -### search(url : `string`, options? : [SearchOptions](https://github.com/play-dl/play-dl/tree/main/play-dl/YouTube#searchoptions)) - -*This enables all searching mechanism (video, channel, playlist)* - -```js -const options = { - limit : 1 -} -const results = await youtube.search('never gonna give you up', options); -console.log(results[0].url); -``` - -- #### SearchOptions - - *type* : `video` | `channel` | `playlist` - - *limit* : `integer` - - - -# Video - -### video_basic_info(url : `string`, cookie? : `string`) -*The basic video details `play-dl` fetches at first.* - -**[Cookies](https://github.com/play-dl/play-dl/discussions/34) are optional and are required for playing age restricted videos.** - -```js -const video = await video_basic_info(url) -``` -### video_info(url : `string`, cookie? : `string`) -*This contains everything with deciphered formats along with `video_details`.* - -**[Cookies](https://github.com/play-dl/play-dl/discussions/34) are optional and are required for playing age restricted videos.** - -```js -const video = await video_info(url) -``` -- #### format `property` - *This returns all the formats available for a video.* - - ```js - const video = await video_info(url) - console.log(video.format) - ``` - - - -# Playlist - -### playlist_info(url : `string`, parseIncomplete : `boolean`) -*This fetches all details about a playlist.* - -**parseIncomplete** is optional parameter if you want to parse playlist with hidden videos. -```js -const playlist = await playlist_info(url) -//This only fetches first 100 videos from a playlist - -const playlist = await playlist_info(url, true) -//This only fetches first 100 videos from a playlist and also parses playlist with hidden videos -``` - -- #### fetch() `method` - *This fetches and returns all videos from the whole provided playlist .* - - ```js - const playlist = await playlist_info(url) - //This only fetches first 100 videos from a playlist - - await playlist.fetch() - // This one fetches all videos from a playlist. - ``` - -- #### page(page_number : `number`) - - *This returns no. of videos from a page.* - - > Every 100 videos have been divided into pages. - > Example: There are 782 videos in a playlist, so there will be 8 pages. - - ```js - const playlist = await playlist_info(url); - // This only fetches first 100 videos from a playlist. - - await playlist.fetch(); - // This one fetches all videos from a playlist. - - console.log(playlist.page(1)); - // This displays first 100 videos of a playlist - -- #### total_videos `property` - *This returns total no. of videos that have been fetched so far.* - - ```js - const playlist = await playlist_info(url) - //This only fetches first 100 videos from a playlist. - - await playlist.fetch() - // This one fetches all videos from a playlist. - - console.log(playlist.total_videos) - // This displays total no. of videos fetched so far. - ``` - -- #### videoCount `property` - - *This returns total no. of videos in the provided playlist.* - - ```js - const playlist = await playlist_info(url) - //This only fetches first 100 videos from a playlist. - - await playlist.fetch() - // This one fetches all videos from a playlist. - - console.log(playlist.videoCount) - // This displays total no. of videos in a playlist. - ``` +- [Main]() +- [YouTube]() +- [Spotify]() \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..5f64dd8 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,25 @@ +# Play-dl commands + +For source specific commands :- +- [YouTube]() +- [Spotify]() + +### Validate + +#### validate(url : `string`) +*This checks all type of urls that are supported by play-dl.* + +**Returns :** `sp_track` | `sp_album` | `sp_playlist` | `yt_video` | `yt_playlist` | `false` + +sp = Spotify + +yt = YouTube +```js +let check = validate(url) + +if(!check) // Invalid URL + +if(check === 'yt_video') // YouTube Video + +if(check === 'sp_track') // Spotify Track +``` \ No newline at end of file diff --git a/docs/Spotify/README.md b/docs/Spotify/README.md new file mode 100644 index 0000000..ea98563 --- /dev/null +++ b/docs/Spotify/README.md @@ -0,0 +1,24 @@ +# Spotify + +## Validate +### sp_validate(url : `string`) +*This checks that given url is spotify url or not.* + +**Returns :** `track` | `album` | `playlist` | `false` +```js +let check = sp_validate(url) + +if(!check) // Invalid Spotify URL + +if(check === 'track') // Spotify Track URL +``` + +## Main +### spotify(url : `string`) +*This returns data from a track | playlist | album url.* + +```js +let data = spotify(url) //Gets the data + +console.log(data.type) // Console logs the type of data that you got. +``` \ No newline at end of file diff --git a/docs/YouTube/README.md b/docs/YouTube/README.md new file mode 100644 index 0000000..b036e72 --- /dev/null +++ b/docs/YouTube/README.md @@ -0,0 +1,189 @@ +# YouTube + +## Basic Usage + +```js +const youtube = require('play-dl'); +// ES6: import youtube from 'play-dl'; +const options = { + limit : 1 +} +const results = await youtube.search('post malone sunflower', options); +``` + +## Validate + +### yt_validate(url : `string`) +*This will validate url and return type or boolean* + +**Returns :** `video` | `playlist` | `false` +```js +let check = yt_validate(url) + +if(!check) // Invalid URL + +if(check === "video") //URL is video url + +if(check === "playlist") //URL is a playlist url +``` + +## Stream + +### stream(url : `string`, cookie? : `string`) +*This is basic to create a youtube stream from a url.* + +**[Cookies](https://github.com/play-dl/play-dl/discussions/34) are optional and are required for playing age restricted videos.** + +```js + let source = await stream("url") // This will create a stream Class which contains type and stream to be played. + let resource = createAudioResource(source.stream, { + inputType : source.type + }) // This creates resource for playing +``` + +### stream_from_info(info : `infoData`) +*This is basic to create a youtube stream from a info [ from [video_info](https://github.com/play-dl/play-dl#video_infourl--string) function ].* +```js +let info = await video_info("url") + let source = await stream_from_info(info) // This will create a stream Class which contains type and stream to be played. + let resource = createAudioResource(source.stream, { + inputType : source.type + }) // This creates resource for playing +``` + +## Search + +### search(url : `string`, options? : [SearchOptions](https://github.com/play-dl/play-dl/tree/main/play-dl/YouTube#searchoptions)) + +*This enables all searching mechanism (video, channel, playlist)* + +```js +const options = { + limit : 1 +} +const results = await youtube.search('never gonna give you up', options); +console.log(results[0].url); +``` + +- #### SearchOptions + - *type* : `video` | `channel` | `playlist` + - *limit* : `integer` + + + +## Video + +### video_basic_info(url : `string`, cookie? : `string`) +*The basic video details `play-dl` fetches at first.* + +**[Cookies](https://github.com/play-dl/play-dl/discussions/34) are optional and are required for playing age restricted videos.** + +```js +const video = await video_basic_info(url) +``` +### video_info(url : `string`, cookie? : `string`) +*This contains everything with deciphered formats along with `video_details`.* + +**[Cookies](https://github.com/play-dl/play-dl/discussions/34) are optional and are required for playing age restricted videos.** + +```js +const video = await video_info(url) +``` +- #### format `property` + *This returns all the formats available for a video.* + + ```js + const video = await video_info(url) + console.log(video.format) + ``` + + + +## Playlist + +### playlist_info(url : `string`, parseIncomplete : `boolean`) +*This fetches all details about a playlist.* + +**parseIncomplete** is optional parameter if you want to parse playlist with hidden videos. +```js +const playlist = await playlist_info(url) +//This only fetches first 100 videos from a playlist + +const playlist = await playlist_info(url, true) +//This only fetches first 100 videos from a playlist and also parses playlist with hidden videos +``` + +- #### fetch() `method` + *This fetches and returns all videos from the whole provided playlist .* + + ```js + const playlist = await playlist_info(url) + //This only fetches first 100 videos from a playlist + + await playlist.fetch() + // This one fetches all videos from a playlist. + ``` + +- #### page(page_number : `number`) + + *This returns no. of videos from a page.* + + > Every 100 videos have been divided into pages. + > Example: There are 782 videos in a playlist, so there will be 8 pages. + + ```js + const playlist = await playlist_info(url); + // This only fetches first 100 videos from a playlist. + + await playlist.fetch(); + // This one fetches all videos from a playlist. + + console.log(playlist.page(1)); + // This displays first 100 videos of a playlist + +- #### total_pages `property` + *This returns total no. of pages that have been fetched so far.* + + ```js + const playlist = await playlist_info(url) + //This only fetches first 100 videos from a playlist. + + await playlist.fetch() + // This one fetches all videos from a playlist. + + console.log(playlist.total_pages) + // This displays total no. of pages fetched so far. + + for(let i = 1; i <= playlist.total_pages; i++){ + "Your queue".push(...playlist.page(i)) + } // This will push every video in that playlist to your queue + ``` + +- #### total_videos `property` + *This returns total no. of videos that have been fetched so far.* + + ```js + const playlist = await playlist_info(url) + //This only fetches first 100 videos from a playlist. + + await playlist.fetch() + // This one fetches all videos from a playlist. + + console.log(playlist.total_videos) + // This displays total no. of videos fetched so far. + ``` + +- #### videoCount `property` + + *This returns total no. of videos in the provided playlist.* + + ```js + const playlist = await playlist_info(url) + //This only fetches first 100 videos from a playlist. + + await playlist.fetch() + // This one fetches all videos from a playlist. + + console.log(playlist.videoCount) + // This displays total no. of videos in a playlist. + ``` diff --git a/examples/Spotify/play.js b/examples/Spotify/play.js new file mode 100644 index 0000000..9fefe09 --- /dev/null +++ b/examples/Spotify/play.js @@ -0,0 +1,42 @@ +const discord = require('discord.js') +const { Intents } = require('discord.js') +const { createAudioPlayer, createAudioResource , StreamType, demuxProbe, joinVoiceChannel, NoSubscriberBehavior, AudioPlayerStatus, VoiceConnectionStatus, getVoiceConnection } = require('@discordjs/voice') +const play = require('play-dl') +const client = new discord.Client({ intents : [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.DIRECT_MESSAGES] , partials : ['CHANNEL', 'MESSAGE']}) +const token = '< Your Bot Token >' + + +client.on('messageCreate', async message => { + if(message.content.startsWith('!play')){ + if(!message.member.voice?.channel) return message.channel.send('Connect to a Voice Channel') + const connection = joinVoiceChannel({ + channelId : message.member.voice.channel.id, + guildId : message.guild.id, + adapterCreator: message.guild.voiceAdapterCreator + }) + + let args = message.content.split('play ')[1].split(' ')[0] + let sp_data = await play.spotify(args) // This will get spotify data from the url [ I used track url, make sure to make a logic for playlist, album ] + let searched = await play.search(`${sp_data.name}`, { limit : 1 }) // This will search the found track on youtube. + let stream = await play.stream(searched[0].url) // This will create stream from the above search + + let resource = createAudioResource(stream.stream, { + inputType : stream.type + }) + let player = createAudioPlayer({ + behaviors: { + noSubscriber: NoSubscriberBehavior.Play + } + }) + player.play(resource) + + connection.subscribe(player) + } +}) + +client.on('ready', () => { + console.log(`We have logged in as ${client.user.tag}!`) +}) + +client.login(token); + diff --git a/examples/play - cookies.js b/examples/YouTube/play - cookies.js similarity index 88% rename from examples/play - cookies.js rename to examples/YouTube/play - cookies.js index 1886330..725c585 100644 --- a/examples/play - cookies.js +++ b/examples/YouTube/play - cookies.js @@ -1,7 +1,7 @@ const discord = require('discord.js') const { Intents } = require('discord.js') const { createAudioPlayer, createAudioResource , StreamType, demuxProbe, joinVoiceChannel, NoSubscriberBehavior, AudioPlayerStatus, VoiceConnectionStatus, getVoiceConnection } = require('@discordjs/voice') -const youtube = require('play-dl') +const play = require('play-dl') const client = new discord.Client({ intents : [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.DIRECT_MESSAGES] , partials : ['CHANNEL', 'MESSAGE']}) const token = '< YOUR BOT TOKEN >' const COOKIE = '< YOUR COOKIES >' @@ -17,13 +17,13 @@ client.on('messageCreate', async message => { }) let args = message.content.split('play ')[1].split(' ')[0] - let stream = await youtube.stream(args, COOKIE) + let stream = await play.stream(args, COOKIE) /* OR if you want to get info about youtube link and then stream it - let yt_info = await youtube.video_info(args, COOKIE) + let yt_info = await play.video_info(args, COOKIE) console.log(yt_info.video_details.title) - let stream = await youtube.stream_from_info(yt_info) + let stream = await play.stream_from_info(yt_info) */ let resource = createAudioResource(stream.stream, { diff --git a/examples/play(search).js b/examples/YouTube/play - search.js similarity index 90% rename from examples/play(search).js rename to examples/YouTube/play - search.js index e7b7aef..cfcf36c 100644 --- a/examples/play(search).js +++ b/examples/YouTube/play - search.js @@ -1,7 +1,7 @@ const discord = require('discord.js') const { Intents } = require('discord.js') const { createAudioPlayer, createAudioResource , StreamType, demuxProbe, joinVoiceChannel, NoSubscriberBehavior, AudioPlayerStatus, VoiceConnectionStatus, getVoiceConnection } = require('@discordjs/voice') -const youtube = require('play-dl') +const play = require('play-dl') const client = new discord.Client({ intents : [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.DIRECT_MESSAGES] , partials : ['CHANNEL', 'MESSAGE']}) const token = '< YOUR BOT TOKEN >' @@ -16,8 +16,8 @@ client.on('messageCreate', async message => { }) let args = message.content.split('play')[1] - let yt_info = await youtube.search(args, { limit : 1 }) - let stream = await youtube.stream(yt_info[0].url) + let yt_info = await play.search(args, { limit : 1 }) + let stream = await play.stream(yt_info[0].url) let resource = createAudioResource(stream.stream, { inputType : stream.type }) diff --git a/examples/play(url).js b/examples/YouTube/play - url.js similarity index 88% rename from examples/play(url).js rename to examples/YouTube/play - url.js index a761cbd..730f311 100644 --- a/examples/play(url).js +++ b/examples/YouTube/play - url.js @@ -1,7 +1,7 @@ const discord = require('discord.js') const { Intents } = require('discord.js') const { createAudioPlayer, createAudioResource , StreamType, demuxProbe, joinVoiceChannel, NoSubscriberBehavior, AudioPlayerStatus, VoiceConnectionStatus, getVoiceConnection } = require('@discordjs/voice') -const youtube = require('play-dl') +const play = require('play-dl') const client = new discord.Client({ intents : [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.DIRECT_MESSAGES] , partials : ['CHANNEL', 'MESSAGE']}) const token = '< YOUR BOT TOKEN >' @@ -16,13 +16,13 @@ client.on('messageCreate', async message => { }) let args = message.content.split('play ')[1].split(' ')[0] - let stream = await youtube.stream(args) + let stream = await play.stream(args) /* OR if you want to get info about youtube link and then stream it - let yt_info = await youtube.video_info(args) + let yt_info = await play.video_info(args) console.log(yt_info.video_details.title) - let stream = await youtube.stream_from_info(yt_info) + let stream = await play.stream_from_info(yt_info) */ let resource = createAudioResource(stream.stream, { diff --git a/play-dl/Spotify/classes.ts b/play-dl/Spotify/classes.ts new file mode 100644 index 0000000..c7ee48b --- /dev/null +++ b/play-dl/Spotify/classes.ts @@ -0,0 +1,221 @@ + + +interface SpotifyTrackAlbum{ + name : string; + url : string; + id : string; + release_date : string; + release_date_precision : string; + total_tracks : number; +} + +interface SpotifyArtists{ + name : string; + url : string; + id : string; +} + +interface SpotifyThumbnail{ + height : number; + width : number + url : string +} + +interface SpotifyCopyright{ + text : string; + type : string; +} + +export class SpotifyVideo{ + name : string; + type : "video" | "playlist" | "album" + id : string; + url : string; + explicit : boolean; + durationInSec : number; + durationInMs : number; + artists : SpotifyArtists[] + album : SpotifyTrackAlbum + thumbnail : SpotifyThumbnail + constructor(data : any){ + this.name = data.name + this.id = data.id + this.type = "video" + this.url = data.external_urls.spotify + this.explicit = data.explicit + this.durationInMs = data.duration_ms + this.durationInSec = Math.round(this.durationInMs/1000) + let artists : SpotifyArtists[] = [] + data.artists.forEach((v : any) => { + artists.push({ + name : v.name, + id : v.id, + url : v.external_urls.spotify + }) + }) + this.artists = artists + this.album = { + name : data.album.name, + url : data.external_urls.spotify, + id : data.album.id, + release_date : data.album.release_date, + release_date_precision : data.album.release_date_precision, + total_tracks : data.album.total_tracks + } + this.thumbnail = data.album.images[0] + } + + toJSON(){ + return { + name : this.name, + id : this.id, + type : this.type, + url : this.url, + explicit : this.explicit, + durationInMs : this.durationInMs, + durationInSec : this.durationInSec, + artists : this.artists, + album : this.album, + thumbnail : this.thumbnail + } + } +} + +export class SpotifyPlaylist{ + name : string; + type : "video" | "playlist" | "album" + collaborative : boolean; + description : string; + url : string; + id : string; + thumbnail : SpotifyThumbnail; + owner : SpotifyArtists; + tracks : SpotifyVideo[] + constructor(data : any){ + this.name = data.name + this.type = "playlist" + this.collaborative = data.collaborative + this.description = data.description + this.url = data.external_urls.spotify + this.id = data.id + this.thumbnail = data.images[0] + this.owner = { + name : data.owner.display_name, + url : data.owner.external_urls.spotify, + id : data.owner.id + } + let videos: SpotifyVideo[] = [] + data.tracks.items.forEach((v : any) => { + videos.push(new SpotifyVideo(v.track)) + }) + this.tracks = videos + } + + toJSON(){ + return { + name : this.name, + type : this.type, + collaborative : this.collaborative, + description : this.description, + url : this.url, + id : this.id, + thumbnail : this.thumbnail, + owner : this.owner, + tracks : this.tracks + } + } +} + +export class SpotifyAlbum{ + name : string + type : "video" | "playlist" | "album" + url : string + thumbnail : SpotifyThumbnail + artists : SpotifyArtists[] + copyrights : SpotifyCopyright[] + release_date : string; + release_date_precision : string; + total_tracks : number + tracks : SpotifyTracks[] + constructor(data : any){ + this.name = data.name + this.type = "album" + this.url = data.external_urls.spotify + this.thumbnail = data.images[0] + let artists : SpotifyArtists[] = [] + data.artists.forEach((v : any) => { + artists.push({ + name : v.name, + id : v.id, + url : v.external_urls.spotify + }) + }) + this.artists = artists + this.copyrights = data.copyrights + this.release_date = data.release_date + this.release_date_precision = data.release_date_precision + this.total_tracks = data.total_tracks + let videos: SpotifyTracks[] = [] + data.tracks.items.forEach((v : any) => { + videos.push(new SpotifyTracks(v)) + }) + this.tracks = videos + } + + toJSON(){ + return { + name : this.name, + type : this.type, + url : this.url, + thumbnail : this.thumbnail, + artists : this.artists, + copyrights : this.copyrights, + release_date : this.release_date, + release_date_precision : this.release_date_precision, + total_tracks : this.total_tracks, + tracks : this.tracks + } + } +} + +class SpotifyTracks{ + name : string; + type : "video" | "playlist" | "album" + id : string; + url : string; + explicit : boolean; + durationInSec : number; + durationInMs : number; + artists : SpotifyArtists[] + constructor(data : any){ + this.name = data.name + this.id = data.id + this.type = "video" + this.url = data.external_urls.spotify + this.explicit = data.explicit + this.durationInMs = data.duration_ms + this.durationInSec = Math.round(this.durationInMs/1000) + let artists : SpotifyArtists[] = [] + data.artists.forEach((v : any) => { + artists.push({ + name : v.name, + id : v.id, + url : v.external_urls.spotify + }) + }) + this.artists = artists + } + + toJSON(){ + return { + name : this.name, + id : this.id, + type : this.type, + url : this.url, + explicit : this.explicit, + durationInMs : this.durationInMs, + durationInSec : this.durationInSec, + artists : this.artists, + } + } +} \ No newline at end of file diff --git a/play-dl/Spotify/index.ts b/play-dl/Spotify/index.ts new file mode 100644 index 0000000..a3633cd --- /dev/null +++ b/play-dl/Spotify/index.ts @@ -0,0 +1,56 @@ +import got from "got/dist/source" +import { SpotifyAlbum, SpotifyPlaylist, SpotifyVideo } from "./classes" + + +const pattern = /^((https:)?\/\/)?open.spotify.com\/(track|album|playlist)\// + +export async function spotify(url : string): Promise{ + if(!url.match(pattern)) throw new Error('This is not a Spotify URL') + let embed = embed_url(url) + let response = await got(embed) + return parse_json(embed, response.body) +} + +function parse_json(url : string, data : string): SpotifyAlbum | SpotifyPlaylist | SpotifyVideo{ + let json_data = JSON.parse(decodeURIComponent(data.split('')[0])) + if(url.indexOf('track') !== -1){ + return new SpotifyVideo(json_data) + } + else if(url.indexOf('album') !== -1){ + return new SpotifyAlbum(json_data) + } + else if(url.indexOf('playlist') !== -1){ + return new SpotifyPlaylist(json_data) + } + else throw new Error('Failed to parse data') +} + +function embed_url(url : string): string{ + if(url.indexOf('track') !== -1){ + let trackID = url.split('track/')[1].split('?')[0].split('/')[0].split('&')[0] + return `https://open.spotify.com/embed/track/${trackID}` + } + else if(url.indexOf('album') !== -1){ + let albumID = url.split('album/')[1].split('?')[0].split('/')[0].split('&')[0] + return `https://open.spotify.com/embed/album/${albumID}` + } + else if(url.indexOf('playlist') !== -1){ + let playlistID = url.split('playlist/')[1].split('?')[0].split('/')[0].split('&')[0] + return `https://open.spotify.com/embed/playlist/${playlistID}` + } + else throw new Error('Unable to generate embed url for given spotify url.') +} + +export function sp_validate(url : string): "track" | "playlist" | "album" | boolean{ + if(!url.match(pattern)) return false + if(url.indexOf('track') !== -1){ + return "track" + } + else if(url.indexOf('album') !== -1){ + return "album" + } + else if(url.indexOf('playlist') !== -1){ + return "playlist" + } + else return false +} \ No newline at end of file diff --git a/play-dl/YouTube/stream.ts b/play-dl/YouTube/stream.ts index 7890adf..2ccbaa4 100644 --- a/play-dl/YouTube/stream.ts +++ b/play-dl/YouTube/stream.ts @@ -40,7 +40,7 @@ export async function stream(url : string, cookie? : string): Promise Date: Sun, 5 Sep 2021 18:53:59 +0530 Subject: [PATCH 2/5] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0d5e373..ca70406 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,6 @@ For pre-made examples, head over to [/examples](https://github.com/play-dl/play- ### Docs -- [Main]() -- [YouTube]() -- [Spotify]() \ No newline at end of file +- [Main](https://github.com/play-dl/play-dl/tree/developer/docs#play-dl-commands) +- [YouTube](https://github.com/play-dl/play-dl/tree/developer/docs/YouTube#youtube) +- [Spotify](https://github.com/play-dl/play-dl/tree/developer/docs/Spotify#spotify) From 40aa235c932bd621dc4876fe678eea9deafd842f Mon Sep 17 00:00:00 2001 From: Killer069 <65385476+killer069@users.noreply.github.com> Date: Sun, 5 Sep 2021 18:54:16 +0530 Subject: [PATCH 3/5] Update README.md --- docs/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 5f64dd8..35b0d3a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,8 +1,8 @@ # Play-dl commands For source specific commands :- -- [YouTube]() -- [Spotify]() +- [YouTube](https://github.com/play-dl/play-dl/tree/developer/docs/YouTube#youtube) +- [Spotify](https://github.com/play-dl/play-dl/tree/developer/docs/Spotify#spotify) ### Validate @@ -22,4 +22,4 @@ if(!check) // Invalid URL if(check === 'yt_video') // YouTube Video if(check === 'sp_track') // Spotify Track -``` \ No newline at end of file +``` From 59a1d131804a19f774938a0b324f5b7439ade7a9 Mon Sep 17 00:00:00 2001 From: Killer069 <65385476+killer069@users.noreply.github.com> Date: Sun, 5 Sep 2021 18:56:21 +0530 Subject: [PATCH 4/5] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ca70406..89a5e81 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ npm install play-dl@latest ``` ### Examples - -For pre-made examples, head over to [/examples](https://github.com/play-dl/play-dl/tree/main/examples) folder. +- [YouTube](https://github.com/play-dl/play-dl/tree/developer/examples/YouTube) +- [Spotify](https://github.com/play-dl/play-dl/tree/developer/examples/Spotify) ### Docs From 2928c5773ab386e6a2b0eb8c54d711d8eae731b3 Mon Sep 17 00:00:00 2001 From: killer069 <65385476+killer069@users.noreply.github.com> Date: Sun, 5 Sep 2021 19:12:49 +0530 Subject: [PATCH 5/5] Memory Leak issue fix --- play-dl/YouTube/classes/LiveStream.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/play-dl/YouTube/classes/LiveStream.ts b/play-dl/YouTube/classes/LiveStream.ts index 2b3062d..a67e564 100644 --- a/play-dl/YouTube/classes/LiveStream.ts +++ b/play-dl/YouTube/classes/LiveStream.ts @@ -92,7 +92,7 @@ export class LiveStreaming{ await new Promise((resolve, reject) => { let stream = got.stream(this.base_url + segment) this.request = stream - stream.on('data', (chunk: any) => this.stream.write(chunk)) + stream.pipe(this.stream, { end : false }) stream.on('end', () => { this.packet_count++ resolve('') @@ -154,6 +154,7 @@ export class Stream { } }) this.request = stream + stream.pipe(this.stream, { end : false }) stream.once('data', () => { if(this.per_sec_bytes === 0){ this.per_sec_bytes = Math.ceil((stream.downloadProgress.total as number)/this.duration) @@ -167,7 +168,6 @@ export class Stream { stream.on('data', (chunk: any) => { absolute_bytes += chunk.length this.bytes_count += chunk.length - this.stream.write(chunk) if(absolute_bytes > (this.per_sec_bytes * 300) && this.per_sec_bytes !== 0){ stream.destroy() }