feat(Twitter - Unlock downloads): Unlock GIF downloads
This commit is contained in:
parent
1a89dd9f8c
commit
d0f91c8550
|
@ -2,27 +2,36 @@ package app.revanced.patches.twitter.interaction.downloads
|
||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||||
|
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.getInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprintResult
|
import app.revanced.patcher.fingerprint.MethodFingerprintResult
|
||||||
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.patches.twitter.interaction.downloads.fingerprints.BuildMediaOptionsSheetFingerprint
|
||||||
import app.revanced.patches.twitter.interaction.downloads.fingerprints.ConstructMediaOptionsSheetFingerprint
|
import app.revanced.patches.twitter.interaction.downloads.fingerprints.ConstructMediaOptionsSheetFingerprint
|
||||||
import app.revanced.patches.twitter.interaction.downloads.fingerprints.ShowDownloadVideoUpsellBottomSheetFingerprint
|
import app.revanced.patches.twitter.interaction.downloads.fingerprints.ShowDownloadVideoUpsellBottomSheetFingerprint
|
||||||
import app.revanced.util.exception
|
import app.revanced.util.exception
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
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
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Unlock downloads",
|
name = "Unlock downloads",
|
||||||
description = "Unlocks the ability to download any video.",
|
description = "Unlocks the ability to download any video. GIFs can be downloaded via the menu on long press.",
|
||||||
compatiblePackages = [CompatiblePackage("com.twitter.android")]
|
compatiblePackages = [CompatiblePackage("com.twitter.android")],
|
||||||
)
|
)
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object UnlockDownloadsPatch : BytecodePatch(
|
object UnlockDownloadsPatch : BytecodePatch(
|
||||||
setOf(ConstructMediaOptionsSheetFingerprint, ShowDownloadVideoUpsellBottomSheetFingerprint)
|
setOf(
|
||||||
|
ConstructMediaOptionsSheetFingerprint,
|
||||||
|
ShowDownloadVideoUpsellBottomSheetFingerprint,
|
||||||
|
BuildMediaOptionsSheetFingerprint,
|
||||||
|
),
|
||||||
) {
|
) {
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
fun MethodFingerprint.patch(getRegisterAndIndex: MethodFingerprintResult.() -> Pair<Int, Int>) = result?.let {
|
fun MethodFingerprint.patch(getRegisterAndIndex: MethodFingerprintResult.() -> Pair<Int, Int>) = result?.let {
|
||||||
|
@ -46,5 +55,29 @@ object UnlockDownloadsPatch : BytecodePatch(
|
||||||
|
|
||||||
showDownloadButtonIndex to register
|
showDownloadButtonIndex to register
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make GIFs downloadable.
|
||||||
|
BuildMediaOptionsSheetFingerprint.result?.let {
|
||||||
|
val scanResult = it.scanResult.patternScanResult!!
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
val checkMediaTypeIndex = scanResult.startIndex
|
||||||
|
val checkMediaTypeInstruction = getInstruction<TwoRegisterInstruction>(checkMediaTypeIndex)
|
||||||
|
|
||||||
|
// Treat GIFs as videos.
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
checkMediaTypeIndex + 1,
|
||||||
|
"""
|
||||||
|
const/4 v${checkMediaTypeInstruction.registerB}, 0x2 # GIF
|
||||||
|
if-eq v${checkMediaTypeInstruction.registerA}, v${checkMediaTypeInstruction.registerB}, :video
|
||||||
|
""",
|
||||||
|
ExternalLabel("video", getInstruction(scanResult.endIndex)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Remove media.isDownloadable check.
|
||||||
|
removeInstruction(
|
||||||
|
getInstructions().first { insn -> insn.opcode == Opcode.IGET_BOOLEAN }.location.index + 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} ?: throw BuildMediaOptionsSheetFingerprint.exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package app.revanced.patches.twitter.interaction.downloads.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal object BuildMediaOptionsSheetFingerprint : MethodFingerprint(
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.IF_EQ,
|
||||||
|
Opcode.SGET_OBJECT,
|
||||||
|
Opcode.GOTO_16,
|
||||||
|
Opcode.NEW_INSTANCE,
|
||||||
|
),
|
||||||
|
strings = listOf("resources.getString(R.string.post_video)"),
|
||||||
|
)
|
Loading…
Reference in a new issue