2
2
3
3
import androidx .annotation .NonNull ;
4
4
import app .revanced .extension .shared .Logger ;
5
- import app .revanced .extension .spotify .clienttoken .data .v0 .ClienttokenHttp ;
5
+ import app .revanced .extension .spotify .clienttoken .data .v0 .ClienttokenHttp .* ;
6
6
import com .google .protobuf .MessageLite ;
7
7
import fi .iki .elonen .NanoHTTPD ;
8
8
9
9
import java .io .ByteArrayInputStream ;
10
10
import java .io .FilterInputStream ;
11
11
import java .io .IOException ;
12
12
import java .io .InputStream ;
13
+ import java .net .HttpURLConnection ;
14
+ import java .net .URL ;
13
15
import java .util .Objects ;
14
16
17
+ import static app .revanced .extension .spotify .misc .fix .ClientTokenService .*;
18
+ import static app .revanced .extension .spotify .misc .fix .Constants .*;
15
19
import static fi .iki .elonen .NanoHTTPD .Response .Status .INTERNAL_ERROR ;
16
20
17
21
class RequestListener extends NanoHTTPD {
22
+ private static final String CLIENT_TOKEN_API_PATH = "/v1/clienttoken" ;
23
+ private static final String CLIENT_TOKEN_API_URL = "https://clienttoken.spotify.com" + CLIENT_TOKEN_API_PATH ;
24
+
25
+ private static final String IOS_USER_AGENT ;
26
+
27
+ static {
28
+ String clientVersion = getClientVersion ();
29
+ String version = clientVersion .substring (clientVersion .indexOf ("-" ) + 1 , clientVersion .lastIndexOf ("." ));
30
+
31
+ IOS_USER_AGENT = "Spotify/" + version + " iOS/" + getSystemVersion () + " (" + getHardwareMachine () + ")" ;
32
+ }
33
+
18
34
RequestListener (int port ) {
19
35
super (port );
20
36
@@ -26,49 +42,48 @@ class RequestListener extends NanoHTTPD {
26
42
}
27
43
}
28
44
45
+
29
46
@ NonNull
30
47
@ Override
31
- public Response serve (@ NonNull IHTTPSession request ) {
32
- String uri = request .getUri ();
48
+ public Response serve (IHTTPSession session ) {
49
+ String uri = session .getUri ();
33
50
Logger .printInfo (() -> "Serving request for URI: " + uri );
51
+ if (!uri .equals (CLIENT_TOKEN_API_PATH )) return INTERNAL_ERROR_RESPONSE ;
34
52
35
- if (!uri .equals (ClientTokenFetcher .CLIENT_TOKEN_API_PATH )) return newResponse (INTERNAL_ERROR );
36
-
37
- InputStream requestBodyInputStream = getRequestBodyInputStream (request );
38
-
39
- ClienttokenHttp .ClientTokenRequest clientTokenRequest ;
40
- try {
41
- clientTokenRequest = ClienttokenHttp .ClientTokenRequest .parseFrom (requestBodyInputStream );
53
+ ClientTokenRequest clientTokenRequest ;
54
+ try (InputStream inputStream = getInputStream (session )) {
55
+ clientTokenRequest = ClientTokenRequest .parseFrom (inputStream );
42
56
} catch (IOException ex ) {
43
- Logger .printException (() -> "Failed to parse client token request" , ex );
44
- return newResponse ( INTERNAL_ERROR ) ;
57
+ Logger .printException (() -> "Failed to parse client token request from input stream " , ex );
58
+ return INTERNAL_ERROR_RESPONSE ;
45
59
}
46
60
47
- try {
48
- ClienttokenHttp .ClientTokenResponse clientTokenResponse =
49
- ClientTokenFetcher .fetchClientToken (clientTokenRequest );
50
-
51
- if (clientTokenResponse == null ) {
52
- return newResponse (INTERNAL_ERROR );
53
- }
54
-
55
- ClienttokenHttp .ClientTokenResponseType responseGranted =
56
- ClienttokenHttp .ClientTokenResponseType .RESPONSE_GRANTED_TOKEN_RESPONSE ;
57
- if (clientTokenResponse .getResponseType () == responseGranted ) {
58
- Logger .printInfo (() -> "Fetched iOS client token: " +
59
- clientTokenResponse .getGrantedToken ().getToken ());
60
- }
61
-
62
- return newResponse (Response .Status .OK , clientTokenResponse );
63
- } catch (IOException ex ) {
64
- Logger .printException (() -> "Failed to get client token response" , ex );
61
+ ClientTokenResponse response = getClientTokenResponse (clientTokenRequest , RequestListener ::requestClientToken );
62
+ if (response == null ) {
63
+ Logger .printException (() -> "Failed to get client token response" );
64
+ return INTERNAL_ERROR_RESPONSE ;
65
65
}
66
+
67
+ return newResponse (Response .Status .OK , response );
68
+ }
66
69
67
- return newResponse (INTERNAL_ERROR );
70
+ @ NonNull
71
+ private static ClientTokenResponse requestClientToken (ClientTokenRequest request ) throws IOException {
72
+ HttpURLConnection urlConnection = (HttpURLConnection ) new URL (CLIENT_TOKEN_API_URL ).openConnection ();
73
+ urlConnection .setRequestMethod ("POST" );
74
+ urlConnection .setDoOutput (true );
75
+ urlConnection .setRequestProperty ("Content-Type" , "application/x-protobuf" );
76
+ urlConnection .setRequestProperty ("Accept" , "application/x-protobuf" );
77
+ urlConnection .setRequestProperty ("User-Agent" , IOS_USER_AGENT );
78
+ urlConnection .getOutputStream ().write (request .toByteArray ());
79
+
80
+ try (InputStream inputStream = urlConnection .getInputStream ()) {
81
+ return ClientTokenResponse .parseFrom (inputStream );
82
+ }
68
83
}
69
84
70
85
@ NonNull
71
- private static InputStream limitedInputStream (InputStream inputStream , long contentLength ) {
86
+ private static InputStream newLimitedInputStream (InputStream inputStream , long contentLength ) {
72
87
return new FilterInputStream (inputStream ) {
73
88
private long remaining = contentLength ;
74
89
@@ -92,18 +107,20 @@ public int read(byte[] b, int off, int len) throws IOException {
92
107
}
93
108
94
109
@ NonNull
95
- private static InputStream getRequestBodyInputStream (@ NonNull IHTTPSession request ) {
96
- long requestContentLength =
97
- Long .parseLong (Objects .requireNonNull (request .getHeaders ().get ("content-length" )));
98
- return limitedInputStream (request .getInputStream (), requestContentLength );
110
+ private static InputStream getInputStream (@ NonNull IHTTPSession session ) {
111
+ long requestContentLength = Long .parseLong (Objects .requireNonNull (session .getHeaders ().get ("content-length" )));
112
+ return newLimitedInputStream (session .getInputStream (), requestContentLength );
99
113
}
100
114
115
+ private static final Response INTERNAL_ERROR_RESPONSE = newResponse (INTERNAL_ERROR );
116
+
101
117
@ SuppressWarnings ("SameParameterValue" )
102
118
@ NonNull
103
119
private static Response newResponse (Response .Status status ) {
104
120
return newResponse (status , null );
105
121
}
106
122
123
+
107
124
@ NonNull
108
125
private static Response newResponse (Response .IStatus status , MessageLite messageLite ) {
109
126
if (messageLite == null ) {
0 commit comments