From 0af8c8a766ae4ba6926404d59da2f14d649f91f7 Mon Sep 17 00:00:00 2001 From: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:29:01 +0300 Subject: [PATCH] fix(X / Twitter - Change link sharing domain): Use bytecode patching to resolve patching with Manager (#6125) --- .../links/ChangeLinkSharingDomainPatch.java | 10 +++++++ .../links/ChangeLinkSharingDomainPatch.kt | 28 +++++++++++++++++-- .../twitter/misc/links/Fingerprints.kt | 13 +++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/extensions/twitter/src/main/java/app/revanced/twitter/patches/links/ChangeLinkSharingDomainPatch.java b/extensions/twitter/src/main/java/app/revanced/twitter/patches/links/ChangeLinkSharingDomainPatch.java index 60b2d5cb5..0be07403b 100644 --- a/extensions/twitter/src/main/java/app/revanced/twitter/patches/links/ChangeLinkSharingDomainPatch.java +++ b/extensions/twitter/src/main/java/app/revanced/twitter/patches/links/ChangeLinkSharingDomainPatch.java @@ -11,6 +11,16 @@ public final class ChangeLinkSharingDomainPatch { return ""; } + // TODO remove this once changeLinkSharingDomainResourcePatch is restored + /** + * Injection point. + */ + public static String formatResourceLink(Object... formatArgs) { + String username = (String) formatArgs[0]; + String tweetId = (String) formatArgs[1]; + return String.format(LINK_FORMAT, getShareDomain(), username, tweetId); + } + /** * Injection point. */ diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt index 57120d70b..1a2c99f59 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch.kt @@ -1,14 +1,17 @@ package app.revanced.patches.twitter.misc.links import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.bytecodePatch -import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.stringOption import app.revanced.patches.shared.PATCH_DESCRIPTION_CHANGE_LINK_SHARING_DOMAIN import app.revanced.patches.shared.PATCH_NAME_CHANGE_LINK_SHARING_DOMAIN import app.revanced.patches.twitter.misc.extension.sharedExtensionPatch -import app.revanced.util.findElementByAttributeValueOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.returnEarly +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import java.net.InetAddress import java.net.UnknownHostException import java.util.logging.Logger @@ -40,6 +43,8 @@ internal val domainNameOption = stringOption( true } +// TODO restore this once Manager uses a fixed version of Patcher +/* internal val changeLinkSharingDomainResourcePatch = resourcePatch { execute { val domainName = domainNameOption.value!! @@ -54,6 +59,7 @@ internal val changeLinkSharingDomainResourcePatch = resourcePatch { } } } +*/ @Suppress("unused") val changeLinkSharingDomainPatch = bytecodePatch( @@ -62,7 +68,6 @@ val changeLinkSharingDomainPatch = bytecodePatch( use = false ) { dependsOn( - changeLinkSharingDomainResourcePatch, sharedExtensionPatch, ) @@ -88,5 +93,22 @@ val changeLinkSharingDomainPatch = bytecodePatch( return-object p0 """ ) + + // TODO remove this once changeLinkSharingDomainResourcePatch is restored + // Replace the domain name in the "Share via..." dialog. + linkResourceGetterFingerprint.method.apply { + val templateIdConstIndex = indexOfFirstInstructionOrThrow(Opcode.CONST) + + // Format the link with the new domain name register (1 instruction below the const). + val formatLinkCallIndex = templateIdConstIndex + 1 + val register = getInstruction(formatLinkCallIndex).registerE + + // Replace the original method call with the new method call. + replaceInstruction( + formatLinkCallIndex, + "invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->" + + "formatResourceLink([Ljava/lang/Object;)Ljava/lang/String;", + ) + } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/Fingerprints.kt index 9dbd7aeb1..6117798eb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/links/Fingerprints.kt @@ -1,6 +1,7 @@ package app.revanced.patches.twitter.misc.links import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags internal val openLinkFingerprint = fingerprint { returns("V") @@ -17,6 +18,18 @@ internal val linkBuilderFingerprint = fingerprint { strings("/%1\$s/status/%2\$d") } +// TODO remove this once changeLinkSharingDomainResourcePatch is restored +// Returns a shareable link for the "Share via..." dialog. +internal val linkResourceGetterFingerprint = fingerprint { + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + parameters("Landroid/content/res/Resources;") + custom { _, classDef -> + classDef.fields.any { field -> + field.type.startsWith("Lcom/twitter/model/core/") + } + } +} + internal val linkSharingDomainHelperFingerprint = fingerprint { custom { method, classDef -> method.name == "getShareDomain" && classDef.type == EXTENSION_CLASS_DESCRIPTOR