From 10e028626f2b9d9d01279682198daf135bc82c20 Mon Sep 17 00:00:00 2001 From: d4rkk3y <43563783+d4rkk3y@users.noreply.github.com> Date: Thu, 22 Sep 2022 04:00:03 +0700 Subject: [PATCH] feat: `tiktok-feed-filter` , `tiktok-settings` and `tiktok-force-login` patch (#501) --- .../annotations/FeedFilterCompatibility.kt | 14 +++ .../FeedApiServiceLIZFingerprint.kt | 23 +++++ .../feedfilter/patch/TiktokFeedFilter.kt | 51 ++++++++++ .../DisableForceLoginCompatibility.kt | 14 +++ .../MandatoryLoginServiceFingerprint.kt | 18 ++++ .../MandatoryLoginServiceFingerprint2.kt | 18 ++++ .../patch/DisableForceLoginPatch.kt | 43 ++++++++ .../TikTokIntegrationsCompatibility.kt | 14 +++ .../fingerprints/InitFingerprint.kt | 20 ++++ .../patch/TikTokIntegrationsPatch.kt | 38 +++++++ .../TikTokSettingsCompatibility.kt | 14 +++ .../AdPersonalizationActivityFingerprint.kt | 21 ++++ .../CopyRightSettingsStringFingerprint.kt | 21 ++++ .../SettingsStatusLoadFingerprint.kt | 21 ++++ .../settings/patch/TikTokSettingsPatch.kt | 98 +++++++++++++++++++ 15 files changed, 428 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/TiktokFeedFilter.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/annotations/DisableForceLoginCompatibility.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint2.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/patch/DisableForceLoginPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/annotations/TikTokIntegrationsCompatibility.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/TikTokSettingsCompatibility.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/CopyRightSettingsStringFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/TikTokSettingsPatch.kt diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt new file mode 100644 index 000000000..d33f69851 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.tiktok.feedfilter.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [ + Package("com.ss.android.ugc.trill"), + Package("com.zhiliaoapp.musically") + ] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class FeedFilterCompatibility diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt new file mode 100644 index 000000000..987299029 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt @@ -0,0 +1,23 @@ +package app.revanced.patches.tiktok.feedfilter.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.tiktok.feedfilter.annotations.FeedFilterCompatibility +import org.jf.dexlib2.AccessFlags + +@Name("feed-api-service-fingerprint") +@MatchingMethod( + "Lcom/ss/android/ugc/aweme/feed/FeedApiService;", + "LIZ", +) +@FeedFilterCompatibility +@Version("0.0.1") +object FeedApiServiceLIZFingerprint : MethodFingerprint( + access = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL or AccessFlags.SYNTHETIC, + customFingerprint = { methodDef -> + methodDef.definingClass.endsWith("/FeedApiService;") && methodDef.name == "LIZ" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/TiktokFeedFilter.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/TiktokFeedFilter.kt new file mode 100644 index 000000000..a31ed3b3b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/TiktokFeedFilter.kt @@ -0,0 +1,51 @@ +package app.revanced.patches.tiktok.feedfilter.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.impl.BytecodeData +import app.revanced.patcher.extensions.addInstruction +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.patcher.patch.impl.BytecodePatch +import app.revanced.patches.tiktok.feedfilter.annotations.FeedFilterCompatibility +import app.revanced.patches.tiktok.feedfilter.fingerprints.FeedApiServiceLIZFingerprint +import app.revanced.patches.tiktok.misc.integrations.patch.TikTokIntegrationsPatch +import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint +import app.revanced.patches.tiktok.misc.settings.patch.TikTokSettingsPatch +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch +@DependsOn([TikTokIntegrationsPatch::class, TikTokSettingsPatch::class]) +@Name("tiktok-feed-filter") +@Description("Filters tiktok videos: removing ads, removing livestreams.") +@FeedFilterCompatibility +@Version("0.0.1") +class TiktokFeedFilter : BytecodePatch( + listOf( + FeedApiServiceLIZFingerprint, + SettingsStatusLoadFingerprint + ) +) { + override fun execute(data: BytecodeData): PatchResult { + val method = FeedApiServiceLIZFingerprint.result!!.mutableMethod + for ((index, instruction) in method.implementation!!.instructions.withIndex()) { + if (instruction.opcode != Opcode.RETURN_OBJECT) continue + val feedItemsRegister = (instruction as OneRegisterInstruction).registerA + method.addInstruction( + index, + "invoke-static {v$feedItemsRegister}, Lapp/revanced/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V" + ) + break + } + val method2 = SettingsStatusLoadFingerprint.result!!.mutableMethod + method2.addInstruction( + 0, + "invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableFeedFilter()V" + ) + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/annotations/DisableForceLoginCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/annotations/DisableForceLoginCompatibility.kt new file mode 100644 index 000000000..eaf11e684 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/annotations/DisableForceLoginCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.tiktok.misc.forcelogin.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [ + Package("com.ss.android.ugc.trill"), + Package("com.zhiliaoapp.musically") + ] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class DisableForceLoginCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint.kt new file mode 100644 index 000000000..8c1b85847 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint.kt @@ -0,0 +1,18 @@ +package app.revanced.patches.tiktok.misc.forcelogin.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.tiktok.misc.forcelogin.annotations.DisableForceLoginCompatibility + +@Name("mandatory-login-service-fingerprint") +@MatchingMethod("/MandatoryLoginService;", "enableForcedLogin") +@DisableForceLoginCompatibility +@Version("0.0.1") +object MandatoryLoginServiceFingerprint : MethodFingerprint( + customFingerprint = { methodDef -> + methodDef.definingClass.endsWith("/MandatoryLoginService;") && + methodDef.name == "enableForcedLogin" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint2.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint2.kt new file mode 100644 index 000000000..7c3e51edc --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint2.kt @@ -0,0 +1,18 @@ +package app.revanced.patches.tiktok.misc.forcelogin.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.tiktok.misc.forcelogin.annotations.DisableForceLoginCompatibility + +@Name("mandatory-login-service-fingerprint2") +@MatchingMethod("/MandatoryLoginService;", "shouldShowForcedLogin") +@DisableForceLoginCompatibility +@Version("0.0.1") +object MandatoryLoginServiceFingerprint2 : MethodFingerprint( + customFingerprint = { methodDef -> + methodDef.definingClass.endsWith("/MandatoryLoginService;") && + methodDef.name == "shouldShowForcedLogin" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/patch/DisableForceLoginPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/patch/DisableForceLoginPatch.kt new file mode 100644 index 000000000..8f36d5d1d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/patch/DisableForceLoginPatch.kt @@ -0,0 +1,43 @@ +package app.revanced.patches.tiktok.misc.forcelogin.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.impl.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.impl.BytecodePatch +import app.revanced.patches.tiktok.misc.forcelogin.annotations.DisableForceLoginCompatibility +import app.revanced.patches.tiktok.misc.forcelogin.fingerprints.MandatoryLoginServiceFingerprint +import app.revanced.patches.tiktok.misc.forcelogin.fingerprints.MandatoryLoginServiceFingerprint2 + +@Patch +@Name("tiktok-force-login") +@Description("Do not force login.") +@DisableForceLoginCompatibility +@Version("0.0.1") +class DisableForceLoginPatch : BytecodePatch( + listOf( + MandatoryLoginServiceFingerprint, + MandatoryLoginServiceFingerprint2 + ) +) { + override fun execute(data: BytecodeData): PatchResult { + listOf( + MandatoryLoginServiceFingerprint, + MandatoryLoginServiceFingerprint2 + ).forEach { fingerprint -> + val method = fingerprint.result!!.mutableMethod + method.addInstructions( + 0, + """ + const/4 v0, 0x0 + return v0 + """ + ) + } + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/annotations/TikTokIntegrationsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/annotations/TikTokIntegrationsCompatibility.kt new file mode 100644 index 000000000..5b1c277e6 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/annotations/TikTokIntegrationsCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.tiktok.misc.integrations.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [ + Package("com.ss.android.ugc.trill"), + Package("com.zhiliaoapp.musically") + ] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class TikTokIntegrationsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt new file mode 100644 index 000000000..eb9189665 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt @@ -0,0 +1,20 @@ +package app.revanced.patches.tiktok.misc.integrations.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.tiktok.misc.integrations.annotations.TikTokIntegrationsCompatibility + +@Name("init-fingerprint") +@MatchingMethod( + "Lcom/ss/android/ugc/aweme/app/host/AwemeHostApplication;", "onCreate" +) +@TikTokIntegrationsCompatibility +@Version("0.0.1") +object InitFingerprint : MethodFingerprint( + customFingerprint = { methodDef -> + methodDef.definingClass.endsWith("/AwemeHostApplication;") && + methodDef.name == "onCreate" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt new file mode 100644 index 000000000..14e6ba1b0 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt @@ -0,0 +1,38 @@ +package app.revanced.patches.tiktok.misc.integrations.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.impl.BytecodeData +import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultError +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.impl.BytecodePatch +import app.revanced.patches.tiktok.misc.integrations.annotations.TikTokIntegrationsCompatibility +import app.revanced.patches.tiktok.misc.integrations.fingerprints.InitFingerprint + +@Name("tiktok-integrations") +@Description("Applies mandatory patches to implement the ReVanced integrations into the application.") +@TikTokIntegrationsCompatibility +@Version("0.0.1") +class TikTokIntegrationsPatch : BytecodePatch( + listOf( + InitFingerprint + ) +) { + override fun execute(data: BytecodeData): PatchResult { + if (data.findClass("Lapp/revanced/tiktok/utils/ReVancedUtils") == null) + return PatchResultError("Integrations have not been merged yet. This patch can not succeed without the integrations.") + val result = InitFingerprint.result!! + + val method = result.mutableMethod + val implementation = method.implementation!! + val count = implementation.registerCount - 1 + + method.addInstruction( + 0, "sput-object v$count, Lapp/revanced/tiktok/utils/ReVancedUtils;->context:Landroid/content/Context;" + ) + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/TikTokSettingsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/TikTokSettingsCompatibility.kt new file mode 100644 index 000000000..413a29438 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/TikTokSettingsCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.tiktok.misc.settings.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [ + Package("com.ss.android.ugc.trill"), + Package("com.zhiliaoapp.musically") + ] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class TikTokSettingsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityFingerprint.kt new file mode 100644 index 000000000..2a6ee3690 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.tiktok.misc.settings.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.tiktok.misc.settings.annotations.TikTokSettingsCompatibility + +@Name("ad-personalization-activity-fingerprint") +@MatchingMethod( + "Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;", + "onCreate" +) +@TikTokSettingsCompatibility +@Version("0.0.1") +object AdPersonalizationActivityFingerprint : MethodFingerprint( + customFingerprint = { methodDef -> + methodDef.definingClass.endsWith("/AdPersonalizationActivity;") && + methodDef.name == "onCreate" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/CopyRightSettingsStringFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/CopyRightSettingsStringFingerprint.kt new file mode 100644 index 000000000..a818e2867 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/CopyRightSettingsStringFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.tiktok.misc.settings.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.tiktok.misc.settings.annotations.TikTokSettingsCompatibility + +@Name("copyright-settings-string-fingerprint") +@MatchingMethod( + "Lcom/ss/android/ugc/aweme/setting/ui/SettingNewVersionFragment;", + "onViewCreated" +) +@TikTokSettingsCompatibility +@Version("0.0.1") +object CopyRightSettingsStringFingerprint : MethodFingerprint( + customFingerprint = { methodDef -> + methodDef.definingClass.endsWith("/SettingNewVersionFragment;") && + methodDef.name == "onViewCreated" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt new file mode 100644 index 000000000..8a2a0f96b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.tiktok.misc.settings.fingerprints + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.tiktok.misc.settings.annotations.TikTokSettingsCompatibility + +@Name("settings-status-load-fingerprint") +@MatchingMethod( + "Lapp/revanced/tiktok/settingsmenu/SettingsStatus;", + "load" +) +@TikTokSettingsCompatibility +@Version("0.0.1") +object SettingsStatusLoadFingerprint : MethodFingerprint( + customFingerprint = { methodDef -> + methodDef.definingClass.endsWith("Lapp/revanced/tiktok/settingsmenu/SettingsStatus;") && + methodDef.name == "load" + } +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/TikTokSettingsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/TikTokSettingsPatch.kt new file mode 100644 index 000000000..cb561f9cb --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/TikTokSettingsPatch.kt @@ -0,0 +1,98 @@ +package app.revanced.patches.tiktok.misc.settings.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.impl.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.replaceInstruction +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultError +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.impl.BytecodePatch +import app.revanced.patches.tiktok.misc.integrations.patch.TikTokIntegrationsPatch +import app.revanced.patches.tiktok.misc.settings.annotations.TikTokSettingsCompatibility +import app.revanced.patches.tiktok.misc.settings.fingerprints.AdPersonalizationActivityFingerprint +import app.revanced.patches.tiktok.misc.settings.fingerprints.CopyRightSettingsStringFingerprint +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 +import org.jf.dexlib2.iface.reference.StringReference + +@Patch +@DependsOn([TikTokIntegrationsPatch::class]) +@Name("tiktok-settings") +@Description("Add settings menu to TikTok.") +@TikTokSettingsCompatibility +@Version("0.0.1") +class TikTokSettingsPatch : BytecodePatch( + listOf( + AdPersonalizationActivityFingerprint, + CopyRightSettingsStringFingerprint + ) +) { + override fun execute(data: BytecodeData): PatchResult { + //Replace string `Copyright Policy` to 'Revanced Settings` in TikTok settings. + val method1 = CopyRightSettingsStringFingerprint.result!!.mutableMethod + val implementation1 = method1.implementation!! + for ((index, instruction) in implementation1.instructions.withIndex()) { + if (instruction.opcode != Opcode.CONST_STRING) continue + val string = ((instruction as ReferenceInstruction).reference as StringReference).string + if (string != "copyright_policy") continue + var targetIndex = index + while (targetIndex >= 0) { + targetIndex-- + val invokeInstruction = implementation1.instructions[targetIndex] + if (invokeInstruction.opcode != Opcode.INVOKE_VIRTUAL) continue + val methodName = ((invokeInstruction as Instruction35c).reference as MethodReference).name + if (methodName != "getString") continue + val resultInstruction = implementation1.instructions[targetIndex + 1] + if (resultInstruction.opcode != Opcode.MOVE_RESULT_OBJECT) continue + val overrideRegister = (resultInstruction as OneRegisterInstruction).registerA + method1.replaceInstruction( + targetIndex + 1, + """ + const-string v$overrideRegister, "Revanced Settings" + """ + ) + break + } + //Change onClick to start settings activity. + val clickInstruction = implementation1.instructions[index - 1] + if (clickInstruction.opcode != Opcode.INVOKE_DIRECT) + return PatchResultError("Can not find click listener.") + val clickClass = ((clickInstruction as ReferenceInstruction).reference as MethodReference).definingClass + val mutableClickClass = data.findClass(clickClass)!!.resolve() + val mutableOnClickMethod = mutableClickClass.methods.first { + it.name == "onClick" + } + mutableOnClickMethod.addInstructions( + 0, + """ + invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->startSettingsActivity()V + return-void + """ + ) + break + } + //Implement revanced settings screen in `AdPersonalizationActivity` + val method2 = AdPersonalizationActivityFingerprint.result!!.mutableMethod + for ((index, instruction) in method2.implementation!!.instructions.withIndex()) { + if (instruction.opcode != Opcode.INVOKE_SUPER) continue + val thisRegister = (instruction as Instruction35c).registerC + method2.addInstructions( + index + 1, + """ + invoke-static {v$thisRegister}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->initializeSettings(Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;)V + return-void + """ + ) + break + } + return PatchResultSuccess() + } +} \ No newline at end of file