为了下载ytb上的一级建造师视频

为了下载一建的视频,又不想花扶梯的钱,自然想起了cloudflare workers无服务器应用的羊毛了。
继续开薅,代码记录如下:

function urlutil(url) {
	let reg = new RegExp("^([hH][tT][tT][pP][sS]?):\/\/([^/:]+)([^?:]*)(.*)", 'i');
	let o = url.match(reg);
	return o?{href: o[0],protocol:o[1],host:o[2],pathname:o[3],search:o[4]}:false;
}

function getQueryVariable(url, variable) {
	var query = url.search.substring(1);
	var vars = query.split("&");
	for (var i=0;i {
	 event.respondWith(fetchAndApply(event.request));
});

async function fetchAndApply(request) {
    let Referer = request.headers.get('Referer');
    //反盗链
    const refs = new Array(
        '^[hH][tT][tT][pP][sS]?:\/\/([a-z0-9-]+\\.)*yaoruisheng\\.com',
    );
    
    let pass = false;
    let pattern = null;
    for (let v of refs) {
        pattern = new RegExp(v,'i');
        if (pattern.test(Referer)){
            pass = true;
            break;
        }
    }
    if (pass == false) {
        return new Response('403 Forbidden', {status: 403, statusText: 'Forbidden'});
    }

	let url = new urlutil(request.url);
	if(url.pathname.startsWith('/download/')) {
		let vid = getQueryVariable(url, 'vid');
		let q = getQueryVariable(url, 'q');
		if (q==false) q='l';
		let targetUrl = 'https://www.youtube.com/get_video_info?video_id=' + vid;
		let myHeaders = new Headers();
		myHeaders.append('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0');
		myHeaders.append('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
		myHeaders.append('Accept-Language', 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2');
		let new_request = {
			headers: myHeaders
		};
		let original_response = await fetch(targetUrl, new_request);
		let reg = /player_response=([^&]+)?/i;
		let str = reg.exec(await original_response.text());
		str = decodeURIComponent(str[1]);
		let target = JSON.parse(str);
		
		let vtitle = target.videoDetails.title.replace(/\+/g, " ");
		let vtype = target.streamingData.formats[0].mimeType;
		let vurl = target.streamingData.formats[0].url;
		let width = target.streamingData.formats[0].width;
		for (let formats of target.streamingData.formats) {
			if( (q=='l' && formats.widthwidth) ) {
				width = formats.width;
				vurl = formats.url;
				vtype = formats.mimeType;
			}
		}
		vtype = (/video\/([^;]+)?;/i.exec(vtype))[1];
		let init = {
			method: request.method,
			headers: {}
		};
		const proxyHeaders = [
			"Accept",
			"Range",
			"Accept-Encoding",
			"Accept-Language",
			"Referer",
			"User-Agent",
			"content-length",
		];
		for (let name of proxyHeaders) {
			let value = request.headers.get(name);
			if (value) {
				init.headers[name] = value;
			}
		}
		original_response = await fetch(vurl, init);
		//return new Response(JSON.stringify(original_response,null,4));
		return original_response;
		if(original_response){
			const responseHeaders = [
				"Content-Type",
				"Cache-Control",
				"Expires",
				"Accept-Ranges",
				"Date",
				"Last-Modified",
				"ETag"
			];
			let responseInit = {
				status: original_response.status,
				tatusText: original_response.statusText,
				headers: {}
			};
			for (let name of responseHeaders) {
				let value = original_response.headers.get(name);
				if (value) {
					responseInit.headers[name] = value;
				}
			}
			responseInit.headers['Content-Disposition'] = 'attachment; filename="' + vtitle + '.' + vtype + '"';
			const newResponse = new Response(original_response.body, responseInit);
			return newResponse;
		}

		return original_response;
	}
	return new Response('Error 404 Not Found', {status: 404, statusText: 'Not Found'});
}