feat(Instagram - Hide timeline ads): Make compatible with latest versions
This commit is contained in:
parent
dff4a3fa2d
commit
a212f29bd3
|
@ -1,102 +1,63 @@
|
||||||
package app.revanced.patches.instagram.patches.ads.timeline
|
package app.revanced.patches.instagram.patches.ads.timeline
|
||||||
|
|
||||||
import app.revanced.util.exception
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||||
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.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.MediaFingerprint
|
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckOneFingerprint
|
||||||
|
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.IsAdCheckTwoFingerprint
|
||||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ShowAdFingerprint
|
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ShowAdFingerprint
|
||||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.GenericMediaAdFingerprint
|
import app.revanced.util.exception
|
||||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.MediaAdFingerprint
|
|
||||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.PaidPartnershipAdFingerprint
|
|
||||||
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.ShoppingAdFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Hide timeline ads",
|
name = "Hide timeline ads",
|
||||||
description = "Removes ads from the timeline.",
|
compatiblePackages = [CompatiblePackage("com.instagram.android")],
|
||||||
compatiblePackages = [CompatiblePackage("com.instagram.android", ["275.0.0.27.98"])]
|
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object HideTimelineAdsPatch : BytecodePatch(
|
object HideTimelineAdsPatch : BytecodePatch(
|
||||||
setOf(
|
setOf(
|
||||||
ShowAdFingerprint,
|
ShowAdFingerprint,
|
||||||
MediaFingerprint,
|
IsAdCheckOneFingerprint,
|
||||||
PaidPartnershipAdFingerprint // Unlike the other ads this one is resolved from all classes.
|
IsAdCheckTwoFingerprint,
|
||||||
)
|
),
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
// region Resolve required methods to check for ads.
|
// The exact function of the following methods is unknown.
|
||||||
|
// They are used to check if a post is an ad.
|
||||||
|
val isAdCheckOneMethod = IsAdCheckOneFingerprint.result?.method ?: throw IsAdCheckOneFingerprint.exception
|
||||||
|
val isAdCheckTwoMethod = IsAdCheckTwoFingerprint.result?.method ?: throw IsAdCheckTwoFingerprint.exception
|
||||||
|
|
||||||
ShowAdFingerprint.result ?: throw ShowAdFingerprint.exception
|
ShowAdFingerprint.result?.let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
// The register that holds the post object.
|
||||||
|
val postRegister = getInstruction<FiveRegisterInstruction>(1).registerC
|
||||||
|
|
||||||
PaidPartnershipAdFingerprint.result ?: throw PaidPartnershipAdFingerprint.exception
|
// At this index the check for an ad can be performed.
|
||||||
|
val checkIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
|
|
||||||
MediaFingerprint.result?.let {
|
// If either check returns true, the post is an ad and is hidden by returning false.
|
||||||
GenericMediaAdFingerprint.resolve(context, it.classDef)
|
|
||||||
ShoppingAdFingerprint.resolve(context, it.classDef)
|
|
||||||
|
|
||||||
return@let
|
|
||||||
} ?: throw MediaFingerprint.exception
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
ShowAdFingerprint.result!!.apply {
|
|
||||||
// region Create instructions.
|
|
||||||
|
|
||||||
val scanStart = scanResult.patternScanResult!!.startIndex
|
|
||||||
val jumpIndex = scanStart - 1
|
|
||||||
|
|
||||||
val mediaInstanceRegister = mutableMethod.getInstruction<FiveRegisterInstruction>(scanStart).registerC
|
|
||||||
val freeRegister = mutableMethod.getInstruction<OneRegisterInstruction>(jumpIndex).registerA
|
|
||||||
|
|
||||||
val returnFalseLabel = "an_ad"
|
|
||||||
|
|
||||||
val checkForAdInstructions =
|
|
||||||
listOf(GenericMediaAdFingerprint, PaidPartnershipAdFingerprint, ShoppingAdFingerprint)
|
|
||||||
.map(MediaAdFingerprint::toString)
|
|
||||||
.joinToString("\n") {
|
|
||||||
"""
|
|
||||||
invoke-virtual {v$mediaInstanceRegister}, $it
|
|
||||||
move-result v$freeRegister
|
|
||||||
if-nez v$freeRegister, :$returnFalseLabel
|
|
||||||
""".trimIndent()
|
|
||||||
}.let { "$it\nconst/4 v0, 0x1\nreturn v0" }
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Patch.
|
|
||||||
|
|
||||||
val insertIndex = scanStart + 3
|
|
||||||
|
|
||||||
mutableMethod.addInstructionsWithLabels(
|
|
||||||
insertIndex,
|
|
||||||
checkForAdInstructions,
|
|
||||||
ExternalLabel(
|
|
||||||
returnFalseLabel,
|
|
||||||
mutableMethod.getInstruction(mutableMethod.implementation!!.instructions.size - 2 /* return false = ad */)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Jump to checks for ads from previous patch.
|
|
||||||
|
|
||||||
mutableMethod.apply {
|
|
||||||
addInstructionsWithLabels(
|
addInstructionsWithLabels(
|
||||||
jumpIndex + 1,
|
checkIndex,
|
||||||
"if-nez v$freeRegister, :start_check",
|
"""
|
||||||
ExternalLabel("start_check", getInstruction(insertIndex))
|
invoke-virtual { v$postRegister }, $isAdCheckOneMethod
|
||||||
)
|
move-result v0
|
||||||
}.removeInstruction(jumpIndex)
|
if-nez v0, :hide_ad
|
||||||
|
|
||||||
// endregion
|
invoke-static { v$postRegister }, $isAdCheckTwoMethod
|
||||||
|
move-result v0
|
||||||
|
if-eqz v0, :not_an_ad
|
||||||
|
|
||||||
|
:hide_ad
|
||||||
|
const/4 v0, 0x0 # Returning false to hide the ad.
|
||||||
|
return v0
|
||||||
|
""",
|
||||||
|
ExternalLabel("not_an_ad", getInstruction(checkIndex)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
} ?: throw ShowAdFingerprint.exception
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal object IsAdCheckOneFingerprint : MethodFingerprint(
|
||||||
|
returnType = "Z",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = listOf(),
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.XOR_INT_LIT8,
|
||||||
|
Opcode.IF_NE,
|
||||||
|
Opcode.RETURN,
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
),
|
||||||
|
)
|
|
@ -1,8 +1,14 @@
|
||||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
|
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal object GenericMediaAdFingerprint : MediaAdFingerprint(
|
internal object IsAdCheckTwoFingerprint : MethodFingerprint(
|
||||||
|
returnType = "Z",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
parameters = listOf("L"),
|
||||||
opcodes = listOf(
|
opcodes = listOf(
|
||||||
Opcode.INVOKE_INTERFACE,
|
Opcode.INVOKE_INTERFACE,
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
@ -12,7 +18,5 @@ internal object GenericMediaAdFingerprint : MediaAdFingerprint(
|
||||||
Opcode.IF_EQZ,
|
Opcode.IF_EQZ,
|
||||||
Opcode.CONST_4,
|
Opcode.CONST_4,
|
||||||
Opcode.RETURN,
|
Opcode.RETURN,
|
||||||
)
|
),
|
||||||
) {
|
)
|
||||||
override fun toString() = result!!.method.toString()
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
|
|
||||||
internal object MediaFingerprint : MethodFingerprint(
|
|
||||||
strings = listOf("force_overlay", "Media#updateFields", "live_reels_metadata")
|
|
||||||
)
|
|
|
@ -10,16 +10,12 @@ internal object ShowAdFingerprint : MethodFingerprint(
|
||||||
AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
|
AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
|
||||||
listOf("L", "L", "Z", "Z"),
|
listOf("L", "L", "Z", "Z"),
|
||||||
opcodes = listOf(
|
opcodes = listOf(
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.IF_NE,
|
||||||
|
Opcode.IF_NEZ,
|
||||||
Opcode.INVOKE_STATIC,
|
Opcode.INVOKE_STATIC,
|
||||||
Opcode.MOVE_RESULT,
|
Opcode.MOVE_RESULT,
|
||||||
Opcode.IF_NEZ,
|
Opcode.IF_NEZ,
|
||||||
Opcode.RETURN,
|
Opcode.RETURN,
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.GOTO,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.GOTO,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
Opcode.GOTO,
|
|
||||||
Opcode.CONST_4,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
|
||||||
import com.android.tools.smali.dexlib2.iface.Method
|
|
||||||
|
|
||||||
internal abstract class MediaAdFingerprint(
|
|
||||||
returnType: String? = "Z",
|
|
||||||
accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters: Iterable<String>? = listOf(),
|
|
||||||
opcodes: Iterable<Opcode>?,
|
|
||||||
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null
|
|
||||||
) : MethodFingerprint(
|
|
||||||
returnType,
|
|
||||||
accessFlags,
|
|
||||||
parameters,
|
|
||||||
opcodes,
|
|
||||||
customFingerprint = customFingerprint
|
|
||||||
) {
|
|
||||||
abstract override fun toString(): String
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
|
|
||||||
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|
||||||
|
|
||||||
internal object PaidPartnershipAdFingerprint : MediaAdFingerprint(
|
|
||||||
"V",
|
|
||||||
null,
|
|
||||||
listOf("L", "L"),
|
|
||||||
listOf(
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.IPUT_BOOLEAN,
|
|
||||||
Opcode.IPUT_BOOLEAN
|
|
||||||
),
|
|
||||||
customFingerprint = { methodDef, _ ->
|
|
||||||
methodDef.definingClass.endsWith("ClipsEditMetadataController;")
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
override fun toString() = result!!.let {
|
|
||||||
val adCheckIndex = it.scanResult.patternScanResult!!.startIndex
|
|
||||||
val adCheckInstruction = it.method.implementation!!.instructions.elementAt(adCheckIndex)
|
|
||||||
|
|
||||||
val adCheckMethod = (adCheckInstruction as ReferenceInstruction).reference as MethodReference
|
|
||||||
|
|
||||||
adCheckMethod.toString()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
|
|
||||||
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object ShoppingAdFingerprint : MediaAdFingerprint(
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
Opcode.IGET_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.XOR_INT_LIT8,
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
override fun toString() = result!!.method.toString()
|
|
||||||
}
|
|
Loading…
Reference in a new issue