diff --git a/package.json b/package.json index 4939a64..0487dfa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "play-dl", - "version": "1.6.7", + "version": "1.6.8", "description": "YouTube, SoundCloud, Spotify, Deezer searching and streaming for discord.js bots", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/play-dl/YouTube/classes/SeekStream.ts b/play-dl/YouTube/classes/SeekStream.ts index c87db9f..cb3a6be 100644 --- a/play-dl/YouTube/classes/SeekStream.ts +++ b/play-dl/YouTube/classes/SeekStream.ts @@ -92,8 +92,8 @@ export class SeekStream { * @param sec No of seconds to seek to * @returns Nothing */ - private async seek(sec: number) { - await new Promise(async (res) => { + private async seek(sec: number): Promise { + const parse = await new Promise(async (res, rej) => { if (!this.stream.headerparsed) { const stream = await request_stream(this.url, { headers: { @@ -102,13 +102,13 @@ export class SeekStream { }).catch((err: Error) => err); if (stream instanceof Error) { - this.stream.emit('error', stream); - this.bytes_count = 0; - this.per_sec_bytes = 0; - this.cleanup(); + rej(stream) + return; + } + if (Number(stream.statusCode) >= 400) { + rej(400) return; } - this.request = stream; stream.pipe(this.stream, { end: false }); @@ -117,8 +117,19 @@ export class SeekStream { res(''); }); } else res(''); - }); - + }).catch((err) => err); + if(parse instanceof Error){ + this.stream.emit('error', parse); + this.bytes_count = 0; + this.per_sec_bytes = 0; + this.cleanup(); + return; + } + else if(parse === 400){ + await this.retry(); + this.timer.reuse() + return this.seek(sec); + } const bytes = this.stream.seek(sec); if (bytes instanceof Error) { this.stream.emit('error', bytes); diff --git a/play-dl/YouTube/classes/WebmSeeker.ts b/play-dl/YouTube/classes/WebmSeeker.ts index 3b8ac34..e379428 100644 --- a/play-dl/YouTube/classes/WebmSeeker.ts +++ b/play-dl/YouTube/classes/WebmSeeker.ts @@ -85,7 +85,7 @@ export class WebmSeeker extends Duplex { break; } else continue; } - if (position === 0) return Error('Failed to find Cluster Position'); + if (position === 0) return new Error('Failed to find Cluster Position'); else return position; } diff --git a/play-dl/YouTube/stream.ts b/play-dl/YouTube/stream.ts index 5674895..115d059 100644 --- a/play-dl/YouTube/stream.ts +++ b/play-dl/YouTube/stream.ts @@ -1,7 +1,9 @@ +import { request_stream } from '../Request'; import { LiveStream, Stream } from './classes/LiveStream'; import { SeekStream } from './classes/SeekStream'; import { InfoData, StreamInfoData } from './utils/constants'; import { video_stream_info } from './utils/extractor'; +import { URL } from 'node:url'; export enum StreamType { Arbitrary = 'arbitrary', @@ -81,6 +83,7 @@ export async function stream_from_info( else final.push(info.format[info.format.length - 1]); let type: StreamType = final[0].codec === 'opus' && final[0].container === 'webm' ? StreamType.WebmOpus : StreamType.Arbitrary; + await request_stream(`https://${new URL(final[0].url).host}/generate_204`) if (options.seek) { if (type === StreamType.WebmOpus) { if (options.seek >= info.video_details.durationInSec || options.seek <= 0) diff --git a/play-dl/YouTube/utils/extractor.ts b/play-dl/YouTube/utils/extractor.ts index c6aabdf..b8e3de3 100644 --- a/play-dl/YouTube/utils/extractor.ts +++ b/play-dl/YouTube/utils/extractor.ts @@ -21,7 +21,7 @@ const DEFAULT_API_KEY = 'AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8'; const video_pattern = /^((?:https?:)?\/\/)?(?:(?:www|m|music)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|shorts\/|embed\/|v\/)?)([\w\-]+)(\S+)?$/; const playlist_pattern = - /^((?:https?:)?\/\/)?(?:(?:www|m)\.)?(youtube\.com)\/(?:(playlist|watch))(.*)?((\?|\&)list=)(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{10,}(.*)?$/; + /^((?:https?:)?\/\/)?(?:(?:www|m|music)\.)?(youtube\.com)\/(?:(playlist|watch))(.*)?((\?|\&)list=)(PL|UU|LL|RD|OL)[a-zA-Z\d_-]{10,}(.*)?$/; /** * Validate YouTube URL or ID. * @@ -391,11 +391,6 @@ export async function playlist_info(url: string, options: PlaylistOptions = {}): if (!url.startsWith('https')) url = `https://www.youtube.com/playlist?list=${url}`; if (url.indexOf('list=') === -1) throw new Error('This is not a Playlist URL'); - if (yt_validate(url) === 'playlist') { - const id = extractID(url); - url = `https://www.youtube.com/playlist?list=${id}`; - } - const body = await request(url, { headers: { 'accept-language': options.language || 'en-US;q=0.9' @@ -420,7 +415,7 @@ export async function playlist_info(url: string, options: PlaylistOptions = {}): else throw new Error('While parsing playlist url\nUnknown Playlist Error'); } if (url.indexOf('watch?v=') !== -1) { - return getWatchPlaylist(response, body); + return getWatchPlaylist(response, body, url); } else return getNormalPlaylist(response, body); } /** @@ -468,6 +463,7 @@ export function getContinuationToken(data: any): string { .continuationEndpoint?.continuationCommand?.token; } + async function acceptViewerDiscretion( videoId: string, cookieJar: { [key: string]: string }, @@ -550,7 +546,7 @@ async function acceptViewerDiscretion( return { streamingData }; } -function getWatchPlaylist(response: any, body: any): YouTubePlayList { +function getWatchPlaylit(response: any, body: any): YouTubePlayList { const playlist_details = response.contents.twoColumnWatchNextResults.playlist.playlist; const videos = getWatchPlaylistVideos(playlist_details.contents); @@ -576,7 +572,7 @@ function getWatchPlaylist(response: any, body: any): YouTubePlayList { title: playlist_details.title || '', videoCount: parseInt(videoCount) || 0, videos: videos, - url: `https://www.youtube.com/playlist?list=${playlist_details.playlistId}`, + url: url, channel: { id: channel?.navigationEndpoint?.browseEndpoint?.browseId || null, name: channel?.text || null,