From ccbe91d3f34e38cd38d838a294f32eaaea85bf8f Mon Sep 17 00:00:00 2001 From: inotia00 Date: Tue, 20 Jun 2023 17:21:01 +0900 Subject: [PATCH] feat(youtube): add `hide-suggestions-shelf` patch --- .../fingerprints/BreakingNewsFingerprint.kt | 16 ++++ .../patch/SuggestionsShelfPatch.kt | 67 +++++++++++++++ .../fingerprints/NavBarBuilderFingerprint.kt | 26 ++++++ .../fingerprints/TopBarButtonFingerprint.kt | 19 +++++ .../navbarindex/patch/NavBarIndexPatch.kt | 84 +++++++++++++++++++ 5 files changed, 212 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/BreakingNewsFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/general/suggestions/patch/SuggestionsShelfPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/fingerprints/NavBarBuilderFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/fingerprints/TopBarButtonFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/patch/NavBarIndexPatch.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/BreakingNewsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/BreakingNewsFingerprint.kt new file mode 100644 index 000000000..bfec07db9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/fingerprints/BreakingNewsFingerprint.kt @@ -0,0 +1,16 @@ +package app.revanced.patches.youtube.general.suggestions.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.youtube.utils.resourceid.patch.SharedResourceIdPatch.Companion.HorizontalCardList +import app.revanced.util.bytecode.isWideLiteralExists +import org.jf.dexlib2.Opcode + +object BreakingNewsFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.CONST, + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT + ), + customFingerprint = { it, _ -> it.isWideLiteralExists(HorizontalCardList) } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/patch/SuggestionsShelfPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/patch/SuggestionsShelfPatch.kt new file mode 100644 index 000000000..f1b0217f4 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/general/suggestions/patch/SuggestionsShelfPatch.kt @@ -0,0 +1,67 @@ +package app.revanced.patches.youtube.general.suggestions.patch + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patches.shared.annotation.YouTubeCompatibility +import app.revanced.patches.youtube.general.suggestions.fingerprints.BreakingNewsFingerprint +import app.revanced.patches.youtube.utils.litho.patch.LithoFilterPatch +import app.revanced.patches.youtube.utils.navbarindex.patch.NavBarIndexPatch +import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch +import app.revanced.util.integrations.Constants.GENERAL +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch +@Name("hide-suggestions-shelf") +@Description("Hides the suggestions shelf.") +@DependsOn( + [ + LithoFilterPatch::class, + NavBarIndexPatch::class, + SettingsPatch::class + ] +) +@YouTubeCompatibility +@Version("0.0.1") +class SuggestionsShelfPatch : BytecodePatch( + listOf(BreakingNewsFingerprint) +) { + override fun execute(context: BytecodeContext): PatchResult { + + BreakingNewsFingerprint.result?.let { + it.mutableMethod.apply { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + val targetRegister = getInstruction(targetIndex).registerA + + addInstruction( + targetIndex + 1, + "invoke-static {v$targetRegister}, $GENERAL->hideBreakingNewsShelf(Landroid/view/View;)V" + ) + } + } ?: return BreakingNewsFingerprint.toErrorResult() + + + /** + * Add settings + */ + SettingsPatch.addPreference( + arrayOf( + "PREFERENCE: GENERAL_SETTINGS", + "SETTINGS: HIDE_SUGGESTIONS_SHELF" + ) + ) + + SettingsPatch.updatePatchStatus("hide-suggestions-shelf") + + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/fingerprints/NavBarBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/fingerprints/NavBarBuilderFingerprint.kt new file mode 100644 index 000000000..aaf0c395d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/fingerprints/NavBarBuilderFingerprint.kt @@ -0,0 +1,26 @@ +package app.revanced.patches.youtube.utils.navbarindex.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +object NavBarBuilderFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC.value, + parameters = listOf("L"), + opcodes = listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.CONST_4, + Opcode.INVOKE_STATIC, + Opcode.INVOKE_VIRTUAL, + Opcode.INVOKE_VIRTUAL, + Opcode.NEW_INSTANCE + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/fingerprints/TopBarButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/fingerprints/TopBarButtonFingerprint.kt new file mode 100644 index 000000000..241b51996 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/fingerprints/TopBarButtonFingerprint.kt @@ -0,0 +1,19 @@ +package app.revanced.patches.youtube.utils.navbarindex.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +object TopBarButtonFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("L"), + opcodes = listOf( + Opcode.CONST_HIGH16, + Opcode.AND_INT_2ADDR, + Opcode.IF_EQZ + ), + strings = listOf("parent_csn", "parent_ve_type"), + customFingerprint = { it, _ -> it.name == "onClick" } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/patch/NavBarIndexPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/patch/NavBarIndexPatch.kt new file mode 100644 index 000000000..b3f659975 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/navbarindex/patch/NavBarIndexPatch.kt @@ -0,0 +1,84 @@ +package app.revanced.patches.youtube.utils.navbarindex.patch + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +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.getInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patches.shared.annotation.YouTubeCompatibility +import app.revanced.patches.shared.fingerprints.OnBackPressedFingerprint +import app.revanced.patches.youtube.utils.navbarindex.fingerprints.NavBarBuilderFingerprint +import app.revanced.patches.youtube.utils.navbarindex.fingerprints.TopBarButtonFingerprint +import app.revanced.patches.youtube.utils.resourceid.patch.SharedResourceIdPatch +import app.revanced.util.integrations.Constants.UTILS_PATH +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction +import org.jf.dexlib2.iface.instruction.ReferenceInstruction +import org.jf.dexlib2.iface.instruction.formats.Instruction35c +import org.jf.dexlib2.iface.reference.MethodReference + +@Name("hook-navbar-index-patch") +@DependsOn([SharedResourceIdPatch::class]) +@YouTubeCompatibility +@Version("0.0.1") +class NavBarIndexPatch : BytecodePatch( + listOf( + NavBarBuilderFingerprint, + OnBackPressedFingerprint, + TopBarButtonFingerprint + ) +) { + override fun execute(context: BytecodeContext): PatchResult { + + arrayOf( + OnBackPressedFingerprint, + TopBarButtonFingerprint + ).forEach { fingerprint -> + fingerprint.result?.let { + it.mutableMethod.apply { + addInstructions( + 0, """ + const/4 v0, 0x0 + invoke-static {v0}, $UTILS_PATH/NavBarIndexPatch;->setNavBarIndex(I)V + """ + ) + } + } ?: return fingerprint.toErrorResult() + } + + NavBarBuilderFingerprint.result?.let { + val endIndex = it.scanResult.patternScanResult!!.endIndex + val onClickListener = it.mutableMethod.getInstruction(endIndex).reference.toString() + + val targetMethod = context.findClass(onClickListener)?.mutableClass?.methods?.first { method -> method.name == "onClick" } + + targetMethod?.apply { + for ((index, instruction) in implementation!!.instructions.withIndex()) { + if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue + + val invokeInstruction = instruction as Instruction35c + if ((invokeInstruction.reference as MethodReference).name != "indexOf") continue + + val targetIndex = index + 2 + if (getInstruction(targetIndex).opcode != Opcode.INVOKE_VIRTUAL) continue + + val targetRegister = getInstruction(index + 1).registerA + + addInstruction( + targetIndex, + "invoke-static {v$targetRegister}, $UTILS_PATH/NavBarIndexPatch;->setNavBarIndex(I)V" + ) + break + } + } + } ?: return NavBarBuilderFingerprint.toErrorResult() + + return PatchResultSuccess() + } +} \ No newline at end of file