forked from ReVanced/revanced-patches-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(Tumblr): Use a common filter patch (ReVanced#3018)
Co-authored-by: oSumAtrIX <[email protected]>
- Loading branch information
Showing
8 changed files
with
140 additions
and
57 deletions.
There are no files selected for viewing
42 changes: 23 additions & 19 deletions
42
src/main/kotlin/app/revanced/patches/tumblr/ads/DisableDashboardAds.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,37 @@ | ||
package app.revanced.patches.tumblr.ads | ||
|
||
import app.revanced.extensions.exception | ||
import app.revanced.patcher.data.BytecodeContext | ||
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.annotation.CompatiblePackage | ||
import app.revanced.patcher.patch.annotation.Patch | ||
import app.revanced.patches.tumblr.ads.fingerprints.AdWaterfallFingerprint | ||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction | ||
import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch | ||
|
||
@Patch( | ||
name = "Disable dashboard ads", | ||
description = "Disables ads in the dashboard.", | ||
compatiblePackages = [CompatiblePackage("com.tumblr")] | ||
compatiblePackages = [CompatiblePackage("com.tumblr")], | ||
dependencies = [TimelineFilterPatch::class] | ||
) | ||
@Suppress("unused") | ||
object DisableDashboardAds : BytecodePatch( | ||
setOf(AdWaterfallFingerprint) | ||
) { | ||
override fun execute(context: BytecodeContext) = AdWaterfallFingerprint.result?.let { | ||
it.scanResult.stringsScanResult!!.matches.forEach { match -> | ||
// We just replace all occurrences of "client_side_ad_waterfall" with anything else | ||
// so the app fails to handle ads in the timeline elements array and just skips them. | ||
// See AdWaterfallFingerprint for more info. | ||
val stringRegister = it.mutableMethod.getInstruction<OneRegisterInstruction>(match.index).registerA | ||
it.mutableMethod.replaceInstruction( | ||
match.index, "const-string v$stringRegister, \"dummy\"" | ||
) | ||
object DisableDashboardAds : BytecodePatch() { | ||
override fun execute(context: BytecodeContext) { | ||
// The timeline object types are filtered by their name in the TimelineObjectType enum. | ||
// This is often different from the "object_type" returned in the api (noted in comments here) | ||
arrayOf( | ||
"CLIENT_SIDE_MEDIATION", // "client_side_ad_waterfall" | ||
"GEMINI_AD", // "backfill_ad" | ||
|
||
// The object types below weren't actually spotted in the wild in testing, but they are valid Object types | ||
// and their names clearly indicate that they are ads, so we just block them anyway, | ||
// just in case they will be used in the future. | ||
"NIMBUS_AD", // "nimbus_ad" | ||
"CLIENT_SIDE_AD", // "client_side_ad" | ||
"DISPLAY_IO_INTERSCROLLER_AD", // "display_io_interscroller" | ||
"DISPLAY_IO_HEADLINE_VIDEO_AD", // "display_io_headline_video" | ||
"FACEBOOK_BIDDAABLE", // "facebook_biddable_sdk_ad" | ||
"GOOGLE_NATIVE" // "google_native_ad" | ||
).forEach { | ||
TimelineFilterPatch.addObjectTypeFilter(it) | ||
} | ||
} ?: throw AdWaterfallFingerprint.exception | ||
} | ||
} |
12 changes: 0 additions & 12 deletions
12
src/main/kotlin/app/revanced/patches/tumblr/ads/fingerprints/AdWaterfallFingerprint.kt
This file was deleted.
Oops, something went wrong.
29 changes: 9 additions & 20 deletions
29
src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,26 @@ | ||
package app.revanced.patches.tumblr.live | ||
|
||
import app.revanced.extensions.exception | ||
import app.revanced.patcher.data.BytecodeContext | ||
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.annotation.CompatiblePackage | ||
import app.revanced.patcher.patch.annotation.Patch | ||
import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch | ||
import app.revanced.patches.tumblr.live.fingerprints.LiveMarqueeFingerprint | ||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction | ||
import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch | ||
|
||
@Patch( | ||
name = "Disable Tumblr Live", | ||
description = "Disable the Tumblr Live tab button and dashboard carousel.", | ||
dependencies = [OverrideFeatureFlagsPatch::class], | ||
dependencies = [OverrideFeatureFlagsPatch::class, TimelineFilterPatch::class], | ||
compatiblePackages = [CompatiblePackage("com.tumblr")] | ||
) | ||
@Suppress("unused") | ||
object DisableTumblrLivePatch : BytecodePatch( | ||
setOf(LiveMarqueeFingerprint) | ||
) { | ||
override fun execute(context: BytecodeContext) = LiveMarqueeFingerprint.result?.let { | ||
it.scanResult.stringsScanResult!!.matches.forEach { match -> | ||
// Replace the string constant "live_marquee" | ||
// with a dummy so the app doesn't recognize this type of element in the Dashboard and skips it | ||
it.mutableMethod.apply { | ||
val stringRegister = getInstruction<OneRegisterInstruction>(match.index).registerA | ||
replaceInstruction(match.index, "const-string v$stringRegister, \"dummy2\"") | ||
} | ||
} | ||
object DisableTumblrLivePatch : BytecodePatch() { | ||
override fun execute(context: BytecodeContext) { | ||
// Hide the LIVE_MARQUEE timeline element that appears in the feed | ||
// Called "live_marquee" in api response | ||
TimelineFilterPatch.addObjectTypeFilter("LIVE_MARQUEE") | ||
|
||
// We hide the Tab button for Tumblr Live by forcing the feature flag to false | ||
// Hide the Tab button for Tumblr Live by forcing the feature flag to false | ||
OverrideFeatureFlagsPatch.addOverride("liveStreaming", "false") | ||
} ?: throw LiveMarqueeFingerprint.exception | ||
} | ||
} |
6 changes: 0 additions & 6 deletions
6
src/main/kotlin/app/revanced/patches/tumblr/live/fingerprints/LiveMarqueeFingerprint.kt
This file was deleted.
Oops, something went wrong.
68 changes: 68 additions & 0 deletions
68
src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/TimelineFilterPatch.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package app.revanced.patches.tumblr.timelinefilter | ||
|
||
import app.revanced.extensions.exception | ||
import app.revanced.patcher.data.BytecodeContext | ||
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.removeInstructions | ||
import app.revanced.patcher.patch.BytecodePatch | ||
import app.revanced.patcher.patch.annotation.Patch | ||
import app.revanced.patches.tumblr.timelinefilter.fingerprints.PostsResponseConstructorFingerprint | ||
import app.revanced.patches.tumblr.timelinefilter.fingerprints.TimelineConstructorFingerprint | ||
import app.revanced.patches.tumblr.timelinefilter.fingerprints.TimelineFilterIntegrationFingerprint | ||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c | ||
|
||
@Patch(description = "Filter timeline objects.", requiresIntegrations = true) | ||
object TimelineFilterPatch : BytecodePatch( | ||
setOf(TimelineConstructorFingerprint, TimelineFilterIntegrationFingerprint, PostsResponseConstructorFingerprint) | ||
) { | ||
/** | ||
* Add a filter to hide the given timeline object type. | ||
* The list of all Timeline object types is found in the TimelineObjectType class, | ||
* where they are mapped from their api name (returned by tumblr via the HTTP API) to the enum value name. | ||
* | ||
* @param typeName The enum name of the timeline object type to hide. | ||
*/ | ||
@Suppress("KDocUnresolvedReference") | ||
internal lateinit var addObjectTypeFilter: (typeName: String) -> Unit private set | ||
|
||
override fun execute(context: BytecodeContext) { | ||
TimelineFilterIntegrationFingerprint.result?.let { integration -> | ||
val filterInsertIndex = integration.scanResult.patternScanResult!!.startIndex | ||
|
||
integration.mutableMethod.apply { | ||
val addInstruction = getInstruction<BuilderInstruction35c>(filterInsertIndex + 1) | ||
if (addInstruction.registerCount != 2) throw TimelineFilterIntegrationFingerprint.exception | ||
|
||
val filterListRegister = addInstruction.registerC | ||
val stringRegister = addInstruction.registerD | ||
|
||
// Remove "BLOCKED_OBJECT_DUMMY" | ||
removeInstructions(filterInsertIndex, 2) | ||
|
||
addObjectTypeFilter = { typeName -> | ||
// blockedObjectTypes.add({typeName}) | ||
addInstructionsWithLabels( | ||
filterInsertIndex, """ | ||
const-string v$stringRegister, "$typeName" | ||
invoke-interface { v$filterListRegister, v$stringRegister }, Ljava/util/HashSet;->add(Ljava/lang/Object;)Z | ||
""" | ||
) | ||
} | ||
} | ||
} ?: throw TimelineFilterIntegrationFingerprint.exception | ||
|
||
mapOf( | ||
TimelineConstructorFingerprint to 1, | ||
PostsResponseConstructorFingerprint to 2 | ||
).forEach { (fingerprint, timelineObjectsRegister) -> | ||
fingerprint.result?.mutableMethod?.addInstructions( | ||
0, | ||
"invoke-static {p$timelineObjectsRegister}, " + | ||
"Lapp/revanced/tumblr/patches/TimelineFilterPatch;->" + | ||
"filterTimeline(Ljava/util/List;)V" | ||
) ?: throw fingerprint.exception | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
...evanced/patches/tumblr/timelinefilter/fingerprints/PostsResponseConstructorFingerprint.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package app.revanced.patches.tumblr.timelinefilter.fingerprints | ||
|
||
import app.revanced.patcher.extensions.or | ||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint | ||
import com.android.tools.smali.dexlib2.AccessFlags | ||
|
||
// This is the constructor of the PostsResponse class. | ||
// The same applies here as with the TimelineConstructorFingerprint. | ||
object PostsResponseConstructorFingerprint : MethodFingerprint( | ||
accessFlags = AccessFlags.CONSTRUCTOR or AccessFlags.PUBLIC, | ||
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/PostsResponse;") && methodDef.parameters.size == 4 }, | ||
) |
12 changes: 12 additions & 0 deletions
12
...app/revanced/patches/tumblr/timelinefilter/fingerprints/TimelineConstructorFingerprint.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package app.revanced.patches.tumblr.timelinefilter.fingerprints | ||
|
||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint | ||
|
||
// This is the constructor of the Timeline class. | ||
// It receives the List<TimelineObject> as an argument with a @Json annotation, so this should be the first time | ||
// that the List<TimelineObject> is exposed in non-library code. | ||
object TimelineConstructorFingerprint : MethodFingerprint( | ||
customFingerprint = { methodDef, _ -> | ||
methodDef.definingClass.endsWith("/Timeline;") && methodDef.parameters[0].type == "Ljava/util/List;" | ||
}, strings = listOf("timelineObjectsList") | ||
) |
16 changes: 16 additions & 0 deletions
16
...vanced/patches/tumblr/timelinefilter/fingerprints/TimelineFilterIntegrationFingerprint.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package app.revanced.patches.tumblr.timelinefilter.fingerprints | ||
|
||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint | ||
import com.android.tools.smali.dexlib2.Opcode | ||
|
||
// This fingerprints the Integration TimelineFilterPatch.filterTimeline method. | ||
// The opcode fingerprint is searching for | ||
// if ("BLOCKED_OBJECT_DUMMY".equals(elementType)) iterator.remove(); | ||
object TimelineFilterIntegrationFingerprint : MethodFingerprint( | ||
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/TimelineFilterPatch;") }, | ||
strings = listOf("BLOCKED_OBJECT_DUMMY"), | ||
opcodes = listOf( | ||
Opcode.CONST_STRING, // "BLOCKED_OBJECT_DUMMY" | ||
Opcode.INVOKE_INTERFACE // List.add(^) | ||
) | ||
) |