@@ -131,7 +131,14 @@ public URI resolveFormatUrl(@NotNull HttpInterface httpInterface, @NotNull Strin
131131
132132 if (!DataFormatTools .isNullOrEmpty (nParameter )) {
133133 try {
134- uri .setParameter ("n" , cipher .transform (nParameter , scriptEngine ));
134+ String transformed = cipher .transform (nParameter , scriptEngine );
135+
136+ if (nParameter .equals (transformed )) {
137+ log .warn ("Transformed n parameter is the same as input, n function possibly short-circuited (in: {}, out: {}, player script: {}, source version: {}" ,
138+ nParameter , transformed , playerScript , YoutubeSource .VERSION );
139+ }
140+
141+ uri .setParameter ("n" , transformed );
135142 } catch (ScriptException | NoSuchMethodException e ) {
136143 // URLs can still be played without a resolved n parameter. It just means they're
137144 // throttled. But we shouldn't throw an exception anyway as it's not really fatal.
@@ -267,7 +274,12 @@ private SignatureCipher extractFromScript(@NotNull String script, @NotNull Strin
267274 throw new IllegalStateException ("Must find n function from script: " + sourceUrl );
268275 }
269276
270- SignatureCipher cipherKey = new SignatureCipher (nFunctionMatcher .group (0 ), scriptTimestamp .group (2 ), script );
277+ String nFunction = nFunctionMatcher .group (0 );
278+ String nfParameterName = DataFormatTools .extractBetween (nFunction , "(" , ")" );
279+ // remove short-circuit that prevents n challenge transformation
280+ nFunction = nFunction .replaceAll ("if\\ s*\\ (typeof\\ s*\\ w+\\ s*===?.*?\\ )return " + nfParameterName + "\\ s*;?" , "" );
281+
282+ SignatureCipher cipherKey = new SignatureCipher (nFunction , scriptTimestamp .group (2 ), script );
271283
272284 while (matcher .find ()) {
273285 String type = matcher .group (1 );
0 commit comments