feat(Spotify): Add Unlock premium patch (#4644)

Co-authored-by: Nuckyz <61953774+Nuckyz@users.noreply.github.com>
Co-authored-by: Brosssh <tiabroch@gmail.com>
This commit is contained in:
oSumAtrIX
2025-03-26 04:24:47 +01:00
committed by GitHub
parent bae80204c4
commit f048c50e56
11 changed files with 125 additions and 52 deletions

View File

@ -816,6 +816,10 @@ public final class app/revanced/patches/spotify/lite/ondemand/OnDemandPatchKt {
public static final fun getOnDemandPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/UnlockPremiumPatchKt {
public static final fun getUnlockPremiumPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}
public final class app/revanced/patches/spotify/misc/fix/SpoofSignaturePatchKt {
public static final fun getSpoofSignaturePatch ()Lapp/revanced/patcher/patch/BytecodePatch;
}

View File

@ -0,0 +1,18 @@
package app.revanced.patches.spotify.misc
import app.revanced.patcher.fingerprint
internal val accountAttributeFingerprint = fingerprint {
custom { _, c -> c.endsWith("internal/AccountAttribute;") }
}
internal val productStateProtoFingerprint = fingerprint {
returns("Ljava/util/Map;")
custom { _, classDef ->
classDef.endsWith("ProductStateProto;")
}
}
internal val buildQueryParametersFingerprint = fingerprint {
strings("trackRows", "device_type:tablet")
}

View File

@ -0,0 +1,36 @@
package app.revanced.patches.spotify.misc
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.AccessFlags
@Suppress("unused")
val unlockPremiumPatch = bytecodePatch(
name = "Unlock Spotify Premium",
description = "Unlock Spotify Premium features. Server-sided features like downloading songs are still locked.",
) {
compatibleWith("com.spotify.music")
extendWith("extensions/spotify.rve")
execute {
// Make _value accessible so that it can be overridden in the extension.
accountAttributeFingerprint.classDef.fields.first { it.name == "value_" }.apply {
accessFlags = accessFlags.or(AccessFlags.PUBLIC.value).and(AccessFlags.PRIVATE.value.inv())
}
// Override the attributes map in the getter method.
val attributesMapRegister = 0
val instantiateUnmodifiableMapIndex = 1
productStateProtoFingerprint.method.addInstruction(
instantiateUnmodifiableMapIndex,
"invoke-static { v$attributesMapRegister }," +
"Lapp/revanced/extension/spotify/misc/UnlockPremiumPatch;->overrideAttribute(Ljava/util/Map;)V",
)
// Add the query parameter trackRows to show popular tracks in the artist page.
val addQueryParameterIndex = buildQueryParametersFingerprint.stringMatches!!.first().index - 1
buildQueryParametersFingerprint.method.replaceInstruction(addQueryParameterIndex, "nop")
}
}

View File

@ -1,11 +0,0 @@
package app.revanced.patches.spotify.navbar
import app.revanced.patcher.fingerprint
import app.revanced.util.literal
import com.android.tools.smali.dexlib2.AccessFlags
internal val addNavBarItemFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("V")
literal { showBottomNavigationItemsTextId }
}

View File

@ -1,50 +1,12 @@
package app.revanced.patches.spotify.navbar
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.shared.misc.mapping.get
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
import app.revanced.patches.shared.misc.mapping.resourceMappings
internal var showBottomNavigationItemsTextId = -1L
private set
internal var premiumTabId = -1L
private set
private val premiumNavbarTabResourcePatch = resourcePatch {
dependsOn(resourceMappingPatch)
execute {
premiumTabId = resourceMappings["id", "premium_tab"]
showBottomNavigationItemsTextId = resourceMappings[
"bool",
"show_bottom_navigation_items_text",
]
}
}
import app.revanced.patches.spotify.misc.unlockPremiumPatch
@Deprecated("Superseded by unlockPremiumPatch", ReplaceWith("unlockPremiumPatch"))
@Suppress("unused")
val premiumNavbarTabPatch = bytecodePatch(
name = "Premium navbar tab",
description = "Hides the premium tab from the navigation bar.",
) {
dependsOn(premiumNavbarTabResourcePatch)
compatibleWith("com.spotify.music")
// If the navigation bar item is the premium tab, do not add it.
execute {
addNavBarItemFingerprint.method.addInstructions(
0,
"""
const v1, $premiumTabId
if-ne p5, v1, :continue
return-void
:continue
nop
""",
)
}
dependsOn(unlockPremiumPatch)
}