Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

playdl-music-extractor

Package Overview
Dependencies
Maintainers
1
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

playdl-music-extractor - npm Package Compare versions

Comparing version 3.0.2 to 3.0.3

src/bin/__album.js

16

package.json
{
"name": "playdl-music-extractor",
"version": "3.0.2",
"version": "3.0.3",
"description": "PlayDL Music Extractor is a Extractor/Scrapper and Helps Players to fetch data from play-dl or Custom Extractors , as Per reduces extra work and credentials",

@@ -30,7 +30,7 @@ "main": "./src/index.js",

"devDependencies": {
"@babel/eslint-parser": "^7.18.2",
"@babel/plugin-proposal-class-properties": "^7.17.12",
"@babel/preset-env": "^7.18.2",
"@babel/eslint-parser": "^7.18.9",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/preset-env": "^7.18.9",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.17.0",
"eslint": "^8.20.0",
"eslint-config-airbnb-base": "^15.0.0",

@@ -70,5 +70,4 @@ "eslint-plugin-import": "^2.26.0",

"dependencies": {
"@sidislive/soundcloud-scraper": "^1.0.1",
"axios": "^0.27.2",
"ffmpeg-static": "^5.0.0",
"ffmpeg-static": "^5.0.2",
"is-url": "^1.2.4",

@@ -78,6 +77,7 @@ "isomorphic-unfetch": "^3.1.0",

"play-dl": "^1.9.5",
"prism-media": "^1.3.2",
"prism-media": "^1.3.4",
"proxies-generator": "^1.0.6",
"random-useragent": "^0.5.0",
"reverbnation-scraper": "^2.0.0",
"soundcloud-scraper": "^5.0.3",
"spotify-url-info": "^3.1.2"

@@ -84,0 +84,0 @@ },

@@ -189,3 +189,3 @@ <div align="center">

declare type extractorData = {
playlist: boolean;
album: boolean;
tracks: Array<Track>;

@@ -207,3 +207,3 @@ };

quickHandler.on("tracks", (...eventData) => console.log(eventData));
quickHandler.on("track", (...eventData) => console.log(eventData));

@@ -210,0 +210,0 @@ new Promise(async (resolve, reject) => {

@@ -29,3 +29,3 @@ const playdlEngine = require('./__playdlEngine');

return {
playlist: false,
album: false,
tracks: await playdlEngine.__rawExtractor(

@@ -32,0 +32,0 @@ rawUrl,

@@ -5,5 +5,5 @@ const playdlEngine = require('./__playdlEngine');

static __dezerRegex = [
/^https?:\/\/(?:www\.)?deezer\.com\/([^#/\&\?]+)\/(track|album|playlist)\/(\d+)$/,
/^https?:\/\/(?:www\.)?deezer\.com\/([^#/\&\?]+)\/(track|album|album)\/(\d+)$/,
/^https?:\/\/(?:www\.)?deezer\.com\/([^#/\&\?]+)\/(track)\/(\d+)$/,
/^https?:\/\/(?:www\.)?deezer\.com\/([^#/\&\?]+)\/(album|playlist)\/(\d+)$/,
/^https?:\/\/(?:www\.)?deezer\.com\/([^#/\&\?]+)\/(album|album)\/(\d+)$/,
];

@@ -13,12 +13,12 @@

static __dezerPlaylistRegex = /^https?:\/\/(?:www\.)?deezer\.com\/([^#/\&\?]+)\/(album|playlist)\/(\d+)$/;
static __dezeralbumRegex = /^https?:\/\/(?:www\.)?deezer\.com\/([^#/\&\?]+)\/(album|album)\/(\d+)$/;
static __test(rawUrl, returnRegexValue = false) {
try {
if (!(rawUrl && typeof rawUrl === 'string' && rawUrl !== '')) return false;
if (!(rawUrl && typeof rawUrl === 'string' && rawUrl !== '')) { return false; }
return returnRegexValue
&& Boolean(deezer.__dezerRegex.find((regExp) => regExp.test(rawUrl)))
&& Boolean(deezer.__dezerRegex.find((regExp) => regExp.test(rawUrl)))
? rawUrl?.match(
deezer.__dezerRegex.find((regExp) => rawUrl.match(regExp)),
) ?? false
deezer.__dezerRegex.find((regExp) => rawUrl.match(regExp)),
) ?? false
: Boolean(deezer.__dezerRegex.find((regExp) => regExp.test(rawUrl)));

@@ -32,13 +32,18 @@ } catch {

try {
const rawTracks = await playdlEngine.__rawExtractor(
rawUrl,
{ orignal_extractor: 'deezer' },
__scrapperOptions,
__cacheMain,
);
return {
playlist: deezer.__dezerPlaylistRegex.test(rawUrl),
tracks: await playdlEngine.__rawExtractor(
rawUrl,
{ orignal_extractor: 'deezer' },
__scrapperOptions,
__cacheMain,
),
album:
rawTracks?.find((track) => track?.albumId)?.album
?? deezer.__dezeralbumRegex.test(rawUrl),
tracks: rawTracks,
};
} catch (rawError) {
if (__scrapperOptions?.ignoreInternalError) { return void __cacheMain.__errorHandling(rawError); }
if (__scrapperOptions?.ignoreInternalError) {
return void __cacheMain.__errorHandling(rawError);
}
throw rawError;

@@ -45,0 +50,0 @@ }

@@ -38,3 +38,3 @@ const Axios = require('axios').default;

return {
playlist: false,
album: false,
tracks: await playdlEngine.__rawExtractor(

@@ -41,0 +41,0 @@ __rawData?.title?.slice(0, 10)?.trim(),

@@ -13,2 +13,3 @@ const {

const trackModel = require('./__trackModeler');
const Album = require('./__album');

@@ -25,6 +26,7 @@ class playdlEngine {

__cacheMain,
__preCached,
__albumId,
) {
if (!(rawQuery && typeof rawQuery === 'string' && rawQuery !== '')) return undefined;
let __searchResults;
if (!(rawQuery && typeof rawQuery === 'string' && rawQuery !== '')) {
return undefined;
}
let __cacheGarbage;

@@ -48,3 +50,3 @@ let __indexCount = 0;

&& __scrapperOptions?.fetchOptions?.userAgents?.toLowerCase()?.trim()
=== 'random'
=== 'random'
) {

@@ -70,17 +72,18 @@ playdlEngine.__userAgents = [

const validatedResult = await validate(rawQuery)?.catch(() => undefined);
__searchResults = (
await playdlEngine.#__customSearch(
rawQuery,
__scrapperOptions,
validatedResult,
__trackBlueprint?.orignal_extractor,
)
)?.filter(Boolean);
const __searchResults = await playdlEngine.#__customSearch(
rawQuery,
__scrapperOptions,
validatedResult,
__cacheMain,
__trackBlueprint?.orignal_extractor,
);
if (
!(
__searchResults
&& Array.isArray(__searchResults)
&& __searchResults?.length > 0
__searchResults?.tracks
&& Array.isArray(__searchResults?.tracks)
&& __searchResults?.tracks?.length > 0
)
) return undefined;
) {
return undefined;
}
if (

@@ -94,29 +97,32 @@ __scrapperOptions?.fetchOptions?.fetchLimit

|| validatedResult?.includes('album'))
&& Boolean(__scrapperOptions?.fetchOptions?.skipPlaylistLimit)
&& Boolean(__scrapperOptions?.fetchOptions?.skipalbumLimit)
)
) {
__searchResults = __searchResults
__searchResults.tracks = __searchResults?.tracks
?.slice(0, parseInt(__scrapperOptions?.fetchOptions?.fetchLimit ?? 1))
?.filter(Boolean);
}
return (
await Promise.all(
__searchResults?.map(async (__rawTrack) => {
__searchResults?.tracks?.map(async (__rawTrack) => {
__cacheGarbage = await playdlEngine.__trackModelling(
__rawTrack,
{
{
...__trackBlueprint,
Id: ++__indexCount,
},
__scrapperOptions,
__cacheMain,
__scrapperOptions,
__albumId ?? __searchResults?.albumId ?? undefined,
__cacheMain,
);
if (__cacheGarbage && __scrapperOptions?.eventReturn) {
__cacheMain.emit(
'tracks',
'track',
__trackBlueprint?.orignal_extractor ?? 'youtube',
__cacheGarbage?.album ?? undefined,
__cacheGarbage,
typeof __scrapperOptions?.eventReturn === 'object'
? __scrapperOptions?.eventReturn?.metadata
: undefined,
? __scrapperOptions?.eventReturn?.metadata
: undefined,
);

@@ -134,16 +140,25 @@ } else if (!__cacheGarbage) return undefined;

__validate,
__cacheMain,
extractor = 'arbitary',
) {
if (extractor && extractor?.toLowerCase()?.trim() === 'arbitary') {
return [{
url: rawQuery,
}];
}
let __rawResults;
return [
{
url: rawQuery,
},
];
}
let __rawResults; let rawTracks; let
rawAlbumId;
let __videoDetails;
const __validateResults = [];
if (__validate && __validate?.includes('dz')) __validateResults[0] = 'deezer';
else if (__validate && __validate?.includes('sp')) __validateResults[0] = 'spotify';
else if (__validate && __validate?.includes('so')) __validateResults[0] = 'soundcloud';
else if (__validate && __validate?.includes('yt')) __validateResults[0] = 'youtube';
if (__validate && __validate?.includes('dz')) {
__validateResults[0] = 'deezer';
} else if (__validate && __validate?.includes('sp')) {
__validateResults[0] = 'spotify';
} else if (__validate && __validate?.includes('so')) {
__validateResults[0] = 'soundcloud';
} else if (__validate && __validate?.includes('yt')) {
__validateResults[0] = 'youtube';
}

@@ -159,36 +174,69 @@ __validateResults[1] = __validate ? __validate?.split('_')?.[1] : undefined;

__videoDetails = (await video_info(rawQuery))?.video_details;
return __videoDetails ? [__videoDetails] : undefined;
return __videoDetails ? { tracks: [__videoDetails] } : undefined;
}
__rawResults = await (
await playlist_info(rawQuery, {
incomplete: true,
})
)?.all_videos();
return __rawResults
&& Array.isArray(__rawResults)
&& __rawResults?.length > 0
? __rawResults?.filter(Boolean)
: undefined;
__rawResults = await playlist_info(rawQuery, {
incomplete: true,
});
rawTracks = await __rawResults?.all_videos();
rawAlbumId = Album.generate(
__rawResults,
rawTracks?.length,
__cacheMain,
true,
);
return {
albumId: rawAlbumId,
tracks: rawTracks,
};
case 'deezer':
__rawResults = await deezer(rawQuery);
if (__rawResults && ['playlist', 'album'].includes(__rawResults.type)) return await __rawResults?.all_tracks();
if (__rawResults && ['playlist', 'album'].includes(__rawResults.type)) {
rawTracks = await __rawResults?.all_tracks();
rawAlbumId = Album.generate(
__rawResults,
rawTracks?.length,
__cacheMain,
true,
);
return {
albumId: rawAlbumId,
tracks: rawTracks,
};
}
if (__rawResults && ['user'].includes(__rawResults)) return undefined;
return [__rawResults];
return { tracks: [__rawResults] };
case 'soundcloud':
__rawResults = await soundcloud(rawQuery);
if (__rawResults && ['playlist', 'album'].includes(__rawResults.type)) return await __rawResults?.fetch();
if (__rawResults && ['playlist', 'album'].includes(__rawResults.type)) {
return { tracks: await __rawResults?.fetch() };
}
if (__rawResults && ['user'].includes(__rawResults)) return undefined;
return [__rawResults];
return { tracks: [__rawResults] };
case 'spotify':
__rawResults = await spotify(rawQuery);
if (__rawResults && ['playlist', 'album'].includes(__rawResults.type)) return await __rawResults?.all_tracks();
if (__rawResults && ['playlist', 'album'].includes(__rawResults.type)) {
rawTracks = await __rawResults?.all_tracks();
rawAlbumId = Album.generate(
__rawResults,
rawTracks?.length,
__cacheMain,
true,
);
return {
albumId: rawAlbumId,
tracks: rawTracks,
};
}
if (__rawResults && ['user'].includes(__rawResults)) return undefined;
return [__rawResults];
return { tracks: [__rawResults] };
default:
__rawResults = await search(rawQuery, {
limit: [Infinity, 0].includes(
limit:
[Infinity, 0].includes(
__scrapperOptions?.fetchOptions?.fetchLimit ?? 1,
) || (__scrapperOptions?.fetchOptions?.fetchLimit ?? 1) <= 0
? 10 : __scrapperOptions?.fetchOptions?.fetchLimit ?? 1,
? 10
: __scrapperOptions?.fetchOptions?.fetchLimit ?? 1,
});

@@ -199,3 +247,5 @@ if (

&& __rawResults?.length > 1
) return __rawResults;
) {
return { tracks: __rawResults };
}
if (!__rawResults[0]?.url) return undefined;

@@ -205,3 +255,5 @@

?.video_details;
return __videoDetails ? [__videoDetails] : __rawResults[0];
return __videoDetails
? { tracks: [__videoDetails] }
: { tracks: __rawResults[0] };
}

@@ -214,2 +266,3 @@ }

__scrapperOptions,
__albumId,
__cacheMain,

@@ -220,3 +273,3 @@ ) {

const Track = new trackModel(
{
{
trackId: parseInt(__trackBlueprint?.Id ?? 0) || 0,

@@ -226,6 +279,8 @@ url: __trackBlueprint?.url ?? __rawTrack?.url,

title: __trackBlueprint?.title ?? __rawTrack?.title,
author: __trackBlueprint?.author
author:
__trackBlueprint?.author
?? __rawTrack?.artist?.name
?? __rawTrack?.channel?.name,
author_link: __trackBlueprint?.author_link
author_link:
__trackBlueprint?.author_link
?? __rawTrack?.artist?.url

@@ -235,3 +290,4 @@ ?? __rawTrack?.channel?.url,

custom_extractor: 'play-dl',
duration: (__trackBlueprint?.is_live || __rawTrack?.live
duration:
(__trackBlueprint?.is_live || __rawTrack?.live
? 0

@@ -244,11 +300,14 @@ : __trackBlueprint?.duration)

: __trackBlueprint?.duration)
?? (__rawTrack?.durationInSec ?? 0) * 1000,
?? (__rawTrack?.durationInSec ?? 0) * 1000,
),
orignal_extractor: __trackBlueprint?.orignal_extractor ?? 'youtube',
thumbnail: __trackBlueprint?.thumbnail ?? __rawTrack?.thumbnails?.[0]?.url,
channelName: __trackBlueprint?.channel_Name
thumbnail:
__trackBlueprint?.thumbnail ?? __rawTrack?.thumbnails?.[0]?.url,
channelName:
__trackBlueprint?.channel_Name
?? __rawTrack?.channel?.name
?? __trackBlueprint?.author,
channelId: __trackBlueprint?.author ?? __rawTrack?.channel?.id,
channel_url: __trackBlueprint?.author_link ?? __rawTrack?.channel?.url,
channel_url:
__trackBlueprint?.author_link ?? __rawTrack?.channel?.url,
likes: __trackBlueprint?.likes ?? __rawTrack?.likes ?? 0,

@@ -259,2 +318,3 @@ is_live: __trackBlueprint?.is_live ?? __rawTrack?.live ?? false,

__rawTrack,
__albumId,
);

@@ -266,3 +326,3 @@ if (__scrapperOptions?.streamDownload && __rawTrack?.url) {

__cacheMain,
{
{
userAgents: playdlEngine.__userAgents,

@@ -272,6 +332,10 @@ },

}
if (__scrapperOptions?.fetchLyrics && __rawTrack?.url) await Track.getLyrics();
if (__scrapperOptions?.fetchLyrics && __rawTrack?.url) {
await Track.getLyrics();
}
return Track;
} catch (rawError) {
if (__scrapperOptions?.ignoreInternalError) return void __cacheMain.__errorHandling(rawError);
if (__scrapperOptions?.ignoreInternalError) {
return void __cacheMain.__errorHandling(rawError);
}
throw rawError;

@@ -278,0 +342,0 @@ }

@@ -33,3 +33,3 @@ const reverbnationParser = require('reverbnation-scraper');

return {
playlist: false,
album: false,
tracks: await playdlEngine.__rawExtractor(

@@ -36,0 +36,0 @@ __rawData?.title?.slice(0, 10) ?? __rawData?.[0]?.title?.slice(0, 10),

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

const rawSoundCloud = require('@sidislive/soundcloud-scraper');
const rawSoundCloud = require('soundcloud-scraper');
const { setToken } = require('play-dl');
const playdlEngine = require('./__playdlEngine');
const Album = require('./__album');

@@ -20,3 +20,5 @@ class soundCloud {

try {
if (!(rawUrl && typeof rawUrl === 'string' && rawUrl !== '')) return false;
if (!(rawUrl && typeof rawUrl === 'string' && rawUrl !== '')) {
return false;
}
return returnRegexValue

@@ -53,3 +55,4 @@ && Boolean(

let __rawTracks;
let __cacheCount = 0;
let rawalbummMetadata;
let rawAlbumId;
let __cacheGarbage;

@@ -61,3 +64,3 @@ if (

return {
playlist: Boolean(
album: Boolean(
__rawRegex?.[3]?.includes('/sets/')

@@ -82,5 +85,12 @@ || __rawRegex?.[2]?.includes('/sets/')

) {
__rawTracks = (
await soundCloud.__soundcloudClient.getPlaylist(rawQuery)
)?.tracks?.filter(Boolean);
rawalbummMetadata = await soundCloud.__soundcloudClient.getPlaylist(
rawQuery,
);
__rawTracks = rawalbummMetadata?.tracks?.filter(Boolean);
rawAlbumId = Album.generate(
rawalbummMetadata,
__rawTracks?.length,
__cacheMain,
true,
);
} else {

@@ -93,7 +103,8 @@ __rawTracks = [

const __soundCloudTracks = await Promise.all(
__rawTracks?.map(async (rawTrack) => {
__rawTracks?.map(async (rawTrack, index, rawArray) => {
if (
!rawTrack
|| (__cacheCount
&& __cacheCount >= __scrapperOptions?.fetchOptions?.fetchLimit
|| (index
&& index
=== (__scrapperOptions?.fetchOptions?.fetchLimit ?? 0) - 1
&& !(

@@ -105,6 +116,7 @@ Boolean(

|| rawQuery.includes('/sets/'),
)
&& Boolean(__scrapperOptions?.fetchOptions?.skipPlaylistLimit)
) && Boolean(__scrapperOptions?.fetchOptions?.skipalbumLimit)
))
) return undefined;
) {
return undefined;
}
__cacheGarbage = await soundCloud.__trackParser(

@@ -114,18 +126,23 @@ rawTrack,

__cacheMain,
rawAlbumId,
);
++__cacheCount;
return __cacheGarbage;
}),
);
return {
playlist: Boolean(
__rawRegex?.[3]?.includes('/sets/')
|| __rawRegex?.[2]?.includes('/sets/')
|| __rawRegex?.[4]?.includes('/sets/')
|| rawQuery.includes('/sets/'),
),
album:
__soundCloudTracks?.find((track) => track?.albumId)?.album
?? Boolean(
__rawRegex?.[3]?.includes('/sets/')
|| __rawRegex?.[2]?.includes('/sets/')
|| __rawRegex?.[4]?.includes('/sets/')
|| rawQuery.includes('/sets/'),
),
tracks: __soundCloudTracks?.filter(Boolean),
};
} catch (rawError) {
if (__scrapperOptions?.ignoreInternalError) return void __cacheMain.__errorHandling(rawError);
if (__scrapperOptions?.ignoreInternalError) {
return void __cacheMain.__errorHandling(rawError);
}
throw rawError;

@@ -152,3 +169,4 @@ }

??= __scrapperOptions?.fetchOptions?.tokens?.soundcloud;
return await playdlEngine.__rawExtractor(
const { __rawExtractor } = require('./__playdlEngine');
return await __rawExtractor(
rawUrl,

@@ -160,3 +178,5 @@ { orignal_extractor: 'soundcloud' },

} catch (rawError) {
if (__scrapperOptions?.ignoreInternalError) return void __cacheMain.__errorHandling(rawError);
if (__scrapperOptions?.ignoreInternalError) {
return void __cacheMain.__errorHandling(rawError);
}
throw rawError;

@@ -166,3 +186,8 @@ }

static async __trackParser(rawTrack, __scrapperOptions, __cacheMain) {
static async __trackParser(
rawTrack,
__scrapperOptions,
__cacheMain,
albumId,
) {
const __trackBlueprint = {

@@ -172,4 +197,4 @@ Id: rawTrack?.id,

title: rawTrack?.title,
author: rawTrack?.author.name,
author_link: rawTrack?.author.url,
author: rawTrack?.author?.name,
author_link: rawTrack?.author?.url,
description: rawTrack?.description,

@@ -188,4 +213,5 @@ custom_extractor: 'play-dl',

};
const { __rawExtractor } = require('./__playdlEngine');
return (
await playdlEngine.__rawExtractor(
await __rawExtractor(
__trackBlueprint?.title?.length >= 12

@@ -200,2 +226,3 @@ ? __trackBlueprint?.title?.slice(0, 12)?.trim()

__cacheMain,
albumId,
)

@@ -202,0 +229,0 @@ )?.[0];

@@ -5,2 +5,3 @@ const fetch = require('isomorphic-unfetch');

const playdlEngine = require('./__playdlEngine');
const Album = require('./__album');

@@ -14,7 +15,7 @@ class spotify {

static __spotifyPlaylistRegex = /^(?:spotify:|(?:https?:\/\/(?:open|play)\.spotify\.com\/))(?:embed)?\/?(album|playlist)(?::|\/)((?:[0-9a-zA-Z]){22})/;
static __spotifyalbumRegex = /^(?:spotify:|(?:https?:\/\/(?:open|play)\.spotify\.com\/))(?:embed)?\/?(album|playlist)(?::|\/)((?:[0-9a-zA-Z]){22})/;
static __test(rawUrl, returnRegexValue = false) {
try {
if (!(rawUrl && typeof rawUrl === 'string' && rawUrl !== '')) return false;
if (!(rawUrl && typeof rawUrl === 'string' && rawUrl !== '')) { return false; }
return returnRegexValue

@@ -36,2 +37,3 @@ && Boolean(spotify.__spotifyRegex.find((regExp) => regExp.test(rawUrl)))

let __arryData;
let rawAlbumId;
let __cacheGarbage;

@@ -45,4 +47,3 @@ let __cacheCount = 0;

|| __rawData?.show
) __arryData = [__rawData];
else if (
) { __arryData = [__rawData]; } else if (
__rawData?.tracks?.items

@@ -58,2 +59,8 @@ && Array.isArray(__rawData?.tracks?.items)

?.filter(Boolean);
rawAlbumId = Album.generate(
__rawData,
__arryData?.length,
__cacheMain,
true,
);
}

@@ -68,3 +75,3 @@ if (

return {
playlist: Boolean(
album: Boolean(
__rawData?.tracks?.items

@@ -95,5 +102,5 @@ && Array.isArray(__rawData?.tracks?.items)

)
&& Boolean(__scrapperOptions?.fetchOptions?.skipPlaylistLimit)
&& Boolean(__scrapperOptions?.fetchOptions?.skipalbumLimit)
))
) return undefined;
) { return undefined; }
__cacheGarbage = await spotify.__trackParser(

@@ -104,2 +111,3 @@ rawTrack,

__cacheMain,
rawAlbumId,
);

@@ -111,11 +119,13 @@ return __cacheGarbage?.[0];

return {
playlist: Boolean(
__rawData?.tracks?.items
&& Array.isArray(__rawData?.tracks?.items)
&& __rawData?.tracks?.items?.length > 0,
),
album:
__processedTracks?.find((track) => track?.albumId)?.album
?? Boolean(
__rawData?.tracks?.items
&& Array.isArray(__rawData?.tracks?.items)
&& __rawData?.tracks?.items?.length > 0,
),
tracks: __processedTracks,
};
} catch (rawError) {
if (__scrapperOptions?.ignoreInternalError) return void __cacheMain.__errorHandling(rawError);
if (__scrapperOptions?.ignoreInternalError) { return void __cacheMain.__errorHandling(rawError); }
throw rawError;

@@ -155,3 +165,3 @@ }

} catch (rawError) {
if (__scrapperOptions?.ignoreInternalError) return void __cacheMain.__errorHandling(rawError);
if (__scrapperOptions?.ignoreInternalError) { return void __cacheMain.__errorHandling(rawError); }
throw rawError;

@@ -166,2 +176,3 @@ }

__cacheMain,
rawAlbumId,
) {

@@ -219,2 +230,3 @@ if (!(rawTrack?.id || rawTrack?.track?.id)) return undefined;

__cacheMain,
rawAlbumId,
);

@@ -221,0 +233,0 @@ }

const { stream, setToken, search } = require('play-dl');
const randomUserAgents = require('random-useragent').getRandom;
const ffmpeg = require('prism-media').FFmpeg;
const Album = require('./__album');
const { getLyrics } = require('./__lyrics');
const soundCloud = require('./__soundCloud');
const youtube = require('./__youtube');

@@ -11,9 +11,12 @@ class Track {

constructor(rawBlueprint, __rawPlaydl) {
if (__rawPlaydl) this.#__raw = __rawPlaydl;
this.patch(rawBlueprint);
constructor(rawBlueprint, __rawPlaydl, __albumId) {
if (__rawPlaydl) {
this.#__raw = { ...__rawPlaydl, __albumId };
}
this.patch(rawBlueprint, __albumId);
}
patch(rawBlueprint) {
patch(rawBlueprint, __albumId) {
if (!rawBlueprint?.url) return undefined;
if (__albumId) this.albumId = __albumId;
this.trackId = rawBlueprint?.trackId;

@@ -69,4 +72,8 @@ this.url = rawBlueprint?.url;

(soundCloud.__test(this.#__raw?.url)
|| (this.#__raw?.url?.toLowerCase()?.trim())?.startsWith('https://www.youtube.com/watch'))
&& !streamUrl)
|| this.#__raw?.url
?.toLowerCase()
?.trim()
?.startsWith('https://www.youtube.com/watch'))
&& !streamUrl
)
) {

@@ -228,2 +235,7 @@ __garbageResults = (await search(this.title, { limit: 1 }))?.filter(

get album() {
if (!this.#__raw?.__albumId) return undefined;
return Album.get(this.#__raw?.__albumId);
}
get raw() {

@@ -230,0 +242,0 @@ if (!this.#__raw) return undefined;

@@ -6,20 +6,30 @@ const uriCheck = require('is-url');

/^(?:https?:\/\/)?(?:(?:www|m|music)\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/,
/^.*(youtu.be\/|list=)([^#\&\?]*).*/,
];
static __youtubePlaylistRegex = /[?&]list=([^#\&\?]+)/;
static __youtubealbumRegex = [
/[?&]list=([^#\&\?]+)/,
/^.*(youtu.be\/|list=)([^#\&\?]*).*/,
];
static __test(rawUrl, returnRegexValue = false) {
try {
if (!(rawUrl && typeof rawUrl === 'string' && rawUrl !== '')) return false;
return returnRegexValue
if (!(rawUrl && typeof rawUrl === 'string' && rawUrl !== '')) { return false; }
if (
returnRegexValue
&& Boolean(youtube.__youtubeRegex.find((regExp) => regExp.test(rawUrl)))
? rawUrl?.match(
youtube.__youtubeRegex.find((regExp) => rawUrl.match(regExp)),
)
?? false
?? (!uriCheck(rawUrl) ? rawUrl : false)
: !uriCheck(rawUrl)
?? Boolean(
youtube.__youtubeRegex.find((regExp) => regExp.test(rawUrl)),
);
) {
return (
rawUrl?.match(
youtube.__youtubeRegex.find(
(regExp) => rawUrl.match(regExp)?.length > 2,
),
) ?? (!uriCheck(rawUrl) ? rawUrl : false)
);
}
return (
Boolean(
youtube.__youtubeRegex.find((regExp) => regExp.test(rawUrl)),
) ?? !uriCheck(rawUrl)
);
} catch {

@@ -33,14 +43,18 @@ return false;

const playdlEngine = require('./__playdlEngine');
const rawTracks = (await playdlEngine?.__rawExtractor(
rawQuery,
{ orignal_extractor: 'youtube' },
__scrapperOptions,
__cacheMain,
)) ?? [];
return {
playlist: Boolean(youtube.__youtubePlaylistRegex.test(rawQuery)),
tracks:
(await playdlEngine?.__rawExtractor(
rawQuery,
{ orignal_extractor: 'youtube' },
__scrapperOptions,
__cacheMain,
)) ?? [],
album:
rawTracks?.find((track) => track?.albumId)?.album
?? Boolean(
youtube.__youtubealbumRegex.find((regExp) => regExp.test(rawQuery)),
),
tracks: rawTracks,
};
} catch (rawError) {
if (__scrapperOptions?.ignoreInternalError) return void __cacheMain.__errorHandling(rawError);
if (__scrapperOptions?.ignoreInternalError) { return void __cacheMain.__errorHandling(rawError); }
throw rawError;

@@ -47,0 +61,0 @@ }

@@ -14,3 +14,3 @@ const path = require('path');

/**
* @class playdl -> Main Handler to Fetch and Parse Songs from Youtube and SoundCloud and many Others from play-dl as its base source
* @class playdl Main Handler to Fetch and Parse Songs from Youtube and SoundCloud and many Others from play-dl as its base source
*/

@@ -22,3 +22,3 @@

* @private
* @property {Object} #__privateCaches -> Private Caches for functions to Store basic Options and Queue Data for Ratelimit
* @property {Object} #__privateCaches Private Caches for functions to Store basic Options and Queue Data for Ratelimit
*/

@@ -33,3 +33,3 @@ static #__privateCaches = {

userAgents: undefined,
skipPlaylistLimit: true,
skipalbumLimit: true,
},

@@ -46,3 +46,3 @@ __scrapperOptions: {

userAgents: undefined,
skipPlaylistLimit: true,
skipalbumLimit: true,
},

@@ -55,3 +55,3 @@ streamDownload: false,

* @constructor
* @param {scrapperOptions} __scrapperOptions -> Scrapping Options for functions and base Source Engine
* @param {scrapperOptions} __scrapperOptions Scrapping Options for functions and base Source Engine
*/

@@ -71,6 +71,6 @@ constructor(__scrapperOptions = playdl.#__privateCaches.__scrapperOptions) {

/**
* exec() -> Raw and in-built function for fetching Data for other methods with no exceptions
* @param {string} rawQuery -> A String Value for Song Name or Url to be Parsed and Fetch Data about it
* @param {scrapperOptions} __scrapperOptions -> Scrapping Options for functions and base Source Engine
* @returns {Promise<extractorData>} playlist and Tracks from play-dl
* exec() Raw and in-built function for fetching Data for other methods with no exceptions
* @param {string} rawQuery A String Value for Song Name or Url to be Parsed and Fetch Data about it
* @param {scrapperOptions} __scrapperOptions Scrapping Options for functions and base Source Engine
* @returns {Promise<extractorData>} album and Tracks from play-dl
*/

@@ -99,5 +99,5 @@ async exec(

await this.__customRatelimit(__scrapperOptions?.ratelimit);
if (spotify.__test(rawQuery)) return await spotify.__extractor(rawQuery, __scrapperOptions, this);
if (soundcloud.__test(rawQuery)) return await soundcloud.__extractor(rawQuery, __scrapperOptions, this);
if (facebook.__test(rawQuery)) return await facebook.__extractor(rawQuery, __scrapperOptions, this);
if (spotify.__test(rawQuery)) { return await spotify.__extractor(rawQuery, __scrapperOptions, this); }
if (soundcloud.__test(rawQuery)) { return await soundcloud.__extractor(rawQuery, __scrapperOptions, this); }
if (facebook.__test(rawQuery)) { return await facebook.__extractor(rawQuery, __scrapperOptions, this); }
if (reverbnation.__test(rawQuery)) {

@@ -110,5 +110,5 @@ return await reverbnation.__extractor(

}
if (deezer.__test(rawQuery)) return await deezer.__extractor(rawQuery, __scrapperOptions, this);
if (youtube.__test(rawQuery)) return await youtube.__extractor(rawQuery, __scrapperOptions, this);
if (arbitary.__test(rawQuery)) return await arbitary.__extractor(rawQuery, __scrapperOptions, this);
if (deezer.__test(rawQuery)) { return await deezer.__extractor(rawQuery, __scrapperOptions, this); }
if (youtube.__test(rawQuery)) { return await youtube.__extractor(rawQuery, __scrapperOptions, this); }
if (arbitary.__test(rawQuery)) { return await arbitary.__extractor(rawQuery, __scrapperOptions, this); }
throw new Error(

@@ -118,3 +118,3 @@ 'playdl-music-extractor Error : Un-Supportable Query is Provided to Parse and Stream for Client',

} catch (rawError) {
if (__scrapperOptions?.ignoreInternalError) return void this.__errorHandling(rawError);
if (__scrapperOptions?.ignoreInternalError) { return void this.__errorHandling(rawError); }
throw rawError;

@@ -125,7 +125,7 @@ }

/**
* streamExtractor() -> Raw and in-built function for fetching Data for other methods with no exceptions
* @param {string} rawQuery -> A String Value for Song Name or Url to be Parsed and Fetch Data about it
* @param {scrapperOptions} __scrapperOptions -> Scrapping Options for functions and base Source Engine
* @param {string | "tracks" | "streams"} returnType Return Type for method , And Optional choice and By Default its -> "tracks"
* @returns {Promise<Track[] | Object[]>} playlist and Tracks from play-dl
* streamExtractor() Raw and in-built function for fetching Data for other methods with no exceptions
* @param {string} rawQuery A String Value for Song Name or Url to be Parsed and Fetch Data about it
* @param {scrapperOptions} __scrapperOptions Scrapping Options for functions and base Source Engine
* @param {string | "tracks" | "streams"} returnType Return Type for method , And Optional choice and By Default its "tracks"
* @returns {Promise<Track[] | Object[]>} album and Tracks from play-dl
*/

@@ -148,6 +148,6 @@ async streamExtractor(

/**
* softExtractor() -> Raw and in-built function for fetching Data for other methods with no exceptions
* @param {string} rawQuery -> A String Value for Song Name or Url to be Parsed and Fetch Data about it
* @param {scrapperOptions} __scrapperOptions -> Scrapping Options for functions and base Source Engine
* @returns {Promise<Track[]>} playlist and Tracks from play-dl
* softExtractor() Raw and in-built function for fetching Data for other methods with no exceptions
* @param {string} rawQuery A String Value for Song Name or Url to be Parsed and Fetch Data about it
* @param {scrapperOptions} __scrapperOptions Scrapping Options for functions and base Source Engine
* @returns {Promise<Track[]>} album and Tracks from play-dl
*/

@@ -168,3 +168,3 @@ async softExtractor(

if (!error?.message) return undefined;
if (!fileSystem.existsSync(path.join(__dirname, '/cache'))) fileSystem.mkdirSync(path.join(__dirname, '/cache'));
if (!fileSystem.existsSync(path.join(__dirname, '/cache'))) { fileSystem.mkdirSync(path.join(__dirname, '/cache')); }
const __cacheLocation = path.join(__dirname, '/cache', '/__errorLogs.txt');

@@ -216,3 +216,3 @@ if (!__cacheLocation) return undefined;

#sleep(waitTime = 2 * 1000) {
if (!(waitTime && typeof waitTime === 'number' && waitTime > 500)) return true;
if (!(waitTime && typeof waitTime === 'number' && waitTime > 500)) { return true; }
return new Promise((resolve) => setTimeout(resolve, waitTime));

@@ -219,0 +219,0 @@ }

@@ -1,2 +0,2 @@

import { EventEmitter } from 'events'
import { EventEmitter } from "events";
import {

@@ -8,11 +8,11 @@ Track,

extractorData,
} from './instances'
} from "./instances";
declare class playdl extends EventEmitter {
public constructor(__scrapperOptions: scrapperOptions)
public readonly __scrapperOptions: scrapperOptions
public constructor(__scrapperOptions: scrapperOptions);
public readonly __scrapperOptions: scrapperOptions;
public exec(
rawQuery: string,
__scrapperOptions?: scrapperOptions,
): Promise<extractorData>
__scrapperOptions?: scrapperOptions
): Promise<extractorData>;
public streamExtractor(

@@ -22,5 +22,5 @@ rawQuery: string,

| scrapperOptions
| 'streamDownload object key will always be true',
returnType?: string | 'tracks' | 'streams',
): Promise<Track[] | []>
| "streamDownload object key will always be true",
returnType?: string | "tracks" | "streams"
): Promise<Track[] | []>;
public softExtractor(

@@ -30,16 +30,16 @@ rawQuery: string,

| scrapperOptions
| 'streamDownload and fetcLyrics object key will always be false',
): Promise<Track[]>
public static playdlQuick: playdl
| "streamDownload and fetcLyrics object key will always be false"
): Promise<Track[]>;
public static playdlQuick: playdl;
public on<K extends keyof trackEvents>(
event: K,
listener: (...args: trackEvents[K]) => Awaitable<void>,
): this
listener: (...args: trackEvents[K]) => Awaitable<void>
): this;
public on<S extends string | symbol>(
event: Exclude<S, keyof trackEvents>,
listener: (...args: any[]) => Awaitable<void>,
): this
listener: (...args: any[]) => Awaitable<void>
): this;
}
export const playdlQuick = new playdl()
export { playdl, playdlQuick }
export const playdlQuick = new playdl();
export { playdl, playdlQuick };
declare type secretTokens = {
spotify: {
client_id: string | number
client_secret: string | number
refresh_token: string | number
market: string | 'US'
}
soundcloud: { client_id: string | number }
}
client_id: string | number;
client_secret: string | number;
refresh_token: string | number;
market: string | "US";
};
soundcloud: { client_id: string | number };
};
declare type fetchOptions = {
tokens: secretTokens
fetchLimit: number
streamQuality: string
rawCookies: string
userAgents: string[]
skipPlaylistLimit: Boolean
}
tokens: secretTokens;
fetchLimit: number;
streamQuality: string;
rawCookies: string;
userAgents: string[];
skipalbumLimit: Boolean;
};
export type scrapperOptions = {
fetchLyrics: boolean | 'true'
eventReturn: { metadata: any }
ratelimit: number
ignoreInternalError: boolean | 'true'
fetchOptions: fetchOptions
streamDownload: boolean | 'false'
}
fetchLyrics: boolean | "true";
eventReturn: { metadata: any };
ratelimit: number;
ignoreInternalError: boolean | "true";
fetchOptions: fetchOptions;
streamDownload: boolean | "false";
};
export type extractorData = {
playlist: boolean
tracks: Array<Track>
}
album: Album | boolean;
tracks: Array<Track>;
};
export class Track {
public constructor(__scrapperOptions: scrapperOptions)
public readonly __scrapperOptions: scrapperOptions
public constructor(__scrapperOptions: scrapperOptions);
public readonly __scrapperOptions: scrapperOptions;
public getStream(

@@ -42,41 +42,42 @@ extraStream: string,

__streamCaches: { userAgents: string[] },
reTryonRatelimit?: boolean | 'true',
): Promise<Track> | undefined
public getLyrics(): Promise<string>
readonly trackId: number
readonly url: string
readonly videoId: string | number
readonly title: string
readonly description: string
readonly author: { name: string; url: string }
reTryonRatelimit?: boolean | "true"
): Promise<Track> | undefined;
public getLyrics(): Promise<string>;
readonly albumId: String | number | undefined;
readonly trackId: number;
readonly url: string;
readonly videoId: string | number;
readonly title: string;
readonly description: string;
readonly author: { name: string; url: string };
readonly extractorModel: {
orignal:
| string
| 'deezer'
| 'youtube'
| 'spotify'
| 'facebook'
| 'reverbnation'
| 'soundcloud'
| 'arbitary'
custom: string | 'play-dl'
}
| "deezer"
| "youtube"
| "spotify"
| "facebook"
| "reverbnation"
| "soundcloud"
| "arbitary";
custom: string | "play-dl";
};
readonly duration: {
ms: number
readable: string
}
ms: number;
readable: string;
};
readonly thumbnail: {
Id: string | number
url: string
}
Id: string | number;
url: string;
};
readonly channel: {
name: string
Id: string | number
url: string
}
readonly isLive: boolean
name: string;
Id: string | number;
url: string;
};
readonly isLive: boolean;
readonly ratings: {
likes: number | string
dislikes: number | string
}
likes: number | string;
dislikes: number | string;
};
readonly stream: {

@@ -86,26 +87,55 @@ buffer:

| ReadableStream<Buffer>
| 'Fetched Stream from play-dl using stream() function or ffmpeg parsed Stream Url'
videoUrl: string
type: string
| "Fetched Stream from play-dl using stream() function or ffmpeg parsed Stream Url";
videoUrl: string;
type: string;
duration: {
ms: number
readable: string
}
videoId: string | number
}
ms: number;
readable: string;
};
videoId: string | number;
};
readonly lyrics:
| string
| ''
| 'Lyrics fetched from Un-Official Source , so limited Resources are expected'
readonly raw: {} | 'Unparsed and fetched Track Data from play-dl'
| ""
| "Lyrics fetched from Un-Official Source , so limited Resources are expected";
readonly album: Album | "Related Playlist or Album with Track";
readonly raw: {} | "Unparsed and fetched Track Data from play-dl";
}
export type Awaitable<T> = T | PromiseLike<T>
export class Album {
readonly Id: Number | String | undefined;
readonly name: String;
readonly url: String;
readonly description: String;
readonly thumbnail: String;
readonly tracksCount: Number;
readonly channel:
| {
name: String;
description: String;
url: String;
thumbnail: String;
}
| undefined;
readonly views: Number;
}
export type Awaitable<T> = T | PromiseLike<T>;
export interface trackEvents {
tracks: [
orignal_extractor: string | 'deezer' | 'youtube' | 'spotify' | 'facebook' | 'reverbnation' | 'soundcloud' | 'arbitary',
track: [
orignal_extractor:
| string
| "deezer"
| "youtube"
| "spotify"
| "facebook"
| "reverbnation"
| "soundcloud"
| "arbitary",
track: Track,
playlistId: String | Number | undefined,
metadata: any
]
];
playlist: [Album];
}
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc