From 2c20844eaae698f185a9d321e2c70bde4b485cee Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 8 Feb 2024 20:11:18 +0100 Subject: [PATCH] feat(X): Add `Unlock downloads` patch --- api/revanced-patches.api | 6 +++ .../downloads/UnlockDownloadsPatch.kt | 50 +++++++++++++++++++ .../ConstructMediaOptionsSheetFingerprint.kt | 12 +++++ ...wnloadVideoUpsellBottomSheetFingerprint.kt | 10 ++++ 4 files changed, 78 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/fingerprints/ConstructMediaOptionsSheetFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/fingerprints/ShowDownloadVideoUpsellBottomSheetFingerprint.kt diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 262eb3e948..10956e60cb 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -1065,6 +1065,12 @@ public final class app/revanced/patches/twitch/misc/settings/SettingsResourcePat public static final field INSTANCE Lapp/revanced/patches/twitch/misc/settings/SettingsResourcePatch; } +public final class app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch; + 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/twitter/layout/viewcount/HideViewCountPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/twitter/layout/viewcount/HideViewCountPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V diff --git a/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt new file mode 100644 index 0000000000..ee13fab686 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt @@ -0,0 +1,50 @@ +package app.revanced.patches.twitter.interaction.downloads + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstructions +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprintResult +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.twitter.interaction.downloads.fingerprints.ConstructMediaOptionsSheetFingerprint +import app.revanced.patches.twitter.interaction.downloads.fingerprints.ShowDownloadVideoUpsellBottomSheetFingerprint +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction + +@Patch( + name = "Unlock downloads", + description = "Unlocks the ability to download any video.", + compatiblePackages = [CompatiblePackage("com.twitter.android")] +) +@Suppress("unused") +object UnlockDownloadsPatch : BytecodePatch( + setOf(ConstructMediaOptionsSheetFingerprint, ShowDownloadVideoUpsellBottomSheetFingerprint) +) { + override fun execute(context: BytecodeContext) { + fun MethodFingerprint.patch(getRegisterAndIndex: MethodFingerprintResult.() -> Pair) = result?.let { + getRegisterAndIndex(it).let { (index, register) -> + it.mutableMethod.addInstruction(index, "const/4 v$register, 0x1") + } + } ?: throw exception + + // Allow downloads for non-premium users. + ShowDownloadVideoUpsellBottomSheetFingerprint.patch { + val checkIndex = scanResult.patternScanResult!!.startIndex + val register = mutableMethod.getInstruction(checkIndex).registerA + + checkIndex to register + } + + // Force show the download menu item. + ConstructMediaOptionsSheetFingerprint.patch { + val showDownloadButtonIndex = mutableMethod.getInstructions().lastIndex - 1 + val register = mutableMethod.getInstruction(showDownloadButtonIndex).registerA + + showDownloadButtonIndex to register + } + } +} diff --git a/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/fingerprints/ConstructMediaOptionsSheetFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/fingerprints/ConstructMediaOptionsSheetFingerprint.kt new file mode 100644 index 0000000000..86b2a247bb --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/fingerprints/ConstructMediaOptionsSheetFingerprint.kt @@ -0,0 +1,12 @@ +package app.revanced.patches.twitter.interaction.downloads.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags + + +internal object ConstructMediaOptionsSheetFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, + strings = listOf("captionsState") +) diff --git a/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/fingerprints/ShowDownloadVideoUpsellBottomSheetFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/fingerprints/ShowDownloadVideoUpsellBottomSheetFingerprint.kt new file mode 100644 index 0000000000..1257d0f58e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/fingerprints/ShowDownloadVideoUpsellBottomSheetFingerprint.kt @@ -0,0 +1,10 @@ +package app.revanced.patches.twitter.interaction.downloads.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +internal object ShowDownloadVideoUpsellBottomSheetFingerprint : MethodFingerprint( + returnType = "Z", + strings = listOf("variantToDownload.url"), + opcodes = listOf(Opcode.IF_EQZ) +)