diff --git a/extensions/spotify/build.gradle.kts b/extensions/spotify/build.gradle.kts index fd346d93b5..39d58a0227 100644 --- a/extensions/spotify/build.gradle.kts +++ b/extensions/spotify/build.gradle.kts @@ -1,14 +1,7 @@ -plugins { - alias(libs.plugins.protobuf) -} - dependencies { compileOnly(project(":extensions:shared:library")) compileOnly(project(":extensions:spotify:stub")) compileOnly(libs.annotation) - - implementation(libs.nanohttpd) - implementation(libs.protobuf.javalite) } android { @@ -21,19 +14,3 @@ android { targetCompatibility = JavaVersion.VERSION_1_8 } } - -protobuf { - protoc { - artifact = libs.protobuf.protoc.get().toString() - } - - generateProtoTasks { - all().forEach { task -> - task.builtins { - create("java") { - option("lite") - } - } - } - } -} diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/ClientTokenService.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/ClientTokenService.java deleted file mode 100644 index 0345b19ef6..0000000000 --- a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/ClientTokenService.java +++ /dev/null @@ -1,115 +0,0 @@ -package app.revanced.extension.spotify.misc.fix; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import app.revanced.extension.shared.Logger; -import app.revanced.extension.spotify.misc.fix.clienttoken.data.v0.ClienttokenHttp.*; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; - -import static app.revanced.extension.spotify.misc.fix.Constants.*; - -class ClientTokenService { - private static final String IOS_CLIENT_ID = "58bd3c95768941ea9eb4350aaa033eb3"; - private static final String IOS_USER_AGENT; - - static { - String clientVersion = getClientVersion(); - int commitHashIndex = clientVersion.lastIndexOf("."); - String version = clientVersion.substring( - clientVersion.indexOf("-") + 1, - clientVersion.lastIndexOf(".", commitHashIndex - 1) - ); - - IOS_USER_AGENT = "Spotify/" + version + " iOS/" + getSystemVersion() + " (" + getHardwareMachine() + ")"; - } - - private static final ConnectivitySdkData.Builder IOS_CONNECTIVITY_SDK_DATA = - ConnectivitySdkData.newBuilder() - .setPlatformSpecificData(PlatformSpecificData.newBuilder() - .setIos(NativeIOSData.newBuilder() - .setHwMachine(getHardwareMachine()) - .setSystemVersion(getSystemVersion()) - ) - ); - - private static final ClientDataRequest.Builder IOS_CLIENT_DATA_REQUEST = - ClientDataRequest.newBuilder() - .setClientVersion(getClientVersion()) - .setClientId(IOS_CLIENT_ID); - - private static final ClientTokenRequest.Builder IOS_CLIENT_TOKEN_REQUEST = - ClientTokenRequest.newBuilder() - .setRequestType(ClientTokenRequestType.REQUEST_CLIENT_DATA_REQUEST); - - - @NonNull - static ClientTokenRequest newIOSClientTokenRequest(String deviceId) { - Logger.printInfo(() -> "Creating new iOS client token request with device ID: " + deviceId); - - return IOS_CLIENT_TOKEN_REQUEST - .setClientData(IOS_CLIENT_DATA_REQUEST - .setConnectivitySdkData(IOS_CONNECTIVITY_SDK_DATA - .setDeviceId(deviceId) - ) - ) - .build(); - } - - @Nullable - static ClientTokenResponse getClientTokenResponse(@NonNull ClientTokenRequest request) { - if (request.getRequestType() == ClientTokenRequestType.REQUEST_CLIENT_DATA_REQUEST) { - Logger.printInfo(() -> "Requesting iOS client token"); - String deviceId = request.getClientData().getConnectivitySdkData().getDeviceId(); - request = newIOSClientTokenRequest(deviceId); - } - - ClientTokenResponse response; - try { - response = requestClientToken(request); - } catch (IOException ex) { - Logger.printException(() -> "Failed to handle request", ex); - return null; - } - - return response; - } - - @NonNull - private static ClientTokenResponse requestClientToken(@NonNull ClientTokenRequest request) throws IOException { - HttpURLConnection urlConnection = (HttpURLConnection) new URL(CLIENT_TOKEN_API_URL).openConnection(); - urlConnection.setRequestMethod("POST"); - urlConnection.setDoOutput(true); - urlConnection.setRequestProperty("Content-Type", "application/x-protobuf"); - urlConnection.setRequestProperty("Accept", "application/x-protobuf"); - urlConnection.setRequestProperty("User-Agent", IOS_USER_AGENT); - - byte[] requestArray = request.toByteArray(); - urlConnection.setFixedLengthStreamingMode(requestArray.length); - urlConnection.getOutputStream().write(requestArray); - - try (InputStream inputStream = urlConnection.getInputStream()) { - return ClientTokenResponse.parseFrom(inputStream); - } - } - - @Nullable - static ClientTokenResponse serveClientTokenRequest(@NonNull InputStream inputStream) { - ClientTokenRequest request; - try { - request = ClientTokenRequest.parseFrom(inputStream); - } catch (IOException ex) { - Logger.printException(() -> "Failed to parse request from input stream", ex); - return null; - } - Logger.printInfo(() -> "Request of type: " + request.getRequestType()); - - ClientTokenResponse response = getClientTokenResponse(request); - if (response != null) Logger.printInfo(() -> "Response of type: " + response.getResponseType()); - - return response; - } -} diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/Constants.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/Constants.java deleted file mode 100644 index 4928da7adc..0000000000 --- a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/Constants.java +++ /dev/null @@ -1,26 +0,0 @@ -package app.revanced.extension.spotify.misc.fix; - -import androidx.annotation.NonNull; - -class Constants { - static final String CLIENT_TOKEN_API_PATH = "/v1/clienttoken"; - static final String CLIENT_TOKEN_API_URL = "https://clienttoken.spotify.com" + CLIENT_TOKEN_API_PATH; - - // Modified by a patch. Do not touch. - @NonNull - static String getClientVersion() { - return ""; - } - - // Modified by a patch. Do not touch. - @NonNull - static String getSystemVersion() { - return ""; - } - - // Modified by a patch. Do not touch. - @NonNull - static String getHardwareMachine() { - return ""; - } -} diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/RequestListener.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/RequestListener.java deleted file mode 100644 index 2de6caa3ee..0000000000 --- a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/RequestListener.java +++ /dev/null @@ -1,94 +0,0 @@ -package app.revanced.extension.spotify.misc.fix; - -import androidx.annotation.NonNull; -import app.revanced.extension.shared.Logger; -import app.revanced.extension.spotify.misc.fix.clienttoken.data.v0.ClienttokenHttp.ClientTokenResponse; -import com.google.protobuf.MessageLite; -import fi.iki.elonen.NanoHTTPD; - -import java.io.ByteArrayInputStream; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Objects; - -import static app.revanced.extension.spotify.misc.fix.ClientTokenService.serveClientTokenRequest; -import static app.revanced.extension.spotify.misc.fix.Constants.CLIENT_TOKEN_API_PATH; -import static fi.iki.elonen.NanoHTTPD.Response.Status.INTERNAL_ERROR; - -class RequestListener extends NanoHTTPD { - RequestListener(int port) { - super(port); - - try { - start(); - } catch (IOException ex) { - Logger.printException(() -> "Failed to start request listener on port " + port, ex); - throw new RuntimeException(ex); - } - } - - @NonNull - @Override - public Response serve(@NonNull IHTTPSession session) { - String uri = session.getUri(); - if (!uri.equals(CLIENT_TOKEN_API_PATH)) return INTERNAL_ERROR_RESPONSE; - - Logger.printInfo(() -> "Serving request for URI: " + uri); - - ClientTokenResponse response = serveClientTokenRequest(getInputStream(session)); - if (response != null) return newResponse(Response.Status.OK, response); - - Logger.printException(() -> "Failed to serve client token request"); - return INTERNAL_ERROR_RESPONSE; - } - - @NonNull - private static InputStream newLimitedInputStream(InputStream inputStream, long contentLength) { - return new FilterInputStream(inputStream) { - private long remaining = contentLength; - - @Override - public int read() throws IOException { - if (remaining <= 0) return -1; - int result = super.read(); - if (result != -1) remaining--; - return result; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - if (remaining <= 0) return -1; - len = (int) Math.min(len, remaining); - int result = super.read(b, off, len); - if (result != -1) remaining -= result; - return result; - } - }; - } - - @NonNull - private static InputStream getInputStream(@NonNull IHTTPSession session) { - long requestContentLength = Long.parseLong(Objects.requireNonNull(session.getHeaders().get("content-length"))); - return newLimitedInputStream(session.getInputStream(), requestContentLength); - } - - private static final Response INTERNAL_ERROR_RESPONSE = newResponse(INTERNAL_ERROR); - - @SuppressWarnings("SameParameterValue") - @NonNull - private static Response newResponse(Response.Status status) { - return newResponse(status, null); - } - - @NonNull - private static Response newResponse(Response.IStatus status, MessageLite messageLite) { - if (messageLite == null) { - return newFixedLengthResponse(status, "application/x-protobuf", null); - } - - byte[] messageBytes = messageLite.toByteArray(); - InputStream stream = new ByteArrayInputStream(messageBytes); - return newFixedLengthResponse(status, "application/x-protobuf", stream, messageBytes.length); - } -} diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/SpoofClientPatch.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/SpoofClientPatch.java deleted file mode 100644 index fee58b26c0..0000000000 --- a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/fix/SpoofClientPatch.java +++ /dev/null @@ -1,25 +0,0 @@ -package app.revanced.extension.spotify.misc.fix; - -import app.revanced.extension.shared.Logger; - -@SuppressWarnings("unused") -public class SpoofClientPatch { - private static RequestListener listener; - - /** - * Injection point. Launch requests listener server. - */ - public synchronized static void launchListener(int port) { - if (listener != null) { - Logger.printInfo(() -> "Listener already running on port " + port); - return; - } - - try { - Logger.printInfo(() -> "Launching listener on port " + port); - listener = new RequestListener(port); - } catch (Exception ex) { - Logger.printException(() -> "launchListener failure", ex); - } - } -} diff --git a/extensions/spotify/src/main/proto/app/revanced/extension/spotify/misc/fix/clienttoken_http.proto b/extensions/spotify/src/main/proto/app/revanced/extension/spotify/misc/fix/clienttoken_http.proto deleted file mode 100644 index 8e7f242b76..0000000000 --- a/extensions/spotify/src/main/proto/app/revanced/extension/spotify/misc/fix/clienttoken_http.proto +++ /dev/null @@ -1,73 +0,0 @@ -syntax = "proto3"; - -package spotify.clienttoken.data.v0; - -option optimize_for = LITE_RUNTIME; -option java_package = "app.revanced.extension.spotify.misc.fix.clienttoken.data.v0"; - -message ClientTokenRequest { - ClientTokenRequestType request_type = 1; - - oneof request { - ClientDataRequest client_data = 2; - } -} - -enum ClientTokenRequestType { - REQUEST_UNKNOWN = 0; - REQUEST_CLIENT_DATA_REQUEST = 1; - REQUEST_CHALLENGE_ANSWERS_REQUEST = 2; -} - -message ClientDataRequest { - string client_version = 1; - string client_id = 2; - - oneof data { - ConnectivitySdkData connectivity_sdk_data = 3; - } -} - -message ConnectivitySdkData { - PlatformSpecificData platform_specific_data = 1; - string device_id = 2; -} - -message PlatformSpecificData { - oneof data { - NativeIOSData ios = 2; - } -} - -message NativeIOSData { - int32 user_interface_idiom = 1; - bool target_iphone_simulator = 2; - string hw_machine = 3; - string system_version = 4; - string simulator_model_identifier = 5; -} - -message ClientTokenResponse { - ClientTokenResponseType response_type = 1; - - oneof response { - GrantedTokenResponse granted_token = 2; - } -} - -enum ClientTokenResponseType { - RESPONSE_UNKNOWN = 0; - RESPONSE_GRANTED_TOKEN_RESPONSE = 1; - RESPONSE_CHALLENGES_RESPONSE = 2; -} - -message GrantedTokenResponse { - string token = 1; - int32 expires_after_seconds = 2; - int32 refresh_after_seconds = 3; - repeated TokenDomain domains = 4; -} - -message TokenDomain { - string domain = 1; -} diff --git a/gradle.properties b/gradle.properties index bd3cc17632..b5f9f37d62 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,5 +2,6 @@ org.gradle.caching = true org.gradle.jvmargs = -Xms512M -Xmx2048M org.gradle.parallel = true android.useAndroidX = true +android.uniquePackageNames=false kotlin.code.style = official version = 5.50.0-dev.4 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dfecc641eb..8fd0fd2ee0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,25 +11,15 @@ appcompat = "1.7.1" okhttp = "5.3.2" retrofit = "3.0.0" guava = "33.5.0-jre" -protobuf-javalite = "4.33.2" -protoc = "4.33.2" -protobuf = "0.9.6" -antlr4 = "4.13.2" -nanohttpd = "2.3.1" apksig = "8.12.3" [libraries] annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" } -antlr4 = { module = "org.antlr:antlr4", version.ref = "antlr4" } appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } -nanohttpd = { module = "org.nanohttpd:nanohttpd", version.ref = "nanohttpd" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } -protobuf-javalite = { module = "com.google.protobuf:protobuf-javalite", version.ref = "protobuf-javalite" } -protobuf-protoc = { module = "com.google.protobuf:protoc", version.ref = "protoc" } retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } guava = { module = "com.google.guava:guava", version.ref = "guava" } apksig = { group = "com.android.tools.build", name = "apksig", version.ref = "apksig" } [plugins] android-library = { id = "com.android.library" } -protobuf = { id = "com.google.protobuf", version.ref = "protobuf" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3ae1e2f124..37f78a6af8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists