diff --git a/patches/api/patches.api b/patches/api/patches.api index ee1d3f881..382490791 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -305,6 +305,10 @@ public final class app/revanced/patches/kakaotalk/misc/RemoveShopTabPatchKt { public static final fun getRemoveShopTabPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/kakaotalk/send/AllowReplyToFeedPatchKt { + public static final fun getAllowReplyToFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/kakaotalk/versioninfo/VersionInfoPatchKt { public static final fun getVersionInfoPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } diff --git a/patches/src/main/kotlin/app/revanced/patches/kakaotalk/send/AllowReplyToFeedPatch.kt b/patches/src/main/kotlin/app/revanced/patches/kakaotalk/send/AllowReplyToFeedPatch.kt new file mode 100644 index 000000000..7d04db0f4 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/kakaotalk/send/AllowReplyToFeedPatch.kt @@ -0,0 +1,44 @@ +package app.revanced.patches.kakaotalk.send + +import app.revanced.patcher.Fingerprint +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.instructions +import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction +import app.revanced.patches.kakaotalk.send.fingerprints.allowSwipeReplyToFeedFingerprint +import app.revanced.patches.kakaotalk.send.fingerprints.realActionForReplyFingerprint +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21t + +@Suppress("unused") +val allowReplyToFeedPatch = app.revanced.patcher.patch.bytecodePatch( + name = "Allow reply to feed", + description = "Allows replying to feed messages", +) { + compatibleWith("com.kakao.talk"("25.4.2")) + + execute { + val patch: (Fingerprint, String, Boolean) -> Unit = { fp, register, bool -> + val method = fp.method + val insns = method.instructions + + val idxIfnez = insns.indexOfFirst { it is Instruction21t && it.opcode == Opcode.IF_NEZ } + + val idxInvoke = insns.subList(0, idxIfnez) + .indexOfLast { it.opcode == Opcode.INVOKE_VIRTUAL } + + (idxInvoke until idxIfnez).toList() + .sortedDescending() + .forEach { method.removeInstruction(it) } + + method.addInstructions( + idxInvoke, + """ + const/4 $register, ${if (bool) "0x1" else "0x0"} + """.trimIndent() + ) + } + + patch(realActionForReplyFingerprint, "v0", false) + patch(allowSwipeReplyToFeedFingerprint, "p2", false) + } +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/kakaotalk/send/fingerprints/AllowReplyToFeedFingerprint.kt b/patches/src/main/kotlin/app/revanced/patches/kakaotalk/send/fingerprints/AllowReplyToFeedFingerprint.kt new file mode 100644 index 000000000..b86dc6f07 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/kakaotalk/send/fingerprints/AllowReplyToFeedFingerprint.kt @@ -0,0 +1,53 @@ +package app.revanced.patches.kakaotalk.send.fingerprints + +import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal val realActionForReplyFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) + returns("V") + strings( + "chatLog", + "chatRoom" + ) + opcodes( + Opcode.CONST_STRING, + Opcode.CONST_STRING, + Opcode.CONST, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_4, + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.SGET_OBJECT, + Opcode.IF_NE, + Opcode.GOTO_16 + ) +} + +internal val allowSwipeReplyToFeedFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameters("Landroidx/recyclerview/widget/RecyclerView;", "Landroidx/recyclerview/widget/RecyclerView\$D;") + returns("I") + strings("recyclerView", "viewHolder") + opcodes( + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.CONST_STRING, + Opcode.INVOKE_STATIC, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.CONST_4, + Opcode.CONST_4, + ) + custom { method, classDef -> method.name == "getMovementFlags" } +} \ No newline at end of file