diff --git a/CHANGELOG.md b/CHANGELOG.md index 79e017b34..8a0c9e0f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +# [4.6.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.1-dev.2...v4.6.0-dev.1) (2024-03-31) + + +### Features + +* **Tumblr:** Add `Fix old versions` patch ([#2954](https://github.com/ReVanced/revanced-patches/issues/2954)) ([2fde60e](https://github.com/ReVanced/revanced-patches/commit/2fde60eceb0a96fa857c32cd55c1fd7fe776a679)) + +## [4.5.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.1-dev.1...v4.5.1-dev.2) (2024-03-30) + + +### Bug Fixes + +* **Mi Fitness - Fix login:** Patch correct register ([#2942](https://github.com/ReVanced/revanced-patches/issues/2942)) ([dc96942](https://github.com/ReVanced/revanced-patches/commit/dc969422b5d50f21e6ea7a64b67dfc650fee6e36)) + +## [4.5.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.5.0...v4.5.1-dev.1) (2024-03-30) + + +### Bug Fixes + +* **Tumblr:** Restore compatibility with latest versions ([#2955](https://github.com/ReVanced/revanced-patches/issues/2955)) ([2954ba7](https://github.com/ReVanced/revanced-patches/commit/2954ba78d21d77308404961f79234bbec606d42e)) + +# [4.5.0](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0) (2024-03-30) + + +### Features + +* **YouTube - Alternative thumbnails:** Selectively enable for home / subscription / search ([#2926](https://github.com/ReVanced/revanced-patches/issues/2926)) ([8549e1b](https://github.com/ReVanced/revanced-patches/commit/8549e1ba58ad1e1608f5e3ceacd31eeb94578949)) +* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([c0bef25](https://github.com/ReVanced/revanced-patches/commit/c0bef255909ca884838675ca6f7ac5b0e2e21730)) + +# [4.5.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.5.0-dev.1...v4.5.0-dev.2) (2024-03-30) + + +### Features + +* **YouTube - GmsCore:** Require ignoring battery optimizations ([#2952](https://github.com/ReVanced/revanced-patches/issues/2952)) ([c0bef25](https://github.com/ReVanced/revanced-patches/commit/c0bef255909ca884838675ca6f7ac5b0e2e21730)) + # [4.5.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.4.0...v4.5.0-dev.1) (2024-03-29) diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 1bdd4051b..4bebe5e6e 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -1056,6 +1056,16 @@ public final class app/revanced/patches/tumblr/featureflags/OverrideFeatureFlags public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/tumblr/fixes/FixOldVersionsPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/tumblr/fixes/FixOldVersionsPatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + +public final class app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint : app/revanced/patcher/fingerprint/MethodFingerprint { + public static final field INSTANCE Lapp/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint; +} + public final class app/revanced/patches/tumblr/live/DisableTumblrLivePatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/tumblr/live/DisableTumblrLivePatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V diff --git a/gradle.properties b/gradle.properties index 04ea7f7c8..75732fcb8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true kotlin.code.style = auto # Use Project style setting. -version = 4.5.0-dev.1 +version = 4.6.0-dev.1 diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt index cf67c893d..fdb8f315a 100644 --- a/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt @@ -2,13 +2,11 @@ package app.revanced.patches.mifitness.misc.login import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.mifitness.misc.login.fingerprints.XiaomiAccountManagerConstructorFingerprint import app.revanced.util.exception -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @Patch( name = "Fix login", @@ -20,16 +18,9 @@ object FixLoginPatch : BytecodePatch( setOf(XiaomiAccountManagerConstructorFingerprint), ) { override fun execute(context: BytecodeContext) { - XiaomiAccountManagerConstructorFingerprint.result?.let { - it.mutableMethod.apply { - val isCertifiedIndex = it.scanResult.patternScanResult!!.startIndex - val isCertifiedRegister = getInstruction(isCertifiedIndex).registerA - - addInstruction( - isCertifiedIndex, - "const/4 p$isCertifiedRegister, 0x0", - ) - } - } ?: throw XiaomiAccountManagerConstructorFingerprint.exception + XiaomiAccountManagerConstructorFingerprint.result?.mutableMethod?.addInstruction( + 0, + "const/16 p2, 0x0", + ) ?: throw XiaomiAccountManagerConstructorFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt index e5d06acef..d81aa33f7 100644 --- a/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt @@ -3,12 +3,14 @@ package app.revanced.patches.mifitness.misc.login.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint( accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR, customFingerprint = { methodDef, _ -> methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;" }, - opcodes = listOf(Opcode.IF_NEZ), + parameters = listOf( + "Landroid/content/Context;", + "Z", + ), ) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt index 65d905396..060d3447c 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/gms/GmsCoreSupportPatch.kt @@ -34,5 +34,5 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( PrimeMethodFingerprint, ), ) { - override val gmsCoreVendor by gmsCoreVendorGroupIdOption + override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption } diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt index f7bfcb6ef..9d2544b7e 100644 --- a/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportPatch.kt @@ -2,7 +2,7 @@ package app.revanced.patches.shared.misc.gms import app.revanced.patcher.PatchClass import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.fingerprint.MethodFingerprint @@ -12,7 +12,7 @@ import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AC import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.AUTHORITIES import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportPatch.Constants.PERMISSIONS import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint -import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_METHOD_NAME +import app.revanced.patches.shared.misc.gms.fingerprints.GmsCoreSupportFingerprint.GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME import app.revanced.util.exception import app.revanced.util.getReference import app.revanced.util.returnEarly @@ -32,7 +32,7 @@ import com.android.tools.smali.dexlib2.util.MethodUtil * @param toPackageName The package name to fall back to if no custom package name is specified in patch options. * @param primeMethodFingerprint The fingerprint of the "prime" method that needs to be patched. * @param earlyReturnFingerprints The fingerprints of methods that need to be returned early. - * @param mainActivityOnCreateFingerprint The fingerprint of the main activity's onCreate method. + * @param mainActivityOnCreateFingerprint The fingerprint of the main activity onCreate method. * @param integrationsPatchDependency The patch responsible for the integrations. * @param gmsCoreSupportResourcePatch The corresponding resource patch that is used to patch the resources. * @param dependencies Additional dependencies of this patch. @@ -60,7 +60,10 @@ abstract class BaseGmsCoreSupportPatch( integrationsPatchDependency, ) + dependencies, compatiblePackages = compatiblePackages, - fingerprints = setOf(GmsCoreSupportFingerprint, mainActivityOnCreateFingerprint) + fingerprints, + fingerprints = setOf( + GmsCoreSupportFingerprint, + mainActivityOnCreateFingerprint, + ) + fingerprints, requiresIntegrations = true, ) { init { @@ -68,7 +71,7 @@ abstract class BaseGmsCoreSupportPatch( gmsCoreSupportResourcePatch.options.values.forEach(options::register) } - internal abstract val gmsCoreVendor: String? + internal abstract val gmsCoreVendorGroupId: String? override fun execute(context: BytecodeContext) { val packageName = ChangePackageNamePatch.setOrGetFallbackPackageName(toPackageName) @@ -93,16 +96,17 @@ abstract class BaseGmsCoreSupportPatch( // Return these methods early to prevent the app from crashing. earlyReturnFingerprints.toList().returnEarly() - // Check the availability of GmsCore. - mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstruction( - 1, // Hack to not disturb other patches (such as the integrations patch). - "invoke-static {}, Lapp/revanced/integrations/shared/GmsCoreSupport;->checkAvailability()V", + // Verify GmsCore is installed and whitelisted for power optimizations and background usage. + mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions( + 1, // Hack to not disturb other patches (such as the YTMusic integrations patch). + "invoke-static/range { p0 .. p0 }, Lapp/revanced/integrations/shared/GmsCoreSupport;->" + + "checkGmsCore(Landroid/content/Context;)V", ) ?: throw mainActivityOnCreateFingerprint.exception // Change the vendor of GmsCore in ReVanced Integrations. GmsCoreSupportFingerprint.result?.mutableClass?.methods - ?.single { it.name == GET_GMS_CORE_VENDOR_METHOD_NAME } - ?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendor\"") + ?.single { it.name == GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME } + ?.replaceInstruction(0, "const-string v0, \"$gmsCoreVendorGroupId\"") ?: throw GmsCoreSupportFingerprint.exception } @@ -146,10 +150,10 @@ abstract class BaseGmsCoreSupportPatch( in PERMISSIONS, in ACTIONS, in AUTHORITIES, - -> referencedString.replace("com.google", gmsCoreVendor!!) + -> referencedString.replace("com.google", gmsCoreVendorGroupId!!) // No vendor prefix for whatever reason... - "subscribedfeeds" -> "$gmsCoreVendor.subscribedfeeds" + "subscribedfeeds" -> "$gmsCoreVendorGroupId.subscribedfeeds" else -> null } @@ -162,7 +166,7 @@ abstract class BaseGmsCoreSupportPatch( if (str.startsWith(uriPrefix)) { return str.replace( uriPrefix, - "content://${authority.replace("com.google", gmsCoreVendor!!)}", + "content://${authority.replace("com.google", gmsCoreVendorGroupId!!)}", ) } } @@ -170,7 +174,7 @@ abstract class BaseGmsCoreSupportPatch( // gms also has a 'subscribedfeeds' authority, check for that one too val subFeedsUriPrefix = "content://subscribedfeeds" if (str.startsWith(subFeedsUriPrefix)) { - return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendor.subscribedfeeds") + return str.replace(subFeedsUriPrefix, "content://$gmsCoreVendorGroupId.subscribedfeeds") } } diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch.kt b/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch.kt index eef039f74..f77a6d361 100644 --- a/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/misc/gms/BaseGmsCoreSupportResourcePatch.kt @@ -121,7 +121,6 @@ abstract class BaseGmsCoreSupportResourcePatch( } private companion object { - private const val VANCED_VENDOR = "com.mgoogle" private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$" } } diff --git a/src/main/kotlin/app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint.kt index b75addcd3..52cef8fd6 100644 --- a/src/main/kotlin/app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/misc/gms/fingerprints/GmsCoreSupportFingerprint.kt @@ -7,5 +7,5 @@ internal object GmsCoreSupportFingerprint : MethodFingerprint( classDef.type.endsWith("GmsCoreSupport;") }, ) { - const val GET_GMS_CORE_VENDOR_METHOD_NAME = "getGmsCoreVendor" + const val GET_GMS_CORE_VENDOR_GROUP_ID_METHOD_NAME = "getGmsCoreVendorGroupId" } diff --git a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/fingerprints/ShowGiftMessagePopupFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/fingerprints/ShowGiftMessagePopupFingerprint.kt index 3ca9e3681..dc5a168a6 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/fingerprints/ShowGiftMessagePopupFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/annoyances/popups/fingerprints/ShowGiftMessagePopupFingerprint.kt @@ -1,9 +1,12 @@ package app.revanced.patches.tumblr.annoyances.popups.fingerprints +import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags // This method is responsible for loading and displaying the visual Layout of the Gift Message Popup. internal object ShowGiftMessagePopupFingerprint : MethodFingerprint( - strings = listOf("activity", "anchorView"), - customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("GiftMessagePopup;") }, -) + strings = listOf("activity", "anchorView", "textMessage"), + returnType = "V", + accessFlags = AccessFlags.FINAL or AccessFlags.PUBLIC +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt index f9e2d5128..bedc60f79 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt @@ -28,6 +28,9 @@ object OverrideFeatureFlagsPatch : BytecodePatch( internal lateinit var addOverride: (name: String, value: String) -> Unit private set override fun execute(context: BytecodeContext) = GetFeatureValueFingerprint.result?.let { + val configurationClass = it.method.definingClass + val featureClass = it.method.parameterTypes[0].toString() + // The method we want to inject into does not have enough registers, so we inject a helper method // and inject more instructions into it later, see addOverride. // This is not in an integration since the unused variable would get compiled away and the method would @@ -35,7 +38,7 @@ object OverrideFeatureFlagsPatch : BytecodePatch( val helperMethod = ImmutableMethod( it.method.definingClass, "getValueOverride", - listOf(ImmutableMethodParameter("Lcom/tumblr/configuration/Feature;", null, "feature")), + listOf(ImmutableMethodParameter(featureClass, null, "feature")), "Ljava/lang/String;", AccessFlags.PUBLIC or AccessFlags.FINAL, null, @@ -50,7 +53,7 @@ object OverrideFeatureFlagsPatch : BytecodePatch( 0, """ # toString() the enum value - invoke-virtual {p1}, Lcom/tumblr/configuration/Feature;->toString()Ljava/lang/String; + invoke-virtual {p1}, $featureClass->toString()Ljava/lang/String; move-result-object v0 # !!! If you add more instructions above this line, update helperInsertIndex below! @@ -75,7 +78,7 @@ object OverrideFeatureFlagsPatch : BytecodePatch( getFeatureIndex, """ # Call the Helper Method with the Feature - invoke-virtual {p0, p1}, Lcom/tumblr/configuration/Configuration;->getValueOverride(Lcom/tumblr/configuration/Feature;)Ljava/lang/String; + invoke-virtual {p0, p1}, $configurationClass->getValueOverride($featureClass)Ljava/lang/String; move-result-object v0 # If it returned null, skip if-eqz v0, :is_null diff --git a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt index e51d9b338..0088c3aa6 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/featureflags/fingerprints/GetFeatureValueFingerprint.kt @@ -1,6 +1,8 @@ package app.revanced.patches.tumblr.featureflags.fingerprints +import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode // This fingerprint targets the method to get the value of a Feature in the class "com.tumblr.configuration.Feature". @@ -17,7 +19,9 @@ internal object GetFeatureValueFingerprint : MethodFingerprint( opcodes = listOf( Opcode.IF_EQZ, Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, + Opcode.MOVE_RESULT ), - customFingerprint = { method, _ -> method.definingClass == "Lcom/tumblr/configuration/Configuration;" }, -) + returnType = "Ljava/lang/String;", + parameters = listOf("L", "Z"), + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt new file mode 100644 index 000000000..9fe883d9e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt @@ -0,0 +1,38 @@ +package app.revanced.patches.tumblr.fixes + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.tumblr.fixes.fingerprints.HttpPathParserFingerprint +import app.revanced.util.exception + +@Patch( + name = "Fix old versions", + description = "Fixes old versions of the app (v33.2 and earlier) breaking due to Tumblr removing remnants of Tumblr" + + " Live from the API, which causes many requests to fail. This patch has no effect on newer versions of the app.", + compatiblePackages = [CompatiblePackage("com.tumblr")], + use = false, +) +@Suppress("unused") +object FixOldVersionsPatch : BytecodePatch( + setOf(HttpPathParserFingerprint), +) { + override fun execute(context: BytecodeContext) = + HttpPathParserFingerprint.result?.let { + val endIndex = it.scanResult.patternScanResult!!.endIndex + + it.mutableMethod.addInstructions( + endIndex + 1, + """ + # Remove "?live_now" from the request path p2. + # p2 = p2.replace(p1, p3) + const-string p1, ",?live_now" + const-string p3, "" + invoke-virtual {p2, p1, p3}, Ljava/lang/String;->replace(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String; + move-result-object p2 + """, + ) + } ?: throw HttpPathParserFingerprint.exception +} diff --git a/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint.kt b/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint.kt new file mode 100644 index 000000000..0ef376ed9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/tumblr/fixes/fingerprints/HttpPathParserFingerprint.kt @@ -0,0 +1,15 @@ +package app.revanced.patches.tumblr.fixes.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +// Fingerprint for the parseHttpMethodAndPath from retrofit2 +// https://github.com/square/retrofit/blob/ebf87b10997e2136af4d335276fa950221852c64/retrofit/src/main/java/retrofit2/RequestFactory.java#L270-L302 +// Injecting here allows modifying the path/query params of API endpoints defined via annotations +object HttpPathParserFingerprint : MethodFingerprint( + strings = listOf("Only one HTTP method is allowed. Found: %s and %s."), + opcodes = listOf( + Opcode.IPUT_OBJECT, + Opcode.IPUT_BOOLEAN + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt b/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt index 8cbdaca6e..f5b53133a 100644 --- a/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt +++ b/src/main/kotlin/app/revanced/patches/tumblr/live/DisableTumblrLivePatch.kt @@ -8,11 +8,11 @@ import app.revanced.patches.tumblr.featureflags.OverrideFeatureFlagsPatch import app.revanced.patches.tumblr.timelinefilter.TimelineFilterPatch @Patch( - name = "Disable Tumblr Live", description = "Disable the Tumblr Live tab button and dashboard carousel.", dependencies = [OverrideFeatureFlagsPatch::class, TimelineFilterPatch::class], compatiblePackages = [CompatiblePackage("com.tumblr")], ) +@Deprecated("Tumblr Live was removed and is no longer served in the feed, making this patch useless.") @Suppress("unused") object DisableTumblrLivePatch : BytecodePatch(emptySet()) { override fun execute(context: BytecodeContext) { diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt index 00d9dfe61..904de9c05 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/player/flyoutmenupanel/HidePlayerFlyoutMenuPatch.kt @@ -46,7 +46,6 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch ) @Suppress("unused") object HidePlayerFlyoutMenuPatch : ResourcePatch() { - private const val KEY = "revanced_hide_player_flyout" private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/components/PlayerFlyoutMenuItemsFilter;" @@ -55,21 +54,21 @@ object HidePlayerFlyoutMenuPatch : ResourcePatch() { AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.PLAYER.addPreferences( - PreferenceScreen( - key = KEY, - preferences = setOf( - SwitchPreference("${KEY}_captions"), - SwitchPreference("${KEY}_additional_settings"), - SwitchPreference("${KEY}_loop_video"), - SwitchPreference("${KEY}_ambient_mode"), - SwitchPreference("${KEY}_report"), - SwitchPreference("${KEY}_help"), - SwitchPreference("${KEY}_speed"), - SwitchPreference("${KEY}_more_info"), - SwitchPreference("${KEY}_audio_track"), - SwitchPreference("${KEY}_watch_in_vr"), - ), - ) + PreferenceScreen( + key = "revanced_hide_player_flyout", + preferences = setOf( + SwitchPreference("revanced_hide_player_flyout_captions"), + SwitchPreference("revanced_hide_player_flyout_additional_settings"), + SwitchPreference("revanced_hide_player_flyout_loop_video"), + SwitchPreference("revanced_hide_player_flyout_ambient_mode"), + SwitchPreference("revanced_hide_player_flyout_report"), + SwitchPreference("revanced_hide_player_flyout_help"), + SwitchPreference("revanced_hide_player_flyout_speed"), + SwitchPreference("revanced_hide_player_flyout_more_info"), + SwitchPreference("revanced_hide_player_flyout_audio_track"), + SwitchPreference("revanced_hide_player_flyout_watch_in_vr"), + ) + ) ) LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch.kt index 693ef4c6a..434ddcaa2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/announcements/AnnouncementsPatch.kt @@ -2,26 +2,24 @@ package app.revanced.patches.youtube.misc.announcements import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.extensions.InstructionExtensions.getInstructions import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.all.misc.resources.AddResourcesPatch import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.settings.SettingsPatch -import app.revanced.patches.youtube.shared.fingerprints.MainActivityFingerprint -import app.revanced.util.exception -import com.android.tools.smali.dexlib2.Opcode +import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint +import app.revanced.util.resultOrThrow @Patch( name = "Announcements", description = "Adds an option to show announcements from ReVanced on app startup.", compatiblePackages = [CompatiblePackage("com.google.android.youtube")], - dependencies = [SettingsPatch::class, AddResourcesPatch::class], + dependencies = [SettingsPatch::class,AddResourcesPatch::class] ) @Suppress("unused") object AnnouncementsPatch : BytecodePatch( - setOf(MainActivityFingerprint), + setOf(MainActivityOnCreateFingerprint) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/announcements/AnnouncementsPatch;" @@ -30,18 +28,14 @@ object AnnouncementsPatch : BytecodePatch( AddResourcesPatch(this::class) SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference("revanced_announcements"), + SwitchPreference("revanced_announcements") ) - val onCreateMethod = MainActivityFingerprint.result?.let { - it.mutableClass.methods.find { method -> method.name == "onCreate" } - } ?: throw MainActivityFingerprint.exception - - val superCallIndex = onCreateMethod.getInstructions().indexOfFirst { it.opcode == Opcode.INVOKE_SUPER_RANGE } - - onCreateMethod.addInstructions( - superCallIndex + 1, - "invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V", + MainActivityOnCreateFingerprint.resultOrThrow().mutableMethod.addInstructions( + // Insert index must be great than the insert index used by GmsCoreSupport, + // as both patch the same method and GmsCore check should be first. + 1, + "invoke-static/range { p0 .. p0 }, $INTEGRATIONS_CLASS_DESCRIPTOR->showAnnouncement(Landroid/app/Activity;)V" ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt index ff2902351..6547f0ec3 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/gms/GmsCoreSupportPatch.kt @@ -9,7 +9,7 @@ import app.revanced.patches.youtube.misc.gms.Constants.YOUTUBE_PACKAGE_NAME import app.revanced.patches.youtube.misc.gms.GmsCoreSupportResourcePatch.gmsCoreVendorGroupIdOption import app.revanced.patches.youtube.misc.gms.fingerprints.* import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch -import app.revanced.patches.youtube.shared.fingerprints.HomeActivityFingerprint +import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint @Suppress("unused") object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( @@ -23,7 +23,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( CastDynamiteModuleV2Fingerprint, CastContextFetchFingerprint, ), - mainActivityOnCreateFingerprint = HomeActivityFingerprint, + mainActivityOnCreateFingerprint = MainActivityOnCreateFingerprint, integrationsPatchDependency = IntegrationsPatch::class, dependencies = setOf( HideCastButtonPatch::class, @@ -57,5 +57,5 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch( PrimeMethodFingerprint, ), ) { - override val gmsCoreVendor by gmsCoreVendorGroupIdOption + override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption } diff --git a/src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/MainActivityOnCreateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/MainActivityOnCreateFingerprint.kt new file mode 100644 index 000000000..fa63c0fde --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/MainActivityOnCreateFingerprint.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.youtube.shared.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint + +internal object MainActivityOnCreateFingerprint : MethodFingerprint( + returnType = "V", + parameters = listOf("Landroid/os/Bundle;"), + customFingerprint = { methodDef, classDef -> + methodDef.name == "onCreate" && + (classDef.type.endsWith("MainActivity;") + // Old versions of YouTube called this class "WatchWhileActivity" instead. + || classDef.type.endsWith("WatchWhileActivity;")) + } +) \ No newline at end of file diff --git a/src/main/resources/addresources/values/strings.xml b/src/main/resources/addresources/values/strings.xml index d7ac91cf7..50e59bf27 100644 --- a/src/main/resources/addresources/values/strings.xml +++ b/src/main/resources/addresources/values/strings.xml @@ -13,8 +13,14 @@ Import failed: %s - GmsCore is not installed. Please install. - GmsCore is failing to run. Please follow the \"Don\'t kill my app\" guide for GmsCore. + + GmsCore is not installed. Install it. + + Follow the \"Don\'t kill my app\" guide for GmsCore. + Action needed + GmsCore is not whitelisted from battery optimization.\n\nFollow the \"Don\'t kill my app\" guide for GmsCore. + GmsCore does not have permission to run in the background.\n\nFollow the \"Don\'t kill my app\" guide for GmsCore. + Open website @@ -183,8 +189,8 @@ Keywords and phrases to hide, separated by new lines\n\nWords with uppercase letters in the middle must be entered with the casing (ie: iPhone, TikTok, LeBlanc) About keyword filtering Home/Subscription/Search results are filtered to hide content that matches keyword phrases\n\nLimitations\n• Some Shorts may not be hidden\n• Some UI components may not be hidden\n• Searching for a keyword may show no results - Invalid keyword. Cannot use: \'%s\' as a filter - Invalid keyword. \'%s\' is less than %s characters + Invalid keyword. Cannot use: \'%s\' as a filter + Invalid keyword. \'%1$s\' is less than %2$s characters Hide general ads @@ -462,9 +468,6 @@ Button is hidden Button is shown - - Video - Disable rolling number animations Rolling numbers are not animated @@ -560,16 +563,16 @@ Return YouTube Dislike Hidden Dislikes temporarily not available (API timed out) - Dislikes not available (status %d) + Dislikes not available (status %d) Dislikes not available (client API limit reached) Dislikes not available (%s) - + Reload video to vote using ReturnYouTubeDislike Return YouTube Dislike Dislikes are shown Dislikes are not shown Show dislikes on Shorts + Dislikes shown on Shorts %s Dislikes hidden on Shorts Limitation: Dislikes may not appear in incognito mode @@ -585,6 +588,7 @@ About ReturnYouTubeDislike.com Data is provided by the Return YouTube Dislike API. Tap here to learn more + ReturnYouTubeDislike API statistics of this device API response time, average API response time, minimum @@ -595,8 +599,7 @@ No network calls made %d network calls made API fetch votes, number of timeouts - No - network calls timed out + No network calls timed out %d network calls timed out API client rate limits No client rate limits encountered @@ -727,19 +730,19 @@ Show a skip button Show in seek bar Disable - Unable to submit segment: %s + Unable to submit segment: %s SponsorBlock is temporarily down - Unable to submit segment (status: %d %s) + Unable to submit segment (status: %1$d %2$s) Unable to submit segment.\nRate Limited (too many from the same user or IP) - Can\'t submit the segment: %s + Can\'t submit the segment: %s Can\'t submit the segment.\nAlready exists Segment submitted successfully SponsorBlock temporarily not available - SponsorBlock temporarily not available (status %d) + SponsorBlock temporarily not available (status %d) SponsorBlock temporarily not available (API timed out) Unable to vote for segment (API timed out) - Unable to vote for segment (status: %d %s) - Unable to vote for segment: %s + Unable to vote for segment (status: %1$d %2$s) + Unable to vote for segment: %s Upvote Downvote Change category @@ -747,14 +750,14 @@ Choose the segment category Category is disabled in settings. Enable category to submit. New SponsorBlock segment - Set %02d:%02d:%03d as the start or end of a new segment? + Set %1$02d:%2$02d:%3$03d as the start or end of a new segment? start end now Time the segment begins at Time the segment ends at Are the times correct? - The segment lasts from %02d:%02d to %02d:%02d (%d minutes %02d seconds)\nIs it ready to submit? + The segment lasts from %1$02d:%2$02d to %3$02d:%4$02d (%5$d minutes %6$02d seconds)\nIs it ready to submit? Start must be before the end Mark two locations on the time bar first Preview the segment, and ensure it skips smoothly @@ -765,22 +768,22 @@ Stats temporarily not available (API is down) Loading... SponsorBlock is disabled - Your username: <b>%s</b> + Your username: <b>%s</b> Tap here to change your username - Unable to change username: Status: %d %s + Unable to change username: Status: %1$d %2$s Username successfully changed - Your reputation is <b>%.2f</b> - You\'ve created <b>%s</b> segments + Your reputation is <b>%.2f</b> + You\'ve created <b>%s</b> segments SponsorBlock leaderboard - You\'ve saved people from <b>%s</b> segments + You\'ve saved people from <b>%s</b> segments Tap here to see the global stats and top contributors - That\'s <b>%s</b> of their lives.<br>Tap here to see the leaderboard - You\'ve skipped <b>%s</b> segments - That\'s <b>%s</b> + That\'s <b>%s</b> of their lives.<br>Tap here to see the leaderboard + You\'ve skipped <b>%s</b> segments + That\'s <b>%s</b> Reset skipped segments counter? - %s hours %s minutes - %s minutes %s seconds - %s seconds + %1$s hours %2$s minutes + %1$s minutes %2$s seconds + %s seconds Color: Color changed Color reset @@ -796,7 +799,10 @@ Version spoofed Version not spoofed App version will be spoofed to an older version of YouTube.\n\nThis will change the appearance and features of the app, but unknown side effects may occur.\n\nIf later turned off, it is recommended to clear the app data to prevent UI bugs. + Spoof app version target + 18.33.40 - Restore RYD on Shorts incognito mode 18.20.39 - Restore wide video speed & quality menu 18.09.39 - Restore library tab @@ -881,6 +887,7 @@ Announcements are not shown on startup Show announcements on startup Failed connecting to announcements provider + Dismiss Enable auto-repeat @@ -892,6 +899,7 @@ Device dimensions spoofed Device dimensions not spoofed\n\nSpoofing the device dimensions can unlock higher video qualities but unknown side effects may occur + Spoof app signature Spoof the app signature to prevent playback issues @@ -936,6 +944,7 @@ Haptics are disabled Haptics are enabled + Enable auto HDR brightness Auto HDR brightness is enabled @@ -958,12 +967,12 @@ Default video quality on mobile network mobile wifi - Changed default %s quality to: %s + Changed default %1$s quality to: %2$s Custom playback speeds Add or change the available playback speeds - Custom speeds must be less than %s Using default values. + Custom speeds must be less than %s Using default values. Invalid custom playback speeds. Using default values. @@ -971,7 +980,7 @@ Playback speed changes apply to all videos Playback speed changes only apply to the current video Default playback speed - Changed default speed to: %s + Changed default speed to: %s Restore old video quality menu