From af5a418d0952f379c83487a6ac67a7b260117ff4 Mon Sep 17 00:00:00 2001 From: killer069 <65385476+killer069@users.noreply.github.com> Date: Tue, 14 Dec 2021 15:01:10 +0530 Subject: [PATCH] prettier code --- play-dl/YouTube/classes/Playlist.ts | 2 +- play-dl/YouTube/classes/SeekStream.ts | 65 +++--- play-dl/YouTube/classes/WebmSeeker.ts | 319 +++++++++++++------------- play-dl/YouTube/stream.ts | 34 +-- play-dl/YouTube/utils/extractor.ts | 93 ++++---- 5 files changed, 258 insertions(+), 255 deletions(-) diff --git a/play-dl/YouTube/classes/Playlist.ts b/play-dl/YouTube/classes/Playlist.ts index 1fa6fb9..3fe8c05 100644 --- a/play-dl/YouTube/classes/Playlist.ts +++ b/play-dl/YouTube/classes/Playlist.ts @@ -94,7 +94,7 @@ export class YouTubePlayList { this.views = data.views || 0; this.link = data.link || undefined; this.channel = new YouTubeChannel(data.channel) || undefined; - this.thumbnail = (data.thumbnail) ? new YouTubeThumbnail(data.thumbnail) : undefined; + this.thumbnail = data.thumbnail ? new YouTubeThumbnail(data.thumbnail) : undefined; this.videos = data.videos || []; this.__count++; this.fetched_videos.set(`${this.__count}`, this.videos as YouTubeVideo[]); diff --git a/play-dl/YouTube/classes/SeekStream.ts b/play-dl/YouTube/classes/SeekStream.ts index f45b20b..d7e1f24 100644 --- a/play-dl/YouTube/classes/SeekStream.ts +++ b/play-dl/YouTube/classes/SeekStream.ts @@ -1,14 +1,14 @@ -import { IncomingMessage } from "http"; -import { request_stream } from "../../Request"; -import { parseAudioFormats, StreamOptions, StreamType } from "../stream"; -import { video_info } from "../utils"; -import { Timer } from "./LiveStream"; -import { WebmSeeker, WebmSeekerState } from "./WebmSeeker"; +import { IncomingMessage } from 'http'; +import { request_stream } from '../../Request'; +import { parseAudioFormats, StreamOptions, StreamType } from '../stream'; +import { video_info } from '../utils'; +import { Timer } from './LiveStream'; +import { WebmSeeker, WebmSeekerState } from './WebmSeeker'; /** * YouTube Stream Class for seeking audio to a timeStamp. */ - export class SeekStream { +export class SeekStream { /** * WebmSeeker Stream through which data passes */ @@ -61,14 +61,12 @@ import { WebmSeeker, WebmSeekerState } from "./WebmSeeker"; * @param video_url YouTube video url. * @param options Options provided to stream function. */ - constructor( - url: string, - duration: number, - contentLength: number, - video_url: string, - options: StreamOptions - ) { - this.stream = new WebmSeeker({ highWaterMark: 5 * 1000 * 1000, readableObjectMode : true, mode : options.seekMode }); + constructor(url: string, duration: number, contentLength: number, video_url: string, options: StreamOptions) { + this.stream = new WebmSeeker({ + highWaterMark: 5 * 1000 * 1000, + readableObjectMode: true, + mode: options.seekMode + }); this.url = url; this.quality = options.quality as number; this.type = StreamType.Opus; @@ -85,18 +83,18 @@ import { WebmSeeker, WebmSeekerState } from "./WebmSeeker"; this.timer.destroy(); this.cleanup(); }); - this.seek(options.seek!) + this.seek(options.seek!); } /** * **INTERNAL Function** - * + * * Uses stream functions to parse Webm Head and gets Offset byte to seek to. * @param sec No of seconds to seek to * @returns Nothing */ - private async seek(sec : number){ - await new Promise(async(res) => { - if(!this.stream.headerparsed){ + private async seek(sec: number) { + await new Promise(async (res) => { + if (!this.stream.headerparsed) { const stream = await request_stream(this.url, { headers: { range: `bytes=0-1000` @@ -111,18 +109,17 @@ import { WebmSeeker, WebmSeekerState } from "./WebmSeeker"; return; } - this.request = stream - stream.pipe(this.stream, { end : false }) + this.request = stream; + stream.pipe(this.stream, { end: false }); stream.once('end', () => { - this.stream.state = WebmSeekerState.READING_DATA - res('') - }) - } - else res('') - }) + this.stream.state = WebmSeekerState.READING_DATA; + res(''); + }); + } else res(''); + }); - const bytes = this.stream.seek(sec) + const bytes = this.stream.seek(sec); if (bytes instanceof Error) { this.stream.emit('error', bytes); this.bytes_count = 0; @@ -131,10 +128,10 @@ import { WebmSeeker, WebmSeekerState } from "./WebmSeeker"; return; } - this.stream.seekfound = false - this.bytes_count = bytes - this.timer.reuse() - this.loop() + this.stream.seekfound = false; + this.bytes_count = bytes; + this.timer.reuse(); + this.loop(); } /** * Retry if we get 404 or 403 Errors. @@ -186,7 +183,7 @@ import { WebmSeeker, WebmSeekerState } from "./WebmSeeker"; return; } this.request = stream; - stream.pipe(this.stream, { end : false }) + stream.pipe(this.stream, { end: false }); stream.once('error', async () => { this.cleanup(); diff --git a/play-dl/YouTube/classes/WebmSeeker.ts b/play-dl/YouTube/classes/WebmSeeker.ts index 0956851..3b8ac34 100644 --- a/play-dl/YouTube/classes/WebmSeeker.ts +++ b/play-dl/YouTube/classes/WebmSeeker.ts @@ -1,217 +1,224 @@ -import { WebmElements, WebmHeader } from 'play-audio' -import { Duplex, DuplexOptions } from 'stream' +import { WebmElements, WebmHeader } from 'play-audio'; +import { Duplex, DuplexOptions } from 'stream'; -enum DataType { master, string, uint, binary, float } +enum DataType { + master, + string, + uint, + binary, + float +} -export enum WebmSeekerState{ +export enum WebmSeekerState { READING_HEAD = 'READING_HEAD', - READING_DATA = 'READING_DATA', + READING_DATA = 'READING_DATA' } -interface WebmSeekerOptions extends DuplexOptions{ - mode? : "precise" | "granular" +interface WebmSeekerOptions extends DuplexOptions { + mode?: 'precise' | 'granular'; } -export class WebmSeeker extends Duplex{ - remaining? : Buffer - state : WebmSeekerState - mode : "precise" | "granular" - chunk? : Buffer - cursor : number - header : WebmHeader - headfound : boolean - headerparsed : boolean - time_left : number - seekfound : boolean - private data_size : number - private data_length : number +export class WebmSeeker extends Duplex { + remaining?: Buffer; + state: WebmSeekerState; + mode: 'precise' | 'granular'; + chunk?: Buffer; + cursor: number; + header: WebmHeader; + headfound: boolean; + headerparsed: boolean; + time_left: number; + seekfound: boolean; + private data_size: number; + private data_length: number; - constructor(options : WebmSeekerOptions){ - super(options) - this.state = WebmSeekerState.READING_HEAD - this.cursor = 0 - this.header = new WebmHeader() - this.headfound = false - this.time_left = 0 - this.headerparsed = false - this.seekfound = false - this.data_length = 0 - this.mode = options.mode || "granular" - this.data_size = 0 + constructor(options: WebmSeekerOptions) { + super(options); + this.state = WebmSeekerState.READING_HEAD; + this.cursor = 0; + this.header = new WebmHeader(); + this.headfound = false; + this.time_left = 0; + this.headerparsed = false; + this.seekfound = false; + this.data_length = 0; + this.mode = options.mode || 'granular'; + this.data_size = 0; } - private get vint_length(): number{ + private get vint_length(): number { let i = 0; - for (; i < 8; i++){ - if ((1 << (7 - i)) & this.chunk![this.cursor]) - break; - } - return ++i; + for (; i < 8; i++) { + if ((1 << (7 - i)) & this.chunk![this.cursor]) break; + } + return ++i; } private get vint_value(): boolean { - if (!this.chunk) return false - const length = this.vint_length - if(this.chunk.length < this.cursor + length) return false - let value = this.chunk[this.cursor] & ((1 << (8 - length)) - 1) + if (!this.chunk) return false; + const length = this.vint_length; + if (this.chunk.length < this.cursor + length) return false; + let value = this.chunk[this.cursor] & ((1 << (8 - length)) - 1); for (let i = this.cursor + 1; i < this.cursor + length; i++) value = (value << 8) + this.chunk[i]; - this.data_size = length - this.data_length = value - return true + this.data_size = length; + this.data_length = value; + return true; } - cleanup(){ - this.cursor = 0 - this.chunk = undefined - this.remaining = undefined + cleanup() { + this.cursor = 0; + this.chunk = undefined; + this.remaining = undefined; } _read() {} - seek(sec : number): Error | number{ - let position = 0 - let time = (Math.floor(sec / 10) * 10) - this.time_left = (sec - time) * 1000 || 0 - if (!this.header.segment.cues) return new Error("Failed to Parse Cues") + seek(sec: number): Error | number { + let position = 0; + let time = Math.floor(sec / 10) * 10; + this.time_left = (sec - time) * 1000 || 0; + if (!this.header.segment.cues) return new Error('Failed to Parse Cues'); - for(const data of this.header.segment.cues){ - if(Math.floor(data.time as number / 1000) === time) { - position = data.position as number + for (const data of this.header.segment.cues) { + if (Math.floor((data.time as number) / 1000) === time) { + position = data.position as number; break; - } - else continue; + } else continue; } - if(position === 0) return Error("Failed to find Cluster Position") - else return position + if (position === 0) return Error('Failed to find Cluster Position'); + else return position; } _write(chunk: Buffer, _: BufferEncoding, callback: (error?: Error | null) => void): void { if (this.remaining) { - this.chunk = Buffer.concat([this.remaining, chunk]) - this.remaining = undefined - } - else this.chunk = chunk + this.chunk = Buffer.concat([this.remaining, chunk]); + this.remaining = undefined; + } else this.chunk = chunk; - let err : Error | undefined; + let err: Error | undefined; - if(this.state === WebmSeekerState.READING_HEAD) err = this.readHead() - else if(!this.seekfound) err = this.getClosetCluster() - else err = this.readTag() + if (this.state === WebmSeekerState.READING_HEAD) err = this.readHead(); + else if (!this.seekfound) err = this.getClosetCluster(); + else err = this.readTag(); - if(err) callback(err) - else callback() + if (err) callback(err); + else callback(); } - private readHead(): Error | undefined{ - if (!this.chunk) return new Error("Chunk is missing") - - while(this.chunk.length > this.cursor ){ - const oldCursor = this.cursor - const id = this.vint_length - if(this.chunk.length < this.cursor + id) break; + private readHead(): Error | undefined { + if (!this.chunk) return new Error('Chunk is missing'); - const ebmlID = this.parseEbmlID(this.chunk.slice(this.cursor, this.cursor + id).toString('hex')) - this.cursor += id - const vint = this.vint_value + while (this.chunk.length > this.cursor) { + const oldCursor = this.cursor; + const id = this.vint_length; + if (this.chunk.length < this.cursor + id) break; - if(!vint) { - this.cursor = oldCursor - break; - } - if(!ebmlID){ - this.cursor += this.data_size + this.data_length - continue; - } + const ebmlID = this.parseEbmlID(this.chunk.slice(this.cursor, this.cursor + id).toString('hex')); + this.cursor += id; + const vint = this.vint_value; - if(!this.headfound){ - if(ebmlID.name === "ebml") this.headfound = true - else return new Error("Failed to find EBML ID at start of stream.") - } - const data = this.chunk.slice(this.cursor + this.data_size, this.cursor + this.data_size + this.data_length) - const parse = this.header.parse(ebmlID, data) - if(parse instanceof Error) return parse - - if(ebmlID.type === DataType.master) { - this.cursor += this.data_size - continue; - } - - if(this.chunk.length < this.cursor + this.data_size + this.data_length) { + if (!vint) { this.cursor = oldCursor; break; } - else this.cursor += this.data_size + this.data_length + if (!ebmlID) { + this.cursor += this.data_size + this.data_length; + continue; + } + + if (!this.headfound) { + if (ebmlID.name === 'ebml') this.headfound = true; + else return new Error('Failed to find EBML ID at start of stream.'); + } + const data = this.chunk.slice( + this.cursor + this.data_size, + this.cursor + this.data_size + this.data_length + ); + const parse = this.header.parse(ebmlID, data); + if (parse instanceof Error) return parse; + + if (ebmlID.type === DataType.master) { + this.cursor += this.data_size; + continue; + } + + if (this.chunk.length < this.cursor + this.data_size + this.data_length) { + this.cursor = oldCursor; + break; + } else this.cursor += this.data_size + this.data_length; } - this.remaining = this.chunk.slice(this.cursor) - this.cursor = 0 + this.remaining = this.chunk.slice(this.cursor); + this.cursor = 0; } - private readTag(): Error | undefined{ - if (!this.chunk) return new Error("Chunk is missing") - - while(this.chunk.length > this.cursor ){ - const oldCursor = this.cursor - const id = this.vint_length - if(this.chunk.length < this.cursor + id) break; + private readTag(): Error | undefined { + if (!this.chunk) return new Error('Chunk is missing'); - const ebmlID = this.parseEbmlID(this.chunk.slice(this.cursor, this.cursor + id).toString('hex')) - this.cursor += id - const vint = this.vint_value + while (this.chunk.length > this.cursor) { + const oldCursor = this.cursor; + const id = this.vint_length; + if (this.chunk.length < this.cursor + id) break; - if(!vint) { - this.cursor = oldCursor - break; - } - if(!ebmlID){ - this.cursor += this.data_size + this.data_length - continue; - } + const ebmlID = this.parseEbmlID(this.chunk.slice(this.cursor, this.cursor + id).toString('hex')); + this.cursor += id; + const vint = this.vint_value; - const data = this.chunk.slice(this.cursor + this.data_size, this.cursor + this.data_size + this.data_length) - const parse = this.header.parse(ebmlID, data) - if(parse instanceof Error) return parse - - if(ebmlID.type === DataType.master) { - this.cursor += this.data_size - continue; - } - - if(this.chunk.length < this.cursor + this.data_size + this.data_length) { + if (!vint) { this.cursor = oldCursor; break; } - else this.cursor += this.data_size + this.data_length + if (!ebmlID) { + this.cursor += this.data_size + this.data_length; + continue; + } - if(ebmlID.name === 'simpleBlock'){ - if(this.time_left !== 0 && this.mode === "precise"){ - if(data.readUInt16BE(1) === this.time_left) this.time_left = 0 + const data = this.chunk.slice( + this.cursor + this.data_size, + this.cursor + this.data_size + this.data_length + ); + const parse = this.header.parse(ebmlID, data); + if (parse instanceof Error) return parse; + + if (ebmlID.type === DataType.master) { + this.cursor += this.data_size; + continue; + } + + if (this.chunk.length < this.cursor + this.data_size + this.data_length) { + this.cursor = oldCursor; + break; + } else this.cursor += this.data_size + this.data_length; + + if (ebmlID.name === 'simpleBlock') { + if (this.time_left !== 0 && this.mode === 'precise') { + if (data.readUInt16BE(1) === this.time_left) this.time_left = 0; else continue; } - const track = this.header.segment.tracks![this.header.audioTrack] - if(!track || track.trackType !== 2) return new Error("No audio Track in this webm file.") - if((data[0] & 0xf) === track.trackNumber) this.push(data.slice(4)) + const track = this.header.segment.tracks![this.header.audioTrack]; + if (!track || track.trackType !== 2) return new Error('No audio Track in this webm file.'); + if ((data[0] & 0xf) === track.trackNumber) this.push(data.slice(4)); } } - this.remaining = this.chunk.slice(this.cursor) - this.cursor = 0 + this.remaining = this.chunk.slice(this.cursor); + this.cursor = 0; } - private getClosetCluster(): Error | undefined{ - if(!this.chunk) return new Error("Chunk is missing") - const count = this.chunk.indexOf('1f43b675', 0, 'hex') - if(count === -1) throw new Error("Failed to find nearest Cluster.") - else this.chunk = this.chunk.slice(count) - this.seekfound = true - return this.readTag() + private getClosetCluster(): Error | undefined { + if (!this.chunk) return new Error('Chunk is missing'); + const count = this.chunk.indexOf('1f43b675', 0, 'hex'); + if (count === -1) throw new Error('Failed to find nearest Cluster.'); + else this.chunk = this.chunk.slice(count); + this.seekfound = true; + return this.readTag(); } - private parseEbmlID(ebmlID : string){ - if(Object.keys(WebmElements).includes(ebmlID)) return WebmElements[ebmlID] - else return false + private parseEbmlID(ebmlID: string) { + if (Object.keys(WebmElements).includes(ebmlID)) return WebmElements[ebmlID]; + else return false; } - _destroy(error : Error | null, callback : (error : Error | null) => void) : void { - this.cleanup() + _destroy(error: Error | null, callback: (error: Error | null) => void): void { + this.cleanup(); callback(error); } @@ -219,4 +226,4 @@ export class WebmSeeker extends Duplex{ this.cleanup(); callback(); } -} \ No newline at end of file +} diff --git a/play-dl/YouTube/stream.ts b/play-dl/YouTube/stream.ts index c67e745..cfc9d9d 100644 --- a/play-dl/YouTube/stream.ts +++ b/play-dl/YouTube/stream.ts @@ -12,8 +12,8 @@ export enum StreamType { } export interface StreamOptions { - seekMode? : "precise" | "granular" - seek? : number + seekMode?: 'precise' | 'granular'; + seek?: number; quality?: number; htmldata?: boolean; } @@ -80,25 +80,25 @@ 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; - if(options.seek){ - if(type === StreamType.WebmOpus) { - if(options.seek >= info.video_details.durationInSec) throw new Error(`Seeking beyond limit. [0 - ${info.video_details.durationInSec - 1}]`) + if (options.seek) { + if (type === StreamType.WebmOpus) { + if (options.seek >= info.video_details.durationInSec || options.seek <= 0) + throw new Error(`Seeking beyond limit. [ 1 - ${info.video_details.durationInSec - 1}]`); return new SeekStream( final[0].url, info.video_details.durationInSec, Number(final[0].contentLength), info.video_details.url, options - ) - } - else throw new Error("Seek is only supported in Webm Opus Files.") - } - else return new Stream( - final[0].url, - type, - info.video_details.durationInSec, - Number(final[0].contentLength), - info.video_details.url, - options - ); + ); + } else throw new Error('Seek is only supported in Webm Opus Files.'); + } else + return new Stream( + final[0].url, + type, + info.video_details.durationInSec, + Number(final[0].contentLength), + info.video_details.url, + options + ); } diff --git a/play-dl/YouTube/utils/extractor.ts b/play-dl/YouTube/utils/extractor.ts index f4a5294..924f9f3 100644 --- a/play-dl/YouTube/utils/extractor.ts +++ b/play-dl/YouTube/utils/extractor.ts @@ -327,12 +327,12 @@ export async function decipher_info(data: T */ export async function playlist_info(url: string, options: PlaylistOptions = {}): Promise { if (!url || typeof url !== 'string') throw new Error(`Expected playlist url, received ${typeof url}!`); - 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 (!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}` + if (yt_validate(url) === 'playlist') { + const id = extractID(url); + url = `https://www.youtube.com/playlist?list=${id}`; } const body = await request(url, { @@ -353,10 +353,9 @@ export async function playlist_info(url: string, options: PlaylistOptions = {}): throw new Error(`While parsing playlist url\n${response.alerts[0].alertRenderer.text.runs[0].text}`); else throw new Error('While parsing playlist url\nUnknown Playlist Error'); } - if(url.indexOf('watch?v=') !== -1){ - return getWatchPlaylist(response, body) - } - else return getNormalPlaylist(response, body) + if (url.indexOf('watch?v=') !== -1) { + return getWatchPlaylist(response, body); + } else return getNormalPlaylist(response, body); } /** * Function to parse Playlist from YouTube search @@ -377,7 +376,7 @@ export function getPlaylistVideos(data: any, limit = Infinity): YouTubeVideo[] { id: info.videoId, duration: parseInt(info.lengthSeconds) || 0, duration_raw: info.lengthText?.simpleText ?? '0:00', - thumbnails : info.thumbnail.thumbnails, + thumbnails: info.thumbnail.thumbnails, title: info.title.runs[0].text, channel: { id: info.shortBylineText.runs[0].navigationEndpoint.browseEndpoint.browseId || undefined, @@ -403,19 +402,18 @@ export function getContinuationToken(data: any): string { .continuationEndpoint?.continuationCommand?.token; } +function getWatchPlaylist(response: any, body: any): YouTubePlayList { + const playlist_details = response.contents.twoColumnWatchNextResults.playlist.playlist; -function getWatchPlaylist(response : any, body : any) : YouTubePlayList{ - const playlist_details = response.contents.twoColumnWatchNextResults.playlist.playlist - - const videos = getWatchPlaylistVideos(playlist_details.contents) + const videos = getWatchPlaylistVideos(playlist_details.contents); const API_KEY = body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ?? body.split('innertubeApiKey":"')[1]?.split('"')[0] ?? DEFAULT_API_KEY; - - const videoCount = playlist_details.totalVideos - const channel = playlist_details.shortBylineText?.runs?.[0] - const badge = playlist_details.badges?.[0]?.metadataBadgeRenderer?.style.toLowerCase() + + const videoCount = playlist_details.totalVideos; + const channel = playlist_details.shortBylineText?.runs?.[0]; + const badge = playlist_details.badges?.[0]?.metadataBadgeRenderer?.style.toLowerCase(); return new YouTubePlayList({ continuation: { @@ -426,12 +424,12 @@ function getWatchPlaylist(response : any, body : any) : YouTubePlayList{ body.split('"innertube_context_client_version":"')[1]?.split('"')[0] ?? '' }, - id : playlist_details.playlistId || '', - title : playlist_details.title || '', - videoCount : parseInt(videoCount) || 0, - videos : videos, - url : `https://www.youtube.com/playlist?list=${playlist_details.playlistId}`, - channel : { + id: playlist_details.playlistId || '', + title: playlist_details.title || '', + videoCount: parseInt(videoCount) || 0, + videos: videos, + url: `https://www.youtube.com/playlist?list=${playlist_details.playlistId}`, + channel: { id: channel?.navigationEndpoint?.browseEndpoint?.browseId || null, name: channel?.text || null, url: `https://www.youtube.com${ @@ -441,12 +439,13 @@ function getWatchPlaylist(response : any, body : any) : YouTubePlayList{ verified: Boolean(badge?.includes('verified')), artist: Boolean(badge?.includes('artist')) } - }) + }); } -function getNormalPlaylist(response : any, body : any): YouTubePlayList{ - - const json_data = response.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents[0].itemSectionRenderer.contents[0].playlistVideoListRenderer.contents; +function getNormalPlaylist(response: any, body: any): YouTubePlayList { + const json_data = + response.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents[0] + .itemSectionRenderer.contents[0].playlistVideoListRenderer.contents; const playlist_details = response.sidebar.playlistSidebarRenderer.items; const API_KEY = @@ -507,21 +506,21 @@ function getNormalPlaylist(response : any, body : any): YouTubePlayList{ return res; } -function getWatchPlaylistVideos(data : any, limit = Infinity): YouTubeVideo[] { - const videos: YouTubeVideo[] = [] +function getWatchPlaylistVideos(data: any, limit = Infinity): YouTubeVideo[] { + const videos: YouTubeVideo[] = []; - for(let i = 0; i < data.length ; i++) { - if(limit === videos.length) break; + for (let i = 0; i < data.length; i++) { + if (limit === videos.length) break; const info = data[i].playlistPanelVideoRenderer; - if(!info || !info.shortBylineText) continue; - const channel_info = info.shortBylineText.runs[0] + if (!info || !info.shortBylineText) continue; + const channel_info = info.shortBylineText.runs[0]; videos.push( new YouTubeVideo({ id: info.videoId, duration: parseDuration(info.lengthText?.simpleText) || 0, duration_raw: info.lengthText?.simpleText ?? '0:00', - thumbnails : info.thumbnail.thumbnails, + thumbnails: info.thumbnail.thumbnails, title: info.title.simpleText, channel: { id: channel_info.navigationEndpoint.browseEndpoint.browseId || undefined, @@ -536,21 +535,21 @@ function getWatchPlaylistVideos(data : any, limit = Infinity): YouTubeVideo[] { ); } - return videos + return videos; } -function parseDuration(text : string): number{ - if(!text) return 0 - const split = text.split(':') +function parseDuration(text: string): number { + if (!text) return 0; + const split = text.split(':'); - switch (split.length){ + switch (split.length) { case 2: - return (parseInt(split[0]) * 60) + (parseInt(split[1])) - - case 3: - return (parseInt(split[0]) * 60 * 60) + (parseInt(split[1]) * 60) + (parseInt(split[2])) + return parseInt(split[0]) * 60 + parseInt(split[1]); - default : - return 0 + case 3: + return parseInt(split[0]) * 60 * 60 + parseInt(split[1]) * 60 + parseInt(split[2]); + + default: + return 0; } -} \ No newline at end of file +}