From 9d946a84a6c081d7504d04a75669e5944e6e5c16 Mon Sep 17 00:00:00 2001 From: killer069 <65385476+killer069@users.noreply.github.com> Date: Tue, 28 Sep 2021 19:20:58 +0530 Subject: [PATCH] Proxy support added completely --- play-dl/YouTube/classes/LiveStream.ts | 2 +- play-dl/YouTube/utils/request.ts | 129 +++++++++++++++++++++++--- 2 files changed, 116 insertions(+), 15 deletions(-) diff --git a/play-dl/YouTube/classes/LiveStream.ts b/play-dl/YouTube/classes/LiveStream.ts index 0c32f9a..0dec6ff 100644 --- a/play-dl/YouTube/classes/LiveStream.ts +++ b/play-dl/YouTube/classes/LiveStream.ts @@ -47,7 +47,7 @@ export class LiveStreaming { if ( info.LiveStreamData.isLive === true && info.LiveStreamData.hlsManifestUrl !== null && - info.video_details.durationInSec === '0' + info.video_details.durationInSec === 0 ) { this.url = info.LiveStreamData.dashManifestUrl; } diff --git a/play-dl/YouTube/utils/request.ts b/play-dl/YouTube/utils/request.ts index ea972d6..1d065b3 100644 --- a/play-dl/YouTube/utils/request.ts +++ b/play-dl/YouTube/utils/request.ts @@ -1,7 +1,10 @@ import https, { RequestOptions } from 'https'; -import { IncomingMessage } from 'http'; +import tls from 'tls'; +import http , { ClientRequest, IncomingMessage } from 'http'; import { URL } from 'url'; +export type Proxy = ProxyOpts | string + interface ProxyOpts { host : string, port : number, @@ -11,10 +14,16 @@ interface ProxyOpts { } } +interface ProxyOutput { + statusCode : number; + head : string; + body : string; +} + interface RequestOpts extends RequestOptions { body?: string; method?: 'GET' | 'POST'; - proxies? : string[] | ProxyOpts[] + proxies? : Proxy[] } function https_getter(req_url: string, options: RequestOpts = {}): Promise { @@ -37,22 +46,114 @@ function https_getter(req_url: string, options: RequestOpts = {}): Promise{ + return new Promise((resolve, reject) => { + const proxy : string | ProxyOpts = req_proxy[randomIntFromInterval(0, req_proxy.length)] + const parsed_url = new URL(req_url) + let opts : ProxyOpts + if(typeof proxy === 'string'){ + const parsed = new URL(proxy) + opts = { + host : parsed.hostname, + port : Number(parsed.port), + authentication : { + username : parsed.username, + password : parsed.password + } + } + } + else opts = proxy + let req : ClientRequest + if(opts.authentication?.username.length === 0){ + req = http.request({ + host: opts.host, + port: opts.port, + method: 'CONNECT', + path: `${parsed_url.host}:443`, + }); + } + else { + req = http.request({ + host: opts.host, + port: opts.port, + method: 'CONNECT', + path: `${parsed_url.host}:443`, + headers : { + "Proxy-Authorization" : `Basic ${Buffer.from(`${opts.authentication?.username}:${opts.authentication?.password}`).toString('base64')}` + } + }); + } + + req.on('connect', function (res, socket, head) { + console.log('Connected') + const tlsConnection = tls.connect({ + host : parsed_url.hostname, + port : 443, + socket : socket, + rejectUnauthorized : false + }, function() { + tlsConnection.write(`GET ${parsed_url.pathname}${parsed_url.search} HTTP/1.1\r\n` + + `Host : ${parsed_url.hostname}\r\n` + + 'Connection: close\r\n' + + '\r\n') + }) + + tlsConnection.setEncoding('utf-8') + let data = '' + tlsConnection.once('error', (e) => reject(e)) + tlsConnection.on('data', (c) => data+=c) + tlsConnection.on('end', () => { + const y = data.split('\r\n\r\n') + const head = y.shift() as string + resolve({ + statusCode : Number(head.split('\n')[0].split(' ')[1]), + head : head, + body : y.join('\n') + }) + }) + }) + req.on('error', (e : Error) => reject(e)) + req.end() + }) +} + export async function request(url: string, options?: RequestOpts): Promise { return new Promise(async (resolve, reject) => { - let data = ''; - let res = await https_getter(url, options).catch((err: Error) => err); - if (res instanceof Error) { - reject(res); - return; + if(!options?.proxies){ + let data = ''; + let res = await https_getter(url, options).catch((err: Error) => err); + if (res instanceof Error) { + reject(res); + return; + } + if (Number(res.statusCode) >= 300 && Number(res.statusCode) < 400) { + res = await https_getter(res.headers.location as string, options); + } else if (Number(res.statusCode) > 400) { + reject(new Error(`Got ${res.statusCode} from the request`)); + } + res.setEncoding('utf-8'); + res.on('data', (c) => (data += c)); + res.on('end', () => resolve(data)); } - if (Number(res.statusCode) >= 300 && Number(res.statusCode) < 400) { - res = await https_getter(res.headers.location as string, options); - } else if (Number(res.statusCode) > 400) { - reject(new Error(`Got ${res.statusCode} from the request`)); + else { + let res = await proxy_getter(url, options.proxies).catch((e : Error) => e) + if (res instanceof Error) { + reject(res); + return; + } + if(res.statusCode >= 300 && res.statusCode < 400){ + res = await proxy_getter(res.head.split('Location: ')[1].split('\n')[0], options.proxies) + } else if (res.statusCode > 400){ + reject(new Error(`GOT ${res.statusCode} from proxy request`)) + } + resolve(res.body) } - res.setEncoding('utf-8'); - res.on('data', (c) => (data += c)); - res.on('end', () => resolve(data)); }); }