@@ -201,6 +201,7 @@ private YoutubeParsingHelper() {
201201 private static String [] youtubeMusicKey ;
202202
203203 private static boolean keyAndVersionExtracted = false ;
204+ private static final Object KEY_AND_VERSION_EXTRACTED_LOCK = new Object ();
204205 @ SuppressWarnings ("OptionalUsedAsFieldOrParameterType" )
205206 private static Optional <Boolean > hardcodedClientVersionAndKeyValid = Optional .empty ();
206207
@@ -619,82 +620,89 @@ public static boolean areHardcodedClientVersionAndKeyValid()
619620
620621 private static void extractClientVersionAndKeyFromSwJs ()
621622 throws IOException , ExtractionException {
622- if (keyAndVersionExtracted ) {
623- return ;
624- }
625- final String url = "https://www.youtube.com/sw.js" ;
626- final Map <String , List <String >> headers = new HashMap <>();
627- headers .put ("Origin" , singletonList ("https://www.youtube.com" ));
628- headers .put ("Referer" , singletonList ("https://www.youtube.com" ));
629- final String response = getDownloader ().get (url , headers ).responseBody ();
630- try {
631- clientVersion = getStringResultFromRegexArray (response ,
632- INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES , 1 );
633- key = getStringResultFromRegexArray (response , INNERTUBE_API_KEY_REGEXES , 1 );
634- } catch (final Parser .RegexException e ) {
635- throw new ParsingException ("Could not extract YouTube WEB InnerTube client version "
636- + "and API key from sw.js" , e );
623+ synchronized (KEY_AND_VERSION_EXTRACTED_LOCK ) {
624+ if (keyAndVersionExtracted ) {
625+ return ;
626+ }
627+ final String url = "https://www.youtube.com/sw.js" ;
628+ final Map <String , List <String >> headers = new HashMap <>();
629+ headers .put ("Origin" , singletonList ("https://www.youtube.com" ));
630+ headers .put ("Referer" , singletonList ("https://www.youtube.com" ));
631+ final String response = getDownloader ().get (url , headers ).responseBody ();
632+ try {
633+ clientVersion = getStringResultFromRegexArray (response ,
634+ INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES , 1 );
635+ key = getStringResultFromRegexArray (response , INNERTUBE_API_KEY_REGEXES , 1 );
636+ } catch (final Parser .RegexException e ) {
637+ throw new ParsingException ("Could not extract YouTube WEB InnerTube client version "
638+ + "and API key from sw.js" , e );
639+ }
640+ keyAndVersionExtracted = true ;
637641 }
638- keyAndVersionExtracted = true ;
639642 }
640643
641644 private static void extractClientVersionAndKeyFromHtmlSearchResultsPage ()
642645 throws IOException , ExtractionException {
643- // Don't extract the client version and the InnerTube key if it has been already extracted
644- if (keyAndVersionExtracted ) {
645- return ;
646- }
647646
648- // Don't provide a search term in order to have a smaller response
649- final String url = "https://www.youtube.com/results?search_query=&ucbcb=1" ;
650- final String html = getDownloader ().get (url , getCookieHeader ()).responseBody ();
651- final JsonObject initialData = getInitialData (html );
652- final JsonArray serviceTrackingParams = initialData .getObject ("responseContext" )
653- .getArray ("serviceTrackingParams" );
647+ synchronized (KEY_AND_VERSION_EXTRACTED_LOCK ) {
654648
655- // Try to get version from initial data first
656- final Stream <JsonObject > serviceTrackingParamsStream = serviceTrackingParams .stream ()
657- .filter (JsonObject .class ::isInstance )
658- .map (JsonObject .class ::cast );
649+ // Don't extract the client version and the InnerTube key
650+ // if it has been already extracted
651+ if (keyAndVersionExtracted ) {
652+ return ;
653+ }
659654
660- clientVersion = getClientVersionFromServiceTrackingParam (
661- serviceTrackingParamsStream , "CSI" , "cver" );
655+ // Don't provide a search term in order to have a smaller response
656+ final String url = "https://www.youtube.com/results?search_query=&ucbcb=1" ;
657+ final String html = getDownloader ().get (url , getCookieHeader ()).responseBody ();
658+ final JsonObject initialData = getInitialData (html );
659+ final JsonArray serviceTrackingParams = initialData .getObject ("responseContext" )
660+ .getArray ("serviceTrackingParams" );
661+
662+ // Try to get version from initial data first
663+ final Stream <JsonObject > serviceTrackingParamsStream = serviceTrackingParams .stream ()
664+ .filter (JsonObject .class ::isInstance )
665+ .map (JsonObject .class ::cast );
666+
667+ clientVersion = getClientVersionFromServiceTrackingParam (
668+ serviceTrackingParamsStream , "CSI" , "cver" );
669+
670+ if (clientVersion == null ) {
671+ try {
672+ clientVersion = getStringResultFromRegexArray (html ,
673+ INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES , 1 );
674+ } catch (final Parser .RegexException ignored ) {
675+ }
676+ }
677+
678+ // Fallback to get a shortened client version which does not contain the last two
679+ // digits
680+ if (isNullOrEmpty (clientVersion )) {
681+ clientVersion = getClientVersionFromServiceTrackingParam (
682+ serviceTrackingParamsStream , "ECATCHER" , "client.version" );
683+ }
662684
663- if (clientVersion == null ) {
664685 try {
665- clientVersion = getStringResultFromRegexArray (html ,
666- INNERTUBE_CONTEXT_CLIENT_VERSION_REGEXES , 1 );
686+ key = getStringResultFromRegexArray (html , INNERTUBE_API_KEY_REGEXES , 1 );
667687 } catch (final Parser .RegexException ignored ) {
668688 }
669- }
670689
671- // Fallback to get a shortened client version which does not contain the last two
672- // digits
673- if (isNullOrEmpty (clientVersion )) {
674- clientVersion = getClientVersionFromServiceTrackingParam (
675- serviceTrackingParamsStream , "ECATCHER" , "client.version" );
676- }
677-
678- try {
679- key = getStringResultFromRegexArray (html , INNERTUBE_API_KEY_REGEXES , 1 );
680- } catch (final Parser .RegexException ignored ) {
681- }
690+ if (isNullOrEmpty (key )) {
691+ throw new ParsingException (
692+ // CHECKSTYLE:OFF
693+ "Could not extract YouTube WEB InnerTube API key from HTML search results page" );
694+ // CHECKSTYLE:ON
695+ }
682696
683- if (isNullOrEmpty ( key ) ) {
684- throw new ParsingException (
685- // CHECKSTYLE:OFF
686- "Could not extract YouTube WEB InnerTube API key from HTML search results page" );
687- // CHECKSTYLE:ON
688- }
697+ if (clientVersion == null ) {
698+ throw new ParsingException (
699+ // CHECKSTYLE:OFF
700+ "Could not extract YouTube WEB InnerTube client version from HTML search results page" );
701+ // CHECKSTYLE:ON
702+ }
689703
690- if (clientVersion == null ) {
691- throw new ParsingException (
692- // CHECKSTYLE:OFF
693- "Could not extract YouTube WEB InnerTube client version from HTML search results page" );
694- // CHECKSTYLE:ON
704+ keyAndVersionExtracted = true ;
695705 }
696-
697- keyAndVersionExtracted = true ;
698706 }
699707
700708 @ Nullable
0 commit comments