feat(Instagram): Add Limit feed to followed profiles patch (#5908)
This commit is contained in:
parent
6862200a28
commit
8ba9a19ade
9 changed files with 132 additions and 1 deletions
3
extensions/instagram/build.gradle.kts
Normal file
3
extensions/instagram/build.gradle.kts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
dependencies {
|
||||||
|
compileOnly(project(":extensions:shared:library"))
|
||||||
|
}
|
||||||
1
extensions/instagram/src/main/AndroidManifest.xml
Normal file
1
extensions/instagram/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<manifest/>
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package app.revanced.extension.instagram.feed;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class LimitFeedToFollowedProfiles {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection point.
|
||||||
|
*/
|
||||||
|
public static Map<String, String> setFollowingHeader(Map<String, String> requestHeaderMap) {
|
||||||
|
// Create new map as original is unmodifiable.
|
||||||
|
Map<String, String> patchedRequestHeaderMap = new HashMap<>(requestHeaderMap);
|
||||||
|
patchedRequestHeaderMap.put("pagination_source", "following");
|
||||||
|
return patchedRequestHeaderMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -264,6 +264,10 @@ public final class app/revanced/patches/instagram/ads/HideAdsPatchKt {
|
||||||
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/instagram/feed/LimitFeedToFollowedProfilesKt {
|
||||||
|
public static final fun getLimitFeedToFollowedProfiles ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/instagram/hide/explore/HideExploreFeedKt {
|
public final class app/revanced/patches/instagram/hide/explore/HideExploreFeedKt {
|
||||||
public static final fun getHideExportFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getHideExportFeedPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
@ -276,6 +280,10 @@ public final class app/revanced/patches/instagram/hide/stories/HideStoriesKt {
|
||||||
public static final fun getHideStoriesPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getHideStoriesPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class app/revanced/patches/instagram/misc/extension/SharedExtensionPatchKt {
|
||||||
|
public static final fun getSharedExtensionPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
|
}
|
||||||
|
|
||||||
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
|
public final class app/revanced/patches/instagram/misc/signature/SignatureCheckPatchKt {
|
||||||
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
public static final fun getSignatureCheckPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package app.revanced.patches.instagram.feed
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint
|
||||||
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
|
|
||||||
|
internal val mainFeedRequestClassFingerprint = fingerprint {
|
||||||
|
strings("Request{mReason=", ", mInstanceNumber=")
|
||||||
|
}
|
||||||
|
|
||||||
|
context(BytecodePatchContext)
|
||||||
|
internal val initMainFeedRequestFingerprint get() = fingerprint {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "<init>" &&
|
||||||
|
classDef == mainFeedRequestClassFingerprint.classDef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val mainFeedHeaderMapFinderFingerprint = fingerprint {
|
||||||
|
strings("pagination_source", "FEED_REQUEST_SENT")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package app.revanced.patches.instagram.feed
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
|
||||||
|
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/instagram/feed/LimitFeedToFollowedProfiles;"
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
val limitFeedToFollowedProfiles = bytecodePatch(
|
||||||
|
name = "Limit feed to followed profiles",
|
||||||
|
description = "Filters the home feed to display only content from profiles you follow.",
|
||||||
|
) {
|
||||||
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
|
dependsOn(sharedExtensionPatch)
|
||||||
|
|
||||||
|
execute {
|
||||||
|
/**
|
||||||
|
* Since the header field is obfuscated and there is no easy way to identify it among all the class fields,
|
||||||
|
* an additional method is fingerprinted.
|
||||||
|
* This method uses the map, so we can get the field name of the map field using this.
|
||||||
|
*/
|
||||||
|
val mainFeedRequestHeaderFieldName: String
|
||||||
|
|
||||||
|
with(mainFeedHeaderMapFinderFingerprint.method) {
|
||||||
|
mainFeedRequestHeaderFieldName = indexOfFirstInstructionOrThrow {
|
||||||
|
getReference<FieldReference>().let { ref ->
|
||||||
|
ref?.type == "Ljava/util/Map;" &&
|
||||||
|
ref.definingClass == mainFeedRequestClassFingerprint.classDef.toString()
|
||||||
|
|
||||||
|
}
|
||||||
|
}.let { instructionIndex ->
|
||||||
|
getInstruction(instructionIndex).getReference<FieldReference>()!!.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initMainFeedRequestFingerprint.method.apply {
|
||||||
|
// Finds the instruction where the map is being initialized in the constructor
|
||||||
|
val getHeaderIndex = indexOfFirstInstructionOrThrow {
|
||||||
|
getReference<FieldReference>().let {
|
||||||
|
it?.name == mainFeedRequestHeaderFieldName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val paramHeaderRegister = getInstruction<TwoRegisterInstruction>(getHeaderIndex).registerA
|
||||||
|
|
||||||
|
// Replace the `pagination_source` header value with `following` in the feed/timeline request.
|
||||||
|
addInstructions(
|
||||||
|
getHeaderIndex,
|
||||||
|
"""
|
||||||
|
invoke-static { v$paramHeaderRegister }, $EXTENSION_CLASS_DESCRIPTOR->setFollowingHeader(Ljava/util/Map;)Ljava/util/Map;
|
||||||
|
move-result-object v$paramHeaderRegister
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -49,7 +49,7 @@ val hideNavigationButtonsPatch = bytecodePatch(
|
||||||
val freeRegister = findFreeRegister(insertIndex, loopIndexRegister)
|
val freeRegister = findFreeRegister(insertIndex, loopIndexRegister)
|
||||||
val instruction = getInstruction(endIndex - 1)
|
val instruction = getInstruction(endIndex - 1)
|
||||||
|
|
||||||
var instructions = buildString {
|
val instructions = buildString {
|
||||||
if (hideCreate!!) {
|
if (hideCreate!!) {
|
||||||
appendLine(
|
appendLine(
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package app.revanced.patches.instagram.misc.extension
|
||||||
|
|
||||||
|
import app.revanced.patches.instagram.misc.extension.hooks.applicationInitHook
|
||||||
|
import app.revanced.patches.shared.misc.extension.sharedExtensionPatch
|
||||||
|
|
||||||
|
val sharedExtensionPatch = sharedExtensionPatch(
|
||||||
|
"instagram",
|
||||||
|
applicationInitHook,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package app.revanced.patches.instagram.misc.extension.hooks
|
||||||
|
|
||||||
|
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||||
|
|
||||||
|
internal val applicationInitHook = extensionHook {
|
||||||
|
custom { method, classDef ->
|
||||||
|
method.name == "onCreate" && classDef.endsWith("/InstagramAppShell;")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue