mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-05-01 23:24:29 +02:00
fix(Spotify - Unlock Spotify Premium): Remove restrictions for Google voice assistant (#4702)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
parent
e5ffd2c353
commit
106202f9eb
@ -94,7 +94,7 @@ public final class UnlockPremiumPatch {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override attributes injection point.
|
* Injection point. Override account attributes.
|
||||||
*/
|
*/
|
||||||
public static void overrideAttribute(Map<String, /*AccountAttribute*/ Object> attributes) {
|
public static void overrideAttribute(Map<String, /*AccountAttribute*/ Object> attributes) {
|
||||||
try {
|
try {
|
||||||
@ -119,7 +119,14 @@ public final class UnlockPremiumPatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove ads sections from home injection point.
|
* Injection point. Remove station data from Google assistant URI.
|
||||||
|
*/
|
||||||
|
public static String removeStationString(String spotifyUriOrUrl) {
|
||||||
|
return spotifyUriOrUrl.replace("spotify:station:", "spotify:");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point. Remove ads sections from home.
|
||||||
*/
|
*/
|
||||||
public static void removeHomeSections(List<Section> sections) {
|
public static void removeHomeSections(List<Section> sections) {
|
||||||
try {
|
try {
|
||||||
|
@ -35,6 +35,27 @@ internal val contextMenuExperimentsFingerprint = fingerprint {
|
|||||||
strings("remove_ads_upsell_enabled")
|
strings("remove_ads_upsell_enabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal val contextFromJsonFingerprint = fingerprint {
|
||||||
|
opcodes(
|
||||||
|
Opcode.INVOKE_STATIC,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_STATIC
|
||||||
|
)
|
||||||
|
custom { methodDef, classDef ->
|
||||||
|
methodDef.name == "fromJson" &&
|
||||||
|
classDef.endsWith("voiceassistants/playermodels/ContextJsonAdapter;")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val readPlayerOptionOverridesFingerprint = fingerprint {
|
||||||
|
custom { methodDef, classDef ->
|
||||||
|
methodDef.name == "readPlayerOptionOverrides" &&
|
||||||
|
classDef.endsWith("voiceassistants/playermodels/PreparePlayOptionsJsonAdapter;")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal val homeSectionFingerprint = fingerprint {
|
internal val homeSectionFingerprint = fingerprint {
|
||||||
custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") }
|
custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") }
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package app.revanced.patches.spotify.misc
|
package app.revanced.patches.spotify.misc
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||||
@ -8,9 +9,12 @@ import app.revanced.patcher.fingerprint
|
|||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
|
import app.revanced.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
|
||||||
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.spotify.misc.extension.sharedExtensionPatch
|
||||||
import app.revanced.util.*
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
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.FieldReference
|
||||||
@ -47,6 +51,7 @@ val unlockPremiumPatch = bytecodePatch(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add the query parameter trackRows to show popular tracks in the artist page.
|
// Add the query parameter trackRows to show popular tracks in the artist page.
|
||||||
with(buildQueryParametersFingerprint) {
|
with(buildQueryParametersFingerprint) {
|
||||||
val addQueryParameterConditionIndex = method.indexOfFirstInstructionReversedOrThrow(
|
val addQueryParameterConditionIndex = method.indexOfFirstInstructionReversedOrThrow(
|
||||||
@ -55,12 +60,50 @@ val unlockPremiumPatch = bytecodePatch(
|
|||||||
method.replaceInstruction(addQueryParameterConditionIndex, "nop")
|
method.replaceInstruction(addQueryParameterConditionIndex, "nop")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
|
if (IS_SPOTIFY_LEGACY_APP_TARGET) {
|
||||||
return@execute Logger.getLogger(this::class.java.name).info(
|
return@execute Logger.getLogger(this::class.java.name).warning(
|
||||||
"Patching a legacy Spotify version. Patch functionality may be limited."
|
"Patching a legacy Spotify version. Patch functionality may be limited."
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Enable choosing a specific song/artist via Google Assistant.
|
||||||
|
contextFromJsonFingerprint.method.apply {
|
||||||
|
val insertIndex = contextFromJsonFingerprint.patternMatch!!.startIndex
|
||||||
|
// Both the URI and URL need to be modified.
|
||||||
|
val registerUrl = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
|
||||||
|
val registerUri = getInstruction<FiveRegisterInstruction>(insertIndex + 2).registerD
|
||||||
|
|
||||||
|
val extensionMethodDescriptor = "$EXTENSION_CLASS_DESCRIPTOR->" +
|
||||||
|
"removeStationString(Ljava/lang/String;)Ljava/lang/String;"
|
||||||
|
|
||||||
|
addInstructions(
|
||||||
|
insertIndex,
|
||||||
|
"""
|
||||||
|
invoke-static { v$registerUrl }, $extensionMethodDescriptor
|
||||||
|
move-result-object v$registerUrl
|
||||||
|
invoke-static { v$registerUri }, $extensionMethodDescriptor
|
||||||
|
move-result-object v$registerUri
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Disable forced shuffle when asking for an album/playlist via Google Assistant.
|
||||||
|
readPlayerOptionOverridesFingerprint.method.apply {
|
||||||
|
val shufflingContextCallIndex = indexOfFirstInstructionOrThrow {
|
||||||
|
getReference<MethodReference>()?.name == "shufflingContext"
|
||||||
|
}
|
||||||
|
|
||||||
|
val registerBool = getInstruction<FiveRegisterInstruction>(shufflingContextCallIndex).registerD
|
||||||
|
addInstruction(
|
||||||
|
shufflingContextCallIndex,
|
||||||
|
"sget-object v$registerBool, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Disable the "Spotify Premium" upsell experiment in context menus.
|
// Disable the "Spotify Premium" upsell experiment in context menus.
|
||||||
with(contextMenuExperimentsFingerprint) {
|
with(contextMenuExperimentsFingerprint) {
|
||||||
val moveIsEnabledIndex = method.indexOfFirstInstructionOrThrow(
|
val moveIsEnabledIndex = method.indexOfFirstInstructionOrThrow(
|
||||||
@ -70,6 +113,7 @@ val unlockPremiumPatch = bytecodePatch(
|
|||||||
method.replaceInstruction(moveIsEnabledIndex, "const/4 v$isUpsellEnabledRegister, 0")
|
method.replaceInstruction(moveIsEnabledIndex, "const/4 v$isUpsellEnabledRegister, 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Make featureTypeCase_ accessible so we can check the home section type in the extension.
|
// Make featureTypeCase_ accessible so we can check the home section type in the extension.
|
||||||
homeSectionFingerprint.classDef.fields.first { it.name == "featureTypeCase_" }.apply {
|
homeSectionFingerprint.classDef.fields.first { it.name == "featureTypeCase_" }.apply {
|
||||||
accessFlags = accessFlags.or(AccessFlags.PUBLIC.value).and(AccessFlags.PRIVATE.value.inv())
|
accessFlags = accessFlags.or(AccessFlags.PUBLIC.value).and(AccessFlags.PRIVATE.value.inv())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user