Compare commits

..

19 Commits

Author SHA1 Message Date
semantic-release-bot
651e34b997 chore: Release v4.17.0-dev.10 [skip ci]
# [4.17.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.9...v4.17.0-dev.10) (2024-10-17)

### Features

* **Facebook:** Add `Hide sponsored stories` patch ([#3627](https://github.com/ReVanced/revanced-patches/issues/3627)) ([fc7644d](fc7644d3b7))
2024-10-17 15:39:04 +00:00
PantlessCoding
fc7644d3b7 feat(Facebook): Add Hide sponsored stories patch (#3627)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-10-17 17:36:35 +02:00
semantic-release-bot
061ebcb7c6 chore: Release v4.17.0-dev.9 [skip ci]
# [4.17.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.8...v4.17.0-dev.9) (2024-10-17)

### Features

* **Sync for Reddit:** Add `Fix video downloads` patch ([#3739](https://github.com/ReVanced/revanced-patches/issues/3739)) ([38e7884](38e7884d17))
2024-10-17 15:30:41 +00:00
1fexd
38e7884d17 feat(Sync for Reddit): Add Fix video downloads patch (#3739)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-10-17 17:28:30 +02:00
semantic-release-bot
64680c718b chore: Release v4.17.0-dev.8 [skip ci]
# [4.17.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.7...v4.17.0-dev.8) (2024-10-17)

### Features

* **Twitter:** Add `Change link sharing domain` patch ([#3753](https://github.com/ReVanced/revanced-patches/issues/3753)) ([0077028](007702825b))
2024-10-17 15:26:18 +00:00
Alex
007702825b feat(Twitter): Add Change link sharing domain patch (#3753)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-10-17 17:24:06 +02:00
semantic-release-bot
596c2b0f8d chore: Release v4.17.0-dev.7 [skip ci]
# [4.17.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.6...v4.17.0-dev.7) (2024-10-17)

### Bug Fixes

* **Twitter - Unlock downloads:** Make it work with latest versions ([#3782](https://github.com/ReVanced/revanced-patches/issues/3782)) ([773fd81](773fd81dfd))
* **YouTube - Spoof video streams:** Fix playback for Android VR by removing invalid body as well ([#3769](https://github.com/ReVanced/revanced-patches/issues/3769)) ([68b61b4](68b61b4725))
2024-10-17 15:21:25 +00:00
Alex
773fd81dfd fix(Twitter - Unlock downloads): Make it work with latest versions (#3782) 2024-10-17 17:18:48 +02:00
oSumAtrIX
68b61b4725 fix(YouTube - Spoof video streams): Fix playback for Android VR by removing invalid body as well (#3769) 2024-10-17 17:16:45 +02:00
semantic-release-bot
10efb20e35 chore: Release v4.17.0-dev.6 [skip ci]
# [4.17.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.5...v4.17.0-dev.6) (2024-10-14)

### Features

* **YouTube - Hide Shorts components:** Add option to hide `Use template`, `Upcoming`, `Green screen` buttons ([#3752](https://github.com/ReVanced/revanced-patches/issues/3752)) ([d5a1368](d5a13684f6))
2024-10-14 12:13:04 +00:00
MarcaD
d5a13684f6 feat(YouTube - Hide Shorts components): Add option to hide Use template, Upcoming, Green screen buttons (#3752) 2024-10-14 14:10:53 +02:00
semantic-release-bot
e2dd1bdaf3 chore: Release v4.17.0-dev.5 [skip ci]
# [4.17.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.4...v4.17.0-dev.5) (2024-10-07)

### Features

* **Backdrops - Pro unlock:** Support latest versions by removing version constraint ([98c33f0](98c33f03dd))
2024-10-07 20:58:34 +00:00
KAZI MMT
98c33f03dd feat(Backdrops - Pro unlock): Support latest versions by removing version constraint 2024-10-07 22:56:31 +02:00
semantic-release-bot
d73e5b77df chore: Release v4.17.0-dev.4 [skip ci]
# [4.17.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.3...v4.17.0-dev.4) (2024-10-06)

### Bug Fixes

* **YouTube - Hide layout components:** Adjust settings text ([#3745](https://github.com/ReVanced/revanced-patches/issues/3745)) ([2f7e1f6](2f7e1f601a))
2024-10-06 22:57:38 +00:00
LisoUseInAIKyrios
2f7e1f601a fix(YouTube - Hide layout components): Adjust settings text (#3745) 2024-10-06 18:55:20 -04:00
semantic-release-bot
bcdc7a4589 chore: Release v4.17.0-dev.3 [skip ci]
# [4.17.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.2...v4.17.0-dev.3) (2024-10-06)

### Features

* **YouTube - Hide layout components:** Add option to hide Yoodles (YouTube Doodles) ([#3743](https://github.com/ReVanced/revanced-patches/issues/3743)) ([0679a47](0679a47b22))
2024-10-06 00:11:05 +00:00
LisoUseInAIKyrios
0679a47b22 feat(YouTube - Hide layout components): Add option to hide Yoodles (YouTube Doodles) (#3743)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-10-05 20:09:06 -04:00
semantic-release-bot
5a08620356 chore: Release v4.17.0-dev.2 [skip ci]
# [4.17.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.1...v4.17.0-dev.2) (2024-10-05)

### Features

* **Willhaben:** Add `Hide ads` patch ([#3740](https://github.com/ReVanced/revanced-patches/issues/3740)) ([42ed29b](42ed29b4c0))
2024-10-05 23:21:37 +00:00
1fexd
42ed29b4c0 feat(Willhaben): Add Hide ads patch (#3740) 2024-10-06 01:19:39 +02:00
26 changed files with 605 additions and 12 deletions

View File

@@ -1,3 +1,67 @@
# [4.17.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.9...v4.17.0-dev.10) (2024-10-17)
### Features
* **Facebook:** Add `Hide sponsored stories` patch ([#3627](https://github.com/ReVanced/revanced-patches/issues/3627)) ([214c72b](https://github.com/ReVanced/revanced-patches/commit/214c72baeb7f87f21cd2ca34301ab11fa0ff1a4f))
# [4.17.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.8...v4.17.0-dev.9) (2024-10-17)
### Features
* **Sync for Reddit:** Add `Fix video downloads` patch ([#3739](https://github.com/ReVanced/revanced-patches/issues/3739)) ([a47ee38](https://github.com/ReVanced/revanced-patches/commit/a47ee38b1cdd974a959008006ecaf58917addc60))
# [4.17.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.7...v4.17.0-dev.8) (2024-10-17)
### Features
* **Twitter:** Add `Change link sharing domain` patch ([#3753](https://github.com/ReVanced/revanced-patches/issues/3753)) ([9269a07](https://github.com/ReVanced/revanced-patches/commit/9269a076b674ecdcf478bca842238f6e30869f44))
# [4.17.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.6...v4.17.0-dev.7) (2024-10-17)
### Bug Fixes
* **Twitter - Unlock downloads:** Make it work with latest versions ([#3782](https://github.com/ReVanced/revanced-patches/issues/3782)) ([5189122](https://github.com/ReVanced/revanced-patches/commit/5189122006b0f72d5bfb50422021c3b0f3a9ae4a))
* **YouTube - Spoof video streams:** Fix playback for Android VR by removing invalid body as well ([#3769](https://github.com/ReVanced/revanced-patches/issues/3769)) ([5150a15](https://github.com/ReVanced/revanced-patches/commit/5150a15ad4ca73a747f0a89f933db7f2d686ec2d))
# [4.17.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.5...v4.17.0-dev.6) (2024-10-14)
### Features
* **YouTube - Hide Shorts components:** Add option to hide `Use template`, `Upcoming`, `Green screen` buttons ([#3752](https://github.com/ReVanced/revanced-patches/issues/3752)) ([f71c406](https://github.com/ReVanced/revanced-patches/commit/f71c4068bc646d02954b59fac4756f1419c55dbe))
# [4.17.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.4...v4.17.0-dev.5) (2024-10-07)
### Features
* **Backdrops - Pro unlock:** Support latest versions by removing version constraint ([a62b506](https://github.com/ReVanced/revanced-patches/commit/a62b50691c49d1ce529a7c9c4e49da0d0dd46df2))
# [4.17.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.3...v4.17.0-dev.4) (2024-10-06)
### Bug Fixes
* **YouTube - Hide layout components:** Adjust settings text ([#3745](https://github.com/ReVanced/revanced-patches/issues/3745)) ([13998bb](https://github.com/ReVanced/revanced-patches/commit/13998bbf95ac3cde8bf24754d60258d0ff9bc4f4))
# [4.17.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.2...v4.17.0-dev.3) (2024-10-06)
### Features
* **YouTube - Hide layout components:** Add option to hide Yoodles (YouTube Doodles) ([#3743](https://github.com/ReVanced/revanced-patches/issues/3743)) ([b8c8916](https://github.com/ReVanced/revanced-patches/commit/b8c89164cf3911ac3842df9b0d2ec42b52213505))
# [4.17.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.1...v4.17.0-dev.2) (2024-10-05)
### Features
* **Willhaben:** Add `Hide ads` patch ([#3740](https://github.com/ReVanced/revanced-patches/issues/3740)) ([1fe3a52](https://github.com/ReVanced/revanced-patches/commit/1fe3a523e99ccfe556d88800686e34ac6ed77b2c))
# [4.17.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.16.1-dev.1...v4.17.0-dev.1) (2024-10-02)

View File

@@ -263,6 +263,12 @@ public final class app/revanced/patches/duolingo/debug/EnableDebugMenuPatch : ap
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/facebook/ads/story/HideStoryAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/facebook/ads/story/HideStoryAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -840,6 +846,12 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/u
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/video/FixVideoDownloadsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch;
}
@@ -1490,6 +1502,12 @@ public final class app/revanced/patches/twitter/misc/hook/patch/recommendation/H
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/hook/patch/recommendation/HideRecommendedUsersPatch;
}
public final class app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -1520,6 +1538,12 @@ public final class app/revanced/patches/warnwetter/misc/promocode/PromoCodeUnloc
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/willhaben/ads/HideAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/willhaben/ads/HideAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
@@ -2178,6 +2202,7 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun containsWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z
public static final fun findMutableMethodOf (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;
public static final fun findOpcodeIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List;
public static final fun findOpcodeIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun getException (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/patch/PatchException;
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;)I
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 4.17.0-dev.1
version = 4.17.0-dev.10

View File

@@ -12,7 +12,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch(
name = "Pro unlock",
compatiblePackages = [CompatiblePackage("com.backdrops.wallpapers", ["4.52"])]
compatiblePackages = [CompatiblePackage("com.backdrops.wallpapers")]
)
@Suppress("unused")
object ProUnlockPatch : BytecodePatch(
@@ -34,4 +34,4 @@ object ProUnlockPatch : BytecodePatch(
} ?: throw ProUnlockFingerprint.exception
}
}
}

View File

@@ -0,0 +1,96 @@
package app.revanced.patches.facebook.ads.mainfeed
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.or
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.facebook.ads.mainfeed.fingerprints.BaseModelMapperFingerprint
import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetSponsoredDataModelTemplateFingerprint
import app.revanced.patches.facebook.ads.mainfeed.fingerprints.GetStoryVisibilityFingerprint
import app.revanced.util.exception
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
@Patch(
name = "Hide 'Sponsored Stories'",
compatiblePackages = [CompatiblePackage("com.facebook.katana")],
)
@Suppress("unused")
object HideSponsoredStoriesPatch : BytecodePatch(
setOf(GetStoryVisibilityFingerprint, GetSponsoredDataModelTemplateFingerprint, BaseModelMapperFingerprint),
) {
private const val GRAPHQL_STORY_TYPE = "Lcom/facebook/graphql/model/GraphQLStory;"
override fun execute(context: BytecodeContext) {
GetStoryVisibilityFingerprint.result?.apply {
val sponsoredDataModelTemplateMethod = GetSponsoredDataModelTemplateFingerprint.resultOrThrow().method
val baseModelMapperMethod = BaseModelMapperFingerprint.resultOrThrow().method
val baseModelWithTreeType = baseModelMapperMethod.returnType
// The "SponsoredDataModelTemplate" methods has the ids in its body to extract sponsored data
// from GraphQL models, but targets the wrong derived type of "BaseModelWithTree". Since those ids
// could change in future version, we need to extract them and call the base implementation directly.
val getSponsoredDataHelperMethod = ImmutableMethod(
classDef.type,
"getSponsoredData",
listOf(ImmutableMethodParameter(GRAPHQL_STORY_TYPE, null, null)),
baseModelWithTreeType,
AccessFlags.PRIVATE or AccessFlags.STATIC,
null,
null,
MutableMethodImplementation(4),
).toMutable().apply {
// Extract the ids of the original method. These ids seem to correspond to model types for
// GraphQL data structure. They are then fed to a method of BaseModelWithTree that populate
// and cast the requested GraphQL subtype. The Ids are found in the two first "CONST" instructions.
val constInstructions = sponsoredDataModelTemplateMethod.implementation!!.instructions
.asSequence()
.filterIsInstance<Instruction31i>()
.take(2)
.toList()
val storyTypeId = constInstructions[0].narrowLiteral
val sponsoredDataTypeId = constInstructions[1].narrowLiteral
addInstructions(
"""
const-class v2, $baseModelWithTreeType
const v1, $storyTypeId
const v0, $sponsoredDataTypeId
invoke-virtual {p0, v2, v1, v0}, $baseModelMapperMethod
move-result-object v0
check-cast v0, $baseModelWithTreeType
return-object v0
""",
)
}
mutableClass.methods.add(getSponsoredDataHelperMethod)
// Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value.
// If so, hide the story by setting the visibility to StoryVisibility.GONE.
mutableMethod.addInstructionsWithLabels(
scanResult.patternScanResult!!.startIndex,
"""
instance-of v0, p0, $GRAPHQL_STORY_TYPE
if-eqz v0, :resume_normal
invoke-static {p0}, $getSponsoredDataHelperMethod
move-result-object v0
if-eqz v0, :resume_normal
const-string v0, "GONE"
return-object v0
:resume_normal
nop
""",
)
} ?: throw GetStoryVisibilityFingerprint.exception
}
}

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.facebook.ads.mainfeed.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object BaseModelMapperFingerprint : MethodFingerprint(
accessFlags = (AccessFlags.PUBLIC or AccessFlags.FINAL),
parameters = listOf("Ljava/lang/Class","I","I"),
returnType = "Lcom/facebook/graphql/modelutil/BaseModelWithTree;",
opcodes = listOf(
Opcode.SGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_4,
Opcode.IF_EQ
)
)

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.facebook.ads.mainfeed.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object GetSponsoredDataModelTemplateFingerprint : MethodFingerprint(
accessFlags = (AccessFlags.PUBLIC or AccessFlags.FINAL),
parameters = listOf(),
returnType = "L",
opcodes = listOf(
Opcode.CONST,
Opcode.CONST,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT
),
customFingerprint = { methodDef, classDef ->
classDef.type == "Lcom/facebook/graphql/model/GraphQLFBMultiAdsFeedUnit;"
}
)

View File

@@ -0,0 +1,23 @@
package app.revanced.patches.facebook.ads.mainfeed.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Annotation
import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue
internal object GetStoryVisibilityFingerprint : MethodFingerprint(
returnType = "Ljava/lang/String;",
accessFlags = (AccessFlags.PUBLIC or AccessFlags.STATIC),
opcodes = listOf(
Opcode.INSTANCE_OF,
Opcode.IF_NEZ,
Opcode.INSTANCE_OF,
Opcode.IF_NEZ,
Opcode.INSTANCE_OF,
Opcode.IF_NEZ,
Opcode.CONST
),
strings = listOf("This should not be called for base class object"),
)

View File

@@ -0,0 +1,62 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.video
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints.ParseRedditVideoNetworkResponseFingerprint
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
@Patch(
name = "Fix video downloads",
description = "Fixes a bug in Sync's MPD parser resulting in only the audio-track being saved.",
compatiblePackages = [
CompatiblePackage("com.laurencedawson.reddit_sync"),
CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
CompatiblePackage("com.laurencedawson.reddit_sync.dev"),
],
requiresIntegrations = true,
)
@Suppress("unused")
object FixVideoDownloadsPatch : BytecodePatch(
fingerprints = setOf(ParseRedditVideoNetworkResponseFingerprint),
) {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/syncforreddit/FixRedditVideoDownloadPatch;"
private const val GET_LINKS_METHOD = "getLinks([B)[Ljava/lang/String;"
override fun execute(context: BytecodeContext) {
ParseRedditVideoNetworkResponseFingerprint.resultOrThrow().let {
val scanResult = it.scanResult.patternScanResult!!
val newInstanceIndex = scanResult.startIndex
val invokeDirectIndex = scanResult.endIndex - 1
val buildResponseInstruction = it.mutableMethod.getInstruction<Instruction35c>(invokeDirectIndex)
it.mutableMethod.addInstructions(
newInstanceIndex + 1,
"""
# Get byte array from response.
iget-object v2, p1, Lcom/android/volley/NetworkResponse;->data:[B
# Parse the videoUrl and audioUrl from the byte array.
invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->$GET_LINKS_METHOD
move-result-object v2
# Get videoUrl (Index 0).
const/4 v5, 0x0
aget-object v${buildResponseInstruction.registerE}, v2, v5
# Get audioUrl (Index 1).
const/4 v6, 0x1
aget-object v${buildResponseInstruction.registerF}, v2, v6
# Register E and F are used to build the response.
""",
)
}
}
}

View File

@@ -0,0 +1,16 @@
package app.revanced.patches.reddit.customclients.syncforreddit.fix.video.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object ParseRedditVideoNetworkResponseFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.NEW_INSTANCE,
Opcode.IGET_OBJECT,
Opcode.INVOKE_DIRECT,
Opcode.CONST_WIDE_32
),
customFingerprint = { methodDef, classDef ->
classDef.sourceFile == "RedditVideoRequest.java" && methodDef.name == "parseNetworkResponse"
}
)

View File

@@ -10,5 +10,5 @@ internal object BuildMediaOptionsSheetFingerprint : MethodFingerprint(
Opcode.GOTO_16,
Opcode.NEW_INSTANCE,
),
strings = listOf("resources.getString(R.string.post_video)"),
strings = listOf("mediaEntity", "media_options_sheet"),
)

View File

@@ -5,6 +5,6 @@ import com.android.tools.smali.dexlib2.Opcode
internal object ShowDownloadVideoUpsellBottomSheetFingerprint : MethodFingerprint(
returnType = "Z",
strings = listOf("variantToDownload.url"),
strings = listOf("mediaEntity", "url"),
opcodes = listOf(Opcode.IF_EQZ)
)

View File

@@ -0,0 +1,93 @@
package app.revanced.patches.twitter.misc.links
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.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderFingerprint
import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFingerprint
import app.revanced.patches.twitter.misc.links.fingerprints.LinkSharingDomainFingerprint
import app.revanced.util.exception
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.StringReference
@Patch(
name = "Change link sharing domain",
description = "Replaces the domain name of Twitter links when sharing them.",
compatiblePackages = [CompatiblePackage("com.twitter.android")],
)
@Suppress("unused")
object ChangeLinkSharingDomainPatch : BytecodePatch(
setOf(
LinkBuilderFingerprint,
LinkResourceGetterFingerprint,
LinkSharingDomainFingerprint,
),
) {
private var domainName by stringPatchOption(
key = "domainName",
default = "fxtwitter.com",
title = "Domain name",
description = "The domain name to use when sharing links.",
required = true,
)
// This method is used to build the link that is shared when the "Share via..." button is pressed.
private const val FORMAT_METHOD_RESOURCE_REFERENCE =
"Lapp/revanced/integrations/twitter/patches/links/ChangeLinkSharingDomainPatch;->" +
"formatResourceLink([Ljava/lang/Object;)Ljava/lang/String;"
// This method is used to build the link that is shared when the "Copy link" button is pressed.
private const val FORMAT_METHOD_REFERENCE =
"Lapp/revanced/integrations/twitter/patches/links/ChangeLinkSharingDomainPatch;->" +
"formatLink(JLjava/lang/String;)Ljava/lang/String;"
override fun execute(context: BytecodeContext) {
LinkSharingDomainFingerprint.result?.let {
val replacementIndex = it.scanResult.stringsScanResult!!.matches.first().index
val domainRegister = it.mutableMethod.getInstruction<OneRegisterInstruction>(replacementIndex).registerA
it.mutableMethod.replaceInstruction(
replacementIndex,
"const-string v$domainRegister, \"https://$domainName\"",
)
} ?: throw LinkSharingDomainFingerprint.exception
// Replace the domain name when copying a link with "Copy link" button.
LinkBuilderFingerprint.result?.let {
it.mutableMethod.apply {
addInstructions(
0,
"""
invoke-static { p0, p1, p2 }, $FORMAT_METHOD_REFERENCE
move-result-object p0
return-object p0
""",
)
}
} ?: throw LinkBuilderFingerprint.exception
// Used in the Share via... dialog.
LinkResourceGetterFingerprint.result?.mutableMethod?.apply {
val constWithParameterName = indexOfFirstInstructionOrThrow {
getReference<StringReference>()?.string?.contains("id.toString()") == true
}
// Format the link with the new domain name register (2 instructions above the const-string).
val formatLinkCallIndex = constWithParameterName - 2
val formatLinkCall = getInstruction<Instruction35c>(formatLinkCallIndex)
// Replace the original method call with the new method call.
replaceInstruction(
formatLinkCallIndex,
"invoke-static { v${formatLinkCall.registerE} }, $FORMAT_METHOD_RESOURCE_REFERENCE",
)
} ?: throw LinkResourceGetterFingerprint.exception
}
}

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.twitter.misc.links.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
// Returns a shareable link string based on a tweet ID and a username.
internal object LinkBuilderFingerprint : MethodFingerprint(
strings = listOf("/%1\$s/status/%2\$d"),
)

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.twitter.misc.links.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
// Gets Resource string for share link view available by pressing "Share via" button.
internal object LinkResourceGetterFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroid/content/res/Resources;"),
strings = listOf("res.getString(R.string.t…lUsername, id.toString())"),
)

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.twitter.misc.links.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object LinkSharingDomainFingerprint : MethodFingerprint(
strings = listOf("https://fxtwitter.com"),
)

View File

@@ -0,0 +1,28 @@
package app.revanced.patches.willhaben.ads
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.willhaben.ads.fingerprints.AdResolverFingerprint
import app.revanced.patches.willhaben.ads.fingerprints.WHAdViewInjectorFingerprint
import app.revanced.util.returnEarly
@Patch(
name = "Hide ads",
description = "Hides all in-app ads.",
compatiblePackages = [CompatiblePackage("at.willhaben")]
)
@Suppress("unused")
object HideAdsPatch : BytecodePatch(
fingerprints = setOf(
AdResolverFingerprint,
WHAdViewInjectorFingerprint
)
) {
override fun execute(context: BytecodeContext) {
arrayOf(AdResolverFingerprint, WHAdViewInjectorFingerprint).forEach {
it.returnEarly()
}
}
}

View File

@@ -0,0 +1,17 @@
package app.revanced.patches.willhaben.ads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object AdResolverFingerprint : MethodFingerprint(
"L",
parameters = listOf("L", "L"),
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf(
"Google Ad is invalid ",
"Google Native Ad is invalid ",
"Criteo Ad is invalid ",
"Amazon Ad is invalid "
)
)

View File

@@ -0,0 +1,15 @@
package app.revanced.patches.willhaben.ads.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object WHAdViewInjectorFingerprint : MethodFingerprint(
"V",
parameters = listOf("L", "L", "L", "Z"),
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf("successfulAdView"),
customFingerprint = { _, classDef ->
classDef.type == "Lat/willhaben/advertising/WHAdView;"
}
)

View File

@@ -18,13 +18,18 @@ import app.revanced.patches.youtube.layout.hide.general.fingerprints.HideShowMor
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint
import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint
import app.revanced.patches.youtube.layout.hide.general.fingerprints.YoodlesImageViewFingerprint
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import app.revanced.util.findOpcodeIndicesReversed
import app.revanced.util.getReference
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch(
name = "Hide layout components",
@@ -70,7 +75,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
)
@Suppress("unused")
object HideLayoutComponentsPatch : BytecodePatch(
setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint, HideShowMoreButtonFingerprint),
setOf(
ParseElementFromBufferFingerprint,
PlayerOverlayFingerprint,
HideShowMoreButtonFingerprint,
YoodlesImageViewFingerprint,
),
) {
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/patches/components/LayoutComponentsFilter;"
@@ -128,6 +138,7 @@ object HideLayoutComponentsPatch : BytecodePatch(
SwitchPreference("revanced_hide_search_result_recommendations"),
SwitchPreference("revanced_hide_search_result_shelf_header"),
SwitchPreference("revanced_hide_show_more_button"),
SwitchPreference("revanced_hide_doodles"),
PreferenceScreen(
key = "revanced_hide_keyword_content_screen",
sorting = Sorting.UNSORTED,
@@ -226,5 +237,28 @@ object HideLayoutComponentsPatch : BytecodePatch(
}
// endregion
// region 'Yoodles'
YoodlesImageViewFingerprint.resultOrThrow().mutableMethod.apply {
findOpcodeIndicesReversed{
opcode == Opcode.INVOKE_VIRTUAL
&& getReference<MethodReference>()?.name == "setImageDrawable"
}.forEach { insertIndex ->
val register = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
addInstructionsWithLabels(
insertIndex,
"""
invoke-static { v$register }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->hideYoodles(Landroid/graphics/drawable/Drawable;)Landroid/graphics/drawable/Drawable;
move-result-object v$register
if-eqz v$register, :hide
""",
ExternalLabel("hide", getInstruction(insertIndex + 1)),
)
}
}
// endregion
}
}

View File

@@ -17,10 +17,17 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
internal object HideLayoutComponentsResourcePatch : ResourcePatch() {
internal var expandButtonDownId: Long = -1
var youTubeLogo = -1L
override fun execute(context: ResourceContext) {
expandButtonDownId = ResourceMappingPatch[
"layout",
"expand_button_down",
]
youTubeLogo = ResourceMappingPatch[
"id",
"youtube_logo"
]
}
}

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.layout.hide.general.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patches.youtube.layout.hide.general.HideLayoutComponentsResourcePatch
import app.revanced.util.patch.LiteralValueFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object YoodlesImageViewFingerprint : LiteralValueFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("L", "L"),
returnType = "Landroid/view/View;",
literalSupplier = { HideLayoutComponentsResourcePatch.youTubeLogo }
)

View File

@@ -42,6 +42,9 @@ object HideShortsComponentsResourcePatch : ResourcePatch() {
SwitchPreference("revanced_hide_shorts_subscribe_button"),
SwitchPreference("revanced_hide_shorts_paused_overlay_buttons"),
SwitchPreference("revanced_hide_shorts_save_sound_button"),
SwitchPreference("revanced_hide_shorts_use_template_button"),
SwitchPreference("revanced_hide_shorts_upcoming_button"),
SwitchPreference("revanced_hide_shorts_green_screen_button"),
SwitchPreference("revanced_hide_shorts_shop_button"),
SwitchPreference("revanced_hide_shorts_tagged_products"),
SwitchPreference("revanced_hide_shorts_stickers"),

View File

@@ -254,7 +254,9 @@ object SpoofVideoStreamsPatch : BytecodePatch(
// endregion
// region Remove /videoplayback request body to fix playback.
// This is needed when using iOS client as streaming data source.
// It is assumed, YouTube makes a request with a body tuned for Android.
// Requesting streams intended for other platforms with a body tuned for Android could be the cause of 400 errors.
// A proper fix may include modifying the request body to match the platforms expected body.
BuildMediaDataSourceFingerprint.resultOrThrow().let {
it.mutableMethod.apply {

View File

@@ -224,18 +224,25 @@ fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, predicate: Instru
/**
* @return The list of indices of the opcode in reverse order.
*/
fun Method.findOpcodeIndicesReversed(opcode: Opcode): List<Int> {
fun Method.findOpcodeIndicesReversed(opcode: Opcode): List<Int> =
findOpcodeIndicesReversed { this.opcode == opcode }
/**
* @return The list of indices of the opcode in reverse order.
*/
fun Method.findOpcodeIndicesReversed(filter: Instruction.() -> Boolean): List<Int> {
val indexes = implementation!!.instructions
.withIndex()
.filter { (_, instruction) -> instruction.opcode == opcode }
.filter { (_, instruction) -> filter(instruction) }
.map { (index, _) -> index }
.reversed()
if (indexes.isEmpty()) throw PatchException("No ${opcode.name} instructions found in: $this")
if (indexes.isEmpty()) throw PatchException("No matching instructions found in: $this")
return indexes
}
/**
* Return the resolved method early.
*/

View File

@@ -231,6 +231,13 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_transcript_section_summary_off">Transcript section is shown</string>
<string name="revanced_hide_description_components_screen_title">Video description</string>
<string name="revanced_hide_description_components_screen_summary">Hide or show video description components</string>
<!-- https://logos.fandom.com/wiki/YouTube/Yoodles -->
<string name="revanced_hide_doodles_title">Hide YouTube Doodles</string>
<string name="revanced_hide_doodles_summary_on">Search bar Doodles are hidden</string>
<string name="revanced_hide_doodles_summary_off">Search bar Doodles are shown</string>
<string name="revanced_hide_doodles_user_dialog_message">YouTube Doodles show up a few days each year.\n\nIf a Doodle is currently showing in your region and this hide setting is on, then the filter bar below the search bar will also be hidden.</string>
<string name="revanced_custom_filter_screen_title">Custom filter</string>
<string name="revanced_custom_filter_screen_summary">Hide components using custom filters</string>
<string name="revanced_custom_filter_title">Enable custom filter</string>
@@ -240,6 +247,7 @@ This is because Crowdin requires temporarily flattening this file and removing t
<!-- 'Component path builder strings' is the technical name for identifying the Litho UI layout items to hide. This is an advanced feature and most users will never use this. -->
<string name="revanced_custom_filter_strings_summary">List of component path builder strings to filter separated by new line</string>
<string name="revanced_custom_filter_toast_invalid_syntax">Invalid custom filter: %s</string>
<string name="revanced_hide_keyword_content_screen_title">Hide keyword content</string>
<string name="revanced_hide_keyword_content_screen_summary">Hide search and feed videos using keyword filters</string>
<string name="revanced_hide_keyword_content_home_title">Hide home videos by keywords</string>
@@ -629,8 +637,17 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_hide_shorts_location_label_summary_on">Location label is hidden</string>
<string name="revanced_hide_shorts_location_label_summary_off">Location label is shown</string>
<string name="revanced_hide_shorts_save_sound_button_title">Hide save music button</string>
<string name="revanced_hide_shorts_save_sound_button_summary_on">Save music is hidden</string>
<string name="revanced_hide_shorts_save_sound_button_summary_off">Save music is shown</string>
<string name="revanced_hide_shorts_save_sound_button_summary_on">Save music button is hidden</string>
<string name="revanced_hide_shorts_save_sound_button_summary_off">Save music button is shown</string>
<string name="revanced_hide_shorts_use_template_button_title">Hide use template button</string>
<string name="revanced_hide_shorts_use_template_button_summary_on">Use template button is hidden</string>
<string name="revanced_hide_shorts_use_template_button_summary_off">Use template button is shown</string>
<string name="revanced_hide_shorts_upcoming_button_title">Hide upcoming button</string>
<string name="revanced_hide_shorts_upcoming_button_summary_on">Upcoming button is hidden</string>
<string name="revanced_hide_shorts_upcoming_button_summary_off">Upcoming button is shown</string>
<string name="revanced_hide_shorts_green_screen_button_title">Hide green screen button</string>
<string name="revanced_hide_shorts_green_screen_button_summary_on">Green screen button is hidden</string>
<string name="revanced_hide_shorts_green_screen_button_summary_off">Green screen button is shown</string>
<string name="revanced_hide_shorts_search_suggestions_title">Hide search suggestions</string>
<string name="revanced_hide_shorts_search_suggestions_summary_on">Search suggestions are hidden</string>
<string name="revanced_hide_shorts_search_suggestions_summary_off">Search suggestions are shown</string>