Skip to content

Commit

Permalink
feat(Twitter): Added mod settings
Browse files Browse the repository at this point in the history
  • Loading branch information
crimera committed Feb 27, 2024
1 parent c399a52 commit 76ee8a1
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package crimera.patches.twitter.interaction.downloads

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import crimera.patches.twitter.interaction.downloads.fingerprints.SetDownloadDestinationFingerprint
import crimera.patches.twitter.settings.SettingsPatch.UTILS_DESCRIPTOR

@Patch(
name = "Change download folder",
description = "Unlocks the ability to download videos from Twitter",
requiresIntegrations = true,
compatiblePackages = [CompatiblePackage("com.twitter.android")]
)
@Suppress("unused")
object ChangeDownloadFolderPatch : BytecodePatch(
setOf(SetDownloadDestinationFingerprint)
) {
private const val GETFOLDER_DESCRIPTOR =
"invoke-static {p1}, $UTILS_DESCRIPTOR;->getVideoFolder(Ljava/lang/String;)Ljava/lang/String;"
override fun execute(context: BytecodeContext) {
val result = SetDownloadDestinationFingerprint.result
?: throw PatchException("Could not find fingerprint")

val method = result.mutableMethod

val insertAt = method.getInstructions()
.first { it.opcode == Opcode.INVOKE_VIRTUAL }.location.index

// when replacing values we should avoid hardcoding the registers
val publicFolderRegister = method.getInstruction<OneRegisterInstruction>(insertAt-1).registerA
method.replaceInstruction(insertAt-1, """
sget-object v$publicFolderRegister, Landroid/os/Environment;->DIRECTORY_MOVIES:Ljava/lang/String;
""".trimIndent())

method.addInstructions(insertAt, """
$GETFOLDER_DESCRIPTOR
move-result-object p1
""".trimIndent())
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package crimera.patches.twitter.download
package crimera.patches.twitter.interaction.downloads

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
Expand All @@ -11,8 +11,8 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import com.android.tools.smali.dexlib2.Opcode
import crimera.patches.twitter.download.fingerprints.DownloadPatchFingerprint
import crimera.patches.twitter.download.fingerprints.FIleDownloaderFingerprint
import crimera.patches.twitter.interaction.downloads.fingerprints.DownloadPatchFingerprint
import crimera.patches.twitter.interaction.downloads.fingerprints.FIleDownloaderFingerprint

// Credits to @iKirby
@Patch(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package crimera.patches.twitter.download.fingerprints
package crimera.patches.twitter.interaction.downloads.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package crimera.patches.twitter.download.fingerprints
package crimera.patches.twitter.interaction.downloads.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package crimera.patches.twitter.interaction.downloads.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

object SetDownloadDestinationFingerprint: MethodFingerprint(
returnType = "V",
strings = listOf(
"parse(downloadData.url)"
)
)
105 changes: 105 additions & 0 deletions src/main/kotlin/crimera/patches/twitter/settings/SettingsPatch.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package crimera.patches.twitter.settings

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.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import com.android.tools.smali.dexlib2.Opcode
import crimera.patches.twitter.settings.fingerprints.InitActivityFingerprint
import crimera.patches.twitter.settings.fingerprints.SettingsFingerprint
import crimera.patches.twitter.settings.fingerprints.SettingsInitFingerprint

@Patch(
name = "Settings",
description = "Adds settings",
requiresIntegrations = true,
dependencies = [SettingsResourcePatch::class],
compatiblePackages = [CompatiblePackage("com.twitter.android")],
)
object SettingsPatch : BytecodePatch(
setOf(SettingsFingerprint, SettingsInitFingerprint, InitActivityFingerprint)
) {
private const val INTEGRATIONS_PACKAGE = "Lapp/revanced/integrations/twitter"
const val UTILS_DESCRIPTOR = "$INTEGRATIONS_PACKAGE/settings/Utils"
private const val START_ACTIVITY_DESCRIPTOR =
"invoke-static {}, $UTILS_DESCRIPTOR;->startActivity()V"

private const val ADD_CONTEXT_DESCRIPTOR = "invoke-static {p0}, $UTILS_DESCRIPTOR;->setCtx(Landroid/app/Application;)V"

override fun execute(context: BytecodeContext) {
val result = SettingsInitFingerprint.result
?: throw PatchException("Fingerprint not found")

val initMethod = result.mutableClass.methods.first()

val arrayCreation = initMethod.getInstructions()
.first { it.opcode == Opcode.FILLED_NEW_ARRAY_RANGE }.location.index

initMethod.addInstructions(
arrayCreation + 2, """
array-length v1, v0
add-int/lit8 v1, v1, 0x1
invoke-static {v0, v1}, Ljava/util/Arrays;->copyOf([Ljava/lang/Object;I)[Ljava/lang/Object;
move-result-object v1
check-cast v1, [Ljava/lang/String;
.local v1, "bigger":[Ljava/lang/String;
array-length v2, v0
const-string v3, "pref_mod"
aput-object v3, v1, v2
move-object v0, v1
""".trimIndent()
)

val h0Method = result.mutableClass.methods.first { it.returnType == "Z" }

val igetObjectIndex = h0Method.getInstructions()
.first { it.opcode == Opcode.IGET_OBJECT }.location.index

// startActivity
h0Method.addInstructions(
igetObjectIndex + 1, """
const-string v0, "Working"
$START_ACTIVITY_DESCRIPTOR
const/4 v3, 0x1
return v3
""".trimIndent(),
)

// if block end
val ifBlockEnd = h0Method.getInstructions().first { it.opcode == Opcode.RETURN }.location.index+1

h0Method.addInstructionsWithLabels(igetObjectIndex+1,
"""
const-string v1, "pref_mod"
invoke-virtual {p1, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v2
if-nez v2, :cond_idk
goto :end
""".trimIndent(),
ExternalLabel("end", h0Method.getInstructions().first { it.opcode == Opcode.CONST_STRING }),
ExternalLabel("cond_idk", h0Method.getInstruction(ifBlockEnd)),
)

// Add context reference
val initActivity = InitActivityFingerprint.result!!.mutableClass.methods.last{ it.name == "onCreate" }
print(initActivity.name)

initActivity.addInstruction(initActivity.getInstructions().lastIndex, ADD_CONTEXT_DESCRIPTOR)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package crimera.patches.twitter.settings

import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import org.w3c.dom.Element

@Patch(
compatiblePackages = [CompatiblePackage("com.twitter.android")],
)
object SettingsResourcePatch: ResourcePatch() {
override fun execute(context: ResourceContext) {
val settingsRoot = context["res/xml/settings_root.xml"]
if (!settingsRoot.exists()) throw PatchException("settings_root not found")

context.xmlEditor["res/xml/settings_root.xml"].use { editor ->
val parent = editor.file.getElementsByTagName("PreferenceScreen").item(0) as Element

val prefMod = editor.file.createElement("Preference")
prefMod.setAttribute("android:icon", "@drawable/ic_vector_settings_stroke")
prefMod.setAttribute("android:title", "Mod Settings")
prefMod.setAttribute("android:key", "pref_mod")
prefMod.setAttribute("android:order", "110")

parent.appendChild(prefMod)
}

context.xmlEditor["AndroidManifest.xml"].use {
val applicationNode = it.file.getElementsByTagName("application").item(0)

val modActivity = it.file.createElement("activity").apply {
setAttribute("android:label", "Mod Settings")
setAttribute("android:name", "app.revanced.integrations.twitter.settings.SettingsActivity")
setAttribute("android:excludeFromRecents", "true")
}

applicationNode.appendChild(modActivity)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package crimera.patches.twitter.settings.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

object InitActivityFingerprint: MethodFingerprint(
strings = listOf("com.twitter.util.config.ApplicationObjectGraphConfig"),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package crimera.patches.twitter.settings.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

object SettingsFingerprint : MethodFingerprint(
returnType = "Z",
strings = listOf(
"pref_proxy"
),
parameters = listOf(
"Landroidx/preference/Preference;",
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package crimera.patches.twitter.settings.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

object SettingsInitFingerprint : MethodFingerprint(
returnType = "V",
strings = listOf(
"pref_proxy"
),
customFingerprint = { it, _ ->
it.name == "<clinit>"
}
)

2 comments on commit 76ee8a1

@crimera
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patch requires revanced-integrations did you built twitter with it? https://github.com/crimera/revanced-integrations

@VixenSugo
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added mod settings cause app crash

Please sign in to comment.