From af77a3cbd0f60ac818b6d39d3fab1a59b21c62ee Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 10 Jul 2025 19:12:11 -0300 Subject: [PATCH 1/3] chore(Spotify): Remove legacy version support --- .../spotify/misc/UnlockPremiumPatch.java | 40 ++++--------------- .../useraccount/v1/AccountAttribute.java | 8 ---- .../createbutton/HideCreateButtonPatch.kt | 9 ----- .../spotify/layout/theme/CustomThemePatch.kt | 10 +---- .../spotify/lite/ondemand/Fingerprints.kt | 23 ----------- .../spotify/lite/ondemand/OnDemandPatch.kt | 14 +------ .../patches/spotify/misc/Fingerprints.kt | 17 +------- .../spotify/misc/UnlockPremiumPatch.kt | 10 ----- .../spotify/misc/privacy/Fingerprints.kt | 4 +- .../misc/privacy/SanitizeSharingLinksPatch.kt | 23 ++++------- .../widgets/FixThirdPartyLaunchersWidgets.kt | 10 ----- .../patches/spotify/shared/Fingerprints.kt | 25 +----------- 12 files changed, 22 insertions(+), 171 deletions(-) delete mode 100644 extensions/spotify/stub/src/main/java/com/spotify/useraccount/v1/AccountAttribute.java delete mode 100644 patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/Fingerprints.kt diff --git a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java b/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java index 65c3f0e2c1..e99d94bd8e 100644 --- a/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java +++ b/extensions/spotify/src/main/java/app/revanced/extension/spotify/misc/UnlockPremiumPatch.java @@ -5,6 +5,7 @@ import app.revanced.extension.spotify.shared.ComponentFilters.ComponentFilter; import app.revanced.extension.spotify.shared.ComponentFilters.ResourceIdComponentFilter; import app.revanced.extension.spotify.shared.ComponentFilters.StringComponentFilter; +import com.spotify.remoteconfig.internal.AccountAttribute; import java.util.*; @@ -14,25 +15,6 @@ @SuppressWarnings("unused") public final class UnlockPremiumPatch { - private static final String SPOTIFY_MAIN_ACTIVITY_LEGACY = "com.spotify.music.MainActivity"; - - /** - * If the app target is 8.6.98.900. - */ - private static final boolean IS_SPOTIFY_LEGACY_APP_TARGET; - - static { - boolean isLegacy; - try { - Class.forName(SPOTIFY_MAIN_ACTIVITY_LEGACY); - isLegacy = true; - } catch (ClassNotFoundException ex) { - isLegacy = false; - } - - IS_SPOTIFY_LEGACY_APP_TARGET = isLegacy; - } - private static class OverrideAttribute { /** * Account attribute key. @@ -66,7 +48,7 @@ private static class OverrideAttribute { new OverrideAttribute("ads", FALSE), // Works along on-demand, allows playing any song without restriction. new OverrideAttribute("player-license", "premium"), - new OverrideAttribute("player-license-v2", "premium", !IS_SPOTIFY_LEGACY_APP_TARGET), + new OverrideAttribute("player-license-v2", "premium"), // Disables shuffle being initially enabled when first playing a playlist. new OverrideAttribute("shuffle", FALSE), // Allows playing any song on-demand, without a shuffled order. @@ -75,7 +57,7 @@ private static class OverrideAttribute { new OverrideAttribute("streaming", TRUE), // Allows adding songs to queue and removes the smart shuffle mode restriction, // allowing to pick any of the other modes. Flag is not present in legacy app target. - new OverrideAttribute("pick-and-shuffle", FALSE, !IS_SPOTIFY_LEGACY_APP_TARGET), + new OverrideAttribute("pick-and-shuffle", FALSE), // Disables shuffle-mode streaming-rule, which forces songs to be played shuffled // and breaks the player when other patches are applied. new OverrideAttribute("streaming-rules", ""), @@ -131,10 +113,10 @@ private static class OverrideAttribute { /** * Injection point. Override account attributes. */ - public static void overrideAttributes(Map attributes) { + public static void overrideAttributes(Map attributes) { try { for (OverrideAttribute override : PREMIUM_OVERRIDES) { - Object attribute = attributes.get(override.key); + AccountAttribute attribute = attributes.get(override.key); if (attribute == null) { if (override.isExpected) { @@ -145,11 +127,7 @@ public static void overrideAttributes(Map a Object overrideValue = override.overrideValue; Object originalValue; - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - originalValue = ((com.spotify.useraccount.v1.AccountAttribute) attribute).value_; - } else { - originalValue = ((com.spotify.remoteconfig.internal.AccountAttribute) attribute).value_; - } + originalValue = attribute.value_; if (overrideValue.equals(originalValue)) { continue; @@ -158,11 +136,7 @@ public static void overrideAttributes(Map a Logger.printInfo(() -> "Overriding account attribute " + override.key + " from " + originalValue + " to " + overrideValue); - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - ((com.spotify.useraccount.v1.AccountAttribute) attribute).value_ = overrideValue; - } else { - ((com.spotify.remoteconfig.internal.AccountAttribute) attribute).value_ = overrideValue; - } + attribute.value_ = overrideValue; } } catch (Exception ex) { Logger.printException(() -> "overrideAttributes failure", ex); diff --git a/extensions/spotify/stub/src/main/java/com/spotify/useraccount/v1/AccountAttribute.java b/extensions/spotify/stub/src/main/java/com/spotify/useraccount/v1/AccountAttribute.java deleted file mode 100644 index a03b583bf5..0000000000 --- a/extensions/spotify/stub/src/main/java/com/spotify/useraccount/v1/AccountAttribute.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.spotify.useraccount.v1; - -/** - * Used for target 8.6.98.900. Class is still present in newer app targets. - */ -public class AccountAttribute { - public Object value_; -} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatch.kt index e01d05ecc6..5149514791 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/hide/createbutton/HideCreateButtonPatch.kt @@ -6,12 +6,10 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch -import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import java.util.logging.Logger private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/layout/hide/createbutton/HideCreateButtonPatch;" @@ -26,13 +24,6 @@ val hideCreateButtonPatch = bytecodePatch( dependsOn(sharedExtensionPatch) execute { - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - Logger.getLogger(this::class.java.name).warning( - "Create button does not exist in legacy app target. No changes applied." - ) - return@execute - } - val oldNavigationBarAddItemMethod = oldNavigationBarAddItemFingerprint.originalMethodOrNull // Only throw the fingerprint error when oldNavigationBarAddItemMethod does not exist. val navigationBarItemSetClassDef = if (oldNavigationBarAddItemMethod == null) { diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt index 61e847aa24..4546d80f47 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/layout/theme/CustomThemePatch.kt @@ -7,8 +7,8 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.stringOption import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch -import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET -import app.revanced.util.* +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference import org.w3c.dom.Element @@ -19,12 +19,6 @@ private val customThemeBytecodePatch = bytecodePatch { dependsOn(sharedExtensionPatch) execute { - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - // Bytecode changes are not needed for legacy app target. - // Player background color is changed with existing resource patch. - return@execute - } - val colorSpaceUtilsClassDef = colorSpaceUtilsClassFingerprint.originalClassDef // Hook a util method that converts ARGB to RGBA in the sRGB color space to replace hardcoded accent colors. diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/Fingerprints.kt deleted file mode 100644 index 365235bee0..0000000000 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/Fingerprints.kt +++ /dev/null @@ -1,23 +0,0 @@ -package app.revanced.patches.spotify.lite.ondemand - -import com.android.tools.smali.dexlib2.Opcode -import app.revanced.patcher.fingerprint - -internal val onDemandFingerprint = fingerprint(fuzzyPatternScanThreshold = 2) { - returns("L") - parameters() - opcodes( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_EQZ, - Opcode.SGET_OBJECT, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IPUT, - Opcode.RETURN_OBJECT, - ) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt index a624b42fd5..b33654a28c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt @@ -1,21 +1,9 @@ package app.revanced.patches.spotify.lite.ondemand -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.patch.bytecodePatch @Deprecated("Patch no longer works and will be deleted soon") @Suppress("unused") val onDemandPatch = bytecodePatch( description = "Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.", -) { - compatibleWith("com.spotify.lite") - - execute { - // Spoof a premium account - - onDemandFingerprint.method.addInstruction( - onDemandFingerprint.patternMatch!!.endIndex - 1, - "const/4 v0, 0x2", - ) - } -} +) {} diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt index 54cc0c661f..090359ad3e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt @@ -2,7 +2,6 @@ package app.revanced.patches.spotify.misc import app.revanced.patcher.fingerprint import app.revanced.patcher.patch.BytecodePatchContext -import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags @@ -13,25 +12,13 @@ import com.android.tools.smali.dexlib2.iface.reference.TypeReference context(BytecodePatchContext) internal val accountAttributeFingerprint get() = fingerprint { - custom { _, classDef -> - classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) { - "Lcom/spotify/useraccount/v1/AccountAttribute;" - } else { - "Lcom/spotify/remoteconfig/internal/AccountAttribute;" - } - } + custom { _, classDef -> classDef.type == "Lcom/spotify/remoteconfig/internal/AccountAttribute;" } } context(BytecodePatchContext) internal val productStateProtoGetMapFingerprint get() = fingerprint { returns("Ljava/util/Map;") - custom { _, classDef -> - classDef.type == if (IS_SPOTIFY_LEGACY_APP_TARGET) { - "Lcom/spotify/ucs/proto/v0/UcsResponseWrapper${'$'}AccountAttributesResponse;" - } else { - "Lcom/spotify/remoteconfig/internal/ProductStateProto;" - } - } + custom { _, classDef -> classDef.type == "Lcom/spotify/remoteconfig/internal/ProductStateProto;" } } internal val buildQueryParametersFingerprint = fingerprint { diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt index 8418783b62..b7fe3e5dc6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/UnlockPremiumPatch.kt @@ -14,7 +14,6 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch -import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.* import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -23,7 +22,6 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.TypeReference -import java.util.logging.Logger internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/spotify/misc/UnlockPremiumPatch;" @@ -78,14 +76,6 @@ val unlockPremiumPatch = bytecodePatch( } - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - Logger.getLogger(this::class.java.name).warning( - "Patching a legacy Spotify version. Patch functionality may be limited." - ) - return@execute - } - - // Enable choosing a specific song/artist via Google Assistant. contextFromJsonFingerprint.method.apply { val insertIndex = contextFromJsonFingerprint.patternMatch!!.startIndex diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt index f8ce3a262a..a84aa699bf 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/Fingerprints.kt @@ -14,7 +14,7 @@ internal val shareCopyUrlFingerprint = fingerprint { } } -internal val shareCopyUrlLegacyFingerprint = fingerprint { +internal val oldShareCopyUrlFingerprint = fingerprint { returns("Ljava/lang/Object;") parameters("Ljava/lang/Object;") strings("clipboard", "createNewSession failed") @@ -38,7 +38,7 @@ internal val formatAndroidShareSheetUrlFingerprint = fingerprint { } } -internal val formatAndroidShareSheetUrlLegacyFingerprint = fingerprint { +internal val oldFormatAndroidShareSheetUrlFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC) returns("Ljava/lang/String;") parameters("Lcom/spotify/share/social/sharedata/ShareData;", "Ljava/lang/String;") diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt index 707896bf52..f7be30432d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt @@ -1,11 +1,9 @@ package app.revanced.patches.spotify.misc.privacy -import app.revanced.patcher.Fingerprint import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch -import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import com.android.tools.smali.dexlib2.AccessFlags @@ -28,13 +26,9 @@ val sanitizeSharingLinksPatch = bytecodePatch( val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" + "sanitizeUrl(Ljava/lang/String;)Ljava/lang/String;" - val copyFingerprint = if (IS_SPOTIFY_LEGACY_APP_TARGET) { - shareCopyUrlLegacyFingerprint - } else { - shareCopyUrlFingerprint - } + val copyMethod = shareCopyUrlFingerprint.methodOrNull ?: oldShareCopyUrlFingerprint.method - copyFingerprint.method.apply { + copyMethod.apply { val newPlainTextInvokeIndex = indexOfFirstInstructionOrThrow { getReference()?.name == "newPlainText" } @@ -50,13 +44,8 @@ val sanitizeSharingLinksPatch = bytecodePatch( } // Android native share sheet is used for all other quick share types (X, WhatsApp, etc). - val shareUrlParameter : String - val shareSheetFingerprint : Fingerprint - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - shareSheetFingerprint = formatAndroidShareSheetUrlLegacyFingerprint - shareUrlParameter = "p2" - } else { - shareSheetFingerprint = formatAndroidShareSheetUrlFingerprint + var shareUrlParameter = "" + val shareSheetMethod = formatAndroidShareSheetUrlFingerprint.methodOrNull?.also { val methodAccessFlags = formatAndroidShareSheetUrlFingerprint.originalMethod.accessFlags shareUrlParameter = if (AccessFlags.STATIC.isSet(methodAccessFlags)) { // In newer implementations the method is static, so p0 is not `this`. @@ -66,9 +55,11 @@ val sanitizeSharingLinksPatch = bytecodePatch( // For that reason, add one to the parameter register. "p2" } + } ?: oldFormatAndroidShareSheetUrlFingerprint.method.also { + shareUrlParameter = "p2" } - shareSheetFingerprint.method.addInstructions( + shareSheetMethod.addInstructions( 0, """ invoke-static { $shareUrlParameter }, $extensionMethodDescriptor diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunchersWidgets.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunchersWidgets.kt index c84b43f71e..ad40f24e2e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunchersWidgets.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/widgets/FixThirdPartyLaunchersWidgets.kt @@ -1,9 +1,7 @@ package app.revanced.patches.spotify.misc.widgets import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.returnEarly -import java.util.logging.Logger @Suppress("unused") val fixThirdPartyLaunchersWidgets = bytecodePatch( @@ -13,14 +11,6 @@ val fixThirdPartyLaunchersWidgets = bytecodePatch( compatibleWith("com.spotify.music") execute { - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - // The permission check does not exist in legacy versions. - Logger.getLogger(this::class.java.name).warning( - "Legacy app target does not have any third party launcher restrictions. No changes applied." - ) - return@execute - } - // Only system app launchers are granted the BIND_APPWIDGET permission. // Override the method that checks for it to always return true, as this permission is not actually required // for the widgets to work. diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt index cd3e3cf6bb..103f47750a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/shared/Fingerprints.kt @@ -1,38 +1,15 @@ package app.revanced.patches.spotify.shared import app.revanced.patcher.fingerprint -import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags private const val SPOTIFY_MAIN_ACTIVITY = "Lcom/spotify/music/SpotifyMainActivity;" -/** - * Main activity of target 8.6.98.900. - */ -internal const val SPOTIFY_MAIN_ACTIVITY_LEGACY = "Lcom/spotify/music/MainActivity;" - internal val mainActivityOnCreateFingerprint = fingerprint { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returns("V") parameters("Landroid/os/Bundle;") custom { method, classDef -> - method.name == "onCreate" && (classDef.type == SPOTIFY_MAIN_ACTIVITY - || classDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY) + method.name == "onCreate" && classDef.type == SPOTIFY_MAIN_ACTIVITY } } - -private var isLegacyAppTarget: Boolean? = null - -/** - * If patching a legacy 8.x target. This may also be set if patching slightly older/newer app targets, - * but the only legacy target of interest is 8.6.98.900 as it's the last version that - * supports Spotify integration on Kenwood/Pioneer car stereos. - */ -context(BytecodePatchContext) -internal val IS_SPOTIFY_LEGACY_APP_TARGET - get(): Boolean { - if (isLegacyAppTarget == null) { - isLegacyAppTarget = mainActivityOnCreateFingerprint.originalClassDef.type == SPOTIFY_MAIN_ACTIVITY_LEGACY - } - return isLegacyAppTarget!! - } From d36ba9defcaac9631795a9345c1a8fd874c32f09 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 10 Jul 2025 19:18:52 -0300 Subject: [PATCH 2/3] Forgot to remove this --- .../spotify/misc/lyrics/ChangeLyricsProviderPatch.kt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt index 99ec038c20..b877e89a67 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt @@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.stringOption import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.spotify.shared.IS_SPOTIFY_LEGACY_APP_TARGET import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow @@ -57,13 +56,6 @@ val changeLyricsProviderPatch = bytecodePatch( } execute { - if (IS_SPOTIFY_LEGACY_APP_TARGET) { - Logger.getLogger(this::class.java.name).severe( - "Change lyrics provider patch is not supported for this target version." - ) - return@execute - } - val httpClientBuilderMethod = httpClientBuilderFingerprint.originalMethod // region Create a modified copy of the HTTP client builder method with the custom lyrics provider host. From 886b9dd3815e075588987948756565fa869a9c3e Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 11 Jul 2025 11:02:11 -0300 Subject: [PATCH 3/3] Clean up --- .../spotify/lite/ondemand/OnDemandPatch.kt | 2 +- .../patches/spotify/misc/Fingerprints.kt | 10 ++++---- .../misc/lyrics/ChangeLyricsProviderPatch.kt | 4 ++++ .../misc/privacy/SanitizeSharingLinksPatch.kt | 23 ++++++++++++------- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt index b33654a28c..4d2d04a553 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/lite/ondemand/OnDemandPatch.kt @@ -6,4 +6,4 @@ import app.revanced.patcher.patch.bytecodePatch @Suppress("unused") val onDemandPatch = bytecodePatch( description = "Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads.", -) {} +) diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt index 090359ad3e..4fc811175d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/Fingerprints.kt @@ -77,14 +77,14 @@ internal val contextFromJsonFingerprint = fingerprint { ) custom { method, classDef -> method.name == "fromJson" && - classDef.endsWith("voiceassistants/playermodels/ContextJsonAdapter;") + classDef.type.endsWith("voiceassistants/playermodels/ContextJsonAdapter;") } } internal val readPlayerOptionOverridesFingerprint = fingerprint { custom { method, classDef -> method.name == "readPlayerOptionOverrides" && - classDef.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;") + classDef.type.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;") } } @@ -106,21 +106,21 @@ internal val abstractProtobufListEnsureIsMutableFingerprint = fingerprint { internal fun structureGetSectionsFingerprint(className: String) = fingerprint { custom { method, classDef -> - classDef.endsWith(className) && method.indexOfFirstInstruction { + classDef.type.endsWith(className) && method.indexOfFirstInstruction { opcode == Opcode.IGET_OBJECT && getReference()?.name == "sections_" } >= 0 } } internal val homeSectionFingerprint = fingerprint { - custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") } + custom { _, classDef -> classDef.type.endsWith("homeapi/proto/Section;") } } internal val homeStructureGetSectionsFingerprint = structureGetSectionsFingerprint("homeapi/proto/HomeStructure;") internal val browseSectionFingerprint = fingerprint { - custom { _, classDef-> classDef.endsWith("browsita/v1/resolved/Section;") } + custom { _, classDef-> classDef.type.endsWith("browsita/v1/resolved/Section;") } } internal val browseStructureGetSectionsFingerprint = diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt index b877e89a67..6adaec7c79 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/lyrics/ChangeLyricsProviderPatch.kt @@ -59,6 +59,7 @@ val changeLyricsProviderPatch = bytecodePatch( val httpClientBuilderMethod = httpClientBuilderFingerprint.originalMethod // region Create a modified copy of the HTTP client builder method with the custom lyrics provider host. + val patchedHttpClientBuilderMethod = with(httpClientBuilderMethod) { val invokeBuildUrlIndex = indexOfFirstInstructionOrThrow { getReference()?.returnType == "Lokhttp3/HttpUrl;" @@ -81,9 +82,11 @@ val changeLyricsProviderPatch = bytecodePatch( httpClientBuilderFingerprint.classDef.methods.add(this) } } + //endregion // region Replace the call to the HTTP client builder method used exclusively for lyrics by the modified one. + getLyricsHttpClientFingerprint(httpClientBuilderMethod).method.apply { val getLyricsHttpClientIndex = indexOfFirstInstructionOrThrow { getReference() == httpClientBuilderMethod @@ -110,6 +113,7 @@ val changeLyricsProviderPatch = bytecodePatch( ) ) } + //endregion } } diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt index f7be30432d..ff74565c64 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/privacy/SanitizeSharingLinksPatch.kt @@ -26,9 +26,13 @@ val sanitizeSharingLinksPatch = bytecodePatch( val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" + "sanitizeUrl(Ljava/lang/String;)Ljava/lang/String;" - val copyMethod = shareCopyUrlFingerprint.methodOrNull ?: oldShareCopyUrlFingerprint.method + val copyFingerprint = if (shareCopyUrlFingerprint.originalMethodOrNull != null) { + shareCopyUrlFingerprint + } else { + oldShareCopyUrlFingerprint + } - copyMethod.apply { + copyFingerprint.method.apply { val newPlainTextInvokeIndex = indexOfFirstInstructionOrThrow { getReference()?.name == "newPlainText" } @@ -44,10 +48,10 @@ val sanitizeSharingLinksPatch = bytecodePatch( } // Android native share sheet is used for all other quick share types (X, WhatsApp, etc). - var shareUrlParameter = "" - val shareSheetMethod = formatAndroidShareSheetUrlFingerprint.methodOrNull?.also { - val methodAccessFlags = formatAndroidShareSheetUrlFingerprint.originalMethod.accessFlags - shareUrlParameter = if (AccessFlags.STATIC.isSet(methodAccessFlags)) { + val shareUrlParameter: String + val shareSheetFingerprint = if (formatAndroidShareSheetUrlFingerprint.originalMethodOrNull != null) { + val methodAccessFlags = formatAndroidShareSheetUrlFingerprint.originalMethod + shareUrlParameter = if (AccessFlags.STATIC.isSet(methodAccessFlags.accessFlags)) { // In newer implementations the method is static, so p0 is not `this`. "p1" } else { @@ -55,11 +59,14 @@ val sanitizeSharingLinksPatch = bytecodePatch( // For that reason, add one to the parameter register. "p2" } - } ?: oldFormatAndroidShareSheetUrlFingerprint.method.also { + + formatAndroidShareSheetUrlFingerprint + } else { shareUrlParameter = "p2" + oldFormatAndroidShareSheetUrlFingerprint } - shareSheetMethod.addInstructions( + shareSheetFingerprint.method.addInstructions( 0, """ invoke-static { $shareUrlParameter }, $extensionMethodDescriptor