11using System ;
22using System . Linq ;
3- using System . Text ;
3+ using System . Net . Http ;
4+ using System . Net . Http . Headers ;
5+ using System . Text . Json ;
6+ using System . Threading . Tasks ;
47using YoutubeExplode . Utils ;
58using YoutubeExplode . Utils . Extensions ;
69
@@ -11,6 +14,7 @@ internal static class VisitorData
1114 private static readonly Random Random = new ( ) ;
1215 private static readonly char [ ] SessionIdAllowedChars =
1316 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" . ToCharArray ( ) ;
17+ private static string _visitorData = string . Empty ;
1418
1519 public static string Generate ( ) =>
1620 new ProtoBuilder ( )
@@ -36,4 +40,53 @@ public static string Generate() =>
3640 . ToBytes ( )
3741 )
3842 . ToUrlEncodedBase64 ( ) ;
43+
44+ public static async Task < string > ExtractFromYoutube ( HttpClient http )
45+ {
46+ //avoid fetching visitor data for each request (?) could slow down the app
47+ if ( ! string . IsNullOrEmpty ( _visitorData ) )
48+ return _visitorData ;
49+
50+ //use the same iOS user agent (?) idk if it's necessary
51+ http . DefaultRequestHeaders . UserAgent . ParseAdd (
52+ "com.google.ios.youtube/19.45.4 (iPhone16,2; U; CPU iOS 18_1_0 like Mac OS X; US)"
53+ ) ;
54+
55+ //request JSON format
56+ http . DefaultRequestHeaders . Accept . Add (
57+ new MediaTypeWithQualityHeaderValue ( "application/json" )
58+ ) ;
59+
60+ var url = "https://www.youtube.com/sw.js_data" ;
61+ HttpResponseMessage response = await http . GetAsync ( url ) ;
62+ response . EnsureSuccessStatusCode ( ) ;
63+ string jsonString = await response . Content . ReadAsStringAsync ( ) ;
64+
65+ //Remove the prefix ")]}'"
66+ if ( jsonString . StartsWith ( ")]}'" ) )
67+ jsonString = jsonString . Substring ( 4 ) ;
68+
69+ using ( JsonDocument doc = JsonDocument . Parse ( jsonString ) )
70+ {
71+ JsonElement root = doc . RootElement ;
72+
73+ //jsonArray[0][2][0][0][13]
74+ var value = root [ 0 ]
75+ . EnumerateArray ( )
76+ . ElementAt ( 2 )
77+ . EnumerateArray ( )
78+ . ElementAt ( 0 )
79+ . EnumerateArray ( )
80+ . ElementAt ( 0 )
81+ . EnumerateArray ( )
82+ . ElementAt ( 13 )
83+ . GetString ( ) ;
84+
85+ if ( value == null )
86+ throw new Exception ( "Failed to fetch visitor data" ) ;
87+
88+ _visitorData = value ;
89+ }
90+ return _visitorData ;
91+ }
3992}
0 commit comments