Compare commits

...

25 Commits

Author SHA1 Message Date
semantic-release-bot
5f2536814d chore(release): 2.191.0-dev.24 [skip ci]
# [2.191.0-dev.24](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.23...v2.191.0-dev.24) (2023-09-30)

### Features

* **Duolingo:** Remove `Unlock Duolingo Super` patch ([99bc879](99bc87909e))
2023-09-30 20:04:23 +00:00
oSumAtrIX
99bc87909e feat(Duolingo): Remove Unlock Duolingo Super patch
The patch is not functional anymore, and is being removed according to the contribution guidelines
2023-09-30 22:00:50 +02:00
semantic-release-bot
928df2428d chore(release): 2.191.0-dev.23 [skip ci]
# [2.191.0-dev.23](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.22...v2.191.0-dev.23) (2023-09-30)

### Features

* **SPB Serviceportal Bund:** Add `Remove root detection` patch ([#3049](https://github.com/ReVanced/revanced-patches/issues/3049)) ([3e9e1e2](3e9e1e2577))
2023-09-30 17:25:56 +00:00
David Gnedt
3e9e1e2577 feat(SPB Serviceportal Bund): Add Remove root detection patch (#3049) 2023-09-30 19:22:03 +02:00
semantic-release-bot
5ebec9b424 chore(release): 2.191.0-dev.22 [skip ci]
# [2.191.0-dev.22](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.21...v2.191.0-dev.22) (2023-09-28)

### Bug Fixes

* **YouTube - Premium heading:** Correct inverted logic ([#3042](https://github.com/ReVanced/revanced-patches/issues/3042)) ([0204ff6](0204ff67a9))
2023-09-28 16:10:57 +00:00
aliernfrog
0204ff67a9 fix(YouTube - Premium heading): Correct inverted logic (#3042) 2023-09-28 18:07:55 +02:00
semantic-release-bot
7d2a707030 chore(release): 2.191.0-dev.21 [skip ci]
# [2.191.0-dev.21](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.20...v2.191.0-dev.21) (2023-09-28)

### Bug Fixes

* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#3041](https://github.com/ReVanced/revanced-patches/issues/3041)) ([26e0e4c](26e0e4cd1d))
2023-09-28 13:42:22 +00:00
LisoUseInAIKyrios
26e0e4cd1d fix(YouTube - ReturnYouTubeDislike): Revert support for 18.37.36 (#3041) 2023-09-28 17:39:29 +04:00
semantic-release-bot
40f0a8cd0d chore(release): 2.191.0-dev.20 [skip ci]
# [2.191.0-dev.20](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.19...v2.191.0-dev.20) (2023-09-28)

### Bug Fixes

* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#3038](https://github.com/ReVanced/revanced-patches/issues/3038)) ([47c858e](47c858ef4e))
2023-09-28 13:15:01 +00:00
LisoUseInAIKyrios
47c858ef4e fix(YouTube - Video Id): Fix video id not showing the currently playing video (#3038)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-09-28 15:11:58 +02:00
LisoUseInAIKyrios
b17cd14d7d chore: add missing version 2023-09-28 11:42:15 +04:00
semantic-release-bot
c7383bdf67 chore(release): 2.191.0-dev.19 [skip ci]
# [2.191.0-dev.19](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.18...v2.191.0-dev.19) (2023-09-28)

### Features

* **YouTube:** Add `Bypass URL redirects` patch ([01e3642](01e36428a0))
2023-09-28 02:51:14 +00:00
oSumAtrIX
01e36428a0 feat(YouTube): Add Bypass URL redirects patch 2023-09-28 04:47:41 +02:00
semantic-release-bot
187c1eb14a chore(release): 2.191.0-dev.18 [skip ci]
# [2.191.0-dev.18](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.17...v2.191.0-dev.18) (2023-09-28)

### Features

* **YouTube - Premium heading:** Allow using default heading ([#3029](https://github.com/ReVanced/revanced-patches/issues/3029)) ([acadac3](acadac3049))
2023-09-28 01:06:04 +00:00
aliernfrog
acadac3049 feat(YouTube - Premium heading): Allow using default heading (#3029)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-09-28 03:03:07 +02:00
semantic-release-bot
bf5c197eb8 chore(release): 2.191.0-dev.17 [skip ci]
# [2.191.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.16...v2.191.0-dev.17) (2023-09-27)

### Features

* **YouTube:** Bump compatibility to `18.37.36` ([#3028](https://github.com/ReVanced/revanced-patches/issues/3028)) ([73e8b3f](73e8b3f81b))
2023-09-27 23:32:02 +00:00
oSumAtrIX
73e8b3f81b feat(YouTube): Bump compatibility to 18.37.36 (#3028)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
2023-09-28 01:28:25 +02:00
semantic-release-bot
1c2f499b1c chore(release): 2.191.0-dev.16 [skip ci]
# [2.191.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.15...v2.191.0-dev.16) (2023-09-27)

### Bug Fixes

* **YouTube - Hide info cards:** Fix info cards not hiding for some users ([#3039](https://github.com/ReVanced/revanced-patches/issues/3039)) ([32599ab](32599ab13d))
2023-09-27 20:23:09 +00:00
LisoUseInAIKyrios
32599ab13d fix(YouTube - Hide info cards): Fix info cards not hiding for some users (#3039) 2023-09-28 00:18:31 +04:00
oSumAtrIX
19519d1d06 ci: Bump checkout action 2023-09-27 18:03:12 +02:00
LisoUseInAIKyrios
2ff70e8b8f chore: fix typo 2023-09-27 18:31:27 +04:00
semantic-release-bot
1e21b0b572 chore(release): 2.191.0-dev.15 [skip ci]
# [2.191.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.14...v2.191.0-dev.15) (2023-09-26)

### Bug Fixes

* **YouTube - Client spoof:** adjust settings text ([#3035](https://github.com/ReVanced/revanced-patches/issues/3035)) ([1818074](18180745bc))
2023-09-26 18:29:52 +00:00
LisoUseInAIKyrios
18180745bc fix(YouTube - Client spoof): adjust settings text (#3035) 2023-09-26 22:27:12 +04:00
semantic-release-bot
aa89b8d20c chore(release): 2.191.0-dev.14 [skip ci]
# [2.191.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.13...v2.191.0-dev.14) (2023-09-26)

### Bug Fixes

* **YouTube - Client spoof:** Show seekbar thumbnail for age restricted and paid videos ([287648c](287648cf1e))
2023-09-26 02:51:39 +00:00
oSumAtrIX
287648cf1e fix(YouTube - Client spoof): Show seekbar thumbnail for age restricted and paid videos 2023-09-26 04:48:37 +02:00
72 changed files with 512 additions and 304 deletions

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Open pull request
uses: repo-sync/pull-request@v2
with:

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# Make sure the release step uses its own credentials:
# https://github.com/cycjimmy/semantic-release-action#private-packages

View File

@@ -1,3 +1,80 @@
# [2.191.0-dev.24](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.23...v2.191.0-dev.24) (2023-09-30)
### Features
* **Duolingo:** Remove `Unlock Duolingo Super` patch ([b4b9746](https://github.com/ReVanced/revanced-patches/commit/b4b9746361b5435b9d9429ad065e53364c51904a))
# [2.191.0-dev.23](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.22...v2.191.0-dev.23) (2023-09-30)
### Features
* **SPB Serviceportal Bund:** Add `Remove root detection` patch ([#3049](https://github.com/ReVanced/revanced-patches/issues/3049)) ([481bf58](https://github.com/ReVanced/revanced-patches/commit/481bf583afbf954bef1c4e5349a62ea1c623115a))
# [2.191.0-dev.22](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.21...v2.191.0-dev.22) (2023-09-28)
### Bug Fixes
* **YouTube - Premium heading:** Correct inverted logic ([#3042](https://github.com/ReVanced/revanced-patches/issues/3042)) ([b33ed75](https://github.com/ReVanced/revanced-patches/commit/b33ed757370653b8eb0002b0977eedfbc73dbe5e))
# [2.191.0-dev.21](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.20...v2.191.0-dev.21) (2023-09-28)
### Bug Fixes
* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#3041](https://github.com/ReVanced/revanced-patches/issues/3041)) ([3761073](https://github.com/ReVanced/revanced-patches/commit/37610732da87549c22a430bb62d10793dfa2e696))
# [2.191.0-dev.20](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.19...v2.191.0-dev.20) (2023-09-28)
### Bug Fixes
* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#3038](https://github.com/ReVanced/revanced-patches/issues/3038)) ([f6f226b](https://github.com/ReVanced/revanced-patches/commit/f6f226ba281823cb5d2d468c32f6e48551971726))
# [2.191.0-dev.19](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.18...v2.191.0-dev.19) (2023-09-28)
### Features
* **YouTube:** Add `Bypass URL redirects` patch ([125cac5](https://github.com/ReVanced/revanced-patches/commit/125cac5928c9b71d35253f1fd7651f4a30e15529))
# [2.191.0-dev.18](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.17...v2.191.0-dev.18) (2023-09-28)
### Features
* **YouTube - Premium heading:** Allow using default heading ([#3029](https://github.com/ReVanced/revanced-patches/issues/3029)) ([d5ab35a](https://github.com/ReVanced/revanced-patches/commit/d5ab35a444523baa0586fcb9513d6ae4f2518946))
# [2.191.0-dev.17](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.16...v2.191.0-dev.17) (2023-09-27)
### Features
* **YouTube:** Bump compatibility to `18.37.36` ([#3028](https://github.com/ReVanced/revanced-patches/issues/3028)) ([eda28e5](https://github.com/ReVanced/revanced-patches/commit/eda28e507e7fb5171eeb15a5a0532929ee611211))
# [2.191.0-dev.16](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.15...v2.191.0-dev.16) (2023-09-27)
### Bug Fixes
* **YouTube - Hide info cards:** Fix info cards not hiding for some users ([#3039](https://github.com/ReVanced/revanced-patches/issues/3039)) ([cb38637](https://github.com/ReVanced/revanced-patches/commit/cb38637e6be968d54561a1e0466b9259dbf0b4ee))
# [2.191.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.14...v2.191.0-dev.15) (2023-09-26)
### Bug Fixes
* **YouTube - Client spoof:** adjust settings text ([#3035](https://github.com/ReVanced/revanced-patches/issues/3035)) ([59a2e96](https://github.com/ReVanced/revanced-patches/commit/59a2e9617fc4f898e87cefeb3d2c6996b925fa90))
# [2.191.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.13...v2.191.0-dev.14) (2023-09-26)
### Bug Fixes
* **YouTube - Client spoof:** Show seekbar thumbnail for age restricted and paid videos ([1a79300](https://github.com/ReVanced/revanced-patches/commit/1a793007c919753a8c31ab2382d86c0546eefe20))
# [2.191.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v2.191.0-dev.12...v2.191.0-dev.13) (2023-09-25)

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 2.191.0-dev.13
version = 2.191.0-dev.24

File diff suppressed because one or more lines are too long

View File

@@ -1,62 +0,0 @@
package app.revanced.patches.duolingo.unlocksuper
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.duolingo.unlocksuper.fingerprints.IsUserSuperMethodFingerprint
import app.revanced.patches.duolingo.unlocksuper.fingerprints.UserSerializationMethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22c
import com.android.tools.smali.dexlib2.iface.reference.Reference
@Patch(
name = "Unlock Duolingo Super",
compatiblePackages = [CompatiblePackage("com.duolingo")]
)
@Suppress("unused")
object UnlockDuolingoSuperPatch : BytecodePatch(
setOf(
UserSerializationMethodFingerprint,
IsUserSuperMethodFingerprint
)
) {
/* First find the reference to the isUserSuper field, then patch the instruction that assigns it to false.
* This strategy is used because the method that sets the isUserSuper field is difficult to fingerprint reliably.
*/
override fun execute(context: BytecodeContext) {
// Find the reference to the isUserSuper field.
val isUserSuperReference = IsUserSuperMethodFingerprint
.result
?.mutableMethod
?.getInstructions()
?.filterIsInstance<BuilderInstruction22c>()
?.firstOrNull { it.opcode == Opcode.IGET_BOOLEAN }
?.reference
?: throw IsUserSuperMethodFingerprint.exception
// Patch the instruction that assigns isUserSuper to true.
UserSerializationMethodFingerprint
.result
?.mutableMethod
?.apply {
replaceInstructions(
indexOfReference(isUserSuperReference) - 1,
"const/4 v2, 0x1"
)
}
?: throw UserSerializationMethodFingerprint.exception
}
private fun MutableMethod.indexOfReference(reference: Reference) = getInstructions()
.indexOfFirst { it is BuilderInstruction22c && it.opcode == Opcode.IPUT_BOOLEAN && it.reference == reference }
.let {
if (it == -1) throw PatchException("Could not find index of instruction with supplied reference.")
else it
}
}

View File

@@ -1,20 +0,0 @@
package app.revanced.patches.duolingo.unlocksuper.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object UserSerializationMethodFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
strings = listOf(
"betaStatus",
"coachOutfit",
"globalAmbassadorStatus",
),
opcodes = listOf(
Opcode.MOVE_FROM16,
Opcode.IPUT_BOOLEAN,
),
)

View File

@@ -12,8 +12,8 @@ import app.revanced.util.microg.MicroGBytecodeHelper
@Patch(
name = "MicroG support",
description = "Allows YouTube Music ReVanced to run without root and under a different package name.",
name = "Vanced MicroG support",
description = "Allows YouTube Music to run without root and under a different package name.",
dependencies = [MicroGResourcePatch::class],
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
)

View File

@@ -0,0 +1,21 @@
package app.revanced.patches.serviceportalbund.detection.root
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.serviceportalbund.detection.root.fingerprints.RootDetectionFingerprint
@Patch(
name = "Remove root detection",
description = "Removes the check for root permissions and unlocked bootloader.",
compatiblePackages = [CompatiblePackage("at.gv.bka.serviceportal")]
)
@Suppress("unused")
object RootDetectionPatch : BytecodePatch(
setOf(RootDetectionFingerprint)
) {
override fun execute(context: BytecodeContext) =
RootDetectionFingerprint.result!!.mutableMethod.addInstruction(0, "return-void")
}

View File

@@ -0,0 +1,12 @@
package app.revanced.patches.serviceportalbund.detection.root.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
object RootDetectionFingerprint : MethodFingerprint(
"V",
accessFlags = AccessFlags.PUBLIC.value,
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
}
)

View File

@@ -31,7 +31,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -18,7 +18,17 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
name = "Hide get premium",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage("com.google.android.youtube", ["18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"])
CompatiblePackage(
"com.google.android.youtube", [
"18.16.37",
"18.19.35",
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39",
"18.37.36"
]
)
]
)
object HideGetPremiumPatch : BytecodePatch(setOf(GetPremiumViewFingerprint)) {

View File

@@ -29,7 +29,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -24,7 +24,8 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -24,7 +24,8 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
),
]

View File

@@ -31,7 +31,8 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -31,7 +31,8 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -1,5 +1,6 @@
package app.revanced.patches.youtube.layout.autocaptions
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
@@ -28,7 +29,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
],
@@ -47,38 +49,32 @@ object AutoCaptionsPatch : BytecodePatch(
)
)
val startVideoInformerMethod = StartVideoInformerFingerprint.result!!.mutableMethod
mapOf(
StartVideoInformerFingerprint to 0,
SubtitleButtonControllerFingerprint to 1
).forEach { (fingerprint, enabled) ->
fingerprint.result?.mutableMethod?.addInstructions(
0,
"""
const/4 v0, 0x$enabled
sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
"""
) ?: throw fingerprint.exception
}
startVideoInformerMethod.addInstructions(
0, """
const/4 v0, 0x0
sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
"""
)
val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod
subtitleButtonControllerMethod.addInstructions(
0, """
const/4 v0, 0x1
sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
"""
)
val subtitleTrackMethod = SubtitleTrackFingerprint.result!!.mutableMethod
subtitleTrackMethod.addInstructionsWithLabels(
0, """
invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
move-result v0
if-eqz v0, :auto_captions_enabled
sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
if-nez v0, :auto_captions_enabled
const/4 v0, 0x1
return v0
:auto_captions_enabled
nop
"""
SubtitleTrackFingerprint.result?.mutableMethod?.addInstructionsWithLabels(
0,
"""
invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z
move-result v0
if-eqz v0, :auto_captions_enabled
sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z
if-nez v0, :auto_captions_enabled
const/4 v0, 0x1
return v0
:auto_captions_enabled
nop
"""
)
}
}

View File

@@ -6,25 +6,11 @@ import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object StartVideoInformerFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L", "L", "L"), listOf(
Opcode.INVOKE_STATIC,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.IF_EQZ,
Opcode.CONST_STRING,
Opcode.INVOKE_INTERFACE,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.CONST_4,
Opcode.IF_EQ,
Opcode.GOTO,
)
Opcode.RETURN_VOID
),
strings = listOf("pc")
)

View File

@@ -5,39 +5,57 @@ import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import kotlin.io.path.exists
import app.revanced.patcher.patch.options.types.BooleanPatchOption.Companion.booleanPatchOption
import kotlin.io.path.copyTo
@Patch(
name = "Premium heading",
description = "Shows premium branding on the home screen.",
description = "Show or hide the premium heading.",
compatiblePackages = [
CompatiblePackage("com.google.android.youtube")
]
)
@Suppress("unused")
object PremiumHeadingPatch : ResourcePatch() {
private const val DEFAULT_HEADING_RES = "yt_wordmark_header"
private const val PREMIUM_HEADING_RES = "yt_premium_wordmark_header"
private val usePremiumHeading by booleanPatchOption(
key = "usePremiumHeading",
default = true,
title = "Use premium heading",
description = "Whether to use the premium heading.",
required = true,
)
override fun execute(context: ResourceContext) {
val resDirectory = context["res"]
if (!resDirectory.isDirectory) throw PatchException("The res folder can not be found.")
val (original, replacement) = "yt_premium_wordmark_header" to "yt_wordmark_header"
val modes = arrayOf("light", "dark")
val (original, replacement) = if (usePremiumHeading!!)
PREMIUM_HEADING_RES to DEFAULT_HEADING_RES
else
DEFAULT_HEADING_RES to PREMIUM_HEADING_RES
arrayOf("xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi").forEach { size ->
val headingDirectory = resDirectory.resolve("drawable-$size")
modes.forEach { mode ->
val fromPath = headingDirectory.resolve("${original}_$mode.png").toPath()
val toPath = headingDirectory.resolve("${replacement}_$mode.png").toPath()
val variants = arrayOf("light", "dark")
if (!fromPath.exists())
throw PatchException("The file $fromPath does not exist in the resources. Therefore, this patch can not succeed.")
Files.copy(
fromPath,
toPath,
StandardCopyOption.REPLACE_EXISTING
)
arrayOf(
"xxxhdpi",
"xxhdpi",
"xhdpi",
"hdpi",
"mdpi"
).mapNotNull { dpi ->
resDirectory.resolve("drawable-$dpi").takeIf { it.exists() }?.toPath()
}.also {
if (it.isEmpty())
throw PatchException("The drawable folder can not be found. Therefore, the patch can not be applied.")
}.forEach { path ->
variants.forEach { mode ->
val fromPath = path.resolve("${original}_$mode.png")
val toPath = path.resolve("${replacement}_$mode.png")
fromPath.copyTo(toPath, true)
}
}
}

View File

@@ -27,7 +27,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -37,7 +37,8 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -28,7 +28,8 @@ import com.android.tools.smali.dexlib2.Opcode
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -36,7 +36,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -32,7 +32,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction3rc
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -27,7 +27,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -27,7 +27,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -26,7 +26,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -27,7 +27,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -30,7 +30,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction21c
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -7,8 +7,6 @@ import com.android.tools.smali.dexlib2.Opcode
object LayoutIconFingerprint : LiteralValueFingerprint(
returnType = "Landroid/view/View;",
opcodes = listOf(
Opcode.CONST_4,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,

View File

@@ -27,7 +27,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -23,7 +23,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -27,7 +27,14 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
LithoFilterPatch::class,
SettingsPatch::class
],
compatiblePackages = [CompatiblePackage("com.google.android.youtube", ["18.32.39"])]
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube", [
"18.32.39",
"18.37.36"
]
)
]
)
@Suppress("unused")
object HideLayoutComponentsPatch : BytecodePatch(

View File

@@ -13,6 +13,7 @@ import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.Infocards
import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.InfocardsIncognitoParentFingerprint
import app.revanced.patches.youtube.layout.hide.infocards.fingerprints.InfocardsMethodCallFingerprint
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@@ -22,6 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
description = "Hides info cards in videos.",
dependencies = [
IntegrationsPatch::class,
LithoFilterPatch::class,
HideInfocardsResourcePatch::class
],
compatiblePackages = [
@@ -33,7 +35,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]
@@ -45,6 +48,9 @@ object HideInfoCardsPatch : BytecodePatch(
InfocardsMethodCallFingerprint,
)
) {
private const val FILTER_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/patches/components/HideInfoCardsFilterPatch;"
override fun execute(context: BytecodeContext) {
InfocardsIncognitoFingerprint.also {
it.resolve(context, InfocardsIncognitoParentFingerprint.result!!.classDef)
@@ -79,5 +85,8 @@ object HideInfoCardsPatch : BytecodePatch(
)
)
}
// Info cards can also appear as litho components.
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
}
}

View File

@@ -23,7 +23,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -23,7 +23,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -24,7 +24,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
])
]
)

View File

@@ -32,7 +32,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -36,7 +36,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]
@@ -54,8 +55,6 @@ object HideShortsComponentsPatch : BytecodePatch(
private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/ShortsFilter;"
override fun execute(context: BytecodeContext) {
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
// region Hide the Shorts shelf.
ReelConstructorFingerprint.result?.let {
@@ -74,13 +73,20 @@ object HideShortsComponentsPatch : BytecodePatch(
// endregion
// region Hide the Shorts buttons.
// region Hide the Shorts buttons in older versions of YouTube.
// Some Shorts buttons are views, hide them by setting their visibility to GONE.
CreateShortsButtonsFingerprint.result?.let {
ShortsButtons.values().forEach { button -> button.injectHideCall(it.mutableMethod) }
ShortsButtons.entries.forEach { button -> button.injectHideCall(it.mutableMethod) }
} ?: throw CreateShortsButtonsFingerprint.exception
// endregion
// region Hide the Shorts buttons in newer versions of YouTube.
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
// endregion
// region Hide the navigation bar.

View File

@@ -24,7 +24,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -28,7 +28,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -24,7 +24,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -18,7 +18,8 @@ import org.w3c.dom.Element
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
],

View File

@@ -51,9 +51,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
override fun execute(context: BytecodeContext) {
// region Inject newVideoLoaded event handler to update dislikes when a new video is loaded.
// This patch needs a few adjustments and lots of testing before it can change to the new video id hook.
// There's a few corner cases and some weirdness when loading new videos (specifically with detecting shorts).
VideoIdPatch.legacyInjectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
VideoIdPatch.hookVideoId("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
// endregion

View File

@@ -1,12 +1,12 @@
package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object ShortsTextViewFingerprint : MethodFingerprint(
// 18.29.38 method is public final visibility, but in 18.23.35 and older it's protected final.
// If 18.23.35 is dropped then accessFlags should be specified here.
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("L", "L"),
opcodes = listOf(

View File

@@ -27,7 +27,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -44,7 +44,8 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
],
@@ -95,11 +96,8 @@ object SponsorBlockBytecodePatch : BytecodePatch(
/*
* Set current video id.
*
* The new video id hook seems to work without issues,
* but it's easier to keep using this hook as it's well tested and has no known problems.
*/
VideoIdPatch.legacyInjectCallBackgroundPlay("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
VideoIdPatch.hookBackgroundPlayVideoId("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
/*
* Seekbar drawing

View File

@@ -28,7 +28,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -23,7 +23,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -33,7 +33,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
)
)
]

View File

@@ -25,7 +25,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -29,7 +29,8 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -24,7 +24,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -56,7 +56,7 @@ object SpoofSignaturePatch : BytecodePatch(
+ "Side effects include:\\n"
+ "• Enhanced bitrate is not available\\n"
+ "• Videos cannot be downloaded\\n"
+ "• No seekbar thumbnails for paid or age restricted videos"
+ "• No seekbar thumbnails for paid videos"
),
StringResource(
"revanced_spoof_signature_verification_enabled_summary_off",
@@ -79,7 +79,7 @@ object SpoofSignaturePatch : BytecodePatch(
),
StringResource(
"revanced_spoof_signature_in_feed_enabled_summary_off",
"App signature not spoofed for feed videos\n\n"
"App signature not spoofed for feed videos\\n\\n"
+ "Feed videos will play for less than 1 minute before encountering playback issues"
)
)
@@ -88,11 +88,12 @@ object SpoofSignaturePatch : BytecodePatch(
)
// Hook the player parameters.
PlayerResponseMethodHookPatch.injectProtoBufferHook("$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;")
PlayerResponseMethodHookPatch + PlayerResponseMethodHookPatch.Hook.ProtoBufferParameter(
"$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;)Ljava/lang/String;"
)
// Force the seekbar thumbnails to show up.
// This is only required to show the seekbar time and chapters
// if the storyboard spec fetch fails.
// Force the seekbar time and chapters to always show up.
// This is used only if the storyboard spec fetch fails, or when viewing paid videos.
StoryboardThumbnailParentFingerprint.result?.classDef?.let { classDef ->
StoryboardThumbnailFingerprint.also {
it.resolve(

View File

@@ -0,0 +1,70 @@
package app.revanced.patches.youtube.misc.links
import app.revanced.extensions.exception
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.shared.settings.preference.impl.StringResource
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.links.fingerprints.OpenLinksDirectlyPrimaryFingerprint
import app.revanced.patches.youtube.misc.links.fingerprints.OpenLinksDirectlySecondaryFingerprint
import app.revanced.patches.youtube.misc.settings.SettingsPatch
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch(
name = "Bypass URL redirects",
description = "Bypass URL redirects and open the original URL directly.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.16.37",
"18.19.35",
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39",
"18.37.36"
]
)
]
)
object BypassURLRedirectsPatch : BytecodePatch(
setOf(OpenLinksDirectlyPrimaryFingerprint, OpenLinksDirectlySecondaryFingerprint)
) {
override fun execute(context: BytecodeContext) {
SettingsPatch.PreferenceScreen.MISC.addPreferences(
SwitchPreference(
"revanced_bypass_url_redirects",
StringResource("revanced_bypass_url_redirects_title", "Bypass URL redirects"),
StringResource("revanced_bypass_url_redirects_summary_on", "URL redirects are bypassed"),
StringResource("revanced_bypass_url_redirects_summary_off", "URL redirects are not bypassed"),
)
)
arrayOf(
OpenLinksDirectlyPrimaryFingerprint,
OpenLinksDirectlySecondaryFingerprint
).map {
it.result ?: throw it.exception
}.forEach { result ->
result.mutableMethod.apply {
val insertIndex = result.scanResult.patternScanResult!!.startIndex
val uriStringRegister = getInstruction<FiveRegisterInstruction>(insertIndex).registerC
replaceInstruction(
insertIndex,
"invoke-static {v$uriStringRegister}," +
"Lapp/revanced/integrations/patches/BypassURLRedirectsPatch;" +
"->" +
"parseRedirectUri(Ljava/lang/String;)Landroid/net/Uri;"
)
}
}
}
}

View File

@@ -19,7 +19,20 @@ import com.android.tools.smali.dexlib2.iface.reference.StringReference
@Patch(
name = "Open links externally",
description = "Open links outside of the app directly in your browser.",
compatiblePackages = [CompatiblePackage("com.google.android.youtube", ["18.16.37", "18.19.35", "18.20.39", "18.23.35", "18.29.38", "18.32.39"])]
compatiblePackages = [
CompatiblePackage(
"com.google.android.youtube",
[
"18.16.37",
"18.19.35",
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39",
"18.37.36"
]
)
]
)
@Suppress("unused")
object OpenLinksExternallyPatch : AbstractTransformInstructionsPatch<Pair<Int, Int>>(

View File

@@ -1,14 +1,20 @@
package app.revanced.patches.duolingo.unlocksuper.fingerprints
package app.revanced.patches.youtube.misc.links.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object IsUserSuperMethodFingerprint : MethodFingerprint(
object OpenLinksDirectlyPrimaryFingerprint : MethodFingerprint(
returnType = "Ljava/lang/Object",
parameters = listOf("Ljava/lang/Object"),
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf("user"),
opcodes = listOf(Opcode.IGET_BOOLEAN),
parameters = listOf("Ljava/lang/Object"),
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT,
Opcode.CHECK_CAST,
Opcode.SGET,
Opcode.SGET_OBJECT
)
)

View File

@@ -0,0 +1,17 @@
package app.revanced.patches.youtube.misc.links.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object OpenLinksDirectlySecondaryFingerprint : MethodFingerprint(
returnType = "Landroid/net/Uri",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Ljava/lang/String"),
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT
),
strings = listOf("://")
)

View File

@@ -103,7 +103,7 @@ object LithoFilterPatch : BytecodePatch(
val emptyComponentFieldIndex = builderMethodIndex + 2
bytesToComponentContextMethod.mutableMethod.apply {
val insertHookIndex = bytesToComponentContextMethod.scanResult.patternScanResult!!.endIndex
val insertHookIndex = bytesToComponentContextMethod.scanResult.patternScanResult!!.endIndex + 1
// region Get free registers that this patch uses.
// Registers are overwritten right after they are used in this patch, therefore free to clobber.

View File

@@ -5,9 +5,9 @@ import com.android.tools.smali.dexlib2.Opcode
object ComponentContextParserFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE
),
strings = listOf("Component was not found %s because it was removed due to duplicate converter bindings.")
)

View File

@@ -14,7 +14,7 @@ import app.revanced.util.microg.MicroGBytecodeHelper
@Patch(
name = "Vanced MicroG support",
description = "Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.",
description = "Allows YouTube to run without root and under a different package name with Vanced MicroG.",
dependencies = [
MicroGResourcePatch::class,
HideCastButtonPatch::class,
@@ -28,7 +28,8 @@ import app.revanced.util.microg.MicroGBytecodeHelper
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -34,7 +34,8 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -26,7 +26,8 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -109,9 +109,13 @@ object VideoInformationPatch : BytecodePatch(
}
/*
* Inject call for video id
* Inject call for video ids
*/
VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V")
val videoIdMethodDescriptor = "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V"
VideoIdPatch.hookVideoId(videoIdMethodDescriptor)
VideoIdPatch.hookBackgroundPlayVideoId(videoIdMethodDescriptor)
VideoIdPatch.hookPlayerResponseVideoId(
"$INTEGRATIONS_CLASS_DESCRIPTOR->setPlayerResponseVideoId(Ljava/lang/String;)V")
/*
* Set the video time method

View File

@@ -7,66 +7,58 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.misc.fix.playback.SpoofSignaturePatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
import java.io.Closeable
@Patch(
dependencies = [IntegrationsPatch::class],
)
object PlayerResponseMethodHookPatch : BytecodePatch(
setOf(
PlayerParameterBuilderFingerprint,
)
) {
private const val playerResponseVideoIdParameter = 1
private const val playerResponseProtoBufferParameter = 3
/**
* Insert index when adding a video id hook.
*/
private var playerResponseVideoIdInsertIndex = 0
/**
* Insert index when adding a proto buffer override.
* Must be after all video id hooks in the same method.
*/
private var playerResponseProtoBufferInsertIndex = 0
object PlayerResponseMethodHookPatch :
BytecodePatch(setOf(PlayerParameterBuilderFingerprint)),
Closeable,
MutableSet<PlayerResponseMethodHookPatch.Hook> by mutableSetOf() {
private const val VIDEO_ID_PARAMETER = 1
private const val PROTO_BUFFER_PARAMETER_PARAMETER = 3
private lateinit var playerResponseMethod: MutableMethod
override fun execute(context: BytecodeContext) {
// Hook player parameter.
PlayerParameterBuilderFingerprint.result?.let {
playerResponseMethod = it.mutableMethod
} ?: throw PlayerParameterBuilderFingerprint.exception
playerResponseMethod = PlayerParameterBuilderFingerprint.result?.mutableMethod
?: throw PlayerParameterBuilderFingerprint.exception
}
/**
* Modify the player parameter proto buffer value.
* Used exclusively by [SpoofSignaturePatch].
*/
fun injectProtoBufferHook(methodDescriptor: String) {
playerResponseMethod.addInstructions(
playerResponseProtoBufferInsertIndex,
override fun close() {
fun hookVideoId(hook: Hook) = playerResponseMethod.addInstruction(
0, "invoke-static {p$VIDEO_ID_PARAMETER}, $hook"
)
fun hookProtoBufferParameter(hook: Hook) = playerResponseMethod.addInstructions(
0,
"""
invoke-static {p$playerResponseProtoBufferParameter}, $methodDescriptor
move-result-object p$playerResponseProtoBufferParameter
invoke-static {p$PROTO_BUFFER_PARAMETER_PARAMETER}, $hook
move-result-object p$PROTO_BUFFER_PARAMETER_PARAMETER
"""
)
playerResponseProtoBufferInsertIndex += 2
// Reverse the order in order to preserve insertion order of the hooks.
val beforeVideoIdHooks = filterIsInstance<Hook.ProtoBufferParameterBeforeVideoId>().asReversed()
val videoIdHooks = filterIsInstance<Hook.VideoId>().asReversed()
val afterVideoIdHooks = filterIsInstance<Hook.ProtoBufferParameter>().asReversed()
// Add the hooks in this specific order as they insert instructions at the beginning of the method.
afterVideoIdHooks.forEach(::hookProtoBufferParameter)
videoIdHooks.forEach(::hookVideoId)
beforeVideoIdHooks.forEach(::hookProtoBufferParameter)
}
/**
* Used by [VideoIdPatch].
*/
internal fun injectVideoIdHook(methodDescriptor: String) {
playerResponseMethod.addInstruction(
// Keep injection calls in the order they're added,
// and all video id hooks run before proto buffer hooks.
playerResponseVideoIdInsertIndex++,
"invoke-static {p$playerResponseVideoIdParameter}, $methodDescriptor"
)
playerResponseProtoBufferInsertIndex++
internal abstract class Hook(private val methodDescriptor: String) {
internal class VideoId(methodDescriptor: String) : Hook(methodDescriptor)
internal class ProtoBufferParameter(methodDescriptor: String) : Hook(methodDescriptor)
internal class ProtoBufferParameterBeforeVideoId(methodDescriptor: String) : Hook(methodDescriptor)
override fun toString() = methodDescriptor
}
}

View File

@@ -36,7 +36,8 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -11,7 +11,7 @@ object SetQualityByIndexMethodClassFieldReferenceFingerprint : MethodFingerprint
parameters = listOf("L"),
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.RETURN_VOID
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
)
)

View File

@@ -18,7 +18,8 @@ import app.revanced.patches.youtube.video.speed.remember.RememberPlaybackSpeedPa
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]

View File

@@ -26,8 +26,8 @@ object VideoIdPatch : BytecodePatch(
)
) {
private var videoIdRegister = 0
private var insertIndex = 0
private lateinit var insertMethod: MutableMethod
private var videoIdInsertIndex = 0
private lateinit var videoIdMethod: MutableMethod
private var backgroundPlaybackVideoIdRegister = 0
private var backgroundPlaybackInsertIndex = 0
@@ -52,8 +52,8 @@ object VideoIdPatch : BytecodePatch(
} ?: throw VideoIdFingerprint.exception
VideoIdFingerprint.setFields { method, index, register ->
insertMethod = method
insertIndex = index
videoIdMethod = method
videoIdInsertIndex = index
videoIdRegister = register
}
@@ -65,21 +65,7 @@ object VideoIdPatch : BytecodePatch(
}
/**
* Adds an invoke-static instruction, called with the new id when the video changes.
*
* Called as soon as the player response is parsed, and called before many other hooks are
* updated such as [PlayerTypeHookPatch].
*
* Supports all videos and functions in all situations.
*
* Be aware, this can be called multiple times for the same video id.
*
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
*/
fun injectCall(methodDescriptor: String) = PlayerResponseMethodHookPatch.injectVideoIdHook(methodDescriptor)
/**
* Adds an invoke-static instruction, called with the new id when the video changes.
* Hooks the new video id when the video changes.
*
* Supports all videos (regular videos and Shorts).
*
@@ -89,10 +75,10 @@ object VideoIdPatch : BytecodePatch(
*
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
*/
fun legacyInjectCall(
fun hookVideoId(
methodDescriptor: String
) = insertMethod.addInstruction(
insertIndex++,
) = videoIdMethod.addInstruction(
videoIdInsertIndex++,
"invoke-static {v$videoIdRegister}, $methodDescriptor"
)
@@ -106,11 +92,37 @@ object VideoIdPatch : BytecodePatch(
*
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
*/
fun legacyInjectCallBackgroundPlay(
fun hookBackgroundPlayVideoId(
methodDescriptor: String
) = backgroundPlaybackMethod.addInstruction(
backgroundPlaybackInsertIndex++, // move-result-object offset
"invoke-static {v$backgroundPlaybackVideoIdRegister}, $methodDescriptor"
)
/**
* Hooks the video id of every video when loaded.
* Supports all videos and functions in all situations.
*
* Hook is always called off the main thread.
*
* This hook is called as soon as the player response is parsed,
* and called before many other hooks are updated such as [PlayerTypeHookPatch].
*
* Note: The video id returned here may not be the current video that's being played.
* It's common for multiple Shorts to load at once in preparation
* for the user swiping to the next Short.
*
* For most use cases, you probably want to use
* [hookVideoId] or [hookBackgroundPlayVideoId] instead.
*
* Be aware, this can be called multiple times for the same video id.
*
* @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;`
*/
fun hookPlayerResponseVideoId(methodDescriptor: String) {
PlayerResponseMethodHookPatch + PlayerResponseMethodHookPatch.Hook.VideoId(
methodDescriptor
)
}
}

View File

@@ -28,7 +28,8 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
"18.20.39",
"18.23.35",
"18.29.38",
"18.32.39"
"18.32.39",
"18.37.36"
]
)
]