feat(Soundcloud): Add Hide ads
and Disable telemetry
patch (#3386)
Co-authored-by: bewzusore <bewzusore> Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
parent
d9395fdbca
commit
3c79f3d34d
|
@ -1032,6 +1032,18 @@ public final class app/revanced/patches/songpal/badge/RemoveNotificationBadgePat
|
||||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/soundcloud/ad/HideAdsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
|
public static final field INSTANCE Lapp/revanced/patches/soundcloud/ad/HideAdsPatch;
|
||||||
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/soundcloud/analytics/DisableTelemetryPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||||
|
public static final field INSTANCE Lapp/revanced/patches/soundcloud/analytics/DisableTelemetryPatch;
|
||||||
|
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||||
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/spotify/layout/theme/CustomThemePatch : app/revanced/patcher/patch/ResourcePatch {
|
public final class app/revanced/patches/spotify/layout/theme/CustomThemePatch : app/revanced/patcher/patch/ResourcePatch {
|
||||||
public static final field INSTANCE Lapp/revanced/patches/spotify/layout/theme/CustomThemePatch;
|
public static final field INSTANCE Lapp/revanced/patches/spotify/layout/theme/CustomThemePatch;
|
||||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package app.revanced.patches.soundcloud.ad
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
|
import app.revanced.patches.soundcloud.ad.fingerprints.InterceptFingerprint
|
||||||
|
import app.revanced.patches.soundcloud.ad.fingerprints.FeatureConstructorFingerprint
|
||||||
|
import app.revanced.patches.soundcloud.ad.fingerprints.UserConsumerPlanConstructorFingerprint
|
||||||
|
import app.revanced.util.resultOrThrow
|
||||||
|
|
||||||
|
@Patch(
|
||||||
|
name = "Hide ads",
|
||||||
|
compatiblePackages = [CompatiblePackage("com.soundcloud.android")],
|
||||||
|
)
|
||||||
|
@Suppress("unused")
|
||||||
|
object HideAdsPatch : BytecodePatch(
|
||||||
|
setOf(FeatureConstructorFingerprint, UserConsumerPlanConstructorFingerprint, InterceptFingerprint),
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext) {
|
||||||
|
// Enable a preset feature to disable audio ads by modifying the JSON server response.
|
||||||
|
// This method is the constructor of a class representing a "Feature" object parsed from JSON data.
|
||||||
|
// p1 is the name of the feature.
|
||||||
|
// p2 is true if the feature is enabled, false otherwise.
|
||||||
|
FeatureConstructorFingerprint.resultOrThrow().mutableMethod.apply {
|
||||||
|
val afterCheckNotNullIndex = 2
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
afterCheckNotNullIndex,
|
||||||
|
"""
|
||||||
|
const-string v0, "no_audio_ads"
|
||||||
|
invoke-virtual {p1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
|
||||||
|
move-result v0
|
||||||
|
if-eqz v0, :skip
|
||||||
|
const/4 p2, 0x1
|
||||||
|
""",
|
||||||
|
ExternalLabel("skip", getInstruction(afterCheckNotNullIndex)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite the JSON response from the server to a paid plan, which hides all ads in the app.
|
||||||
|
// This does not enable paid features, as they are all checked for on the backend.
|
||||||
|
// This method is the constructor of a class representing a "UserConsumerPlan" object parsed from JSON data.
|
||||||
|
// p1 is the "currentTier" value, dictating which features to enable in the app.
|
||||||
|
// p4 is the "consumerPlanUpsells" value, a list of plans to try to sell to the user.
|
||||||
|
// p5 is the "currentConsumerPlan" value, the type of plan currently subscribed to.
|
||||||
|
// p6 is the "currentConsumerPlanTitle" value, the name of the plan currently subscribed to, shown to the user.
|
||||||
|
UserConsumerPlanConstructorFingerprint.resultOrThrow().mutableMethod.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const-string p1, "high_tier"
|
||||||
|
new-instance p4, Ljava/util/ArrayList;
|
||||||
|
invoke-direct {p4}, Ljava/util/ArrayList;-><init>()V
|
||||||
|
const-string p5, "go-plus"
|
||||||
|
const-string p6, "SoundCloud Go+"
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Prevent verification of an HTTP header containing the user's current plan, which would contradict the previous patch.
|
||||||
|
InterceptFingerprint.resultOrThrow().let { result ->
|
||||||
|
val conditionIndex = result.scanResult.patternScanResult!!.endIndex
|
||||||
|
result.mutableMethod.addInstruction(
|
||||||
|
conditionIndex,
|
||||||
|
"return-object p1",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package app.revanced.patches.soundcloud.ad.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object FeatureConstructorFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
parameters = listOf("Ljava/lang/String;", "Z", "Ljava/util/List;"),
|
||||||
|
customFingerprint = { _, classDef ->
|
||||||
|
classDef.sourceFile == "Feature.kt"
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,22 @@
|
||||||
|
package app.revanced.patches.soundcloud.ad.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal object InterceptFingerprint : MethodFingerprint(
|
||||||
|
returnType = "L",
|
||||||
|
accessFlags = AccessFlags.PUBLIC.value,
|
||||||
|
parameters = listOf("L"),
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_EQZ,
|
||||||
|
),
|
||||||
|
strings = listOf("SC-Mob-UserPlan", "Configuration"),
|
||||||
|
customFingerprint = { _, classDef ->
|
||||||
|
classDef.sourceFile == "ApiUserPlanInterceptor.java"
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,14 @@
|
||||||
|
package app.revanced.patches.soundcloud.ad.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object UserConsumerPlanConstructorFingerprint : MethodFingerprint(
|
||||||
|
returnType = "V",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
parameters = listOf("Ljava/lang/String;", "Z", "Ljava/lang/String;", "Ljava/util/List;", "Ljava/lang/String;", "Ljava/lang/String;"),
|
||||||
|
customFingerprint = { _, classDef ->
|
||||||
|
classDef.sourceFile == "UserConsumerPlan.kt"
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,24 @@
|
||||||
|
package app.revanced.patches.soundcloud.analytics
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patches.soundcloud.analytics.fingerprints.CreateTrackingApiFingerprint
|
||||||
|
import app.revanced.util.resultOrThrow
|
||||||
|
|
||||||
|
@Patch(
|
||||||
|
name = "Disable telemetry",
|
||||||
|
description = "Disables SoundCloud's telemetry system.",
|
||||||
|
compatiblePackages = [CompatiblePackage("com.soundcloud.android")],
|
||||||
|
)
|
||||||
|
@Suppress("unused")
|
||||||
|
object DisableTelemetryPatch : BytecodePatch(
|
||||||
|
setOf(CreateTrackingApiFingerprint),
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext) =
|
||||||
|
// Empty the "backend" argument to abort the initializer.
|
||||||
|
CreateTrackingApiFingerprint.resultOrThrow()
|
||||||
|
.mutableMethod.addInstruction(0, "const-string p1, \"\"")
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package app.revanced.patches.soundcloud.analytics.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
internal object CreateTrackingApiFingerprint : MethodFingerprint(
|
||||||
|
returnType = "L",
|
||||||
|
accessFlags = AccessFlags.PUBLIC.value,
|
||||||
|
customFingerprint = { methodDef, classDef ->
|
||||||
|
classDef.sourceFile == "DefaultTrackingApiFactory.kt" && methodDef.name == "create"
|
||||||
|
},
|
||||||
|
)
|
Loading…
Reference in a new issue