chore: Merge branch dev
to main
(#3223)
This commit is contained in:
commit
944d1fdc17
|
@ -1,3 +1,10 @@
|
||||||
|
## [4.8.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.8.1...v4.8.2-dev.1) (2024-05-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **YouTube - Client spoof:** Spoof iOS client model to fix various side effects ([#3220](https://github.com/ReVanced/revanced-patches/issues/3220)) ([9b5f4ce](https://github.com/ReVanced/revanced-patches/commit/9b5f4ce2b251c67e24cfcac3edae70c8a8aae230))
|
||||||
|
|
||||||
## [4.8.1](https://github.com/ReVanced/revanced-patches/compare/v4.8.0...v4.8.1) (2024-05-21)
|
## [4.8.1](https://github.com/ReVanced/revanced-patches/compare/v4.8.0...v4.8.1) (2024-05-21)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching = true
|
org.gradle.caching = true
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 4.8.1
|
version = 4.8.2-dev.1
|
||||||
|
|
|
@ -19,6 +19,7 @@ import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
|
||||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||||
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
@ -34,7 +35,6 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||||
name = "Spoof client",
|
name = "Spoof client",
|
||||||
description = "Spoofs the client to allow video playback.",
|
description = "Spoofs the client to allow video playback.",
|
||||||
dependencies = [
|
dependencies = [
|
||||||
SpoofClientResourcePatch::class,
|
|
||||||
PlayerResponseMethodHookPatch::class,
|
PlayerResponseMethodHookPatch::class,
|
||||||
SettingsPatch::class,
|
SettingsPatch::class,
|
||||||
AddResourcesPatch::class,
|
AddResourcesPatch::class,
|
||||||
|
@ -74,6 +74,7 @@ object SpoofClientPatch : BytecodePatch(
|
||||||
BuildPlayerRequestURIFingerprint,
|
BuildPlayerRequestURIFingerprint,
|
||||||
SetPlayerRequestClientTypeFingerprint,
|
SetPlayerRequestClientTypeFingerprint,
|
||||||
CreatePlayerRequestBodyFingerprint,
|
CreatePlayerRequestBodyFingerprint,
|
||||||
|
CreatePlayerRequestBodyWithModelFingerprint,
|
||||||
|
|
||||||
// Storyboard spoof.
|
// Storyboard spoof.
|
||||||
StoryboardRendererSpecFingerprint,
|
StoryboardRendererSpecFingerprint,
|
||||||
|
@ -97,10 +98,9 @@ object SpoofClientPatch : BytecodePatch(
|
||||||
sorting = Sorting.UNSORTED,
|
sorting = Sorting.UNSORTED,
|
||||||
preferences = setOf(
|
preferences = setOf(
|
||||||
SwitchPreference("revanced_spoof_client"),
|
SwitchPreference("revanced_spoof_client"),
|
||||||
SwitchPreference("revanced_spoof_client_use_ios"),
|
SwitchPreference("revanced_spoof_client_use_testsuite"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||||
|
@ -168,6 +168,22 @@ object SpoofClientPatch : BytecodePatch(
|
||||||
Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField)
|
Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val clientInfoClientModelField = CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.let {
|
||||||
|
val instructions = it.getInstructions()
|
||||||
|
|
||||||
|
val getClientModelIndex = it.indexOfFirstInstruction {
|
||||||
|
getReference<FieldReference>().toString() == "Landroid/os/Build;->MODEL:Ljava/lang/String;"
|
||||||
|
}
|
||||||
|
|
||||||
|
// The next IPUT_OBJECT instruction after getting the client model is setting the client model field.
|
||||||
|
instructions.subList(
|
||||||
|
getClientModelIndex,
|
||||||
|
instructions.lastIndex,
|
||||||
|
).first { instruction ->
|
||||||
|
instruction.opcode == Opcode.IPUT_OBJECT
|
||||||
|
}.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientModelField")
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Spoof client type for /player requests.
|
// region Spoof client type for /player requests.
|
||||||
|
@ -189,7 +205,7 @@ object SpoofClientPatch : BytecodePatch(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change requestMessage.clientInfo.clientType and requestMessage.clientInfo.clientVersion to the spoofed values.
|
// Change client info to use the spoofed values.
|
||||||
// Do this in a helper method, to remove the need of picking out multiple free registers from the hooked code.
|
// Do this in a helper method, to remove the need of picking out multiple free registers from the hooked code.
|
||||||
result.mutableClass.methods.add(
|
result.mutableClass.methods.add(
|
||||||
ImmutableMethod(
|
ImmutableMethod(
|
||||||
|
@ -216,12 +232,17 @@ object SpoofClientPatch : BytecodePatch(
|
||||||
move-result v1
|
move-result v1
|
||||||
iput v1, v0, $clientInfoClientTypeField
|
iput v1, v0, $clientInfoClientTypeField
|
||||||
|
|
||||||
|
# Set client model to the spoofed value.
|
||||||
|
iget-object v1, v0, $clientInfoClientModelField
|
||||||
|
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientModel(Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
move-result-object v1
|
||||||
|
iput-object v1, v0, $clientInfoClientModelField
|
||||||
|
|
||||||
# Set client version to the spoofed value.
|
# Set client version to the spoofed value.
|
||||||
iget-object v1, v0, $clientInfoClientVersionField
|
iget-object v1, v0, $clientInfoClientVersionField
|
||||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientVersion(Ljava/lang/String;)Ljava/lang/String;
|
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientVersion(Ljava/lang/String;)Ljava/lang/String;
|
||||||
move-result-object v1
|
move-result-object v1
|
||||||
iput-object v1, v0, $clientInfoClientVersionField
|
iput-object v1, v0, $clientInfoClientVersionField
|
||||||
|
|
||||||
:disabled
|
:disabled
|
||||||
return-void
|
return-void
|
||||||
""",
|
""",
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package app.revanced.patches.youtube.misc.fix.playback
|
|
||||||
|
|
||||||
import app.revanced.patcher.data.ResourceContext
|
|
||||||
import app.revanced.patcher.patch.ResourcePatch
|
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
|
||||||
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
|
|
||||||
|
|
||||||
@Patch(dependencies = [ResourceMappingPatch::class])
|
|
||||||
internal object SpoofClientResourcePatch : ResourcePatch() {
|
|
||||||
internal var scrubbedPreviewThumbnailResourceId: Long = -1
|
|
||||||
|
|
||||||
override fun execute(context: ResourceContext) {
|
|
||||||
scrubbedPreviewThumbnailResourceId = ResourceMappingPatch[
|
|
||||||
"id",
|
|
||||||
"thumbnail",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -43,7 +43,7 @@ object SpoofSignaturePatch : BytecodePatch(
|
||||||
StoryboardRendererDecoderSpecFingerprint,
|
StoryboardRendererDecoderSpecFingerprint,
|
||||||
StoryboardRendererDecoderRecommendedLevelFingerprint,
|
StoryboardRendererDecoderRecommendedLevelFingerprint,
|
||||||
StoryboardThumbnailParentFingerprint,
|
StoryboardThumbnailParentFingerprint,
|
||||||
ScrubbedPreviewLayoutFingerprint,
|
SpoofSignaturePatchScrubbedPreviewLayoutFingerprint,
|
||||||
StatsQueryParameterFingerprint,
|
StatsQueryParameterFingerprint,
|
||||||
ParamsMapPutFingerprint,
|
ParamsMapPutFingerprint,
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import app.revanced.util.getReference
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||||
|
|
||||||
|
internal object CreatePlayerRequestBodyWithModelFingerprint : MethodFingerprint(
|
||||||
|
returnType = "L",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
parameters = listOf(),
|
||||||
|
customFingerprint = { methodDef, _ ->
|
||||||
|
methodDef.implementation!!.instructions.any {
|
||||||
|
it.getReference<FieldReference>().toString() == "Landroid/os/Build;->MODEL:Ljava/lang/String;"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
|
@ -5,6 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Deprecated("Fingerprint is obsolete and will be deleted soon")
|
||||||
internal object ParamsMapPutFingerprint : MethodFingerprint(
|
internal object ParamsMapPutFingerprint : MethodFingerprint(
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
|
|
@ -6,6 +6,7 @@ import app.revanced.util.containsWideLiteralInstructionValue
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Deprecated("Fingerprint is obsolete and will be deleted soon")
|
||||||
internal object PlayerResponseModelImplLiveStreamFingerprint : MethodFingerprint(
|
internal object PlayerResponseModelImplLiveStreamFingerprint : MethodFingerprint(
|
||||||
returnType = "Ljava/lang/String;",
|
returnType = "Ljava/lang/String;",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patches.youtube.misc.fix.playback.SpoofClientResourcePatch
|
|
||||||
import app.revanced.util.patch.LiteralValueFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
internal object ScrubbedPreviewLayoutFingerprint : LiteralValueFingerprint(
|
|
||||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
|
||||||
returnType = "V",
|
|
||||||
parameters = listOf("Landroid/content/Context;", "Landroid/util/AttributeSet;", "I", "I"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.CONST,
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
Opcode.IPUT_OBJECT, // preview imageview
|
|
||||||
),
|
|
||||||
// This resource is used in ~ 40 different locations, but this method has a distinct list of parameters to match to.
|
|
||||||
literalSupplier = { SpoofClientResourcePatch.scrubbedPreviewThumbnailResourceId },
|
|
||||||
)
|
|
|
@ -6,6 +6,7 @@ import app.revanced.util.patch.LiteralValueFingerprint
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
@Deprecated("Fingerprint is obsolete and will be deleted soon")
|
||||||
internal object SpoofSignaturePatchScrubbedPreviewLayoutFingerprint : LiteralValueFingerprint(
|
internal object SpoofSignaturePatchScrubbedPreviewLayoutFingerprint : LiteralValueFingerprint(
|
||||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||||
returnType = "V",
|
returnType = "V",
|
||||||
|
|
|
@ -2,6 +2,7 @@ package app.revanced.patches.youtube.misc.fix.playback.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
|
||||||
|
@Deprecated("Fingerprint is obsolete and will be deleted soon")
|
||||||
internal object StatsQueryParameterFingerprint : MethodFingerprint(
|
internal object StatsQueryParameterFingerprint : MethodFingerprint(
|
||||||
strings = listOf("adunit"),
|
strings = listOf("adunit"),
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
* An additional change here might force the thumbnails to be created,
|
* An additional change here might force the thumbnails to be created,
|
||||||
* or possibly a change somewhere else (maybe involving YouTube 18.23.35 class `hte`)
|
* or possibly a change somewhere else (maybe involving YouTube 18.23.35 class `hte`)
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Fingerprint is obsolete and will be deleted soon")
|
||||||
internal object StoryboardThumbnailParentFingerprint : MethodFingerprint(
|
internal object StoryboardThumbnailParentFingerprint : MethodFingerprint(
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
returnType = "Landroid/graphics/Bitmap;",
|
returnType = "Landroid/graphics/Bitmap;",
|
||||||
|
|
|
@ -1092,11 +1092,10 @@
|
||||||
<string name="revanced_spoof_client_summary_on">Client is spoofed</string>
|
<string name="revanced_spoof_client_summary_on">Client is spoofed</string>
|
||||||
<string name="revanced_spoof_client_summary_off">Client is not spoofed\n\nVideo playback may not work</string>
|
<string name="revanced_spoof_client_summary_off">Client is not spoofed\n\nVideo playback may not work</string>
|
||||||
<string name="revanced_spoof_client_user_dialog_message">Turning off this setting may cause video playback issues.</string>
|
<string name="revanced_spoof_client_user_dialog_message">Turning off this setting may cause video playback issues.</string>
|
||||||
<!-- It is ideal, but not required, if the text here appears is alphabetically after the text used for 'revanced_client_spoof_title' -->
|
<string name="revanced_spoof_client_use_testsuite_title">Spoof client to Android Testsuite</string>
|
||||||
<string name="revanced_spoof_client_use_ios_title">Spoof client to iOS</string>
|
<string name="revanced_spoof_client_use_testsuite_summary">Spoof the client to Android Testsuite</string>
|
||||||
<string name="revanced_spoof_client_use_ios_summary">Spoof the client to iOS instead of an Android Testsuite</string>
|
<string name="revanced_spoof_client_use_testsuite_summary_on">Client is spoofed to an Android Testsuite client (iOS client is used for live streams)\n\nSide effects include, but are not limited to:\n• Speed flyout menu is missing\n• Captions are missing\n• Player swipe gestures may not work\n• Low quality Shorts seekbar thumbnails\n• Watch history may not work</string>
|
||||||
<string name="revanced_spoof_client_use_ios_summary_on">Client is spoofed to an iOS client\n\nSide effects include:\n• 60 fps video may not be available\n• No HDR video\n• Some videos may not load\n• Higher video qualities may be missing</string>
|
<string name="revanced_spoof_client_use_testsuite_summary_off">Client is spoofed to an iOS client\n\nSide effects include:\n• No HDR video\n• Speed flyout menu is missing</string>
|
||||||
<string name="revanced_spoof_client_use_ios_summary_off">Client is spoofed to an Android Testsuite client (iOS client is used for live streams)\n\nSide effects include:\n• Subtitles are missing\n• Player gestures may not work\n• Low quality Shorts seekbar thumbnails</string>
|
|
||||||
<string name="revanced_spoof_client_storyboard_timeout">Spoof client thumbnails not available (API timed out)</string>
|
<string name="revanced_spoof_client_storyboard_timeout">Spoof client thumbnails not available (API timed out)</string>
|
||||||
<string name="revanced_spoof_client_storyboard_io_exception">Spoof client thumbnails temporarily not available: %s</string>
|
<string name="revanced_spoof_client_storyboard_io_exception">Spoof client thumbnails temporarily not available: %s</string>
|
||||||
</patch>
|
</patch>
|
||||||
|
|
Loading…
Reference in a new issue