From c260225f5a631adf2751c6e2ba6261baed2a1c9b Mon Sep 17 00:00:00 2001
From: Kelvin <kelvin@futo.org>
Date: Thu, 20 Feb 2025 23:42:15 +0100
Subject: [PATCH] Cipher fix

---
 YoutubeConfig.json         |  5 ++++-
 YoutubeScript.js           | 20 ++++++++++++++++++--
 YoutubeUnstableConfig.json |  5 ++++-
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/YoutubeConfig.json b/YoutubeConfig.json
index d6a4511..15929ff 100644
--- a/YoutubeConfig.json
+++ b/YoutubeConfig.json
@@ -8,7 +8,7 @@
 	"repositoryUrl": "https://futo.org",
 	"scriptUrl": "./YoutubeScript.js",
 
-	"version": 237,
+	"version": 238,
 	"iconUrl": "./youtube.png",
 	"id": "35ae969a-a7db-11ed-afa1-0242ac120002",
 	
@@ -282,6 +282,9 @@
 
 
 	"changelog": {
+		"238": [
+			"Fix: Cipher edgecase"
+		],
 		"237": [
 			"Fix: Import Subscriptions on some accounts",
 			"Improvement: Playback tracker optimalization in certain scenarios",
diff --git a/YoutubeScript.js b/YoutubeScript.js
index 5a39ed6..e4cd9b2 100644
--- a/YoutubeScript.js
+++ b/YoutubeScript.js
@@ -5907,7 +5907,8 @@ const REGEX_CIPHERS = [
 	new RegExp("\\bc&&\\(c=([a-zA-Z0-9$]{2,})\\(decodeURIComponent\\(c\\)\\)"),
 	new RegExp("([\\w$]+)\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\(\"\"\\)\\s*;"),
 	new RegExp("\\b([\\w$]{2,})\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\(\"\"\\)\\s*;"),
-	new RegExp("\\bc\\s*&&\\s*d\\.set\\([^,]+\\s*,\\s*(:encodeURIComponent\\s*\\()([a-zA-Z0-9$]+)\\(")
+	new RegExp("\\bc\\s*&&\\s*d\\.set\\([^,]+\\s*,\\s*(:encodeURIComponent\\s*\\()([a-zA-Z0-9$]+)\\("),
+	new RegExp("([\\w$]+)\\s*=\\s*function\\((\\w+)\\)\\{\\s*\\2=\\s*\\2\\.split\\([a-z-A-Z0-9\\$_]+\\[[0-9]\\]\\)\\s*;")
 ];
 const REGEX_DECRYPT_N_VARIANTS = [
 	/\.get\(\"n\"\)\)&&\([a-zA-Z0-9$_]=([a-zA-Z0-9$_]+)(?:\[(\d+)])?\([a-zA-Z0-9$_]\)/,
@@ -6159,7 +6160,21 @@ function getCipherFunctionCode(playerCode, jsUrl) {
         if(bridge.devSubmit) bridge.devSubmit("getCipherFunctionCode - Failed to find cipher (function)", jsUrl);
 		throw new ScriptException("Failed to find cipher (function)\n" + jsUrl);
 	}
-	const cipherFunctionCode = cipherFunctionCodeMatch[1];
+	let cipherFunctionCode = cipherFunctionCodeMatch[1];
+	
+
+	//Special case..TBD if better
+	const cipherSplitJoinConstants = cipherFunctionCode.match("split\\((.*?)\\).*?join\\((.*?)\\)");
+	if(cipherSplitJoinConstants && cipherSplitJoinConstants.length > 2) {
+		const splitConstant = cipherSplitJoinConstants[1];
+		const joinConstant = cipherSplitJoinConstants[2];
+		if(splitConstant == joinConstant && splitConstant.length > 0 && splitConstant[0].match(/[a-zA-Z]/)) {
+			log("Detected split/join constant in cipher, replacing (" + splitConstant + ")");
+			cipherFunctionCode = cipherFunctionCode.replaceAll(splitConstant, "\"\"");
+		}
+	}
+
+
 	const cipherFunctionCodeVar = "var " + cipherFunctionCode;
 	const helperObjNameMatch = cipherFunctionCode.match(";([A-Za-z0-9_\\$]{2,3})\\...\\(");
 	if(!helperObjNameMatch) {
@@ -6185,6 +6200,7 @@ function getCipherFunctionCode(playerCode, jsUrl) {
 		cipherFunctionCodeVar + "\n" +
 		functionCode + "})()";
 }
+source.getCipherFunctionCode = getCipherFunctionCode;
 function escapeRegex(str) {
 	return str?.replace("$", "\\$");
 }
diff --git a/YoutubeUnstableConfig.json b/YoutubeUnstableConfig.json
index 79edb0c..36ea38c 100644
--- a/YoutubeUnstableConfig.json
+++ b/YoutubeUnstableConfig.json
@@ -8,7 +8,7 @@
 	"repositoryUrl": "https://futo.org",
 	"scriptUrl": "./YoutubeScript.js",
 
-	"version": 237,
+	"version": 238,
 	"iconUrl": "./youtube.png",
 	"id": "35ae969a-a7db-11ed-afa1-0242ac120003",
 	
@@ -281,6 +281,9 @@
 	"primaryClaimFieldType": 1,
 	
 	"changelog": {
+		"238": [
+			"Fix: Cipher edgecase"
+		],
 		"237": [
 			"Fix: Import Subscriptions on some accounts",
 			"Improvement: Playback tracker optimalization in certain scenarios",
-- 
GitLab