mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 18:03:55 +01:00
Compare commits
18 Commits
v2.177.0-d
...
v2.178.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
920bfea952 | ||
|
|
1c95e0fcad | ||
|
|
7f1b70e625 | ||
|
|
d30797f9b8 | ||
|
|
d5609f65ca | ||
|
|
88e6ab2d07 | ||
|
|
7d85d2ad91 | ||
|
|
21adab5ef3 | ||
|
|
2e7e231e7d | ||
|
|
ae67a762ff | ||
|
|
66118829b3 | ||
|
|
22a18467de | ||
|
|
ccc369a2a8 | ||
|
|
c3d898ae0d | ||
|
|
96add7b8fa | ||
|
|
2ee28e0081 | ||
|
|
fa49810907 | ||
|
|
2814328bfd |
63
CHANGELOG.md
63
CHANGELOG.md
@@ -1,3 +1,66 @@
|
||||
# [2.178.0-dev.4](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.3...v2.178.0-dev.4) (2023-06-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **boostforreddit:** add `change-oauth-client-id` patch ([3dbc4bd](https://github.com/revanced/revanced-patches/commit/3dbc4bd49df1656893ef69c68550a2deb6a92cb7))
|
||||
|
||||
# [2.178.0-dev.3](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.2...v2.178.0-dev.3) (2023-06-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/comments:** add missing filter ([#2423](https://github.com/revanced/revanced-patches/issues/2423)) ([cab04b3](https://github.com/revanced/revanced-patches/commit/cab04b3a56cfc5bf00b7c6fcf6f86ab75aa5d4fd))
|
||||
|
||||
# [2.178.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.178.0-dev.1...v2.178.0-dev.2) (2023-06-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **googlerecorder/remove-device-restrictions:** add missing app constraint ([#2438](https://github.com/revanced/revanced-patches/issues/2438)) ([d5efe26](https://github.com/revanced/revanced-patches/commit/d5efe26f8959cde75dd3865ec3c2df4b05210e4a))
|
||||
|
||||
# [2.178.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.177.1-dev.2...v2.178.0-dev.1) (2023-06-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **google-recorder:** add `remove-device-restrictions` patch ([ef96ed1](https://github.com/revanced/revanced-patches/commit/ef96ed124e12091dde34124eabd8be9f2bb9280c))
|
||||
|
||||
## [2.177.1-dev.2](https://github.com/revanced/revanced-patches/compare/v2.177.1-dev.1...v2.177.1-dev.2) (2023-06-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube:** separate `hide-ads` to `hide-layout-components` patch ([7e0417f](https://github.com/revanced/revanced-patches/commit/7e0417f6728fa7b79a9d8cbcfd3ccba484a5567d))
|
||||
|
||||
## [2.177.1-dev.1](https://github.com/revanced/revanced-patches/compare/v2.177.0...v2.177.1-dev.1) (2023-06-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* don't include all Litho patches, when not included ([fc69491](https://github.com/revanced/revanced-patches/commit/fc69491dfe4b119d46dd3da27b556e55fe0cecfb))
|
||||
|
||||
# [2.177.0](https://github.com/revanced/revanced-patches/compare/v2.176.1...v2.177.0) (2023-06-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **reddit/hide-ads:** search for correct reference class descriptor ([ad2a858](https://github.com/revanced/revanced-patches/commit/ad2a8585b2a5ecbc5eb92dd23b0ab124aa8a2541))
|
||||
* **syncforreddit/change-oauth-client-id:** trim whitespace from OAuth string ([#2402](https://github.com/revanced/revanced-patches/issues/2402)) ([2afea71](https://github.com/revanced/revanced-patches/commit/2afea71557cfe4eb64d7c7ebf5a07dfd24a11824))
|
||||
* **syncforreddit/change-oauth-client-id:** use downloads directory ([9b5af77](https://github.com/revanced/revanced-patches/commit/9b5af77a229a22466cfe8ed41a21d081beeae960))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **syncforreddit/change-oauth-client-id:** support pro version ([d34288b](https://github.com/revanced/revanced-patches/commit/d34288b6e8c7f5bb944622a3c741fcc693868033))
|
||||
|
||||
# [2.177.0-dev.2](https://github.com/revanced/revanced-patches/compare/v2.177.0-dev.1...v2.177.0-dev.2) (2023-06-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **reddit/hide-ads:** search for correct reference class descriptor ([ad2a858](https://github.com/revanced/revanced-patches/commit/ad2a8585b2a5ecbc5eb92dd23b0ab124aa8a2541))
|
||||
|
||||
# [2.177.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.176.2-dev.2...v2.177.0-dev.1) (2023-06-12)
|
||||
|
||||
|
||||
|
||||
98
README.md
98
README.md
@@ -25,7 +25,6 @@ The official ReVanced Patches.
|
||||
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.19.35 |
|
||||
| `hide-ads` | Removes general ads. | 18.19.35 |
|
||||
| `hide-album-cards` | Hides the album cards below the artist description. | 18.19.35 |
|
||||
| `hide-artist-card` | Hides the artist card below the searchbar. | 18.19.35 |
|
||||
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.19.35 |
|
||||
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.19.35 |
|
||||
| `hide-captions-button` | Hides the captions button on video player. | 18.19.35 |
|
||||
@@ -36,6 +35,7 @@ The official ReVanced Patches.
|
||||
| `hide-filter-bar` | Hides the filter bar in video feeds. | 18.19.35 |
|
||||
| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.19.35 |
|
||||
| `hide-info-cards` | Hides info cards in videos. | 18.19.35 |
|
||||
| `hide-layout-components` | Hides general layout components. | 18.19.35 |
|
||||
| `hide-load-more-button` | Hides the button under videos that loads similar videos. | 18.19.35 |
|
||||
| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | 18.19.35 |
|
||||
| `hide-player-overlay` | Hides the dark background overlay from the player when player controls are visible. | all |
|
||||
@@ -205,6 +205,14 @@ The official ReVanced Patches.
|
||||
| `spoof-signature` | Spoofs the signature of the app. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.rubenmayayo.reddit`](https://play.google.com/store/apps/details?id=com.rubenmayayo.reddit)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `change-oauth-client-id` | Changes the OAuth client ID in Boost for Reddit. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.laurencedawson.reddit_sync.pro`](https://play.google.com/store/apps/details?id=com.laurencedawson.reddit_sync.pro)
|
||||
<details>
|
||||
|
||||
@@ -293,6 +301,14 @@ The official ReVanced Patches.
|
||||
| `remove-debugging-detection` | Removes the USB and wireless debugging checks. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.google.android.apps.recorder`](https://play.google.com/store/apps/details?id=com.google.android.apps.recorder)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `remove-device-restrictions` | Removes restrictions from using the app on any device. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.dci.dev.androidtwelvewidgets`](https://play.google.com/store/apps/details?id=com.dci.dev.androidtwelvewidgets)
|
||||
<details>
|
||||
|
||||
@@ -325,6 +341,30 @@ The official ReVanced Patches.
|
||||
| `unlock-prime` | Unlocks Nova Prime and all functions of the app. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | 4.6377 |
|
||||
</details>
|
||||
|
||||
### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.vsco.cam`](https://play.google.com/store/apps/details?id=com.vsco.cam)
|
||||
<details>
|
||||
|
||||
@@ -341,22 +381,6 @@ The official ReVanced Patches.
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.candylink.openvpn`](https://play.google.com/store/apps/details?id=com.candylink.openvpn)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks premium features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
|
||||
<details>
|
||||
|
||||
@@ -365,22 +389,6 @@ The official ReVanced Patches.
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | 4.6377 |
|
||||
</details>
|
||||
|
||||
### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
|
||||
<details>
|
||||
|
||||
@@ -389,14 +397,6 @@ The official ReVanced Patches.
|
||||
| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
|
||||
</details>
|
||||
|
||||
### [📦 `tv.trakt.trakt`](https://play.google.com/store/apps/details?id=tv.trakt.trakt)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.wakdev.apps.nfctools.se`](https://play.google.com/store/apps/details?id=com.wakdev.apps.nfctools.se)
|
||||
<details>
|
||||
|
||||
@@ -405,6 +405,22 @@ The official ReVanced Patches.
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks all pro features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.candylink.openvpn`](https://play.google.com/store/apps/details?id=com.candylink.openvpn)
|
||||
<details>
|
||||
|
||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||
|:--------:|:--------------:|:-----------------:|
|
||||
| `unlock-pro` | Unlocks premium features. | all |
|
||||
</details>
|
||||
|
||||
### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
|
||||
<details>
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@ package android.os;
|
||||
import java.io.File;
|
||||
|
||||
public final class Environment {
|
||||
public static String DIRECTORY_DOWNLOADS = "Download";
|
||||
|
||||
public static File getExternalStoragePublicDirectory(final String type) {
|
||||
public static File getExternalStorageDirectory() {
|
||||
throw new UnsupportedOperationException("Stub");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
kotlin.code.style = official
|
||||
version = 2.177.0-dev.1
|
||||
version = 2.178.0-dev.4
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.googlerecorder.restrictions.fingereprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object OnApplicationCreateFingerprint : MethodFingerprint(
|
||||
strings = listOf("com.google.android.feature.PIXEL_2017_EXPERIENCE"),
|
||||
customFingerprint = custom@{ methodDef, classDef ->
|
||||
if (methodDef.name != "onCreate") return@custom false
|
||||
|
||||
classDef.type.endsWith("RecorderApplication;")
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,45 @@
|
||||
package app.revanced.patches.googlerecorder.restrictions.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Package
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
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.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.googlerecorder.restrictions.fingereprints.OnApplicationCreateFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@Name("remove-device-restrictions")
|
||||
@Description("Removes restrictions from using the app on any device.")
|
||||
@Compatibility([Package("com.google.android.apps.recorder")])
|
||||
@Version("0.0.1")
|
||||
class RemoveDeviceRestrictions : BytecodePatch(
|
||||
listOf(OnApplicationCreateFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
OnApplicationCreateFingerprint.result?.let {
|
||||
val featureStringIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
|
||||
it.mutableMethod.apply {
|
||||
// Remove check for device restrictions.
|
||||
removeInstructions(featureStringIndex - 2, 5)
|
||||
|
||||
val featureAvailableRegister = getInstruction<OneRegisterInstruction>(featureStringIndex).registerA
|
||||
|
||||
// Override "isPixelDevice()" to return true.
|
||||
addInstruction(featureStringIndex, "const/4 v$featureAvailableRegister, 0x1")
|
||||
}
|
||||
} ?: return OnApplicationCreateFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ class HideAdsPatch : BytecodePatch(
|
||||
|
||||
val reference = (it as ReferenceInstruction).reference as MethodReference
|
||||
|
||||
reference.name == "add" && reference.definingClass == "Lava/util/ArrayList;"
|
||||
reference.name == "add" && reference.definingClass == "Ljava/util/ArrayList;"
|
||||
}
|
||||
|
||||
result.mutableMethod.removeInstruction(index)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package app.revanced.patches.reddit.customclients
|
||||
|
||||
import android.os.Environment
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.patch.*
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.api.patch.ChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.patch.ChangeOAuthClientIdPatch.Companion.clientId
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractChangeOAuthClientIdPatch(
|
||||
private val redirectUri: String,
|
||||
private val fingerprint: MethodFingerprint,
|
||||
) : BytecodePatch(listOf(fingerprint)) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
if (ChangeOAuthClientIdPatch.clientId == null) {
|
||||
// Test if on Android
|
||||
try {
|
||||
Class.forName("android.os.Environment")
|
||||
} catch (e: ClassNotFoundException) {
|
||||
return PatchResultError("No client ID provided")
|
||||
}
|
||||
|
||||
File(Environment.getExternalStorageDirectory(), "reddit_client_id_revanced.txt").also {
|
||||
if (it.exists()) return@also
|
||||
|
||||
val error = """
|
||||
In order to use this patch, you need to provide a client ID.
|
||||
You can do this by creating a file at ${it.absolutePath} with the client ID as its content.
|
||||
Alternatively, you can provide the client ID using patch options.
|
||||
|
||||
You can get your client ID from https://www.reddit.com/prefs/apps.
|
||||
The application type has to be "installed app" and the redirect URI has to be set to "$redirectUri"
|
||||
""".trimIndent()
|
||||
|
||||
return PatchResultError(error)
|
||||
}.let { clientId = it.readText().trim() }
|
||||
}
|
||||
|
||||
return fingerprint.patch(context)
|
||||
}
|
||||
|
||||
abstract fun MethodFingerprint.patch(context: BytecodeContext): PatchResult
|
||||
|
||||
companion object Options {
|
||||
open class ChangeOAuthClientIdOptionsContainer : OptionsContainer() {
|
||||
var clientId by option(
|
||||
PatchOption.StringOption(
|
||||
"client-id",
|
||||
null,
|
||||
"OAuth client ID",
|
||||
"The Reddit OAuth client ID."
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object GetClientIdFingerprint : MethodFingerprint(
|
||||
customFingerprint = custom@{ methodDef, classDef ->
|
||||
if (!classDef.type.endsWith("Credentials;")) return@custom false
|
||||
|
||||
methodDef.name == "getClientId"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,36 @@
|
||||
package app.revanced.patches.reddit.customclients.boostforreddit.api.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.*
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("change-oauth-client-id")
|
||||
@Description("Changes the OAuth client ID in Boost for Reddit.")
|
||||
@Compatibility([Package("com.rubenmayayo.reddit")])
|
||||
@Version("0.0.1")
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
"http://rubenmayayo.com",
|
||||
GetClientIdFingerprint
|
||||
) {
|
||||
override fun MethodFingerprint.patch(context: BytecodeContext): PatchResult {
|
||||
result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
"""
|
||||
) ?: return toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object : Options.ChangeOAuthClientIdOptionsContainer()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.syncforreddit.ads.fingerprints
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.syncforreddit.ads.patch
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.ads.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.*
|
||||
@@ -9,8 +9,8 @@ import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint
|
||||
import app.revanced.patches.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.ads.fingerprints.IsAdsEnabledFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
|
||||
|
||||
@Patch
|
||||
@Name("disable-ads")
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.syncforreddit.api.fingerprints
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.syncforreddit.api.fingerprints
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.api.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.*
|
||||
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.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.StringReference
|
||||
import java.util.*
|
||||
|
||||
|
||||
@Patch
|
||||
@Name("change-oauth-client-id")
|
||||
@Description("Changes the OAuth client ID.")
|
||||
@Compatibility([Package("com.laurencedawson.reddit_sync"), Package("com.laurencedawson.reddit_sync.pro")])
|
||||
@Version("0.0.1")
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
"http://redditsync/auth",
|
||||
GetAuthorizationStringFingerprint,
|
||||
) {
|
||||
override fun MethodFingerprint.patch(context: BytecodeContext): PatchResult {
|
||||
result?.also { result ->
|
||||
GetBearerTokenFingerprint.also { it.resolve(context, result.classDef) }.result?.mutableMethod?.apply {
|
||||
val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8))
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "Basic $auth"
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
} ?: return GetBearerTokenFingerprint.toErrorResult()
|
||||
}?.let {
|
||||
val occurrenceIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val authorizationStringInstruction = getInstruction<ReferenceInstruction>(occurrenceIndex)
|
||||
val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA
|
||||
val reference = authorizationStringInstruction.reference as StringReference
|
||||
|
||||
val newAuthorizationUrl = reference.string.replace(
|
||||
"client_id=.*?&".toRegex(),
|
||||
"client_id=${clientId!!}&"
|
||||
)
|
||||
|
||||
replaceInstruction(
|
||||
occurrenceIndex,
|
||||
"const-string v$targetRegister, \"$newAuthorizationUrl\""
|
||||
)
|
||||
}
|
||||
} ?: return toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object : Options.ChangeOAuthClientIdOptionsContainer()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.syncforreddit.detection.piracy.patch
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
@@ -1,104 +0,0 @@
|
||||
package app.revanced.patches.syncforreddit.api.patch
|
||||
|
||||
import android.os.Environment
|
||||
import app.revanced.patcher.annotation.*
|
||||
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.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.*
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
|
||||
import app.revanced.patches.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.StringReference
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@Patch
|
||||
@Name("change-oauth-client-id")
|
||||
@Description("Changes the OAuth client ID.")
|
||||
@Compatibility(
|
||||
[
|
||||
Package("com.laurencedawson.reddit_sync"),
|
||||
Package("com.laurencedawson.reddit_sync.pro")
|
||||
]
|
||||
)
|
||||
@Version("0.0.1")
|
||||
class ChangeOAuthClientIdPatch : BytecodePatch(
|
||||
listOf(GetAuthorizationStringFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
if (clientId == null) {
|
||||
// Test if on Android
|
||||
try {
|
||||
Class.forName("android.os.Environment")
|
||||
} catch (e: ClassNotFoundException) {
|
||||
return PatchResultError("No client ID provided")
|
||||
}
|
||||
|
||||
File(
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
|
||||
"reddit_client_id_revanced.txt"
|
||||
).also {
|
||||
if (it.exists()) return@also
|
||||
|
||||
val error = """
|
||||
In order to use this patch, you need to provide a client ID.
|
||||
You can do this by creating a file at ${it.absolutePath} with the client ID as its content.
|
||||
Alternatively, you can provide the client ID using patch options.
|
||||
|
||||
You can get your client ID from https://www.reddit.com/prefs/apps.
|
||||
The application type has to be "installed app" and the redirect URI has to be set to "http://redditsync/auth"
|
||||
""".trimIndent()
|
||||
|
||||
return PatchResultError(error)
|
||||
}.let { clientId = it.readText().trim() }
|
||||
}
|
||||
|
||||
GetAuthorizationStringFingerprint.result?.also { result ->
|
||||
GetBearerTokenFingerprint.also { it.resolve(context, result.classDef) }.result?.mutableMethod?.apply {
|
||||
val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8))
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "Basic $auth"
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
} ?: return PatchResultError("Could not find required method to patch.")
|
||||
}?.let {
|
||||
val occurrenceIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val authorizationStringInstruction = getInstruction<ReferenceInstruction>(occurrenceIndex)
|
||||
val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA
|
||||
val reference = authorizationStringInstruction.reference as StringReference
|
||||
|
||||
val newAuthorizationUrl = reference.string.replace(
|
||||
"client_id=.*?&".toRegex(),
|
||||
"client_id=${clientId!!}&"
|
||||
)
|
||||
|
||||
replaceInstruction(
|
||||
occurrenceIndex,
|
||||
"const-string v$targetRegister, \"$newAuthorizationUrl\""
|
||||
)
|
||||
}
|
||||
} ?: return PatchResultError("Could not find required method to patch.")
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object : OptionsContainer() {
|
||||
var clientId by option(
|
||||
PatchOption.StringOption(
|
||||
"client-id",
|
||||
null,
|
||||
"OAuth client ID",
|
||||
"The client ID to use for OAuth."
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -7,14 +7,15 @@ import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.*
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.ad.general.annotation.HideAdsCompatibility
|
||||
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
|
||||
|
||||
@DependsOn(
|
||||
dependencies = [
|
||||
[
|
||||
LithoFilterPatch::class,
|
||||
SettingsPatch::class,
|
||||
ResourceMappingPatch::class
|
||||
@@ -23,185 +24,7 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.P
|
||||
@HideAdsCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideAdsResourcePatch : ResourcePatch {
|
||||
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_hide_gray_separator",
|
||||
StringResource("revanced_hide_gray_separator_title", "Hide gray separator"),
|
||||
StringResource("revanced_hide_gray_separator_summary_on", "Gray separators are hidden"),
|
||||
StringResource("revanced_hide_gray_separator_summary_off", "Gray separators are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_channel_guidelines",
|
||||
StringResource("revanced_hide_channel_guidelines_title", "Hide channel guidelines"),
|
||||
StringResource(
|
||||
"revanced_hide_channel_guidelines_summary_on",
|
||||
"Channel guidelines are hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_channel_guidelines_summary_off",
|
||||
"Channel guidelines are shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_chapter_teaser",
|
||||
StringResource(
|
||||
"revanced_hide_chapter_teaser_title",
|
||||
"Hide chapter teaser under videos"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_chapter_teaser_summary_on",
|
||||
"Chapter teasers are hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_chapter_teaser_summary_off",
|
||||
"Chapter teasers are shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_merchandise_banners",
|
||||
StringResource("revanced_hide_merchandise_banners_title", "Hide merchandise banners"),
|
||||
StringResource("revanced_hide_merchandise_banners_summary_on", "Merchandise banners are hidden"),
|
||||
StringResource("revanced_hide_merchandise_banners_summary_off", "Merchandise banners are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_community_posts",
|
||||
StringResource("revanced_hide_community_posts_title", "Hide community posts"),
|
||||
StringResource("revanced_hide_community_posts_summary_on", "Community posts are hidden"),
|
||||
StringResource("revanced_hide_community_posts_summary_off", "Community posts are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_compact_banner",
|
||||
StringResource("revanced_hide_compact_banner_title", "Hide compact banners"),
|
||||
StringResource("revanced_hide_compact_banner_summary_on", "Compact banners are hidden"),
|
||||
StringResource("revanced_hide_compact_banner_summary_off", "Compact banners are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_products_banner",
|
||||
StringResource("revanced_hide_products_banner_title", "Hide banner to view products"),
|
||||
StringResource("revanced_hide_products_banner_summary_on", "Banner is hidden"),
|
||||
StringResource("revanced_hide_products_banner_summary_off", "Banner is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_web_search_results",
|
||||
StringResource("revanced_hide_web_search_results_title", "Hide web search results"),
|
||||
StringResource("revanced_hide_web_search_results_summary_on", "Web search results are hidden"),
|
||||
StringResource("revanced_hide_web_search_results_summary_off", "Web search results are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_movies_section",
|
||||
StringResource("revanced_hide_movies_section_title", "Hide movies section"),
|
||||
StringResource("revanced_hide_movies_section_summary_on", "Movies section is hidden"),
|
||||
StringResource("revanced_hide_movies_section_summary_off", "Movies section is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_feed_survey",
|
||||
StringResource("revanced_hide_feed_survey_title", "Hide feed surveys"),
|
||||
StringResource("revanced_hide_feed_survey_summary_on", "Feed surveys are hidden"),
|
||||
StringResource("revanced_hide_feed_survey_summary_off", "Feed surveys are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_community_guidelines",
|
||||
StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"),
|
||||
StringResource(
|
||||
"revanced_hide_community_guidelines_summary_on",
|
||||
"Community guidelines are hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_community_guidelines_summary_off",
|
||||
"Community guidelines are shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_subscribers_community_guidelines",
|
||||
StringResource(
|
||||
"revanced_hide_subscribers_community_guidelines_title",
|
||||
"Hide subscribers community guidelines"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_subscribers_community_guidelines_summary_on",
|
||||
"Subscribers community guidelines are hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_subscribers_community_guidelines_summary_off",
|
||||
"Subscribers community guidelines are shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_channel_member_shelf",
|
||||
StringResource("revanced_hide_channel_member_shelf_title", "Hide channel member shelf"),
|
||||
StringResource(
|
||||
"revanced_hide_channel_member_shelf_summary_on",
|
||||
"Channel member shelf is hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_channel_member_shelf_summary_off",
|
||||
"Channel member shelf is shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_emergency_box",
|
||||
StringResource("revanced_hide_emergency_box_title", "Hide emergency boxes"),
|
||||
StringResource("revanced_hide_emergency_box_summary_on", "Emergency boxes are hidden"),
|
||||
StringResource("revanced_hide_emergency_box_summary_off", "Emergency boxes are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_info_panels",
|
||||
StringResource("revanced_hide_info_panels_title", "Hide info panels"),
|
||||
StringResource("revanced_hide_info_panels_summary_on", "Info panels are hidden"),
|
||||
StringResource("revanced_hide_info_panels_summary_off", "Info panels are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_medical_panels",
|
||||
StringResource("revanced_hide_medical_panels_title", "Hide medical panels"),
|
||||
StringResource("revanced_hide_medical_panels_summary_on", "Medical panels are hidden"),
|
||||
StringResource("revanced_hide_medical_panels_summary_off", "Medical panels are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_channel_bar",
|
||||
StringResource("revanced_hide_channel_bar_title", "Hide channel bar"),
|
||||
StringResource("revanced_hide_channel_bar_summary_on", "Channel bar is hidden"),
|
||||
StringResource("revanced_hide_channel_bar_summary_off", "Channel bar is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_quick_actions",
|
||||
StringResource("revanced_hide_quick_actions_title", "Hide quick actions in fullscreen"),
|
||||
StringResource("revanced_hide_quick_actions_summary_on", "Quick actions are hidden"),
|
||||
StringResource("revanced_hide_quick_actions_summary_off", "Quick actions are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_related_videos",
|
||||
StringResource("revanced_hide_related_videos_title", "Hide related videos in quick actions"),
|
||||
StringResource("revanced_hide_related_videos_summary_on", "Related videos are hidden"),
|
||||
StringResource("revanced_hide_related_videos_summary_off", "Related videos are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_image_shelf",
|
||||
StringResource("revanced_hide_image_shelf", "Hide image shelf in search results"),
|
||||
StringResource("revanced_hide_image_shelf_summary_on", "Image shelf is hidden"),
|
||||
StringResource("revanced_hide_image_shelf_summary_off", "Image shelf is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_audio_track_button",
|
||||
StringResource("revanced_hide_audio_track_button_title", "Hide audio track button"),
|
||||
StringResource("revanced_hide_audio_track_button_on", "Audio track button is hidden"),
|
||||
StringResource("revanced_hide_audio_track_button_off", "Audio track button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_latest_posts_ads",
|
||||
StringResource("revanced_hide_latest_posts_ads_title", "Hide latest posts"),
|
||||
StringResource("revanced_hide_latest_posts_ads_summary_on", "Latest posts are hidden"),
|
||||
StringResource("revanced_hide_latest_posts_ads_summary_off", "Latest posts are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_mix_playlists",
|
||||
StringResource("revanced_hide_mix_playlists_title", "Hide mix playlists"),
|
||||
StringResource("revanced_hide_mix_playlists_summary_on", "Mix playlists are hidden"),
|
||||
StringResource("revanced_hide_mix_playlists_summary_off", "Mix playlists are shown")
|
||||
),
|
||||
)
|
||||
|
||||
PreferenceScreen.ADS.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_hide_general_ads",
|
||||
@@ -227,38 +50,28 @@ class HideAdsResourcePatch : ResourcePatch {
|
||||
StringResource("revanced_hide_self_sponsor_ads_summary_on", "Self sponsored cards are hidden"),
|
||||
StringResource("revanced_hide_self_sponsor_ads_summary_off", "Self sponsored cards are shown")
|
||||
),
|
||||
PreferenceScreen(
|
||||
"revanced_custom_filter_preference_screen",
|
||||
StringResource("revanced_custom_filter_preference_screen_title", "Custom filter"),
|
||||
listOf(
|
||||
SwitchPreference(
|
||||
"revanced_custom_filter",
|
||||
StringResource(
|
||||
"revanced_custom_filter_title",
|
||||
"Enable custom filter"
|
||||
"revanced_hide_products_banner",
|
||||
StringResource("revanced_hide_products_banner_title", "Hide banner to view products"),
|
||||
StringResource("revanced_hide_products_banner_summary_on", "Banner is hidden"),
|
||||
StringResource("revanced_hide_products_banner_summary_off", "Banner is shown")
|
||||
),
|
||||
StringResource(
|
||||
"revanced_custom_filter_summary_on",
|
||||
"Custom filter is enabled"
|
||||
SwitchPreference(
|
||||
"revanced_hide_web_search_results",
|
||||
StringResource("revanced_hide_web_search_results_title", "Hide web search results"),
|
||||
StringResource("revanced_hide_web_search_results_summary_on", "Web search results are hidden"),
|
||||
StringResource("revanced_hide_web_search_results_summary_off", "Web search results are shown")
|
||||
),
|
||||
StringResource(
|
||||
"revanced_custom_filter_summary_off",
|
||||
"Custom filter is disabled"
|
||||
)
|
||||
),
|
||||
// TODO: This should be a dynamic ListPreference, which does not exist yet
|
||||
TextPreference(
|
||||
"revanced_custom_filter_strings",
|
||||
StringResource("revanced_custom_filter_strings_title", "Custom filter"),
|
||||
StringResource(
|
||||
"revanced_custom_filter_strings_summary",
|
||||
"Filter components by their name separated by a comma"
|
||||
)
|
||||
)
|
||||
)
|
||||
SwitchPreference(
|
||||
"revanced_hide_merchandise_banners",
|
||||
StringResource("revanced_hide_merchandise_banners_title", "Hide merchandise banners"),
|
||||
StringResource("revanced_hide_merchandise_banners_summary_on", "Merchandise banners are hidden"),
|
||||
StringResource("revanced_hide_merchandise_banners_summary_off", "Merchandise banners are shown")
|
||||
)
|
||||
)
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
adAttributionId = ResourceMappingPatch.resourceMappings.single { it.name == "ad_attribution" }.id
|
||||
|
||||
return PatchResultSuccess()
|
||||
@@ -266,5 +79,8 @@ class HideAdsResourcePatch : ResourcePatch {
|
||||
|
||||
internal companion object {
|
||||
var adAttributionId: Long = -1
|
||||
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/AdsFilter;"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,14 @@ class HideButtonsPatch : ResourcePatch {
|
||||
StringResource("revanced_hide_buttons_preference_screen_summary", "Hide or show buttons under videos")
|
||||
)
|
||||
)
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/ButtonsFilter;"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package app.revanced.patches.youtube.layout.hide.artistcards.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class HideArtistCardCompatibility
|
||||
@@ -1,37 +0,0 @@
|
||||
package app.revanced.patches.youtube.layout.hide.artistcards.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.layout.hide.artistcards.annotations.HideArtistCardCompatibility
|
||||
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
|
||||
@Patch
|
||||
@DependsOn([ResourceMappingPatch::class, LithoFilterPatch::class])
|
||||
@Name("hide-artist-card")
|
||||
@Description("Hides the artist card below the searchbar.")
|
||||
@HideArtistCardCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideArtistCardsPatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_hide_artist_cards",
|
||||
StringResource("revanced_hide_artist_cards_title", "Hide artist cards"),
|
||||
StringResource("revanced_hide_artist_cards_on", "Artist cards is hidden"),
|
||||
StringResource("revanced_hide_artist_cards_off", "Artist cards is shown")
|
||||
),
|
||||
)
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -9,21 +9,23 @@ import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.PreferenceScreen
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.layout.hide.comments.annotations.HideCommentsCompatibility
|
||||
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
|
||||
@Patch
|
||||
@Name("comments")
|
||||
@Description("Hides components related to comments.")
|
||||
@HideCommentsCompatibility
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
@DependsOn([SettingsPatch::class, LithoFilterPatch::class])
|
||||
@Version("0.0.1")
|
||||
class CommentsPatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
PreferenceScreen(
|
||||
"revanced_comments_preference_screen",
|
||||
@@ -48,4 +50,8 @@ class CommentsPatch : ResourcePatch {
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/CommentsFilter;"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package app.revanced.patches.youtube.misc.litho.filter.annotation
|
||||
package app.revanced.patches.youtube.layout.hide.general.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.google.android.youtube", arrayOf("18.16.37", "18.19.35"))])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class LithoFilterCompatibility
|
||||
internal annotation class HideLayoutComponentsCompatibility
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
package app.revanced.patches.youtube.layout.hide.general.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.shared.settings.preference.impl.TextPreference
|
||||
import app.revanced.patches.youtube.layout.hide.general.annotations.HideLayoutComponentsCompatibility
|
||||
import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch.PreferenceScreen
|
||||
|
||||
@Patch
|
||||
@Name("hide-layout-components")
|
||||
@Description("Hides general layout components.")
|
||||
@DependsOn([LithoFilterPatch::class, SettingsPatch::class])
|
||||
@HideLayoutComponentsCompatibility
|
||||
@Version("0.0.1")
|
||||
class HideLayoutComponentsPatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
PreferenceScreen.LAYOUT.addPreferences(
|
||||
SwitchPreference(
|
||||
"revanced_hide_gray_separator",
|
||||
StringResource("revanced_hide_gray_separator_title", "Hide gray separator"),
|
||||
StringResource("revanced_hide_gray_separator_summary_on", "Gray separators are hidden"),
|
||||
StringResource("revanced_hide_gray_separator_summary_off", "Gray separators are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_channel_guidelines",
|
||||
StringResource("revanced_hide_channel_guidelines_title", "Hide channel guidelines"),
|
||||
StringResource(
|
||||
"revanced_hide_channel_guidelines_summary_on",
|
||||
"Channel guidelines are hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_channel_guidelines_summary_off",
|
||||
"Channel guidelines are shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_chapter_teaser",
|
||||
StringResource(
|
||||
"revanced_hide_chapter_teaser_title",
|
||||
"Hide chapter teaser under videos"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_chapter_teaser_summary_on",
|
||||
"Chapter teasers are hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_chapter_teaser_summary_off",
|
||||
"Chapter teasers are shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_community_posts",
|
||||
StringResource("revanced_hide_community_posts_title", "Hide community posts"),
|
||||
StringResource("revanced_hide_community_posts_summary_on", "Community posts are hidden"),
|
||||
StringResource("revanced_hide_community_posts_summary_off", "Community posts are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_compact_banner",
|
||||
StringResource("revanced_hide_compact_banner_title", "Hide compact banners"),
|
||||
StringResource("revanced_hide_compact_banner_summary_on", "Compact banners are hidden"),
|
||||
StringResource("revanced_hide_compact_banner_summary_off", "Compact banners are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_movies_section",
|
||||
StringResource("revanced_hide_movies_section_title", "Hide movies section"),
|
||||
StringResource("revanced_hide_movies_section_summary_on", "Movies section is hidden"),
|
||||
StringResource("revanced_hide_movies_section_summary_off", "Movies section is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_feed_survey",
|
||||
StringResource("revanced_hide_feed_survey_title", "Hide feed surveys"),
|
||||
StringResource("revanced_hide_feed_survey_summary_on", "Feed surveys are hidden"),
|
||||
StringResource("revanced_hide_feed_survey_summary_off", "Feed surveys are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_community_guidelines",
|
||||
StringResource("revanced_hide_community_guidelines_title", "Hide community guidelines"),
|
||||
StringResource(
|
||||
"revanced_hide_community_guidelines_summary_on",
|
||||
"Community guidelines are hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_community_guidelines_summary_off",
|
||||
"Community guidelines are shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_subscribers_community_guidelines",
|
||||
StringResource(
|
||||
"revanced_hide_subscribers_community_guidelines_title",
|
||||
"Hide subscribers community guidelines"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_subscribers_community_guidelines_summary_on",
|
||||
"Subscribers community guidelines are hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_subscribers_community_guidelines_summary_off",
|
||||
"Subscribers community guidelines are shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_channel_member_shelf",
|
||||
StringResource("revanced_hide_channel_member_shelf_title", "Hide channel member shelf"),
|
||||
StringResource(
|
||||
"revanced_hide_channel_member_shelf_summary_on",
|
||||
"Channel member shelf is hidden"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_hide_channel_member_shelf_summary_off",
|
||||
"Channel member shelf is shown"
|
||||
)
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_emergency_box",
|
||||
StringResource("revanced_hide_emergency_box_title", "Hide emergency boxes"),
|
||||
StringResource("revanced_hide_emergency_box_summary_on", "Emergency boxes are hidden"),
|
||||
StringResource("revanced_hide_emergency_box_summary_off", "Emergency boxes are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_info_panels",
|
||||
StringResource("revanced_hide_info_panels_title", "Hide info panels"),
|
||||
StringResource("revanced_hide_info_panels_summary_on", "Info panels are hidden"),
|
||||
StringResource("revanced_hide_info_panels_summary_off", "Info panels are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_medical_panels",
|
||||
StringResource("revanced_hide_medical_panels_title", "Hide medical panels"),
|
||||
StringResource("revanced_hide_medical_panels_summary_on", "Medical panels are hidden"),
|
||||
StringResource("revanced_hide_medical_panels_summary_off", "Medical panels are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_channel_bar",
|
||||
StringResource("revanced_hide_channel_bar_title", "Hide channel bar"),
|
||||
StringResource("revanced_hide_channel_bar_summary_on", "Channel bar is hidden"),
|
||||
StringResource("revanced_hide_channel_bar_summary_off", "Channel bar is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_quick_actions",
|
||||
StringResource("revanced_hide_quick_actions_title", "Hide quick actions in fullscreen"),
|
||||
StringResource("revanced_hide_quick_actions_summary_on", "Quick actions are hidden"),
|
||||
StringResource("revanced_hide_quick_actions_summary_off", "Quick actions are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_related_videos",
|
||||
StringResource("revanced_hide_related_videos_title", "Hide related videos in quick actions"),
|
||||
StringResource("revanced_hide_related_videos_summary_on", "Related videos are hidden"),
|
||||
StringResource("revanced_hide_related_videos_summary_off", "Related videos are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_image_shelf",
|
||||
StringResource("revanced_hide_image_shelf", "Hide image shelf in search results"),
|
||||
StringResource("revanced_hide_image_shelf_summary_on", "Image shelf is hidden"),
|
||||
StringResource("revanced_hide_image_shelf_summary_off", "Image shelf is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_audio_track_button",
|
||||
StringResource("revanced_hide_audio_track_button_title", "Hide audio track button"),
|
||||
StringResource("revanced_hide_audio_track_button_on", "Audio track button is hidden"),
|
||||
StringResource("revanced_hide_audio_track_button_off", "Audio track button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_latest_posts_ads",
|
||||
StringResource("revanced_hide_latest_posts_ads_title", "Hide latest posts"),
|
||||
StringResource("revanced_hide_latest_posts_ads_summary_on", "Latest posts are hidden"),
|
||||
StringResource("revanced_hide_latest_posts_ads_summary_off", "Latest posts are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_mix_playlists",
|
||||
StringResource("revanced_hide_mix_playlists_title", "Hide mix playlists"),
|
||||
StringResource("revanced_hide_mix_playlists_summary_on", "Mix playlists are hidden"),
|
||||
StringResource("revanced_hide_mix_playlists_summary_off", "Mix playlists are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_artist_cards",
|
||||
StringResource("revanced_hide_artist_cards_title", "Hide artist cards"),
|
||||
StringResource("revanced_hide_artist_cards_on", "Artist cards is hidden"),
|
||||
StringResource("revanced_hide_artist_cards_off", "Artist cards is shown")
|
||||
),
|
||||
app.revanced.patches.shared.settings.preference.impl.PreferenceScreen(
|
||||
"revanced_custom_filter_preference_screen",
|
||||
StringResource("revanced_custom_filter_preference_screen_title", "Custom filter"),
|
||||
listOf(
|
||||
SwitchPreference(
|
||||
"revanced_custom_filter",
|
||||
StringResource(
|
||||
"revanced_custom_filter_title",
|
||||
"Enable custom filter"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_custom_filter_summary_on",
|
||||
"Custom filter is enabled"
|
||||
),
|
||||
StringResource(
|
||||
"revanced_custom_filter_summary_off",
|
||||
"Custom filter is disabled"
|
||||
)
|
||||
),
|
||||
// TODO: This should be a dynamic ListPreference, which does not exist yet
|
||||
TextPreference(
|
||||
"revanced_custom_filter_strings",
|
||||
StringResource("revanced_custom_filter_strings_title", "Custom filter"),
|
||||
StringResource(
|
||||
"revanced_custom_filter_strings_summary",
|
||||
"Filter components by their name separated by a comma"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
internal companion object {
|
||||
private const val FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/LayoutComponentsFilter;"
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,8 @@ class HideShortsComponentsPatch : BytecodePatch(
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
|
||||
|
||||
// region Hide the Shorts shelf.
|
||||
|
||||
ReelConstructorFingerprint.result?.let {
|
||||
@@ -59,7 +61,7 @@ class HideShortsComponentsPatch : BytecodePatch(
|
||||
injectHideViewCall(
|
||||
insertIndex,
|
||||
viewRegister,
|
||||
CLASS_DESCRIPTOR,
|
||||
FILTER_CLASS_DESCRIPTOR,
|
||||
"hideShortsShelf"
|
||||
)
|
||||
}
|
||||
@@ -89,7 +91,7 @@ class HideShortsComponentsPatch : BytecodePatch(
|
||||
val viewRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
"sput-object v$viewRegister, $CLASS_DESCRIPTOR->pivotBar:" +
|
||||
"sput-object v$viewRegister, $FILTER_CLASS_DESCRIPTOR->pivotBar:" +
|
||||
"Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;"
|
||||
)
|
||||
}
|
||||
@@ -102,7 +104,7 @@ class HideShortsComponentsPatch : BytecodePatch(
|
||||
throw RenderBottomNavigationBarFingerprint.toErrorResult()
|
||||
|
||||
RenderBottomNavigationBarFingerprint.result!!.mutableMethod.apply {
|
||||
addInstruction(0, "invoke-static { }, $CLASS_DESCRIPTOR->hideNavigationBar()V")
|
||||
addInstruction(0, "invoke-static { }, $FILTER_CLASS_DESCRIPTOR->hideNavigationBar()V")
|
||||
}
|
||||
} ?: return RenderBottomNavigationBarParentFingerprint.toErrorResult()
|
||||
|
||||
@@ -115,7 +117,7 @@ class HideShortsComponentsPatch : BytecodePatch(
|
||||
|
||||
addInstruction(
|
||||
insertIndex,
|
||||
"invoke-static { v$viewRegister }, $CLASS_DESCRIPTOR->" +
|
||||
"invoke-static { v$viewRegister }, $FILTER_CLASS_DESCRIPTOR->" +
|
||||
"hideNavigationBar(Landroid/view/View;)Landroid/view/View;"
|
||||
)
|
||||
}
|
||||
@@ -127,7 +129,7 @@ class HideShortsComponentsPatch : BytecodePatch(
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
|
||||
private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
|
||||
|
||||
private enum class ShortsButtons(private val resourceName: String, private val methodName: String) {
|
||||
COMMENTS("reel_dyn_comment", "hideShortsCommentsButton"),
|
||||
@@ -139,7 +141,7 @@ class HideShortsComponentsPatch : BytecodePatch(
|
||||
|
||||
val setIdIndex = referencedIndex + 1
|
||||
val viewRegister = method.getInstruction<FiveRegisterInstruction>(setIdIndex).registerC
|
||||
method.injectHideViewCall(setIdIndex, viewRegister, CLASS_DESCRIPTOR, methodName)
|
||||
method.injectHideViewCall(setIdIndex, viewRegister, FILTER_CLASS_DESCRIPTOR, methodName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.jf.dexlib2.iface.reference.StringReference
|
||||
|
||||
@Patch
|
||||
@DependsOn(
|
||||
dependencies = [
|
||||
[
|
||||
IntegrationsPatch::class,
|
||||
VideoIdPatch::class,
|
||||
// Required to skip segments on time.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package app.revanced.patches.youtube.misc.litho.filter.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object LithoFilterFingerprint : MethodFingerprint(
|
||||
customFingerprint = custom@{ method, classDef ->
|
||||
if (method.name != "<clinit>") return@custom false
|
||||
|
||||
classDef.type.endsWith("LithoFilterPatch;")
|
||||
}
|
||||
)
|
||||
@@ -4,8 +4,11 @@ import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Version
|
||||
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.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
@@ -14,29 +17,27 @@ import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.annotation.LithoFilterCompatibility
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ComponentContextParserFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.EmptyComponentBuilderFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ProtobufBufferFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ReadComponentIdentifierFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.*
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import java.io.Closeable
|
||||
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@Description("Hooks the method which parses the bytes into a ComponentContext to filter components.")
|
||||
@LithoFilterCompatibility
|
||||
@Version("0.0.1")
|
||||
class LithoFilterPatch : BytecodePatch(
|
||||
listOf(ComponentContextParserFingerprint)
|
||||
) {
|
||||
listOf(ComponentContextParserFingerprint, LithoFilterFingerprint)
|
||||
), Closeable {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
ComponentContextParserFingerprint.result?.also {
|
||||
arrayOf(
|
||||
EmptyComponentBuilderFingerprint, ReadComponentIdentifierFingerprint, ProtobufBufferFingerprint
|
||||
EmptyComponentBuilderFingerprint,
|
||||
ReadComponentIdentifierFingerprint,
|
||||
ProtobufBufferFingerprint
|
||||
).forEach { fingerprint ->
|
||||
if (!fingerprint.resolve(context, it.mutableMethod, it.mutableClass))
|
||||
if (fingerprint.resolve(context, it.mutableMethod, it.mutableClass)) return@forEach
|
||||
return fingerprint.toErrorResult()
|
||||
}
|
||||
}?.let { result ->
|
||||
@@ -45,16 +46,28 @@ class LithoFilterPatch : BytecodePatch(
|
||||
|
||||
result.mutableMethod.apply {
|
||||
val insertHookIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
val builderMethodDescriptor = getInstruction(builderMethodIndex).descriptor
|
||||
val emptyComponentFieldDescriptor = getInstruction(emptyComponentFieldIndex).descriptor
|
||||
// Register is overwritten right after it is used in this patch, therefore free to clobber.
|
||||
val free = getInstruction<TwoRegisterInstruction>(insertHookIndex - 1).registerA
|
||||
val free2 = getInstruction<OneRegisterInstruction>(insertHookIndex).registerA
|
||||
|
||||
// region Get free registers that this patch uses
|
||||
// Registers are overwritten right after they are used in this patch, therefore free to clobber.
|
||||
|
||||
val freeRegistersInstruction = getInstruction<FiveRegisterInstruction>(insertHookIndex - 2)
|
||||
|
||||
// Later used to store the protobuf buffer object.
|
||||
val free1 = getInstruction<OneRegisterInstruction>(insertHookIndex).registerA
|
||||
// Later used to store the identifier of the component.
|
||||
// This register currently holds a reference to the StringBuilder object
|
||||
// that is required before clobbering.
|
||||
val free2 = freeRegistersInstruction.registerC
|
||||
|
||||
@Suppress("UnnecessaryVariable")
|
||||
// The register, this patch clobbers, is previously used for the StringBuilder,
|
||||
// later on a new StringBuilder is instantiated on it.
|
||||
val stringBuilderRegister = free
|
||||
val stringBuilderRegister = free2
|
||||
|
||||
// endregion
|
||||
|
||||
// region Get references that this patch needs
|
||||
|
||||
val builderMethodDescriptor = getInstruction(builderMethodIndex).descriptor
|
||||
val emptyComponentFieldDescriptor = getInstruction(emptyComponentFieldIndex).descriptor
|
||||
|
||||
val identifierRegister =
|
||||
getInstruction<OneRegisterInstruction>(ReadComponentIdentifierFingerprint.patternScanEndIndex).registerA
|
||||
@@ -69,57 +82,87 @@ class LithoFilterPatch : BytecodePatch(
|
||||
getInstruction(ProtobufBufferFingerprint.patternScanEndIndex - 1).descriptor
|
||||
val protobufBufferFieldDescriptor = "$protobufBufferRefTypeDescriptor->b:Ljava/nio/ByteBuffer;"
|
||||
|
||||
// endregion
|
||||
|
||||
// region Patch the method
|
||||
|
||||
// Insert the instructions that are responsible
|
||||
// to return an EmptyComponent instead of the original component if the filter method returns false.
|
||||
addInstructionsWithLabels(
|
||||
insertHookIndex, // right after setting the component.pathBuilder field.
|
||||
insertHookIndex,
|
||||
"""
|
||||
# Get the protobuf buffer object.
|
||||
|
||||
move-object/from16 v$free2, p$protobufParameterNumber
|
||||
iget-object v$free2, v$free2, $protobufBufferRefTypeRefFieldDescriptor
|
||||
check-cast v$free2, $protobufBufferRefTypeDescriptor
|
||||
move-object/from16 v$free1, p$protobufParameterNumber
|
||||
iget-object v$free1, v$free1, $protobufBufferRefTypeRefFieldDescriptor
|
||||
check-cast v$free1, $protobufBufferRefTypeDescriptor
|
||||
|
||||
# Register "free" now holds the protobuf buffer object
|
||||
|
||||
iget-object v$free2, v$free2, $protobufBufferFieldDescriptor
|
||||
iget-object v$free1, v$free1, $protobufBufferFieldDescriptor
|
||||
|
||||
# Invoke the filter method.
|
||||
|
||||
invoke-static { v$stringBuilderRegister, v$identifierRegister, v$free2 }, $FILTER_METHOD_DESCRIPTOR
|
||||
move-result v$free
|
||||
invoke-static { v$stringBuilderRegister, v$identifierRegister, v$free1 }, $FILTER_METHOD_DESCRIPTOR
|
||||
move-result v$free1
|
||||
|
||||
if-eqz v$free, :not_an_ad
|
||||
if-eqz v$free1, :unfiltered
|
||||
|
||||
# If the filter method returned true, then return a replacement empty component.
|
||||
|
||||
move-object/from16 v$free, p1
|
||||
invoke-static {v$free}, $builderMethodDescriptor
|
||||
move-result-object v$free
|
||||
iget-object v$free, v$free, $emptyComponentFieldDescriptor
|
||||
return-object v$free
|
||||
move-object/from16 v$free2, p1
|
||||
invoke-static {v$free2}, $builderMethodDescriptor
|
||||
move-result-object v$free2
|
||||
iget-object v$free2, v$free2, $emptyComponentFieldDescriptor
|
||||
return-object v$free2
|
||||
""",
|
||||
ExternalLabel("not_an_ad", getInstruction(insertHookIndex))
|
||||
// Used to jump over the instruction which block the component from being created.
|
||||
ExternalLabel("unfiltered", getInstruction(insertHookIndex))
|
||||
)
|
||||
// endregion
|
||||
}
|
||||
} ?: return ComponentContextParserFingerprint.toErrorResult()
|
||||
|
||||
LithoFilterFingerprint.result?.mutableMethod?.apply {
|
||||
removeInstructions(2, 4) // Remove dummy filter.
|
||||
|
||||
addFilter = { classDescriptor ->
|
||||
addInstructions(
|
||||
2,
|
||||
"""
|
||||
new-instance v1, $classDescriptor
|
||||
invoke-direct {v1}, $classDescriptor-><init>()V
|
||||
const/4 v2, ${filterCount++}
|
||||
aput-object v1, v0, v2
|
||||
"""
|
||||
)
|
||||
}
|
||||
} ?: return LithoFilterFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
override fun close() = LithoFilterFingerprint.result!!
|
||||
.mutableMethod.replaceInstruction(0, "const/4 v0, $filterCount")
|
||||
|
||||
companion object {
|
||||
private val MethodFingerprint.patternScanResult
|
||||
get() = result!!.scanResult.patternScanResult!!
|
||||
|
||||
val MethodFingerprint.patternScanEndIndex
|
||||
private val MethodFingerprint.patternScanEndIndex
|
||||
get() = patternScanResult.endIndex
|
||||
|
||||
val MethodFingerprint.patternScanStartIndex
|
||||
private val MethodFingerprint.patternScanStartIndex
|
||||
get() = patternScanResult.startIndex
|
||||
|
||||
val Instruction.descriptor
|
||||
private val Instruction.descriptor
|
||||
get() = (this as ReferenceInstruction).reference.toString()
|
||||
|
||||
const val FILTER_METHOD_DESCRIPTOR =
|
||||
private const val FILTER_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/LithoFilterPatch;" +
|
||||
"->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/nio/ByteBuffer;)Z"
|
||||
|
||||
internal lateinit var addFilter: (String) -> Unit
|
||||
private set
|
||||
|
||||
private var filterCount = 0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user