mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-04-29 22:24:27 +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) {
|
||||
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) {
|
||||
try {
|
||||
|
@ -35,6 +35,27 @@ internal val contextMenuExperimentsFingerprint = fingerprint {
|
||||
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 {
|
||||
custom { _, classDef -> classDef.endsWith("homeapi/proto/Section;") }
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app.revanced.patches.spotify.misc
|
||||
|
||||
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.removeInstruction
|
||||
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.patches.spotify.misc.extension.IS_SPOTIFY_LEGACY_APP_TARGET
|
||||
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.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.TwoRegisterInstruction
|
||||
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.
|
||||
with(buildQueryParametersFingerprint) {
|
||||
val addQueryParameterConditionIndex = method.indexOfFirstInstructionReversedOrThrow(
|
||||
@ -55,12 +60,50 @@ val unlockPremiumPatch = bytecodePatch(
|
||||
method.replaceInstruction(addQueryParameterConditionIndex, "nop")
|
||||
}
|
||||
|
||||
|
||||
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."
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// 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.
|
||||
with(contextMenuExperimentsFingerprint) {
|
||||
val moveIsEnabledIndex = method.indexOfFirstInstructionOrThrow(
|
||||
@ -70,6 +113,7 @@ val unlockPremiumPatch = bytecodePatch(
|
||||
method.replaceInstruction(moveIsEnabledIndex, "const/4 v$isUpsellEnabledRegister, 0")
|
||||
}
|
||||
|
||||
|
||||
// Make featureTypeCase_ accessible so we can check the home section type in the extension.
|
||||
homeSectionFingerprint.classDef.fields.first { it.name == "featureTypeCase_" }.apply {
|
||||
accessFlags = accessFlags.or(AccessFlags.PUBLIC.value).and(AccessFlags.PRIVATE.value.inv())
|
||||
|
Loading…
x
Reference in New Issue
Block a user