playdl-music-extractor
Version:
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
264 lines (250 loc) • 7.17 kB
JavaScript
const { stream, setToken, search } = require('play-dl');
const randomUserAgents = require('random-useragent').getRandom;
const ffmpeg = require('prism-media').FFmpeg;
const { getLyrics } = require('./__lyrics');
const soundCloud = require('./__soundCloud');
class Track {
#raw = {};
constructor(rawBlueprint, __rawPlaydl, playdl, queue, extras) {
this.#raw = {
...__rawPlaydl,
streamCaches: extras?.streamCaches,
queue,
};
this.playdl = playdl;
this.patch(rawBlueprint, queue);
}
patch(rawBlueprint, queue) {
if (!rawBlueprint?.url) return undefined;
this.trackId = rawBlueprint?.trackId;
this.url = rawBlueprint?.url;
this.videoId = rawBlueprint?.video_Id ?? rawBlueprint?.videoId;
this.views = rawBlueprint?.view ?? rawBlueprint?.views;
this.title = rawBlueprint?.title;
this.description = rawBlueprint?.description;
this.author = {
name: rawBlueprint?.author,
url: rawBlueprint?.author_link,
};
this.extractorModel = {
orignal: rawBlueprint?.orignal_extractor ?? 'Unknown',
custom: rawBlueprint?.custom_extractor ?? 'play-dl',
};
this.duration = {
ms: rawBlueprint?.duration,
readable: rawBlueprint?.human_duration,
};
this.thumbnail = {
Id: rawBlueprint?.video_Id ?? rawBlueprint?.videoId,
url: rawBlueprint?.thumbnail,
};
this.channel = {
name: rawBlueprint?.channelName ?? rawBlueprint?.author,
Id: rawBlueprint?.channelId ?? rawBlueprint?.author,
url: rawBlueprint?.channel_url ?? rawBlueprint?.author_link,
};
this.isLive = rawBlueprint?.is_live;
this.ratings = {
likes: parseInt(rawBlueprint?.likes ?? 0) ?? 0,
dislikes: parseInt(rawBlueprint?.dislikes ?? 0) ?? 0,
};
this.metadata = rawBlueprint?.metadata;
this.queue = queue;
this.uniqueId = this.#generateId();
return this;
}
async getStream(
streamUrl,
ignoreStreamError,
reTryonRatelimit = true,
assignStream = false,
) {
try {
let __rawStream = {};
if (!this.url) return undefined;
if (
!(
(soundCloud.__test(this.#raw?.url)
|| this.#raw?.url
?.toLowerCase()
?.trim()
?.startsWith('https://www.youtube.com/watch'))
&& !streamUrl
)
) {
__rawStream = await stream(this.#raw?.url, {
discordPlayerCompatibility: true,
});
} else if (
streamUrl
&& typeof streamUrl === 'string'
&& streamUrl !== ''
) {
const ffmpegArgs = [
'-i',
streamUrl,
'-analyzeduration',
'0',
'-loglevel',
'0',
'-acodec',
'libopus',
'-f',
'opus',
'-ar',
'48000',
'-ac',
'2',
];
__rawStream = new ffmpeg({
args: ffmpegArgs,
});
} else if (
this.#raw?.url
&& typeof this.#raw?.url === 'string'
&& this.#raw?.url !== ''
) {
__rawStream = await stream(this.#raw?.url, {
discordPlayerCompatibility: true,
});
} else return undefined;
if (!assignStream) {
return {
buffer: __rawStream?.stream ?? __rawStream,
videoUrl: this.#raw?.url,
type: __rawStream?.type,
duration: {
ms: (this.#raw?.durationInSec ?? 0) * 1000,
readable: Track.humanTimeConversion(
(this.#raw?.durationInSec ?? 0) * 1000,
),
},
videoId: this.#raw?.id,
};
}
this.stream = {
buffer: __rawStream?.stream ?? __rawStream,
videoUrl: this.#raw?.url,
type: __rawStream?.type,
duration: {
ms: (this.#raw?.durationInSec ?? 0) * 1000,
readable: Track.humanTimeConversion(
(this.#raw?.durationInSec ?? 0) * 1000,
),
},
videoId: this.#raw?.id,
};
return this;
} catch (rawError) {
if (
(ignoreStreamError
|| rawError?.message?.includes('429')
|| `${rawError}`?.includes('429'))
&& this.playdl
&& !reTryonRatelimit
) {
return void this.playdl.__errorHandling(rawError);
}
if (
(ignoreStreamError
|| rawError?.message?.includes('429')
|| `${rawError}`?.includes('429'))
&& this.playdl
&& reTryonRatelimit
) {
this.playdl.__errorHandling(rawError);
let __rawUserAgents = this.raw?.streamCaches?.userAgents ?? [];
__rawUserAgents = [randomUserAgents(), ...__rawUserAgents];
await setToken({
useragent: __rawUserAgents,
});
return await this.getStream(streamUrl, ignoreStreamError, false);
}
throw rawError;
}
}
async getLyrics() {
if (
!(
this.url
&& this.#raw?.title
&& (this.author?.name
?? this.#raw?.author?.name
?? this.#raw?.artist?.name)
)
) {
return undefined;
}
this.lyrics = await getLyrics(
this.#raw?.title?.slice(0, 25)?.trim(),
this.author?.name ?? this.#raw?.author?.name ?? this.#raw?.artist?.name,
);
return this.lyrics;
}
static humanTimeConversion(__durationMs = 0) {
if (
!(
__durationMs
&& !Number.isNaN(__durationMs)
&& parseInt(__durationMs) > 0
)
) {
return undefined;
}
__durationMs /= 1000;
let __string = '';
for (
let __cacheArray = [
[Math.floor(__durationMs / 31536e3), 'Years'],
[Math.floor((__durationMs % 31536e3) / 86400), 'Days'],
[Math.floor(((__durationMs % 31536e3) % 86400) / 3600), 'Hours'],
[
Math.floor((((__durationMs % 31536e3) % 86400) % 3600) / 60),
'Minutes',
],
[
Math.floor((((__durationMs % 31536e3) % 86400) % 3600) % 60),
'Seconds',
],
],
__alterArray = 0,
__garbageValue = __cacheArray.length;
__alterArray < __garbageValue;
__alterArray++
) {
__cacheArray[__alterArray][0] !== 0
&& (__string += ` ${__cacheArray[__alterArray][0]} ${
__cacheArray[__alterArray][0] === 1
? __cacheArray[__alterArray][1].substr(
0,
__cacheArray[__alterArray][1].length - 1,
)
: __cacheArray[__alterArray][1]
}`);
}
return __string.trim();
}
get album() {
if (!this.queue?.album) return false;
return this.queue?.album;
}
get albumId() {
if (!this.queue?.album) return false;
return this.queue?.album?.id;
}
#generateId() {
let requestedId = '';
while (
this.queue.tracks.has(requestedId?.trim())
|| requestedId?.trim() === ''
) {
requestedId = Math.random().toString(36).slice(2, 15);
}
return requestedId;
}
get raw() {
if (!this.#raw) return undefined;
return this.#raw;
}
}
module.exports = Track;