aboutsummaryrefslogtreecommitdiffstats
path: root/src/server/YoutubeFallback.hx
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/YoutubeFallback.hx')
-rw-r--r--src/server/YoutubeFallback.hx142
1 files changed, 0 insertions, 142 deletions
diff --git a/src/server/YoutubeFallback.hx b/src/server/YoutubeFallback.hx
deleted file mode 100644
index 5360283..0000000
--- a/src/server/YoutubeFallback.hx
+++ /dev/null
@@ -1,142 +0,0 @@
-package server;
-
-import haxe.Json;
-import js.lib.Function;
-import js.lib.Object;
-import js.lib.Promise;
-import js.node.Https.Https;
-import js.node.Https.HttpsRequestOptions;
-import js.node.url.URLSearchParams;
-import utils.YoutubeUtils;
-
-class YoutubeFallback {
- static function httpsGet(
- url:String,
- ?options:HttpsRequestOptions,
- ?callback:(status:Int, data:String) -> Void
- ):Void {
- final request = Https.get(url, options, res -> {
- var data = "";
- res.on("data", chunk -> data += chunk.toString());
- res.on("end", () -> callback(res.statusCode, data));
- });
- request.on("error", err -> {
- trace(url);
- trace("request error: ", err);
- });
- }
-
- public static function resolvePlayerResponse(watchHtml:String):String {
- if (watchHtml == null) return "";
- final resReg = ~/ytInitialPlayerResponse = (.*)}}};/;
- var matches = resReg.match(watchHtml);
- return matches ? resReg.matched(1) + "}}}" : "";
- }
-
- public static function resoleM3U8Link(watchHtml:String):Null<String> {
- if (watchHtml == null) return null;
- final hlsReg = ~/hlsManifestUrl":"(.*\/file\/index\.m3u8)/;
- return hlsReg.match(watchHtml) ? hlsReg.matched(1) : null;
- }
-
- public static function buildDecoder(watchHtml:String, callback:(decoder:(cipher:String) -> String) -> Void):Void {
- if (watchHtml == null) return callback(null);
-
- final jsFileUrlReg = ~/\/s\/player\/[A-Za-z0-9]+\/[A-Za-z0-9_.]+\/[A-Za-z0-9_]+\/base\.js/;
- if (!jsFileUrlReg.match(watchHtml)) return callback(null);
-
- final url = "https://www.youtube.com" + jsFileUrlReg.matched(0);
- httpsGet(url, {}, (status, jsFileContent) -> {
- final funcReg = ~/function.*\.split\(""\).*\.join\(""\)}/;
- if (!funcReg.match(jsFileContent)) return callback(null);
-
- final decodeFunction = funcReg.matched(0);
- final varNameReg = ~/\.split\(""\);([a-zA-Z0-9]+)\./i;
- if (!varNameReg.match(decodeFunction)) return callback(null);
-
- final varStartIndex = jsFileContent.indexOf("var " + varNameReg.matched(1) + "={");
- if (varStartIndex < 0) return callback(null);
-
- final varEndIndex = jsFileContent.indexOf("}};", varStartIndex);
- if (varEndIndex < 0) return callback(null);
-
- final varDeclares = jsFileContent.substring(varStartIndex, varEndIndex + 3);
- if (varDeclares.length == 0) return callback(null);
-
- callback(signatureCipher -> {
- final params = new URLSearchParams(signatureCipher);
- final obj = Object.fromEntries(params);
- final signature = obj.s;
- final signatureParam = obj.sp ?? "signature";
- final url = obj.url;
- final decodedSignature = new Function('
- "use strict";
- $varDeclares
- return ($decodeFunction)("$signature");
- ').call(null);
- return '$url&$signatureParam=${untyped encodeURIComponent(decodedSignature)}';
- });
- });
- }
-
- public static function getInfo(url:String, callback:(info:Null<YouTubeVideoInfo>) -> Void):Void {
- final videoId = YoutubeUtils.extractVideoId(url);
- if (videoId.length == 0) {
- trace("youtube videoId is not found");
- return callback(null);
- }
-
- final url = 'https://www.youtube.com/watch?v=$videoId';
- httpsGet(url, {}, (status, data) -> {
- if (status != 200 || data.length == 0) {
- trace("Cannot get youtube video response");
- return callback(null);
- }
-
- final ytInitialPlayerResponse = resolvePlayerResponse(data);
- final parsedResponse = Json.parse(ytInitialPlayerResponse);
- final streamingData:YouTubeVideoInfo = parsedResponse.streamingData ?? cast {};
- streamingData.formats ??= [];
- streamingData.adaptiveFormats ??= [];
- var formats:Array<YoutubeVideoFormat> = streamingData.formats.concat(streamingData.adaptiveFormats);
-
- final promises:Array<Promise<Any>> = [];
-
- final isEncryptedVideo = formats.exists(it -> it.signatureCipher != null);
- if (isEncryptedVideo) {
- final promise = new Promise((resolve, reject) -> {
- buildDecoder(data, decoder -> {
- if (decoder != null) {
- formats = formats.map(item -> {
- if (item.url != null || item.signatureCipher == null) return item;
-
- item.url = decoder(item.signatureCipher);
- item.signatureCipher = null;
- return item;
- });
- }
- resolve(null);
- });
- });
- promises.push(promise);
- }
-
- Promise.all(promises).then(_ -> {
- final result:YouTubeVideoInfo = {
- videoDetails: parsedResponse.videoDetails ?? cast {},
- formats: formats.filter(format -> format.url != null)
- };
- if (result.videoDetails.isLiveContent) {
- final m3u8Link = resoleM3U8Link(data);
- try {
- result.liveData = {
- manifestUrl: m3u8Link,
- // data: m3u8Parser.getResult()
- };
- }
- }
- callback(result);
- });
- });
- }
-}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage