From acac6e960cb8938cd9705f23814595badfc7ee23 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 29 Jan 2026 23:17:33 +0100 Subject: [PATCH] some fixes & update to newest patcher changes --- .../all/misc/resources/AddResourcesPatch.kt | 2 +- .../patches/angulus/ads/Fingerprints.kt | 2 +- .../patches/crunchyroll/ads/Fingerprints.kt | 5 +-- .../patches/crunchyroll/ads/HideAdsPatch.kt | 2 +- .../patches/duolingo/ad/DisableAdsPatch.kt | 19 +++++----- .../patches/duolingo/ad/Fingerprints.kt | 5 +-- .../duolingo/debug/EnableDebugMenuPatch.kt | 7 ++-- .../patches/duolingo/debug/Fingerprints.kt | 4 +-- .../patches/duolingo/energy/Fingerprints.kt | 3 +- .../energy/SkipEnergyRechargeAdsPatch.kt | 17 +++++---- .../facebook/ads/mainfeed/Fingerprints.kt | 2 +- .../ads/mainfeed/HideSponsoredStoriesPatch.kt | 2 +- .../customtabs/EnableCustomTabsPatch.kt | 2 +- .../googlenews/customtabs/Fingerprints.kt | 5 +-- .../restrictions/Fingerprints.kt | 3 +- .../restrictions/RemoveDeviceRestrictions.kt | 2 +- .../instagram/hide/explore/Fingerprints.kt | 5 +-- .../instagram/hide/explore/HideExploreFeed.kt | 2 +- .../instagram/hide/stories/Fingerprints.kt | 3 +- .../instagram/hide/stories/HideStories.kt | 2 +- .../hide/suggestions/Fingerprints.kt | 5 +-- .../hide/suggestions/HideSuggestedContent.kt | 2 +- .../misc/devmenu/EnableDeveloperMenuPatch.kt | 2 +- .../instagram/misc/devmenu/Fingerprints.kt | 3 +- .../instagram/misc/links/Fingerprint.kt | 5 +-- .../misc/links/OpenLinksExternallyPatch.kt | 2 +- .../misc/share/EditShareLinksPatch.kt | 2 +- .../instagram/misc/share/Fingerprints.kt | 11 +++--- .../misc/version/DisableVersionCheckPatch.kt | 2 +- .../lightroom/misc/version/Fingerprints.kt | 5 +-- .../patches/messenger/metaai/Fingerprints.kt | 7 ++-- .../messenger/metaai/RemoveMetaAIPatch.kt | 6 ++-- .../mifitness/misc/locale/Fingerprints.kt | 3 +- .../misc/locale/ForceEnglishLocalePatch.kt | 2 +- .../patches/music/ad/video/Fingerprints.kt | 5 +-- .../patches/music/ad/video/HideVideoAds.kt | 2 +- .../permanentrepeat/Fingerprints.kt | 5 +-- .../permanentrepeat/PermanentRepeatPatch.kt | 2 +- .../music/layout/buttons/Fingerprints.kt | 10 +++--- .../music/layout/buttons/HideButtons.kt | 2 +- .../layout/compactheader/Fingerprints.kt | 3 +- .../layout/compactheader/HideCategoryBar.kt | 2 +- .../miniplayercolor/ChangeMiniplayerColor.kt | 4 +-- .../layout/miniplayercolor/Fingerprints.kt | 4 +-- .../layout/navigationbar/Fingerprints.kt | 3 +- .../navigationbar/NavigationBarPatch.kt | 2 +- .../music/layout/premium/Fingerprints.kt | 4 +-- .../layout/premium/HideGetPremiumPatch.kt | 2 +- .../revanced/patches/nunl/ads/Fingerprints.kt | 4 +-- .../revanced/patches/nunl/ads/HideAdsPatch.kt | 2 +- .../detection/signature/Fingerprints.kt | 5 +-- .../signature/SignatureDetectionPatch.kt | 2 +- .../protonvpn/splittunneling/Fingerprints.kt | 6 ++-- .../splittunneling/UnlockSplitTunneling.kt | 2 +- .../reddit/customclients/SpoofClientPatch.kt | 8 ++--- .../baconreader/api/Fingerprints.kt | 11 +++--- .../baconreader/api/SpoofClientPatch.kt | 8 ++--- .../fix/downloads/Fingerprints.kt | 7 ++-- .../FixAudioMissingInDownloadsPatch.kt | 2 +- .../redditisfun/api/Fingerprints.kt | 8 ++--- .../redditisfun/api/SpoofClientPatch.kt | 5 ++- .../relayforreddit/api/Fingerprints.kt | 16 ++++----- .../relayforreddit/api/SpoofClientPatch.kt | 2 +- .../piracy/DisablePiracyDetectionPatch.kt | 2 +- .../sync/syncforreddit/api/Fingerprints.kt | 10 +++--- .../syncforreddit/api/SpoofClientPatch.kt | 8 ++--- .../syncforreddit/fix/redgifs/Fingerprints.kt | 2 +- .../syncforreddit/fix/user/Fingerprints.kt | 19 +++++----- .../fix/user/UseUserEndpointPatch.kt | 2 +- .../syncforreddit/fix/video/Fingerprints.kt | 3 +- .../fix/video/FixVideoDownloadsPatch.kt | 2 +- .../shared/layout/branding/Fingerprints.kt | 4 +-- .../shared/layout/theme/Fingerprints.kt | 3 +- .../layout/theme/LithoColorHookPatch.kt | 2 +- .../patches/shared/misc/audio/Fingerprints.kt | 7 ++-- .../misc/audio/ForceOriginalAudioPatch.kt | 4 +-- .../misc/debugging/EnableDebuggingPatch.kt | 34 +++++++++--------- ...ckWatchHistoryDomainNameResolutionPatch.kt | 2 +- .../misc/extension/SharedExtensionPatch.kt | 22 ++++++------ .../misc/fix/verticalscroll/Fingerprints.kt | 3 +- .../fix/verticalscroll/VerticalScrollPatch.kt | 2 +- .../shared/misc/gms/GmsCoreSupportPatch.kt | 2 +- .../shared/misc/privacy/Fingerprints.kt | 13 +++---- .../misc/privacy/SanitizeSharingLinksPatch.kt | 15 ++++---- .../patches/shared/misc/spoof/Fingerprints.kt | 36 +++++++++---------- .../misc/spoof/SpoofVideoStreamsPatch.kt | 24 ++++++------- .../functionality/filesize/Fingerprints.kt | 5 +-- .../filesize/RemoveFileSizeLimitPatch.kt | 2 +- .../patches/soundcloud/ad/Fingerprints.kt | 2 +- .../patches/soundcloud/ad/HideAdsPatch.kt | 2 +- .../spotify/misc/extension/Fingerprints.kt | 5 +-- .../DisableSubscriptionSuggestionsPatch.kt | 2 +- .../patches/strava/upselling/Fingerprints.kt | 5 +-- .../ticktick/misc/themeunlock/Fingerprints.kt | 2 +- .../misc/themeunlock/UnlockThemePatch.kt | 2 +- .../tumblr/featureflags/Fingerprints.kt | 7 ++-- .../featureflags/OverrideFeatureFlagsPatch.kt | 2 +- .../patches/tumblr/fixes/Fingerprints.kt | 8 ++--- .../tumblr/fixes/FixOldVersionsPatch.kt | 2 +- .../FilterTimelineObjectsPatch.kt | 2 +- .../tumblr/timelinefilter/Fingerprints.kt | 6 ++-- .../interaction/downloads/Fingerprints.kt | 9 ++--- .../downloads/UnlockDownloadsPatch.kt | 10 +++--- .../patches/twitter/misc/hook/HookPatch.kt | 4 +-- .../twitter/misc/hook/json/Fingerprints.kt | 26 ++++++++------ .../twitter/misc/hook/json/JsonHookPatch.kt | 21 +++++------ .../patches/viber/ads/Fingerprints.kt | 5 +-- .../patches/viber/ads/HideAdsPatch.kt | 4 +-- .../patches/willhaben/ads/HideAdsPatch.kt | 2 +- .../youtube/ad/getpremium/Fingerprints.kt | 3 +- .../ad/getpremium/HideGetPremiumPatch.kt | 2 +- .../interaction/dialog/Fingerprints.kt | 3 +- .../RemoveViewerDiscretionDialogPatch.kt | 2 +- .../seekbar/EnableSeekbarTappingPatch.kt | 8 ++--- .../seekbar/EnableSlideToSeekPatch.kt | 6 ++-- .../interaction/seekbar/Fingerprints.kt | 14 ++++---- .../interaction/seekbar/HideSeekbarPatch.kt | 6 ++-- .../interaction/swipecontrols/Fingerprints.kt | 4 +-- .../swipecontrols/SwipeControlsPatch.kt | 2 +- .../layout/buttons/navigation/Fingerprints.kt | 13 +++---- .../navigation/NavigationButtonsPatch.kt | 12 +++---- .../layout/buttons/overlay/Fingerprints.kt | 6 ++-- .../overlay/HidePlayerOverlayButtonsPatch.kt | 8 ++--- .../formfactor/ChangeFormFactorPatch.kt | 2 +- .../hide/endscreencards/Fingerprints.kt | 6 ++-- .../endscreencards/HideEndScreenCardsPatch.kt | 2 +- .../hide/endscreensuggestion/Fingerprints.kt | 2 +- .../HideEndScreenSuggestedVideoPatch.kt | 2 +- .../layout/hide/general/Fingerprints.kt | 20 +++++------ .../hide/general/HideLayoutComponentsPatch.kt | 20 +++++------ .../layout/hide/infocards/Fingerprints.kt | 4 +-- .../hide/infocards/HideInfoCardsPatch.kt | 2 +- .../DisableRollingNumberAnimationPatch.kt | 4 +-- .../layout/hide/shorts/Fingerprints.kt | 4 +-- .../hide/shorts/HideShortsComponentsPatch.kt | 6 ++-- .../youtube/layout/miniplayer/Fingerprints.kt | 19 +++++----- .../layout/miniplayer/MiniplayerPatch.kt | 27 +++++++------- .../layout/player/fullscreen/Fingerprints.kt | 4 +-- .../OpenVideosFullscreenHookPatch.kt | 10 +++--- .../CustomPlayerOverlayOpacityPatch.kt | 2 +- .../layout/player/overlay/Fingerprints.kt | 3 +- .../returnyoutubedislike/Fingerprints.kt | 15 ++++---- .../ReturnYouTubeDislikePatch.kt | 12 +++---- .../youtube/layout/seekbar/Fingerprints.kt | 16 ++++----- .../layout/seekbar/SeekbarColorPatch.kt | 22 ++++++------ .../layout/shortsautoplay/Fingerprints.kt | 6 ++-- .../shortsautoplay/ShortsAutoplayPatch.kt | 6 ++-- .../layout/shortsplayer/Fingerprints.kt | 6 ++-- .../OpenShortsInRegularPlayerPatch.kt | 6 ++-- .../layout/sponsorblock/Fingerprints.kt | 10 +++--- .../layout/sponsorblock/SponsorBlockPatch.kt | 18 +++++----- .../layout/spoofappversion/Fingerprints.kt | 4 +-- .../spoofappversion/SpoofAppVersionPatch.kt | 6 ++-- .../layout/startpage/ChangeStartPagePatch.kt | 2 +- .../youtube/layout/startpage/Fingerprints.kt | 2 +- .../DisableResumingShortsOnStartupPatch.kt | 2 +- .../layout/startupshortsreset/Fingerprints.kt | 2 +- .../youtube/layout/theme/Fingerprints.kt | 5 +-- .../youtube/layout/theme/ThemePatch.kt | 4 +-- .../BackgroundPlaybackPatch.kt | 2 +- .../misc/backgroundplayback/Fingerprints.kt | 2 +- .../fix/backtoexitgesture/Fingerprints.kt | 5 +-- .../FixBackToExitGesturePatch.kt | 4 +-- .../FIxContentProviderPatch.kt | 2 +- .../misc/fix/contentprovider/Fingerprints.kt | 3 +- .../gms/AccountCredentialsInvalidTextPatch.kt | 2 +- .../patches/youtube/misc/gms/Fingerprints.kt | 7 ++-- .../youtube/misc/imageurlhook/Fingerprints.kt | 2 +- .../misc/links/BypassURLRedirectsPatch.kt | 2 +- .../youtube/misc/links/Fingerprints.kt | 9 ++--- .../youtube/misc/litho/filter/Fingerprints.kt | 4 +-- .../misc/litho/filter/LithoFilterPatch.kt | 4 +-- .../youtube/misc/navigation/Fingerprints.kt | 27 +++++++------- .../misc/navigation/NavigationBarHookPatch.kt | 17 ++++----- .../misc/playercontrols/Fingerprints.kt | 12 +++---- .../PlayerControlsOverlayVisibilityPatch.kt | 2 +- .../playercontrols/PlayerControlsPatch.kt | 16 ++++----- .../youtube/misc/playertype/Fingerprints.kt | 2 +- .../misc/playertype/PlayerTypeHookPatch.kt | 4 +-- .../recyclerviewtree/hook/Fingerprints.kt | 5 +-- .../hook/RecyclerViewTreeHookPatch.kt | 2 +- .../youtube/misc/settings/Fingerprints.kt | 6 ++-- .../youtube/misc/settings/SettingsPatch.kt | 6 ++-- .../patches/youtube/shared/Fingerprints.kt | 13 +++---- .../youtube/video/information/Fingerprints.kt | 25 ++++++------- .../information/VideoInformationPatch.kt | 14 ++++---- .../quality/AdvancedVideoQualityMenuPatch.kt | 6 ++-- .../youtube/video/quality/Fingerprints.kt | 6 ++-- .../quality/RememberVideoQualityPatch.kt | 2 +- .../speed/custom/CustomPlaybackSpeedPatch.kt | 12 +++---- .../video/speed/custom/Fingerprints.kt | 2 +- .../youtube/video/videoid/Fingerprints.kt | 4 +-- .../youtube/video/videoid/VideoIdPatch.kt | 4 +-- .../kotlin/app/revanced/util/BytecodeUtils.kt | 2 +- 194 files changed, 654 insertions(+), 600 deletions(-) diff --git a/patches/src/main/kotlin/app/revanced/patches/all/misc/resources/AddResourcesPatch.kt b/patches/src/main/kotlin/app/revanced/patches/all/misc/resources/AddResourcesPatch.kt index cc94674e8..a77dd364f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/all/misc/resources/AddResourcesPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/all/misc/resources/AddResourcesPatch.kt @@ -366,7 +366,7 @@ val addResourcesPatch = resourcePatch( it.writeText("\n\n") } } - + document("res/$value/$resourceFileName.xml").let { document -> // Save the target node here as well diff --git a/patches/src/main/kotlin/app/revanced/patches/angulus/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/angulus/ads/Fingerprints.kt index 282441aaf..66ed3fc67 100644 --- a/patches/src/main/kotlin/app/revanced/patches/angulus/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/angulus/ads/Fingerprints.kt @@ -12,7 +12,7 @@ import com.android.tools.smali.dexlib2.AccessFlags // dailyAdResetCount // MeasurementPrefs -// This fingerprint targets a method that returns the daily measurement count. +// This targets a method that returns the daily measurement count. // This method is used to determine if the user has reached the daily limit of measurements. internal val BytecodePatchContext.getDailyMeasurementCountMethod by gettingFirstMutableMethodDeclaratively("dailyMeasurementCount") { accessFlags(AccessFlags.PRIVATE) diff --git a/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt index 98250799f..43bd86dbd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.crunchyroll.ads -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke +import app.revanced.patcher.patch.BytecodePatchContext -internal val videoUrlReadyToStringMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.videoUrlReadyToStringMethodMatch by composingFirstMethod { instructions("VideoUrlReady(url="(), ", enableAds="()) } diff --git a/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/HideAdsPatch.kt index 51b4322c1..718d9fdc6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/HideAdsPatch.kt @@ -19,7 +19,7 @@ val hideAdsPatch = bytecodePatch("Hide ads") { apply { // Get obfuscated "enableAds" field from toString method. val enableAdsField = videoUrlReadyToStringMethodMatch.method.apply { - val stringIndex = videoUrlReadyToStringMethodMatch.indices.last() + val stringIndex = videoUrlReadyToStringMethodMatch[-1] val fieldIndex = indexOfFirstInstruction(stringIndex, Opcode.IGET_BOOLEAN) getInstruction(fieldIndex).getReference()!! diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt index 0143f4f3c..b83834c67 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/DisableAdsPatch.kt @@ -3,6 +3,7 @@ package app.revanced.patches.duolingo.ad import app.revanced.patcher.classDef import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction +import app.revanced.patcher.immutableClassDef import app.revanced.patcher.patch.bytecodePatch import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @@ -19,16 +20,16 @@ val disableAdsPatch = bytecodePatch("Disable ads") { // SharedPreferences has a debug boolean value with key "disable_ads", which maps to "DebugCategory.DISABLE_ADS". // // MonetizationDebugSettings seems to be the most general setting to work fine. - initializeMonetizationDebugSettingsMethodMatch.match( - monetizationDebugSettingsToStringMethod.classDef, - ).method.apply { - val insertIndex = initializeMonetizationDebugSettingsMethodMatch.indices.first() - val register = getInstruction(insertIndex).registerA + monetizationDebugSettingsToStringMethod.immutableClassDef.initializeMonetizationDebugSettingsMethodMatch.let { + it.method.apply { + val insertIndex = it[0] + val register = getInstruction(insertIndex).registerA - addInstructions( - insertIndex, - "const/4 v$register, 0x1", - ) + addInstructions( + insertIndex, + "const/4 v$register, 0x1", + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/Fingerprints.kt index 20b047f9f..6d0cebeb2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/ad/Fingerprints.kt @@ -4,11 +4,12 @@ import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef -internal val initializeMonetizationDebugSettingsMethodMatch = firstMethodComposite { +internal val ClassDef.initializeMonetizationDebugSettingsMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) returnType("V") - // Parameters have not been reliable for fingerprinting between versions. + // Parameters have not been reliable for matching between versions. opcodes(Opcode.IPUT_BOOLEAN) } diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/EnableDebugMenuPatch.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/EnableDebugMenuPatch.kt index 56892c0fb..0d9681e8f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/EnableDebugMenuPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/EnableDebugMenuPatch.kt @@ -3,6 +3,7 @@ package app.revanced.patches.duolingo.debug import app.revanced.patcher.classDef import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.getInstruction +import app.revanced.patcher.immutableClassDef import app.revanced.patcher.patch.bytecodePatch import app.revanced.util.returnEarly import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -19,10 +20,8 @@ val enableDebugMenuPatch = bytecodePatch( debugCategoryAllowOnReleaseBuildsMethod.returnEarly(true) // Change build config debug build flag. - buildConfigProviderConstructorMethodMatch.match( - buildConfigProviderToStringMethod.classDef, - ).let { - val index = it.indices.first() + buildConfigProviderToStringMethod.immutableClassDef.buildConfigProviderConstructorMethodMatch.let { + val index = it[0] val register = it.method.getInstruction(index).registerA it.method.addInstruction(index + 1, "const/4 v$register, 0x1") diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/Fingerprints.kt index 312333ec5..a92b68890 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/debug/Fingerprints.kt @@ -4,6 +4,7 @@ import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef internal val BytecodePatchContext.debugCategoryAllowOnReleaseBuildsMethod by gettingFirstMutableMethodDeclaratively { name("getAllowOnReleaseBuilds") @@ -12,8 +13,7 @@ internal val BytecodePatchContext.debugCategoryAllowOnReleaseBuildsMethod by get parameterTypes() } -internal val buildConfigProviderConstructorMethodMatch = firstMethodComposite { - +internal val ClassDef.buildConfigProviderConstructorMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameterTypes() opcodes(Opcode.CONST_4) diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/Fingerprints.kt index abdd634eb..da434e0fe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/Fingerprints.kt @@ -4,8 +4,9 @@ import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef -internal val initializeEnergyConfigMethodMatch = firstMethodComposite { +internal val ClassDef.initializeEnergyConfigMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes(Opcode.RETURN_VOID) } diff --git a/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/SkipEnergyRechargeAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/SkipEnergyRechargeAdsPatch.kt index c8e16b332..cb7be5566 100644 --- a/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/SkipEnergyRechargeAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/duolingo/energy/SkipEnergyRechargeAdsPatch.kt @@ -2,6 +2,7 @@ package app.revanced.patches.duolingo.energy import app.revanced.patcher.classDef import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.immutableClassDef import app.revanced.patcher.patch.bytecodePatch import app.revanced.util.findFieldFromToString @@ -13,17 +14,19 @@ val skipEnergyRechargeAdsPatch = bytecodePatch( compatibleWith("com.duolingo") apply { - initializeEnergyConfigMethodMatch.match(energyConfigToStringMethod.classDef).method.apply { - val energyField = energyConfigToStringMethod.findFieldFromToString("energy=") - val insertIndex = initializeEnergyConfigMethodMatch.indices.first() // TODO + energyConfigToStringMethod.immutableClassDef.initializeEnergyConfigMethodMatch.let { + it.method.apply { + val energyField = energyConfigToStringMethod.findFieldFromToString("energy=") + val insertIndex = it[0] - addInstructions( - insertIndex, - """ + addInstructions( + insertIndex, + """ const/16 v0, 99 iput v0, p0, $energyField """, - ) + ) + } } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/Fingerprints.kt index 3ec53872b..bc75d4eb8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/Fingerprints.kt @@ -30,7 +30,7 @@ internal val BytecodePatchContext.getSponsoredDataModelTemplateMethod by getting Opcode.RETURN_OBJECT, ) } -internal val getStoryVisibilityMethodMatch = firstMethodComposite("This should not be called for base class object") { +internal val BytecodePatchContext.getStoryVisibilityMethodMatch by composingFirstMethod("This should not be called for base class object") { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returnType("Ljava/lang/String;") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt index 92ab63516..8a2647eb5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/facebook/ads/mainfeed/HideSponsoredStoriesPatch.kt @@ -64,7 +64,7 @@ val hideSponsoredStoriesPatch = bytecodePatch("Hide 'Sponsored Stories'") { // Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value. // If so, hide the story by setting the visibility to StoryVisibility.GONE. getStoryVisibilityMethodMatch.method.addInstructionsWithLabels( - getStoryVisibilityMethodMatch.indices.first(), + getStoryVisibilityMethodMatch[0], """ instance-of v0, p0, $graphQlStoryClassDescriptor if-eqz v0, :resume_normal diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/EnableCustomTabsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/EnableCustomTabsPatch.kt index e09afa967..a095f0d74 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/EnableCustomTabsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/EnableCustomTabsPatch.kt @@ -14,7 +14,7 @@ val enableCustomTabsPatch = bytecodePatch( apply { launchCustomTabMethodMatch.method.apply { - val checkIndex = launchCustomTabMethodMatch.indices.last() + 1 + val checkIndex = launchCustomTabMethodMatch[-1] + 1 val register = getInstruction(checkIndex).registerA replaceInstruction(checkIndex, "const/4 v$register, 0x1") diff --git a/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/Fingerprints.kt index 74ffbb3e8..9e387f898 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlenews/customtabs/Fingerprints.kt @@ -1,13 +1,14 @@ package app.revanced.patches.googlenews.customtabs import app.revanced.patcher.accessFlags +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.definingClass -import app.revanced.patcher.firstMethodComposite import app.revanced.patcher.opcodes +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val launchCustomTabMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.launchCustomTabMethodMatch by composingFirstMethod { definingClass { endsWith("CustomTabsArticleLauncher;") } accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/Fingerprints.kt index 7b2e615be..219574f1c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/Fingerprints.kt @@ -1,8 +1,9 @@ package app.revanced.patches.googlerecorder.restrictions import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext -internal val onApplicationCreateMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.onApplicationCreateMethodMatch by composingFirstMethod { name("onCreate") definingClass { endsWith("RecorderApplication") } instructions("com.google.android.feature.PIXEL_2017_EXPERIENCE"()) diff --git a/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt b/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt index 8c65e1194..ee67ea3ce 100644 --- a/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt +++ b/patches/src/main/kotlin/app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions.kt @@ -14,7 +14,7 @@ val removeDeviceRestrictionsPatch = bytecodePatch( compatibleWith("com.google.android.apps.recorder") apply { - val featureStringIndex = onApplicationCreateMethodMatch.indices.first() + val featureStringIndex = onApplicationCreateMethodMatch[0] onApplicationCreateMethodMatch.method.apply { // Remove check for device restrictions. diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/explore/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/explore/Fingerprints.kt index cfaaa2604..a9b705dd4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/explore/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/explore/Fingerprints.kt @@ -1,11 +1,12 @@ package app.revanced.patches.instagram.hide.explore -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke import app.revanced.patcher.name +import app.revanced.patcher.patch.BytecodePatchContext -internal val exploreResponseJsonParserMethodMatch = firstMethodComposite("ExploreTopicalFeedResponse") { +internal val BytecodePatchContext.exploreResponseJsonParserMethodMatch by composingFirstMethod("ExploreTopicalFeedResponse") { name("parseFromJson") instructions("sectional_items"()) } diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/explore/HideExploreFeed.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/explore/HideExploreFeed.kt index b8789fc4d..dbab25ba4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/explore/HideExploreFeed.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/explore/HideExploreFeed.kt @@ -15,7 +15,7 @@ val hideExploreFeedPatch = bytecodePatch( apply { exploreResponseJsonParserMethodMatch.method.apply { - val targetStringIndex = exploreResponseJsonParserMethodMatch.indices.first() + val targetStringIndex = exploreResponseJsonParserMethodMatch[0] val targetStringRegister = getInstruction(targetStringIndex).registerA replaceInstruction(targetStringIndex, "const-string v$targetStringRegister, \"BOGUS\"") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/stories/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/stories/Fingerprints.kt index d5609e89a..3c9e11833 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/stories/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/stories/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.instagram.hide.stories import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val getOrCreateAvatarViewMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.getOrCreateAvatarViewMethodMatch by composingFirstMethod { definingClass("Lcom/instagram/reels/ui/views/reelavatar/RecyclerReelAvatarView;") parameterTypes() returnType("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/stories/HideStories.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/stories/HideStories.kt index 51bc3e8d6..fed889d77 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/stories/HideStories.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/stories/HideStories.kt @@ -13,7 +13,7 @@ val hideStoriesFromHomePatch = bytecodePatch( apply { getOrCreateAvatarViewMethodMatch.let { - val addStoryEndIndex = it.indices.last() + val addStoryEndIndex = it[-1] // Remove addView of Story. it.method.removeInstruction(addStoryEndIndex) diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/Fingerprints.kt index 5093f7aba..df3c70678 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/Fingerprints.kt @@ -1,8 +1,9 @@ package app.revanced.patches.instagram.hide.suggestions -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.unorderedAllOf internal val FEED_ITEM_KEYS_TO_BE_HIDDEN = arrayOf( @@ -15,7 +16,7 @@ internal val FEED_ITEM_KEYS_TO_BE_HIDDEN = arrayOf( "suggested_users", ) -internal val feedItemParseFromJsonMethodMatch = firstMethodComposite("FeedItem") { +internal val BytecodePatchContext.feedItemParseFromJsonMethodMatch by composingFirstMethod("FeedItem") { instructions( predicates = unorderedAllOf( predicates = diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/HideSuggestedContent.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/HideSuggestedContent.kt index d9e2b7d59..f82335e18 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/HideSuggestedContent.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/hide/suggestions/HideSuggestedContent.kt @@ -15,7 +15,7 @@ val hideSuggestedContentPatch = bytecodePatch( apply { feedItemParseFromJsonMethodMatch.method.apply { - feedItemParseFromJsonMethodMatch.indices.forEach { targetStringIndex -> + feedItemParseFromJsonMethodMatch.indices[0].forEach { targetStringIndex -> val targetStringRegister = getInstruction(targetStringIndex).registerA replaceInstruction(targetStringIndex, "const-string v$targetStringRegister, \"BOGUS\"") diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/devmenu/EnableDeveloperMenuPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/devmenu/EnableDeveloperMenuPatch.kt index 13825e54e..1d44ac825 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/devmenu/EnableDeveloperMenuPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/devmenu/EnableDeveloperMenuPatch.kt @@ -21,7 +21,7 @@ val enableDeveloperMenuPatch = bytecodePatch( apply { clearNotificationReceiverMethodMatch.let { - val stringIndex = it.indices.first() + val stringIndex = it[0] it.immutableMethod.indexOfFirstInstructionReversedOrThrow(stringIndex) { val reference = methodReference diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/devmenu/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/devmenu/Fingerprints.kt index 1ba3c4fd5..13d455eff 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/devmenu/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/devmenu/Fingerprints.kt @@ -1,8 +1,9 @@ package app.revanced.patches.instagram.misc.devmenu import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext -internal val clearNotificationReceiverMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.clearNotificationReceiverMethodMatch by composingFirstMethod { name("onReceive") definingClass("Lcom/instagram/notifications/push/ClearNotificationReceiver;") instructions("NOTIFICATION_DISMISSED"()) diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/links/Fingerprint.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/links/Fingerprint.kt index 3a06dfec7..676a94241 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/links/Fingerprint.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/links/Fingerprint.kt @@ -1,13 +1,14 @@ package app.revanced.patches.instagram.misc.links -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.returnType internal const val TARGET_STRING = "Tracking.ARG_CLICK_SOURCE" -internal val inAppBrowserFunctionMethodMatch = firstMethodComposite("TrackingInfo.ARG_MODULE_NAME") { +internal val BytecodePatchContext.inAppBrowserFunctionMethodMatch by composingFirstMethod("TrackingInfo.ARG_MODULE_NAME") { instructions(TARGET_STRING()) returnType("Z") } diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/links/OpenLinksExternallyPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/links/OpenLinksExternallyPatch.kt index b4acecc16..f97fde3e4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/links/OpenLinksExternallyPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/links/OpenLinksExternallyPatch.kt @@ -23,7 +23,7 @@ val openLinksExternallyPatch = bytecodePatch( apply { inAppBrowserFunctionMethodMatch.let { - val stringMatchIndex = it.indices.first() + val stringMatchIndex = it[0] it.method.apply { val urlResultObjIndex = indexOfFirstInstructionOrThrow( diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/share/EditShareLinksPatch.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/share/EditShareLinksPatch.kt index 812bae23c..5f31a6034 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/share/EditShareLinksPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/share/EditShareLinksPatch.kt @@ -18,7 +18,7 @@ internal fun BytecodePatchContext.editShareLinksPatch(block: MutableMethod.(inde for (match in methodsToPatch) { match.method.apply { val putSharingUrlIndex = indexOfFirstInstruction( - match.indices.first(), + match[0], Opcode.IPUT_OBJECT, ) diff --git a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/share/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/share/Fingerprints.kt index 50a13daf6..23b82882e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/instagram/misc/share/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/instagram/misc/share/Fingerprints.kt @@ -1,32 +1,33 @@ package app.revanced.patches.instagram.misc.share -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke import app.revanced.patcher.name +import app.revanced.patcher.patch.BytecodePatchContext -internal val permalinkResponseJsonParserMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.permalinkResponseJsonParserMethodMatch by composingFirstMethod( "PermalinkResponse", ) { name("parseFromJson") instructions("permalink"()) } -internal val storyUrlResponseJsonParserMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.storyUrlResponseJsonParserMethodMatch by composingFirstMethod( "StoryItemUrlResponse", ) { name("parseFromJson") instructions("story_item_to_share_url"()) } -internal val profileUrlResponseJsonParserMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.profileUrlResponseJsonParserMethodMatch by composingFirstMethod( "ProfileUrlResponse", ) { name("parseFromJson") instructions("profile_to_share_url"()) } -internal val liveUrlResponseJsonParserMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.liveUrlResponseJsonParserMethodMatch by composingFirstMethod( "LiveItemLinkUrlResponse", ) { name("parseFromJson") diff --git a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/version/DisableVersionCheckPatch.kt b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/version/DisableVersionCheckPatch.kt index 86916848c..114765540 100644 --- a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/version/DisableVersionCheckPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/version/DisableVersionCheckPatch.kt @@ -11,7 +11,7 @@ val disableVersionCheckPatch = bytecodePatch( compatibleWith("com.adobe.lrmobile"("9.3.0")) apply { - val igetIndex = refreshRemoteConfigurationMethodMatch.indices.last() + val igetIndex = refreshRemoteConfigurationMethodMatch[-1] // This value represents the server command to clear all version restrictions. val statusForceReset = "-0x2" diff --git a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/version/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/version/Fingerprints.kt index 3921d0e06..f8be83517 100644 --- a/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/version/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/lightroom/misc/version/Fingerprints.kt @@ -1,12 +1,13 @@ package app.revanced.patches.lightroom.misc.version import app.revanced.patcher.accessFlags -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.opcodes +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val refreshRemoteConfigurationMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.refreshRemoteConfigurationMethodMatch by composingFirstMethod( "com.adobe.lrmobile.denylisted_version_set_key", "com.adobe.lrmobile.app_min_version_key", ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt index 96753309a..9901339b3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/Fingerprints.kt @@ -1,20 +1,21 @@ package app.revanced.patches.messenger.metaai import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val getMobileConfigBoolMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.getMobileConfigBoolMethodMatch by composingFirstMethod { parameterTypes("J") returnType("Z") opcodes(Opcode.RETURN) custom { "Lcom/facebook/mobileconfig/factory/MobileConfigUnsafeContext;" in immutableClassDef.interfaces } } -internal val metaAIKillSwitchCheckMethodMatch = firstMethodComposite("SearchAiagentImplementationsKillSwitch") { +internal val BytecodePatchContext.metaAIKillSwitchCheckMethodMatch by composingFirstMethod("SearchAiagentImplementationsKillSwitch") { opcodes(Opcode.CONST_WIDE) } -internal val extensionMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.extensionMethodMatch by composingFirstMethod { name(EXTENSION_METHOD_NAME) definingClass(EXTENSION_CLASS_DESCRIPTOR) instructions("REPLACED_BY_PATCH"()) diff --git a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt index aaa490979..7b0d74908 100644 --- a/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/messenger/metaai/RemoveMetaAIPatch.kt @@ -22,7 +22,7 @@ val removeMetaAIPatch = bytecodePatch( apply { getMobileConfigBoolMethodMatch.let { - val returnIndex = it.indices.first() + val returnIndex = it[0] val returnRegister = it.method.getInstruction(returnIndex).registerA it.method.addInstructions( @@ -36,13 +36,13 @@ val removeMetaAIPatch = bytecodePatch( // Extract the common starting digits of Meta AI flag IDs from a flag found in code. val relevantDigits = metaAIKillSwitchCheckMethodMatch.let { - it.method.getInstruction(it.indices.first()).wideLiteral + it.method.getInstruction(it[0]).wideLiteral }.toString().substring(0, 7) // Replace placeholder in the extension method. extensionMethodMatch.let { it.method.replaceInstruction( - it.indices.first(), + it[0], "const-string v1, \"$relevantDigits\"", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/Fingerprints.kt index 9264dd37a..6187e2215 100644 --- a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.mifitness.misc.locale import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val syncBluetoothLanguageMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.syncBluetoothLanguageMethodMatch by composingFirstMethod { name("syncBluetoothLanguage") definingClass("Lcom/xiaomi/fitness/devicesettings/DeviceSettingsSyncer") opcodes(Opcode.MOVE_RESULT_OBJECT) diff --git a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt index 95c41208d..1e65344c5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt @@ -17,7 +17,7 @@ val forceEnglishLocalePatch = bytecodePatch( apply { syncBluetoothLanguageMethodMatch.let { - val resolvePhoneLocaleInstruction = it.indices.first() + val resolvePhoneLocaleInstruction = it[0] val registerIndexToUpdate = it.method.getInstruction(resolvePhoneLocaleInstruction).registerA it.method.replaceInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/ad/video/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/ad/video/Fingerprints.kt index 41573b7e5..1d2f125f0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/ad/video/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/ad/video/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.music.ad.video -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.opcodes +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val showVideoAdsParentMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.showVideoAdsParentMethodMatch by composingFirstMethod( "maybeRegenerateCpnAndStatsClient called unexpectedly, but no error.", ) { opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/ad/video/HideVideoAds.kt b/patches/src/main/kotlin/app/revanced/patches/music/ad/video/HideVideoAds.kt index 5b1366cdc..410a6aff3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/ad/video/HideVideoAds.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/ad/video/HideVideoAds.kt @@ -37,7 +37,7 @@ val hideMusicVideoAdsPatch = bytecodePatch( ) navigate(showVideoAdsParentMethodMatch.immutableMethod) - .to(showVideoAdsParentMethodMatch.indices.first() + 1) + .to(showVideoAdsParentMethodMatch[0] + 1) .stop() .addInstructions( 0, diff --git a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/Fingerprints.kt index b5dfe5703..704a2c88a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.music.interaction.permanentrepeat import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val repeatTrackMethodMatch = firstMethodComposite("w_st") { +internal val BytecodePatchContext.repeatTrackMethodMatch by composingFirstMethod("w_st") { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("L", "L") @@ -14,6 +15,6 @@ internal val repeatTrackMethodMatch = firstMethodComposite("w_st") { Opcode.SGET_OBJECT, Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT, - Opcode.IF_NEZ + Opcode.IF_NEZ, ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt index 9f6a50e37..aa8a0449d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/interaction/permanentrepeat/PermanentRepeatPatch.kt @@ -40,7 +40,7 @@ val permanentRepeatPatch = bytecodePatch( ) repeatTrackMethodMatch.method.apply { - val startIndex = repeatTrackMethodMatch.indices.last() + val startIndex = repeatTrackMethodMatch[-1] val repeatIndex = startIndex + 1 // Start index is at a branch, but the same diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/Fingerprints.kt index ca113c236..9db60e4af 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/Fingerprints.kt @@ -18,7 +18,7 @@ internal val BytecodePatchContext.playerOverlayChipMethod by gettingFirstMutable instructions(playerOverlayChip()) } -internal val historyMenuItemMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.historyMenuItemMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/view/Menu;") @@ -32,7 +32,7 @@ internal val historyMenuItemMethodMatch = firstMethodComposite { } } -internal val historyMenuItemOfflineTabMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.historyMenuItemOfflineTabMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/view/Menu;") @@ -40,9 +40,9 @@ internal val historyMenuItemOfflineTabMethodMatch = firstMethodComposite { Opcode.INVOKE_INTERFACE, Opcode.RETURN_VOID, ) - custom { - instructions.matchIndexed("literals", items = unorderedAllOf(historyMenuItem(), offlineSettingsMenuItem())) - } + + val match = indexedMatcher(items = unorderedAllOf(historyMenuItem(), offlineSettingsMenuItem())) + custom { match(instructions) } } internal val BytecodePatchContext.searchActionViewMethod by gettingFirstMutableMethodDeclaratively { diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/HideButtons.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/HideButtons.kt index cc858dab5..e6dd9e169 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/HideButtons.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/buttons/HideButtons.kt @@ -74,7 +74,7 @@ val hideButtonsPatch = bytecodePatch( historyMenuItemOfflineTabMethodMatch, ).forEach { match -> match.method.apply { - val targetIndex = match.indices.first() + val targetIndex = match[0] val targetRegister = getInstruction(targetIndex).registerD addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/Fingerprints.kt index 9d7fe75ca..00daa527d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.music.layout.compactheader import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.util.literal import com.android.tools.smali.dexlib2.Opcode -internal val chipCloudMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.chipCloudMethodMatch by composingFirstMethod { returnType("V") opcodes( Opcode.CONST, diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt index d56322c10..7bc195419 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt @@ -45,7 +45,7 @@ val hideCategoryBarPatch = bytecodePatch( chipCloud = ResourceType.LAYOUT["chip_cloud"] chipCloudMethodMatch.let { - val targetIndex = it.indices.last() + val targetIndex = it[-1] val targetRegister = it.method.getInstruction(targetIndex).registerA it.method.addInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColor.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColor.kt index 138fc99a0..0b3153aa1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColor.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/ChangeMiniplayerColor.kt @@ -50,8 +50,8 @@ val changeMiniplayerColorPatch = bytecodePatch( SwitchPreference("revanced_music_change_miniplayer_color"), ) - switchToggleColorMethodMatch.match(miniPlayerConstructorMethodMatch.immutableClassDef).let { - val relativeIndex = it.indices.last() + 1 + miniPlayerConstructorMethodMatch.immutableClassDef.switchToggleColorMethodMatch.let { + val relativeIndex = it[-1] + 1 val invokeVirtualIndex = it.method.indexOfFirstInstructionOrThrow( relativeIndex, diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/Fingerprints.kt index 95d32778a..5a3ee206e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/Fingerprints.kt @@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.ClassDef -internal val miniPlayerConstructorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.miniPlayerConstructorMethodMatch by composingFirstMethod { returnType("V") instructions( ResourceType.ID("mpp_player_bottom_sheet"), @@ -18,7 +18,7 @@ internal val miniPlayerConstructorMethodMatch = firstMethodComposite { /** * Matches to the class found in [miniPlayerConstructorMethodMatch]. */ -internal val switchToggleColorMethodMatch = firstMethodComposite { +internal val ClassDef.switchToggleColorMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returnType("V") parameterTypes("L", "J") diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/navigationbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/navigationbar/Fingerprints.kt index de0949c06..00984d1e0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/navigationbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/navigationbar/Fingerprints.kt @@ -1,6 +1,7 @@ package app.revanced.patches.music.layout.navigationbar import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.util.containsLiteralInstruction import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction @@ -9,7 +10,7 @@ import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal val tabLayoutTextMethodMatch = firstMethodComposite("FEmusic_search") { +internal val BytecodePatchContext.tabLayoutTextMethodMatch by composingFirstMethod("FEmusic_search") { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/navigationbar/NavigationBarPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/navigationbar/NavigationBarPatch.kt index aaa61566b..f977920b3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/navigationbar/NavigationBarPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/navigationbar/NavigationBarPatch.kt @@ -100,7 +100,7 @@ val navigationBarPatch = bytecodePatch( ) // Set navigation enum and hide navigation buttons. - val enumIndex = tabLayoutTextMethodMatch.indices.first() + 3 + val enumIndex = tabLayoutTextMethodMatch[0] + 3 val enumRegister = getInstruction(enumIndex).registerA val insertEnumIndex = indexOfFirstInstructionOrThrow(Opcode.AND_INT_LIT8) - 2 diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/Fingerprints.kt index d5ae2ae65..bfa49bdeb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/Fingerprints.kt @@ -5,9 +5,9 @@ import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val hideGetPremiumMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.hideGetPremiumMethodMatch by composingFirstMethod( "FEmusic_history", - "FEmusic_offline" + "FEmusic_offline", ) { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") diff --git a/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt index 9348dbe9a..d6f1c0092 100644 --- a/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt @@ -41,7 +41,7 @@ val hideGetMusicPremiumPatch = bytecodePatch( ) hideGetPremiumMethodMatch.let { - val insertIndex = it.indices.last() + val insertIndex = it[-1] it.method.apply { val setVisibilityInstruction = getInstruction(insertIndex) diff --git a/patches/src/main/kotlin/app/revanced/patches/nunl/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/nunl/ads/Fingerprints.kt index 3b9652a35..173b849e0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/nunl/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/nunl/ads/Fingerprints.kt @@ -14,7 +14,7 @@ import com.android.tools.smali.dexlib2.Opcode val BytecodePatchContext.jwPlayerC accessFlags(AccessFlags.PUBLIC) } -internal val screenMapperMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.screenMapperMethodMatch by composingFirstMethod { name("map") definingClass("Lnl/nu/android/bff/data/mappers/ScreenMapper;") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) @@ -27,7 +27,7 @@ internal val screenMapperMethodMatch = firstMethodComposite { ) } -internal val nextPageRepositoryImplMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.nextPageRepositoryImplMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returnType("Lnl/nu/android/bff/domain/models/Page;") parameterTypes("Lnl/nu/performance/api/client/PacResponse;", "Ljava/lang/String;") diff --git a/patches/src/main/kotlin/app/revanced/patches/nunl/ads/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/nunl/ads/HideAdsPatch.kt index 56296c9c0..b2eea685c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/nunl/ads/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/nunl/ads/HideAdsPatch.kt @@ -27,7 +27,7 @@ val hideAdsPatch = bytecodePatch( // Filter injected content from API calls out of lists. arrayOf(screenMapperMethodMatch, nextPageRepositoryImplMethodMatch).forEach { match -> // Index of instruction moving result of BlockPage;->getBlocks(...). - val moveGetBlocksResultObjectIndex = match.indices.first() + val moveGetBlocksResultObjectIndex = match[0] val moveInstruction = match.method.getInstruction(moveGetBlocksResultObjectIndex) val listRegister = moveInstruction.registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/Fingerprints.kt index 23074c935..f00827eac 100644 --- a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/Fingerprints.kt @@ -1,11 +1,12 @@ package app.revanced.patches.photomath.detection.signature -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val checkSignatureMethodMatch = firstMethodComposite("SHA") { +internal val BytecodePatchContext.checkSignatureMethodMatch by composingFirstMethod("SHA") { instructions( Opcode.CONST_STRING(), Opcode.INVOKE_STATIC(), diff --git a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt index 5114f034f..4bdeaf882 100644 --- a/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/photomath/detection/signature/SignatureDetectionPatch.kt @@ -10,7 +10,7 @@ val signatureDetectionPatch = bytecodePatch( description = "Disables detection of incorrect signature.", ) { apply { - val replacementIndex = checkSignatureMethodMatch.indices.last() + val replacementIndex = checkSignatureMethodMatch[-1] val checkRegister = checkSignatureMethodMatch.method.getInstruction(replacementIndex) .registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/Fingerprints.kt index 0ecc20d44..b68dda1e5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/Fingerprints.kt @@ -4,14 +4,14 @@ import app.revanced.patcher.* import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val enableSplitTunnelingUiMethodMatch = firstMethodComposite("currentModeAppNames") { +internal val BytecodePatchContext.enableSplitTunnelingUiMethodMatch by composingFirstMethod("currentModeAppNames") { opcodes( Opcode.MOVE_OBJECT, Opcode.MOVE_FROM16, - Opcode.INVOKE_DIRECT_RANGE + Opcode.INVOKE_DIRECT_RANGE, ) } internal val BytecodePatchContext.initializeSplitTunnelingSettingsUIMethod by gettingFirstMutableMethodDeclaratively { name("applyRestrictions") -} \ No newline at end of file +} diff --git a/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunneling.kt b/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunneling.kt index 9839de45c..79bc78ec1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunneling.kt +++ b/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunneling.kt @@ -15,7 +15,7 @@ val unlockSplitTunnelingPatch = bytecodePatch("Unlock split tunneling") { apply { enableSplitTunnelingUiMethodMatch.let { - val registerIndex = it.indices.last() - 1 + val registerIndex = it[-1] - 1 val register = it.method.getInstruction(registerIndex).registerA it.method.replaceInstruction(registerIndex, "const/4 v$register, 0x0") } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/SpoofClientPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/SpoofClientPatch.kt index 8306b362f..a4148df75 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/SpoofClientPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/SpoofClientPatch.kt @@ -15,7 +15,7 @@ fun spoofClientPatch( redirectUri: String, block: BytecodePatchBuilder.(Option) -> Unit = {}, ) = bytecodePatch( - name = "Spoof client", // TODO + name = "Spoof client", description = "Restores functionality of the app by using custom client ID.", ) { block( @@ -23,9 +23,9 @@ fun spoofClientPatch( name = "OAuth client ID", values = null, description = "The Reddit OAuth client ID. " + - "You can get your client ID from https://www.reddit.com/prefs/apps. " + - "The application type has to be \"Installed app\" " + - "and the redirect URI has to be set to \"$redirectUri\".", + "You can get your client ID from https://www.reddit.com/prefs/apps. " + + "The application type has to be \"Installed app\" " + + "and the redirect URI has to be set to \"$redirectUri\".", required = true, ), ) diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/Fingerprints.kt index 9bbb82557..07fed4280 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/Fingerprints.kt @@ -1,16 +1,17 @@ package app.revanced.patches.reddit.customclients.baconreader.api -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke +import app.revanced.patcher.patch.BytecodePatchContext -internal val getAuthorizationUrlMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.getAuthorizationUrlMethodMatch by composingFirstMethod { instructions("client_id=zACVn0dSFGdWqQ"()) } -internal val requestTokenMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.requestTokenMethodMatch by composingFirstMethod { instructions( "zACVn0dSFGdWqQ"(), - "kDm2tYpu9DqyWFFyPlNcXGEni4k"(String::contains) + "kDm2tYpu9DqyWFFyPlNcXGEni4k"(String::contains), ) -} \ No newline at end of file +} diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch.kt index 8e753ee4e..5dba2ef80 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/baconreader/api/SpoofClientPatch.kt @@ -1,6 +1,6 @@ package app.revanced.patches.reddit.customclients.baconreader.api -import app.revanced.patcher.MatchBuilder +import app.revanced.patcher.Match import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.extensions.replaceInstruction import app.revanced.patches.reddit.customclients.spoofClientPatch @@ -11,7 +11,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://baconreader.com/au dependsOn( // Redirects from SSL to WWW domain are bugged causing auth problems. // Manually rewrite the URLs to fix this. - replaceStringPatch("ssl.reddit.com", "www.reddit.com") + replaceStringPatch("ssl.reddit.com", "www.reddit.com"), ) compatibleWith( @@ -22,8 +22,8 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://baconreader.com/au val clientId by clientIdOption apply { - fun MatchBuilder.patch(replacementString: String) { - val clientIdIndex = indices.first() + fun Match.patch(replacementString: String) { + val clientIdIndex = get(0) val clientIdRegister = method.getInstruction(clientIdIndex).registerA method.replaceInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/Fingerprints.kt index 126bc84c8..b8cdd1d63 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/Fingerprints.kt @@ -1,12 +1,13 @@ package app.revanced.patches.reddit.customclients.boostforreddit.fix.downloads -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke +import app.revanced.patcher.patch.BytecodePatchContext -internal val downloadAudioMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.downloadAudioMethodMatch by composingFirstMethod { instructions( "/DASH_audio.mp4"(), - "/audio"() + "/audio"(), ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/FixAudioMissingInDownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/FixAudioMissingInDownloadsPatch.kt index 7483aff27..518700ed1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/FixAudioMissingInDownloadsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/boostforreddit/fix/downloads/FixAudioMissingInDownloadsPatch.kt @@ -18,7 +18,7 @@ val fixMissingAudioInVideoDownloadsPatch = bytecodePatch( "/DASH_AUDIO_64.mp4", ) - downloadAudioMethodMatch.indices.forEachIndexed { index, i -> + downloadAudioMethodMatch.indices[0].forEachIndexed { index, i -> val replacement = endpointReplacements[i] val register = downloadAudioMethodMatch.method.getInstruction(index).registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/Fingerprints.kt index ac3c389a4..3850b2967 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/redditisfun/api/Fingerprints.kt @@ -6,17 +6,17 @@ import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val basicAuthorizationMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.basicAuthorizationMethodMatch by composingFirstMethod { instructions( "yyOCBp.RHJhDKd"(), - "fJOxVwBUyo*=f:.() -> Int, ) = method.apply { - val replacementIndex = indices.getReplacementIndex() + val replacementIndex = indices[0].getReplacementIndex() val clientIdRegister = getInstruction(replacementIndex).registerA replaceInstruction(replacementIndex, "const-string v$clientIdRegister, \"$string\"") diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/Fingerprints.kt index 6b081e008..50c39b628 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/Fingerprints.kt @@ -1,28 +1,28 @@ package app.revanced.patches.reddit.customclients.relayforreddit.api +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.gettingFirstMutableMethodDeclaratively -import app.revanced.patcher.firstMethodComposite import app.revanced.patcher.instructions import app.revanced.patcher.invoke import app.revanced.patcher.parameterTypes import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode +import org.stringtemplate.v4.compiler.Bytecode - -internal fun baseClientIdMethod(string: String) = firstMethodComposite { +internal fun baseClientIdMethod(string: String) = composingFirstMethod { instructions( "dj-xCIZQYiLbEg"(), - string() + string(), ) } -internal val getLoggedInBearerTokenMethodMatch = baseClientIdMethod("authorization_code") +internal val BytecodePatchContext.getLoggedInBearerTokenMethodMatch by baseClientIdMethod("authorization_code") -internal val getLoggedOutBearerTokenMethodMatch = baseClientIdMethod("https://oauth.reddit.com/grants/installed_client") +internal val BytecodePatchContext.getLoggedOutBearerTokenMethodMatch by baseClientIdMethod("https://oauth.reddit.com/grants/installed_client") -internal val getRefreshTokenMethodMatch = baseClientIdMethod("refresh_token") +internal val BytecodePatchContext.getRefreshTokenMethodMatch by baseClientIdMethod("refresh_token") -internal val loginActivityClientIdMethodMatch = baseClientIdMethod("&duration=permanent") +internal val BytecodePatchContext.loginActivityClientIdMethodMatch by baseClientIdMethod("&duration=permanent") internal val BytecodePatchContext.redditCheckDisableAPIMethod by gettingFirstMutableMethodDeclaratively("Reddit Disabled") { instructions(Opcode.IF_EQZ()) diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/SpoofClientPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/SpoofClientPatch.kt index fa0f6fbf2..df4c381ad 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/SpoofClientPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/relayforreddit/api/SpoofClientPatch.kt @@ -28,7 +28,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "dbrady://relay") { client getLoggedOutBearerTokenMethodMatch, getRefreshTokenMethodMatch, ).forEach { match -> - val clientIdIndex = match.indices.first() + val clientIdIndex = match[0] val clientIdRegister = match.method.getInstruction(clientIdIndex).registerA match.method.replaceInstruction(clientIdIndex, "const-string v$clientIdRegister, \"$clientId\"") diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/detection/piracy/DisablePiracyDetectionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/detection/piracy/DisablePiracyDetectionPatch.kt index bd90bd127..e84f4cc9e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/detection/piracy/DisablePiracyDetectionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/detection/piracy/DisablePiracyDetectionPatch.kt @@ -8,7 +8,7 @@ val disablePiracyDetectionPatch = bytecodePatch( ) { apply { - // Do not throw an error if the fingerprint is not resolved. + // Do not throw an error if the method can't be found. // This is fine because new versions of the target app do not need this patch. detectPiracyMethodOrNull?.returnEarly() } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/Fingerprints.kt index 5ca6baf3c..1db407111 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/Fingerprints.kt @@ -1,17 +1,19 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.api -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.ClassDefComposing +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.gettingFirstMutableMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.string +import com.android.tools.smali.dexlib2.iface.ClassDef -internal val getAuthorizationStringMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.getAuthorizationStringMethodMatch by composingFirstMethod { instructions(string { startsWith("authorize.compact?client_id") }) } -internal val getBearerTokenMethodMatch = firstMethodComposite { +internal val ClassDef.getBearerTokenMethodMatch by ClassDefComposing.composingFirstMethod { instructions(string { startsWith("Basic") }) } @@ -19,6 +21,6 @@ internal val BytecodePatchContext.getUserAgentMethod by gettingFirstMutableMetho "android:com.laurencedawson.reddit_sync", ) -internal val imgurImageAPIMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.imgurImageAPIMethodMatch by composingFirstMethod { instructions("https://imgur-apiv3.p.rapidapi.com/3/image"()) } diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/SpoofClientPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/SpoofClientPatch.kt index 0d03b7210..4422cdc10 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/SpoofClientPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/api/SpoofClientPatch.kt @@ -18,7 +18,7 @@ val spoofClientPatch = spoofClientPatch( disablePiracyDetectionPatch, // Redirects from SSL to WWW domain are bugged causing auth problems. // Manually rewrite the URLs to fix this. - replaceStringPatch("ssl.reddit.com", "www.reddit.com") + replaceStringPatch("ssl.reddit.com", "www.reddit.com"), ) compatibleWith( @@ -32,11 +32,11 @@ val spoofClientPatch = spoofClientPatch( apply { // region Patch client id. - getBearerTokenMethodMatch.match(getAuthorizationStringMethodMatch.immutableClassDef).method.apply { + getAuthorizationStringMethodMatch.immutableClassDef.getBearerTokenMethodMatch.method.apply { val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8)) returnEarly("Basic $auth") - val occurrenceIndex = getAuthorizationStringMethodMatch.indices.first() + val occurrenceIndex = getAuthorizationStringMethodMatch[0] getAuthorizationStringMethodMatch.method.apply { val authorizationStringInstruction = getInstruction(occurrenceIndex) @@ -68,7 +68,7 @@ val spoofClientPatch = spoofClientPatch( // region Patch Imgur API URL. - val apiUrlIndex = imgurImageAPIMethodMatch.indices.first() + val apiUrlIndex = imgurImageAPIMethodMatch[0] imgurImageAPIMethodMatch.method.replaceInstruction( apiUrlIndex, "const-string v1, \"https://api.imgur.com/3/image\"", diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/redgifs/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/redgifs/Fingerprints.kt index 600a591fd..8938b850e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/redgifs/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/redgifs/Fingerprints.kt @@ -15,7 +15,7 @@ internal val BytecodePatchContext.createOkHttpClientMethod by gettingFirstMutabl returnType("V") parameterTypes() custom { - // There are four functions (each creating a client) defined in this file with very similar fingerprints. + // There are four functions (each creating a client) defined in this file with very similar methods. // We're looking for the one that only creates one object (the builder) and sets client options true // (thus never reloading the register with a 0). immutableClassDef.sourceFile == "OkHttpHelper.java" && instructions.count { diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/Fingerprints.kt index e9fa43f09..5aa03483d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/Fingerprints.kt @@ -1,39 +1,40 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.user import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags internal fun userEndpointMethodMatch( source: String, - accessFlags: Set? = null -) = firstMethodComposite { + accessFlags: Set? = null, +) = composingFirstMethod { instructions("u/"(String::contains)) custom { immutableClassDef.sourceFile == source } - accessFlags(*accessFlags?.toTypedArray() ?: return@firstMethodComposite) + accessFlags(*accessFlags?.toTypedArray() ?: return@composingFirstMethod) } -internal val oAuthFriendRequestMethodMatch = userEndpointMethodMatch( +internal val BytecodePatchContext.oAuthFriendRequestMethodMatch by userEndpointMethodMatch( "OAuthFriendRequest.java", ) -internal val oAuthUnfriendRequestMethodMatch = userEndpointMethodMatch( +internal val BytecodePatchContext.oAuthUnfriendRequestMethodMatch by userEndpointMethodMatch( "OAuthUnfriendRequest.java", ) -internal val oAuthUserIdRequestMethodMatch = userEndpointMethodMatch( +internal val BytecodePatchContext.oAuthUserIdRequestMethodMatch by userEndpointMethodMatch( "OAuthUserIdRequest.java", ) -internal val oAuthUserInfoRequestMethodMatch = userEndpointMethodMatch( +internal val BytecodePatchContext.oAuthUserInfoRequestMethodMatch by userEndpointMethodMatch( "OAuthUserInfoRequest.java", ) -internal val oAuthSubredditInfoRequestConstructorMethodMatch = userEndpointMethodMatch( +internal val BytecodePatchContext.oAuthSubredditInfoRequestConstructorMethodMatch by userEndpointMethodMatch( "OAuthSubredditInfoRequest.java", setOf(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR), ) -internal val oAuthSubredditInfoRequestHelperMethodMatch = userEndpointMethodMatch( +internal val BytecodePatchContext.oAuthSubredditInfoRequestHelperMethodMatch by userEndpointMethodMatch( "OAuthSubredditInfoRequest.java", setOf(AccessFlags.PRIVATE, AccessFlags.STATIC), ) diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatch.kt index 376191ba5..5c0dbf941 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/user/UseUserEndpointPatch.kt @@ -28,7 +28,7 @@ val useUserEndpointPatch = bytecodePatch( oAuthUserIdRequestMethodMatch, oAuthUserInfoRequestMethodMatch, ).map { match -> - match.indices.first() to match.method + match[0] to match.method }.forEach { (userPathStringIndex, method) -> val userPathStringInstruction = method.getInstruction(userPathStringIndex) diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/Fingerprints.kt index a34ef7b71..7f11752ae 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.reddit.customclients.sync.syncforreddit.fix.video import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val parseRedditVideoNetworkResponseMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.parseRedditVideoNetworkResponseMethodMatch by composingFirstMethod { name("parseNetworkResponse") opcodes( Opcode.NEW_INSTANCE, diff --git a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/FixVideoDownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/FixVideoDownloadsPatch.kt index aa0fe5389..0baae8ab9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/FixVideoDownloadsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/reddit/customclients/sync/syncforreddit/fix/video/FixVideoDownloadsPatch.kt @@ -24,7 +24,7 @@ val fixVideoDownloadsPatch = bytecodePatch( ) apply { - val scanResult = parseRedditVideoNetworkResponseMethodMatch.indices + val scanResult = parseRedditVideoNetworkResponseMethodMatch.indices[0] val newInstanceIndex = scanResult.first() val invokeDirectIndex = scanResult.last() - 1 diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/Fingerprints.kt index add3716a6..fd41b8a61 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/branding/Fingerprints.kt @@ -12,8 +12,8 @@ internal val BytecodePatchContext.numberOfPresetAppNamesExtensionMethod by getti parameterTypes() } -// A much simpler fingerprint exists that can set the small icon (contains string "414843287017"), -// but that has limited usage and this fingerprint allows changing any part of the notification. +// A much simpler method exists that can set the small icon (contains string "414843287017"), +// but that has limited usage and this one allows changing any part of the notification. internal val BytecodePatchContext.notificationMethod by gettingFirstMutableMethodDeclaratively( "key_action_priority", ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/Fingerprints.kt index c0ea184c6..cd9fc2b79 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.shared.layout.theme import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val lithoOnBoundsChangeMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.lithoOnBoundsChangeMethodMatch by composingFirstMethod { name("onBoundsChange") accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returnType("V") diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/LithoColorHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/LithoColorHookPatch.kt index f373d593c..6844d9db4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/LithoColorHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/layout/theme/LithoColorHookPatch.kt @@ -11,7 +11,7 @@ val lithoColorHookPatch = bytecodePatch( ) { apply { - var insertionIndex = lithoOnBoundsChangeMethodMatch.indices.last() - 1 + var insertionIndex = lithoOnBoundsChangeMethodMatch[-1] - 1 lithoColorOverrideHook = { targetMethodClass, targetMethodName -> lithoOnBoundsChangeMethodMatch.method.addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/Fingerprints.kt index 5e9d1f2ac..50f48aaf2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/Fingerprints.kt @@ -1,18 +1,19 @@ package app.revanced.patches.shared.misc.audio import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags -internal val formatStreamModelToStringMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.formatStreamModelToStringMethodMatch by composingFirstMethod { name("toString") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Ljava/lang/String;") instructions( "isDefaultAudioTrack="(String::contains), - "audioTrackId="(String::contains) + "audioTrackId="(String::contains), ) } -internal val selectAudioStreamMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.selectAudioStreamMethodMatch by composingFirstMethod { instructions(45666189L()) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/ForceOriginalAudioPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/ForceOriginalAudioPatch.kt index 702cfc22f..636070951 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/ForceOriginalAudioPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/audio/ForceOriginalAudioPatch.kt @@ -39,7 +39,7 @@ internal fun forceOriginalAudioPatch( subclassExtensionClassDescriptor: String, preferenceScreen: BasePreferenceScreen.Screen, ) = bytecodePatch( - name = "Force original audio", // TODO + name = "Force original audio", description = "Adds an option to always use the original audio track.", ) { block() @@ -65,7 +65,7 @@ internal fun forceOriginalAudioPatch( // and instead overrides to the user region language. if (fixUseLocalizedAudioTrackFlag()) { selectAudioStreamMethodMatch.method.insertLiteralOverride( - selectAudioStreamMethodMatch.indices.first(), + selectAudioStreamMethodMatch[0], "$EXTENSION_CLASS_DESCRIPTOR->ignoreDefaultAudioStream(Z)Z", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/EnableDebuggingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/EnableDebuggingPatch.kt index 491e27927..3aafba1dc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/EnableDebuggingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/debugging/EnableDebuggingPatch.kt @@ -26,12 +26,11 @@ internal fun enableDebuggingPatch( executeBlock: BytecodePatchContext.() -> Unit = {}, hookStringFeatureFlag: Boolean, preferenceScreen: BasePreferenceScreen.Screen, - additionalDebugPreferences: List = emptyList() + additionalDebugPreferences: List = emptyList(), ) = bytecodePatch( - name = "Enable debugging", // TODO + name = "Enable debugging", description = "Adds options for debugging and exporting ReVanced logs to the clipboard.", ) { - dependsOn( addResourcesPatch, resourcePatch { @@ -48,11 +47,11 @@ internal fun enableDebuggingPatch( "revanced_settings_arrow_left_double.xml", "revanced_settings_arrow_left_one.xml", "revanced_settings_arrow_right_double.xml", - "revanced_settings_arrow_right_one.xml" - ) + "revanced_settings_arrow_right_one.xml", + ), ) } - } + }, ) block() @@ -75,19 +74,19 @@ internal fun enableDebuggingPatch( NonInteractivePreference( "revanced_debug_export_logs_to_clipboard", tag = "app.revanced.extension.shared.settings.preference.ExportLogToClipboardPreference", - selectable = true + selectable = true, ), NonInteractivePreference( "revanced_debug_logs_clear_buffer", tag = "app.revanced.extension.shared.settings.preference.ClearLogBufferPreference", - selectable = true + selectable = true, ), NonInteractivePreference( "revanced_debug_feature_flags_manager", tag = "app.revanced.extension.shared.settings.preference.FeatureFlagsManagerPreference", - selectable = true - ) - ) + selectable = true, + ), + ), ) preferenceScreen.addPreferences( @@ -95,7 +94,7 @@ internal fun enableDebuggingPatch( key = "revanced_debug_screen", sorting = Sorting.UNSORTED, preferences = preferences, - ) + ), ) // Hook the methods that look up if a feature flag is active. @@ -108,7 +107,7 @@ internal fun enableDebuggingPatch( """ invoke-static { v$register, p1 }, $EXTENSION_CLASS_DESCRIPTOR->isBooleanFeatureFlagEnabled(ZLjava/lang/Long;)Z move-result v$register - """ + """, ) } } @@ -123,7 +122,7 @@ internal fun enableDebuggingPatch( invoke-static/range { v0 .. v5 }, $EXTENSION_CLASS_DESCRIPTOR->isDoubleFeatureFlagEnabled(DJD)D move-result-wide v0 return-wide v0 - """ + """, ) } @@ -137,11 +136,11 @@ internal fun enableDebuggingPatch( invoke-static/range { v0 .. v5 }, $EXTENSION_CLASS_DESCRIPTOR->isLongFeatureFlagEnabled(JJJ)J move-result-wide v0 return-wide v0 - """ + """, ) } - if (hookStringFeatureFlag) + if (hookStringFeatureFlag) { experimentalFeatureFlagParentMethod.immutableClassDef.getExperimentalStringFeatureFlagMethod().apply { val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.MOVE_RESULT_OBJECT) @@ -152,9 +151,10 @@ internal fun enableDebuggingPatch( invoke-static { v0, p1, p2, p3 }, $EXTENSION_CLASS_DESCRIPTOR->isStringFeatureFlagEnabled(Ljava/lang/String;JLjava/lang/String;)Ljava/lang/String; move-result-object v0 return-object v0 - """ + """, ) } + } // There exists other experimental accessor methods for byte[] // and wrappers for obfuscated classes, but currently none of those are hooked. diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt index afec7080c..d355b3837 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/dns/CheckWatchHistoryDomainNameResolutionPatch.kt @@ -18,7 +18,7 @@ internal fun checkWatchHistoryDomainNameResolutionPatch( executeBlock: BytecodePatchContext.() -> Unit = {}, getMainActivityMethod: BytecodePatchContext.() -> MutableMethod, ) = bytecodePatch( - name = "Check watch history domain name resolution", // TODO + name = "Check watch history domain name resolution", description = "Checks if the device DNS server is preventing user watch history from being saved.", ) { block() diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt index 8d485bcf8..7f493623a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/extension/SharedExtensionPatch.kt @@ -1,9 +1,8 @@ package app.revanced.patches.shared.misc.extension import app.revanced.patcher.* -import app.revanced.patcher.firstMutableClassDef -import app.revanced.patcher.firstMutableMethodDeclaratively import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.firstMutableClassDef import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.bytecodePatch import app.revanced.util.returnEarly @@ -85,18 +84,18 @@ fun sharedExtensionPatch( class ExtensionHook internal constructor( private val getInsertIndex: Method.() -> Int, private val getContextRegister: Method.() -> String, - private val predicate: DeclarativePredicate, + private val build: context(MutableList) MutablePredicateList.() -> Unit, ) { - context(_: BytecodePatchContext) + context(context: BytecodePatchContext) operator fun invoke(extensionClassDescriptor: String) { - val method = firstMutableMethodDeclaratively(predicate = predicate) + val method = context.firstMutableMethodDeclaratively(build = build) val insertIndex = method.getInsertIndex() val contextRegister = method.getContextRegister() method.addInstruction( insertIndex, "invoke-static/range { $contextRegister .. $contextRegister }, " + - "$extensionClassDescriptor->setContext(Landroid/content/Context;)V", + "$extensionClassDescriptor->setContext(Landroid/content/Context;)V", ) } } @@ -104,8 +103,8 @@ class ExtensionHook internal constructor( fun extensionHook( getInsertIndex: Method.() -> Int = { 0 }, getContextRegister: Method.() -> String = { "p0" }, - predicate: DeclarativePredicate, -) = ExtensionHook(getInsertIndex, getContextRegister, predicate) + build: context(MutableList) MutablePredicateList.() -> Unit, +) = ExtensionHook(getInsertIndex, getContextRegister, build) /** * Creates an extension hook from a non-obfuscated activity, which typically is the main activity @@ -124,8 +123,11 @@ fun activityOnCreateExtensionHook(activityClassType: String): ExtensionHook { return extensionHook { name("onCreate") - if (fullClassType) definingClass(activityClassType) - else definingClass { endsWith(activityClassType) } + if (fullClassType) { + definingClass(activityClassType) + } else { + definingClass { endsWith(activityClassType) } + } returnType("V") parameterTypes("Landroid/os/Bundle;") diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/Fingerprints.kt index cf7e2aa6d..2037efcdf 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.shared.misc.fix.verticalscroll import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val canScrollVerticallyMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.canScrollVerticallyMethodMatch by composingFirstMethod { definingClass { endsWith("SwipeRefreshLayout;") } accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt index 210447c25..54a396d47 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch.kt @@ -12,7 +12,7 @@ val verticalScrollPatch = bytecodePatch( apply { canScrollVerticallyMethodMatch.let { it.method.apply { - val moveResultIndex = it.indices.last() + val moveResultIndex = it[-1] val moveResultRegister = getInstruction(moveResultIndex).registerA val insertIndex = moveResultIndex + 1 diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt index 91586cf4e..6e481b805 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/gms/GmsCoreSupportPatch.kt @@ -54,7 +54,7 @@ fun gmsCoreSupportPatch( executeBlock: BytecodePatchContext.() -> Unit = {}, block: BytecodePatchBuilder.() -> Unit = {}, ) = bytecodePatch( - name = "GmsCore support", // TODO + name = "GmsCore support", description = "Allows the app to work without root by using a different package name when patched " + "using a GmsCore instead of Google Play Services.", ) { diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/Fingerprints.kt index 3f0a6c5f1..4dfdc92a6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.shared.misc.privacy import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val youTubeCopyTextFingerprintMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.youTubeCopyTextMethodMatch by composingFirstMethod { returnType("V") parameterTypes("L", "Ljava/util/Map;") instructions( @@ -11,22 +12,22 @@ internal val youTubeCopyTextFingerprintMethodMatch = firstMethodComposite { after(0..2, "text/plain"()), after(0..2, method("newPlainText")), after(0..2, Opcode.MOVE_RESULT_OBJECT()), - after(0..2, method("setPrimaryClip")) + after(0..2, method("setPrimaryClip")), ) } -internal val youTubeSystemShareSheetMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.youTubeSystemShareSheetMethodMatch by composingFirstMethod { returnType("V") parameterTypes("L", "Ljava/util/Map;") instructions( method("setClassName"), after(0..4, method("iterator")), after(0..15, allOf(Opcode.IGET_OBJECT(), type("Ljava/lang/String;"))), - after(0..15, method("putExtra")) + after(0..15, method("putExtra")), ) } -internal val youTubeShareSheetMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.youTubeShareSheetMethodMatch by composingFirstMethod { returnType("V") parameterTypes("L", "Ljava/util/Map;") instructions( @@ -34,6 +35,6 @@ internal val youTubeShareSheetMethodMatch = firstMethodComposite { after(allOf(Opcode.CHECK_CAST(), type("Ljava/lang/String;"))), after(Opcode.GOTO()), method("putExtra"), - "YTShare_Logging_Share_Intent_Endpoint_Byte_Array"() + "YTShare_Logging_Share_Intent_Endpoint_Byte_Array"(), ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/SanitizeSharingLinksPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/SanitizeSharingLinksPatch.kt index 84ccc8b75..88462b2b4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/SanitizeSharingLinksPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/privacy/SanitizeSharingLinksPatch.kt @@ -1,6 +1,6 @@ package app.revanced.patches.shared.misc.privacy -import app.revanced.patcher.MatchBuilder +import app.revanced.patcher.Match import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.patch.BytecodePatchBuilder @@ -28,7 +28,7 @@ internal fun sanitizeSharingLinksPatch( preferenceScreen: BasePreferenceScreen.Screen, replaceMusicLinksWithYouTube: Boolean = false, ) = bytecodePatch( - name = "Sanitize sharing links", // TODO + name = "Sanitize sharing links", description = "Removes the tracking query parameters from shared links.", ) { block() @@ -58,8 +58,9 @@ internal fun sanitizeSharingLinksPatch( }, ) - fun MatchBuilder.hookUrlString(matchIndex: Int) { - val index = indices[matchIndex] + fun Match.hookUrlString(matchIndex: Int) { + val index = get(matchIndex) + val urlRegister = method.getInstruction(index).registerA method.addInstructions( @@ -71,8 +72,8 @@ internal fun sanitizeSharingLinksPatch( ) } - fun MatchBuilder.hookIntentPutExtra(matchIndex: Int) { - val index = indices[matchIndex] + fun Match.hookIntentPutExtra(matchIndex: Int) { + val index = get(matchIndex) val urlRegister = method.getInstruction(index).registerE method.addInstructionsAtControlFlowLabel( @@ -85,7 +86,7 @@ internal fun sanitizeSharingLinksPatch( } // YouTube share sheet copy link. - youTubeCopyTextFingerprintMethodMatch.hookUrlString(0) + youTubeCopyTextMethodMatch.hookUrlString(0) // YouTube share sheet other apps. youTubeShareSheetMethodMatch.hookIntentPutExtra(3) diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt index 40adaa3d8..7e3253ebd 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt @@ -1,10 +1,10 @@ package app.revanced.patches.shared.misc.spoof import app.revanced.patcher.accessFlags +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.custom import app.revanced.patcher.definingClass import app.revanced.patcher.extensions.methodReference -import app.revanced.patcher.firstMethodComposite import app.revanced.patcher.gettingFirstMethodDeclaratively import app.revanced.patcher.gettingFirstMutableMethodDeclaratively import app.revanced.patcher.immutableClassDef @@ -21,15 +21,15 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.Method -internal val buildInitPlaybackRequestMatch = firstMethodComposite("Content-Type", "Range") { - returnType("Lorg/chromium/net/UrlRequest\$Builder;") +internal val BytecodePatchContext.buildInitPlaybackRequestMethodMatch by composingFirstMethod("Content-Type", "Range") { + returnType($$"Lorg/chromium/net/UrlRequest$Builder;") instructions( Opcode.MOVE_RESULT_OBJECT(), Opcode.IGET_OBJECT(), // Moves the request URI string to a register to build the request with. ) } -internal val buildPlayerRequestURIMethodMatch = firstMethodComposite("key", "asig") { +internal val BytecodePatchContext.buildPlayerRequestURIMethodMatch by composingFirstMethod("key", "asig") { returnType("Ljava/lang/String;") instructions( Opcode.INVOKE_VIRTUAL(), // Register holds player request URI. @@ -41,7 +41,7 @@ internal val buildPlayerRequestURIMethodMatch = firstMethodComposite("key", "asi ) } -internal val buildRequestMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.buildRequestMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returnType("Lorg/chromium/net/UrlRequest") // UrlRequest; or UrlRequest$Builder; instructions( @@ -80,8 +80,8 @@ internal val buildRequestMethodMatch = firstMethodComposite { val parameterTypes = parameterTypes val parameterTypesSize = parameterTypes.size (parameterTypesSize == 6 || parameterTypesSize == 7 || parameterTypesSize == 8) && - parameterTypes[1] == "Ljava/util/Map;" && // URL headers. - indexOfNewUrlRequestBuilderInstruction(this) >= 0 + parameterTypes[1] == "Ljava/util/Map;" && // URL headers. + indexOfNewUrlRequestBuilderInstruction(this) >= 0 } } @@ -98,7 +98,7 @@ internal val BytecodePatchContext.protobufClassParseByteBufferMethod by gettingF ) } -internal val createStreamingDataMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.createStreamingDataMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameterTypes("L") instructions( @@ -131,7 +131,7 @@ internal val BytecodePatchContext.buildMediaDataSourceMethod by gettingFirstMuta ) } -internal val hlsCurrentTimeMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.hlsCurrentTimeMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameterTypes("Z", "L") instructions( @@ -141,7 +141,7 @@ internal val hlsCurrentTimeMethodMatch = firstMethodComposite { internal const val DISABLED_BY_SABR_STREAMING_URI_STRING = "DISABLED_BY_SABR_STREAMING_URI" -internal val mediaFetchEnumConstructorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.mediaFetchEnumConstructorMethodMatch by composingFirstMethod { returnType("V") instructions( "ENABLED"(), @@ -170,13 +170,13 @@ internal val BytecodePatchContext.patchIncludedExtensionMethodMethod by gettingF // This code appears to replace the player config after the streams are loaded. // Flag is present in YouTube 19.34, but is missing Platypus stream replacement code until 19.43. // Flag and Platypus code is also present in newer versions of YouTube Music. -internal val mediaFetchHotConfigMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.mediaFetchHotConfigMethodMatch by composingFirstMethod { instructions(45645570L()) } // YT 20.10+, YT Music 8.11 - 8.14. // Flag is missing in YT Music 8.15+, and it is not known if a replacement flag/feature exists. -internal val mediaFetchHotConfigAlternativeMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.mediaFetchHotConfigAlternativeMethodMatch by composingFirstMethod { instructions(45683169L()) } @@ -184,7 +184,7 @@ internal val mediaFetchHotConfigAlternativeMethodMatch = firstMethodComposite { // but its exact purpose is not known. If this flag is enabled while stream spoofing // then videos will never start playback and load forever. // Flag does not seem to affect playback if spoofing is off. -internal val playbackStartDescriptorFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playbackStartDescriptorFeatureFlagMethodMatch by composingFirstMethod { parameterTypes() returnType("Z") instructions(45665455L()) @@ -194,9 +194,9 @@ internal fun indexOfNewUrlRequestBuilderInstruction(method: Method) = method.ind val reference = methodReference ?: return@indexOfFirstInstruction false opcode == Opcode.INVOKE_VIRTUAL && reference.definingClass == "Lorg/chromium/net/CronetEngine;" && - reference.name == "newUrlRequestBuilder" && - reference.parameterTypes.size == 3 && - reference.parameterTypes[0] == "Ljava/lang/String;" && - reference.parameterTypes[1] == "Lorg/chromium/net/UrlRequest\$Callback;" && - reference.parameterTypes[2] == "Ljava/util/concurrent/Executor;" + reference.name == "newUrlRequestBuilder" && + reference.parameterTypes.size == 3 && + reference.parameterTypes[0] == "Ljava/lang/String;" && + reference.parameterTypes[1] == "Lorg/chromium/net/UrlRequest\$Callback;" && + reference.parameterTypes[2] == "Ljava/util/concurrent/Executor;" } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt index 33944f0d9..77d4139ae 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt @@ -39,7 +39,7 @@ internal fun spoofVideoStreamsPatch( block: BytecodePatchBuilder.() -> Unit, executeBlock: BytecodePatchContext.() -> Unit = {}, ) = bytecodePatch( - name = "Spoof video streams", // TODO + name = "Spoof video streams", description = "Adds options to spoof the client video streams to fix playback.", ) { block() @@ -64,8 +64,8 @@ internal fun spoofVideoStreamsPatch( // region Block /initplayback requests to fall back to /get_watch requests. - buildInitPlaybackRequestMatch.method.apply { - val moveUriStringIndex = buildInitPlaybackRequestMatch.indices.first() + buildInitPlaybackRequestMethodMatch.method.apply { + val moveUriStringIndex = buildInitPlaybackRequestMethodMatch[0] val targetRegister = getInstruction(moveUriStringIndex).registerA addInstructions( @@ -82,7 +82,7 @@ internal fun spoofVideoStreamsPatch( // region Block /get_watch requests to fall back to /player requests. buildPlayerRequestURIMethodMatch.method.apply { - val invokeToStringIndex = buildPlayerRequestURIMethodMatch.indices.first() + val invokeToStringIndex = buildPlayerRequestURIMethodMatch[0] val uriRegister = getInstruction(invokeToStringIndex).registerC addInstructions( @@ -101,7 +101,7 @@ internal fun spoofVideoStreamsPatch( buildRequestMethodMatch.method.apply { buildRequestMethod = this - val newRequestBuilderIndex = buildRequestMethodMatch.indices.first() + val newRequestBuilderIndex = buildRequestMethodMatch[0] buildRequestMethodUrlRegister = getInstruction(newRequestBuilderIndex).registerD val freeRegister = findFreeRegister(newRequestBuilderIndex, buildRequestMethodUrlRegister) @@ -121,7 +121,7 @@ internal fun spoofVideoStreamsPatch( createStreamingDataMethodMatch.method.apply { val setStreamDataMethodName = "patch_setStreamingData" val resultMethodType = createStreamingDataMethodMatch.classDef.type - val videoDetailsIndex = createStreamingDataMethodMatch.indices.last() + val videoDetailsIndex = createStreamingDataMethodMatch[-1] val videoDetailsRegister = getInstruction(videoDetailsIndex).registerA val videoDetailsClass = getInstruction(videoDetailsIndex).getReference()!!.type @@ -132,7 +132,7 @@ internal fun spoofVideoStreamsPatch( ) val protobufClass = protobufClassParseByteBufferMethod.definingClass - val setStreamingDataIndex = createStreamingDataMethodMatch.indices.first() + val setStreamingDataIndex = createStreamingDataMethodMatch[0] val playerProtoClass = getInstruction(setStreamingDataIndex + 1) .getReference()!!.definingClass @@ -260,7 +260,7 @@ internal fun spoofVideoStreamsPatch( // region Fix iOS livestream current time. hlsCurrentTimeMethodMatch.method.insertLiteralOverride( - hlsCurrentTimeMethodMatch.indices.first(), + hlsCurrentTimeMethodMatch[0], "$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z", ) @@ -270,7 +270,7 @@ internal fun spoofVideoStreamsPatch( // If SABR is disabled, it seems 'MediaFetchHotConfig' may no longer need an override (not confirmed). val (mediaFetchEnumClass, sabrFieldReference) = with(mediaFetchEnumConstructorMethodMatch.method) { - val disabledBySABRStreamingUrlString = mediaFetchEnumConstructorMethodMatch.indices.last() + val disabledBySABRStreamingUrlString = mediaFetchEnumConstructorMethodMatch[-1] val mediaFetchEnumClass = definingClass val sabrFieldIndex = indexOfFirstInstructionOrThrow(disabledBySABRStreamingUrlString) { @@ -311,21 +311,21 @@ internal fun spoofVideoStreamsPatch( if (fixMediaFetchHotConfig()) { mediaFetchHotConfigMethodMatch.method.insertLiteralOverride( - mediaFetchHotConfigMethodMatch.indices.first(), + mediaFetchHotConfigMethodMatch[0], "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z", ) } if (fixMediaFetchHotConfigAlternative()) { mediaFetchHotConfigAlternativeMethodMatch.method.insertLiteralOverride( - mediaFetchHotConfigAlternativeMethodMatch.indices.first(), + mediaFetchHotConfigAlternativeMethodMatch[0], "$EXTENSION_CLASS_DESCRIPTOR->useMediaFetchHotConfigReplacement(Z)Z", ) } if (fixParsePlaybackResponseFeatureFlag()) { playbackStartDescriptorFeatureFlagMethodMatch.method.insertLiteralOverride( - playbackStartDescriptorFeatureFlagMethodMatch.indices.first(), + playbackStartDescriptorFeatureFlagMethodMatch[0], "$EXTENSION_CLASS_DESCRIPTOR->usePlaybackStartFeatureFlag(Z)Z", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/Fingerprints.kt index d53aba8a2..81992f067 100644 --- a/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/Fingerprints.kt @@ -1,12 +1,13 @@ package app.revanced.patches.solidexplorer2.functionality.filesize +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.definingClass -import app.revanced.patcher.firstMethodComposite import app.revanced.patcher.name import app.revanced.patcher.opcodes +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val onReadyMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.onReadyMethodMatch by composingFirstMethod { name("onReady") definingClass("Lpl/solidexplorer/plugins/texteditor/TextEditor;") opcodes( diff --git a/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt b/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt index d588291aa..3119eb9b4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/solidexplorer2/functionality/filesize/RemoveFileSizeLimitPatch.kt @@ -14,7 +14,7 @@ val removeFileSizeLimitPatch = bytecodePatch( apply { onReadyMethodMatch.let { - val cmpIndex = it.indices.first() + 1 + val cmpIndex = it[0] + 1 val cmpResultRegister = it.method.getInstruction(cmpIndex).registerA it.method.replaceInstruction(cmpIndex, "const/4 v$cmpResultRegister, 0x0") diff --git a/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/Fingerprints.kt index e914de5c3..2efebb875 100644 --- a/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/Fingerprints.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val interceptMethodMatch = firstMethodComposite("SC-Mob-UserPlan", "Configuration") { +internal val BytecodePatchContext.interceptMethodMatch by composingFirstMethod("SC-Mob-UserPlan", "Configuration") { accessFlags(AccessFlags.PUBLIC) returnType("L") parameterTypes("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/HideAdsPatch.kt index e1a1ed870..8364062aa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/soundcloud/ad/HideAdsPatch.kt @@ -48,7 +48,7 @@ val hideAdsPatch = bytecodePatch("Hide ads") { // Prevent verification of an HTTP header containing the user's current plan, which would contradict the previous patch. - val conditionIndex = interceptMethodMatch.indices.last() + 1 // TODO + val conditionIndex = interceptMethodMatch[-1] + 1 interceptMethodMatch.method.addInstruction( conditionIndex, "return-object p1", diff --git a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Fingerprints.kt index 8359bd7b0..065fdfa42 100644 --- a/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/spotify/misc/extension/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.spotify.misc.extension import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext -internal val loadOrbitLibraryMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.loadOrbitLibraryMethodMatch by composingFirstMethod { instructions( "orbit_library_load"(), - "orbit-jni-spotify"() + "orbit-jni-spotify"(), ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt index ff22086f0..299353813 100644 --- a/patches/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/strava/upselling/DisableSubscriptionSuggestionsPatch.kt @@ -50,7 +50,7 @@ val disableSubscriptionSuggestionsPatch = bytecodePatch("Disable subscription su }, ) - val getModulesIndex = getModulesMethodMatch.indices.first() + val getModulesIndex = getModulesMethodMatch[0] immutableMethod.removeInstruction(getModulesIndex) immutableMethod.addInstructions( getModulesIndex, diff --git a/patches/src/main/kotlin/app/revanced/patches/strava/upselling/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/strava/upselling/Fingerprints.kt index 856db0d00..2509ba981 100644 --- a/patches/src/main/kotlin/app/revanced/patches/strava/upselling/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/strava/upselling/Fingerprints.kt @@ -1,12 +1,13 @@ package app.revanced.patches.strava.upselling +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.definingClass -import app.revanced.patcher.firstMethodComposite import app.revanced.patcher.name import app.revanced.patcher.opcodes +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val getModulesMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.getModulesMethodMatch by composingFirstMethod { name("getModules") definingClass { endsWith("/GenericLayoutEntry;") } opcodes(Opcode.IGET_OBJECT) diff --git a/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/Fingerprints.kt index 80a53fe10..7ca1dc3b9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/Fingerprints.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.gettingFirstMutableMethodDeclaratively import app.revanced.patcher.name import app.revanced.patcher.patch.BytecodePatchContext -internal val BytecodePatchContext.checkLockedThemesFingerprint by gettingFirstMutableMethodDeclaratively { +internal val BytecodePatchContext.checkLockedThemesMethod by gettingFirstMutableMethodDeclaratively { name("isLockedTheme") definingClass { endsWith("Theme;") } } diff --git a/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatch.kt index 97954126f..3a194f97a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/UnlockThemePatch.kt @@ -12,7 +12,7 @@ val unlockThemesPatch = bytecodePatch( compatibleWith("com.ticktick.task") apply { - checkLockedThemesFingerprint.addInstructions( + checkLockedThemesMethod.addInstructions( 0, """ const/4 v0, 0x0 diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/Fingerprints.kt index c7797a925..cc63899cc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/Fingerprints.kt @@ -1,14 +1,15 @@ package app.revanced.patches.tumblr.featureflags import app.revanced.patcher.accessFlags -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.opcodes import app.revanced.patcher.parameterTypes +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.returnType 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". +// This targets the method to get the value of a Feature in the class "com.tumblr.configuration.Feature". // Features seem to be Tumblr's A/B testing program. // Feature states are loaded from the server in the "api-http2.tumblr.com/v2/config" request on (first) startup. // A lot of features are returned there, but most of them do not seem to do anything (anymore). @@ -17,7 +18,7 @@ import com.android.tools.smali.dexlib2.Opcode // Some features seem to be very old and never removed, though, such as Google Login. // The startIndex of the opcode pattern is at the start of the function after the arg null check. // we want to insert our instructions there. -internal val getFeatureValueMethodMatch = firstMethodComposite("feature") { +internal val BytecodePatchContext.getFeatureValueMethodMatch by composingFirstMethod("feature") { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Ljava/lang/String;") parameterTypes("L", "Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt index 79bcafd3c..ed5849a77 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/featureflags/OverrideFeatureFlagsPatch.kt @@ -70,7 +70,7 @@ val overrideFeatureFlagsPatch = bytecodePatch( // This is equivalent to // String forcedValue = getValueOverride(feature) // if (forcedValue != null) return forcedValue - val getFeatureIndex = match.indices.first() + val getFeatureIndex = match[0] match.method.addInstructionsWithLabels( getFeatureIndex, """ diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/Fingerprints.kt index 5dc2661c3..de6147c70 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/Fingerprints.kt @@ -1,23 +1,23 @@ package app.revanced.patches.tumblr.fixes -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.gettingFirstMutableMethodDeclaratively import app.revanced.patcher.opcodes import app.revanced.patcher.parameterTypes import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -// Fingerprint for the addQueryParam method from retrofit2: +// Matches the addQueryParam method from retrofit2: // https://github.com/square/retrofit/blob/trunk/retrofit/src/main/java/retrofit2/RequestBuilder.java#L186. // Injecting here allows modifying dynamically set query parameters. internal val BytecodePatchContext.addQueryParamMethod by gettingFirstMutableMethodDeclaratively("Malformed URL. Base: ", ", Relative: ") { parameterTypes("Ljava/lang/String;", "Ljava/lang/String;", "Z") } -// Fingerprint for the parseHttpMethodAndPath method from retrofit2: +// Matches the parseHttpMethodAndPath method 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. -internal val httpPathParserMethodMatch = firstMethodComposite("Only one HTTP method is allowed. Found: %s and %s.") { +internal val BytecodePatchContext.httpPathParserMethodMatch by composingFirstMethod("Only one HTTP method is allowed. Found: %s and %s.") { opcodes( Opcode.IPUT_OBJECT, Opcode.IPUT_BOOLEAN, diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt index a3e72f3d8..b6f0174f8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/fixes/FixOldVersionsPatch.kt @@ -21,7 +21,7 @@ val fixOldVersionsPatch = bytecodePatch( // Remove the live query parameters from the path when it's specified via a @METHOD annotation. for (liveQueryParameter in liveQueryParameters) { httpPathParserMethodMatch.method.addInstructions( - httpPathParserMethodMatch.indices.last() + 1, + httpPathParserMethodMatch[-1] + 1, """ # urlPath = urlPath.replace(liveQueryParameter, "") const-string p1, "$liveQueryParameter" diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/FilterTimelineObjectsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/FilterTimelineObjectsPatch.kt index a108fd1b7..f61816e0d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/FilterTimelineObjectsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/FilterTimelineObjectsPatch.kt @@ -24,7 +24,7 @@ val filterTimelineObjectsPatch = bytecodePatch( dependsOn(sharedExtensionPatch) apply { - val filterInsertIndex = timelineFilterExtensionMethodMatch.indices.first() + val filterInsertIndex = timelineFilterExtensionMethodMatch[0] timelineFilterExtensionMethodMatch.method.apply { val addInstruction = getInstruction(filterInsertIndex + 1) diff --git a/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/Fingerprints.kt index b508b0968..e98cda794 100644 --- a/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/tumblr/timelinefilter/Fingerprints.kt @@ -21,10 +21,10 @@ internal val BytecodePatchContext.timelineConstructorMethod by gettingFirstMutab custom { parameters[0].type == "Ljava/util/List;" } } -// This fingerprints the extension TimelineFilterPatch.filterTimeline method. -// The opcode fingerprint is searching for +// This gets the extension method TimelineFilterPatch.filterTimeline. +// Looking for // if ("BLOCKED_OBJECT_DUMMY".equals(elementType)) iterator.remove(); -internal val timelineFilterExtensionMethodMatch = firstMethodComposite("BLOCKED_OBJECT_DUMMY") { +internal val BytecodePatchContext.timelineFilterExtensionMethodMatch by composingFirstMethod("BLOCKED_OBJECT_DUMMY") { definingClass { endsWith("/TimelineFilterPatch;") } opcodes( Opcode.CONST_STRING, // "BLOCKED_OBJECT_DUMMY" diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/Fingerprints.kt index 15061ac17..a8fdc19d7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/Fingerprints.kt @@ -1,13 +1,14 @@ package app.revanced.patches.twitter.interaction.downloads import app.revanced.patcher.accessFlags -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.opcodes +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.returnType import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val buildMediaOptionsSheetMethodMatch = firstMethodComposite("mediaEntity", "media_options_sheet") { +internal val BytecodePatchContext.buildMediaOptionsSheetMethodMatch by composingFirstMethod("mediaEntity", "media_options_sheet") { opcodes( Opcode.IF_EQ, Opcode.SGET_OBJECT, @@ -16,11 +17,11 @@ internal val buildMediaOptionsSheetMethodMatch = firstMethodComposite("mediaEnti ) } -internal val constructMediaOptionsSheetMethodMatch = firstMethodComposite("captionsState") { +internal val BytecodePatchContext.constructMediaOptionsSheetMethodMatch by composingFirstMethod("captionsState") { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) } -internal val showDownloadVideoUpsellBottomSheetMethodMatch = firstMethodComposite("mediaEntity", "url") { +internal val BytecodePatchContext.showDownloadVideoUpsellBottomSheetMethodMatch by composingFirstMethod("mediaEntity", "url") { returnType("Z") opcodes(Opcode.IF_EQZ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt index f3134cbdc..090d42a4b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/interaction/downloads/UnlockDownloadsPatch.kt @@ -1,6 +1,6 @@ package app.revanced.patches.twitter.interaction.downloads -import app.revanced.patcher.MatchBuilder +import app.revanced.patcher.Match import app.revanced.patcher.extensions.* import app.revanced.patcher.patch.bytecodePatch import com.android.tools.smali.dexlib2.Opcode @@ -15,14 +15,14 @@ val unlockDownloadsPatch = bytecodePatch( compatibleWith("com.twitter.android") apply { - fun MatchBuilder.patch(getRegisterAndIndex: MatchBuilder.() -> Pair) { + fun Match.patch(getRegisterAndIndex: Match.() -> Pair) { val (index, register) = getRegisterAndIndex() method.addInstruction(index, "const/4 v$register, 0x1") } // Allow downloads for non-premium users. showDownloadVideoUpsellBottomSheetMethodMatch.patch { - val checkIndex = indices.first() + val checkIndex = showDownloadVideoUpsellBottomSheetMethodMatch[0] val register = method.getInstruction(checkIndex).registerA checkIndex to register @@ -39,7 +39,7 @@ val unlockDownloadsPatch = bytecodePatch( // Make GIFs downloadable. buildMediaOptionsSheetMethodMatch.let { it.method.apply { - val checkMediaTypeIndex = it.indices.first() + val checkMediaTypeIndex = it[0] val checkMediaTypeInstruction = getInstruction(checkMediaTypeIndex) // Treat GIFs as videos. @@ -49,7 +49,7 @@ val unlockDownloadsPatch = bytecodePatch( const/4 v${checkMediaTypeInstruction.registerB}, 0x2 # GIF if-eq v${checkMediaTypeInstruction.registerA}, v${checkMediaTypeInstruction.registerB}, :video """, - ExternalLabel("video", getInstruction(it.indices.last())), + ExternalLabel("video", getInstruction(it[-1])), ) // Remove media.isDownloadable check. diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/HookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/HookPatch.kt index c545379b0..e1aac1db7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/HookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/HookPatch.kt @@ -8,14 +8,14 @@ import app.revanced.patches.twitter.misc.hook.json.jsonHookPatch fun hookPatch( name: String, hookClassDescriptor: String, -) = bytecodePatch(name) { // TODO: NAME +) = bytecodePatch(name) { dependsOn(jsonHookPatch) compatibleWith( "com.twitter.android"( "10.60.0-release.0", "10.86.0-release.0", - ) + ), ) apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt index 6086f87a9..ec453770c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/Fingerprints.kt @@ -1,26 +1,32 @@ package app.revanced.patches.twitter.misc.hook.json import app.revanced.patcher.* -import app.revanced.patcher.gettingFirstClassDef import app.revanced.patcher.firstMutableMethodDeclaratively +import app.revanced.patcher.gettingFirstClassDef import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.ClassDef +import kotlin.properties.ReadOnlyProperty -internal val jsonHookPatchMethodMatch = firstMethodComposite { - name("") - instructions( - Opcode.INVOKE_INTERFACE(), // Add dummy hook to hooks list. - // Add hooks to the hooks list. - Opcode.INVOKE_STATIC(), // Call buildList. - ) +internal val BytecodePatchContext.jsonHookPatchMethodMatch by ReadOnlyProperty { context, _ -> + context.firstClassDef(JSON_HOOK_PATCH_CLASS_DESCRIPTOR).firstMethodComposite { + name("") + instructions( + Opcode.INVOKE_INTERFACE(), // Add dummy hook to hooks list. + // Add hooks to the hooks list. + Opcode.INVOKE_STATIC(), // Call buildList. + ) + } } context(_: BytecodePatchContext) internal fun ClassDef.getJsonInputStreamMethod() = firstMutableMethodDeclaratively { custom { - if (parameterTypes.isEmpty()) false - else parameterTypes.first() == "Ljava/io/InputStream;" + if (parameterTypes.isEmpty()) { + false + } else { + parameterTypes.first() == "Ljava/io/InputStream;" + } } } diff --git a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt index 12aaeccd6..dc0b7cfbe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/twitter/misc/hook/json/JsonHookPatch.kt @@ -1,8 +1,8 @@ package app.revanced.patches.twitter.misc.hook.json -import app.revanced.patcher.firstClassDef import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.removeInstructions +import app.revanced.patcher.firstClassDef import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch @@ -21,7 +21,7 @@ fun BytecodePatchContext.addJsonHook( if (jsonHook.added) return // Insert hooks right before calling buildList. - val insertIndex = jsonHookPatchMethodMatch.indices.last() + val insertIndex = jsonHookPatchMethodMatch[-1] jsonHookPatchMethodMatch.method.addInstructions( insertIndex, @@ -35,7 +35,7 @@ fun BytecodePatchContext.addJsonHook( } private const val JSON_HOOK_CLASS_NAMESPACE = "app/revanced/extension/twitter/patches/hook/json" -private const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;" +internal const val JSON_HOOK_PATCH_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/JsonHookPatch;" private const val BASE_PATCH_CLASS_NAME = "BaseJsonHook" private const val JSON_HOOK_CLASS_DESCRIPTOR = "L$JSON_HOOK_CLASS_NAMESPACE/$BASE_PATCH_CLASS_NAME;" @@ -45,10 +45,8 @@ val jsonHookPatch = bytecodePatch( dependsOn(sharedExtensionPatch) apply { - jsonHookPatchMethodMatch.apply { - match(firstClassDef(JSON_HOOK_PATCH_CLASS_DESCRIPTOR)).methodOrNull - ?: throw PatchException("Unexpected extension.") - } + jsonHookPatchMethodMatch.methodOrNull + ?: throw PatchException("Unexpected extension.") val jsonFactoryClassDef = loganSquareClassDef // Conveniently find the type to hook a method in, via a named field. @@ -70,13 +68,12 @@ val jsonHookPatch = bytecodePatch( afterDependents { // Remove hooks.add(dummyHook). - val addDummyHookIndex = jsonHookPatchMethodMatch.indices.last() + val addDummyHookIndex = jsonHookPatchMethodMatch[-1] jsonHookPatchMethodMatch.method.removeInstructions(addDummyHookIndex, 2) } } - class JsonHook internal constructor( internal val descriptor: String, ) { @@ -91,9 +88,9 @@ class JsonHook internal constructor( * @param descriptor The class descriptor of the hook. * @throws ClassNotFoundException If the class could not be found. */ -context(_: BytecodePatchContext) +context(context: BytecodePatchContext) fun jsonHook(descriptor: String): JsonHook { - firstClassDef(descriptor).let { + context.firstClassDef(descriptor).let { it.also { classDef -> if ( classDef.superclass != JSON_HOOK_CLASS_DESCRIPTOR || @@ -105,4 +102,4 @@ fun jsonHook(descriptor: String): JsonHook { } return JsonHook(JSON_HOOK_CLASS_DESCRIPTOR) -} \ No newline at end of file +} diff --git a/patches/src/main/kotlin/app/revanced/patches/viber/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/viber/ads/Fingerprints.kt index 134279d9a..7274ec124 100644 --- a/patches/src/main/kotlin/app/revanced/patches/viber/ads/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/viber/ads/Fingerprints.kt @@ -1,11 +1,12 @@ package app.revanced.patches.viber.ads -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.instructions import app.revanced.patcher.invoke +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.Opcode -internal val findAdStringMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.findAdStringMethodMatch by composingFirstMethod { instructions( Opcode.NEW_INSTANCE(), "viber_plus_debug_ads_free_flag"(), diff --git a/patches/src/main/kotlin/app/revanced/patches/viber/ads/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/viber/ads/HideAdsPatch.kt index b6bb5deba..9a3216891 100644 --- a/patches/src/main/kotlin/app/revanced/patches/viber/ads/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/viber/ads/HideAdsPatch.kt @@ -18,12 +18,12 @@ val hideAdsPatch = bytecodePatch( compatibleWith("com.viber.voip"("25.9.2.0", "26.1.2.0")) apply { - val referenceIndex = findAdStringMethodMatch.indices.first() + val referenceIndex = findAdStringMethodMatch[0] val targetClass = findAdStringMethodMatch.immutableMethod.getInstruction(referenceIndex).typeReference - val adFreeFingerprint = firstMutableMethodDeclaratively { + val adFreeMethod = firstMutableMethodDeclaratively { definingClass(targetClass!!.type) returnType("I") parameterTypes() diff --git a/patches/src/main/kotlin/app/revanced/patches/willhaben/ads/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/willhaben/ads/HideAdsPatch.kt index 1213b4bf9..3f3c36699 100644 --- a/patches/src/main/kotlin/app/revanced/patches/willhaben/ads/HideAdsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/willhaben/ads/HideAdsPatch.kt @@ -11,7 +11,7 @@ val hideAdsPatch = bytecodePatch( compatibleWith("at.willhaben") apply { - adResolverMethod.returnEarly() // TODO + adResolverMethod.returnEarly() whAdViewInjectorMethod.returnEarly() } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/Fingerprints.kt index 16e2f6244..b8ce3bbb2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.youtube.ad.getpremium import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val getPremiumViewMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.getPremiumViewMethodMatch by composingFirstMethod { name("onMeasure") definingClass("Lcom/google/android/apps/youtube/app/red/presenter/CompactYpcOfferModuleView;") accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt index aadb87f97..3b1954220 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/ad/getpremium/HideGetPremiumPatch.kt @@ -40,7 +40,7 @@ val hideGetPremiumPatch = bytecodePatch( ) getPremiumViewMethodMatch.let { - val startIndex = it.indices.first() + val startIndex = it[0] val measuredWidthRegister = it.method.getInstruction(startIndex).registerA val measuredHeightInstruction = it.method.getInstruction(startIndex + 1) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/Fingerprints.kt index f022f7ab8..fa5c83ebe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/Fingerprints.kt @@ -1,8 +1,9 @@ package app.revanced.patches.youtube.interaction.dialog import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext -internal val createDialogMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.createDialogMethodMatch by composingFirstMethod { returnType("V") parameterTypes("L", "L", "Ljava/lang/String;") instructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt index a0da1ff73..c0d7e173e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/dialog/RemoveViewerDiscretionDialogPatch.kt @@ -44,7 +44,7 @@ val removeViewerDiscretionDialogPatch = bytecodePatch( createDialogMethodMatch.let { it.method.apply { - val showDialogIndex = it.indices.last() + val showDialogIndex = it[-1] val dialogRegister = getInstruction(showDialogIndex).registerC replaceInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt index a454d9dba..c3e867c49 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSeekbarTappingPatch.kt @@ -39,13 +39,13 @@ val enableSeekbarTappingPatch = bytecodePatch( .reference as MethodReference listOf( - getReference(it.indices.first()), - getReference(it.indices.last()), + getReference(it[0]), + getReference(it[-1]), ) } seekbarTappingMethodMatch.let { - val insertIndex = it.indices.last() + 1 + val insertIndex = it[-1] + 1 it.method.apply { val thisInstanceRegister = getInstruction( @@ -53,7 +53,7 @@ val enableSeekbarTappingPatch = bytecodePatch( ).registerC val xAxisRegister = this.getInstruction( - it.indices[2], + it[2], ).registerD val freeRegister = findFreeRegister( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt index 28ac4dce5..ceefafbb9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/EnableSlideToSeekPatch.kt @@ -43,7 +43,7 @@ val enableSlideToSeekPatch = bytecodePatch( // Restore the behaviour to slide to seek. - val checkIndex = slideToSeekMethodMatch.indices.first() + val checkIndex = slideToSeekMethodMatch[0] val checkReference = slideToSeekMethodMatch.method.getInstruction(checkIndex) .getReference()!! @@ -76,7 +76,7 @@ val enableSlideToSeekPatch = bytecodePatch( if (is_19_17_or_greater) { disableFastForwardGestureMethodMatch.let { it.method.apply { - val targetIndex = it.indices.last() + val targetIndex = it[-1] val targetRegister = getInstruction(targetIndex).registerA addInstructions( @@ -91,7 +91,7 @@ val enableSlideToSeekPatch = bytecodePatch( } else { disableFastForwardLegacyMethodMatch.let { it.method.apply { - val insertIndex = it.indices.last() + 1 + val insertIndex = it[-1] + 1 val targetRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt index 84104d894..c9fe13ba8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/Fingerprints.kt @@ -40,7 +40,7 @@ internal fun ClassDef.getAllowSwipingUpGestureMethod() = firstMutableMethodDecla parameterTypes("L") } -internal val disableFastForwardLegacyMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.disableFastForwardLegacyMethodMatch by composingFirstMethod { returnType("Z") parameterTypes() opcodes(Opcode.MOVE_RESULT) @@ -48,7 +48,7 @@ internal val disableFastForwardLegacyMethodMatch = firstMethodComposite { literal { 45411330 } } -internal val disableFastForwardGestureMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.disableFastForwardGestureMethodMatch by composingFirstMethod { definingClass { endsWith("/NextGenWatchLayout;") } accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") @@ -61,7 +61,7 @@ internal val disableFastForwardGestureMethodMatch = firstMethodComposite { custom { instructions.count() > 30 } } -internal val customTapAndHoldMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.customTapAndHoldMethodMatch by composingFirstMethod { name("run") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") @@ -80,7 +80,7 @@ internal val customTapAndHoldMethodMatch = firstMethodComposite { } } -internal val onTouchEventHandlerMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.onTouchEventHandlerMethodMatch by composingFirstMethod { name("onTouchEvent") accessFlags(AccessFlags.PUBLIC, AccessFlags.PUBLIC) returnType("Z") @@ -103,7 +103,7 @@ internal val onTouchEventHandlerMethodMatch = firstMethodComposite { ) } -internal val seekbarTappingMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.seekbarTappingMethodMatch by composingFirstMethod { name("onTouchEvent") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") @@ -119,7 +119,7 @@ internal val seekbarTappingMethodMatch = firstMethodComposite { ) } -internal val slideToSeekMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.slideToSeekMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/view/View;", "F") @@ -141,7 +141,7 @@ internal val BytecodePatchContext.fullscreenSeekbarThumbnailsQualityMethod by ge ) } -internal val fullscreenLargeSeekbarFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.fullscreenLargeSeekbarFeatureFlagMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") parameterTypes() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/HideSeekbarPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/HideSeekbarPatch.kt index bd9af7f2c..47b69d8b3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/HideSeekbarPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/HideSeekbarPatch.kt @@ -12,8 +12,8 @@ import app.revanced.patches.youtube.misc.playservice.is_20_28_or_greater import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch -import app.revanced.patches.youtube.shared.getSeekbarOnDrawMethodMatch import app.revanced.patches.youtube.shared.seekbarMethod +import app.revanced.patches.youtube.shared.seekbarOnDrawMethodMatch import app.revanced.util.insertLiteralOverride private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/patches/HideSeekbarPatch;" @@ -38,7 +38,7 @@ val hideSeekbarPatch = bytecodePatch( SwitchPreference("revanced_fullscreen_large_seekbar"), ) - getSeekbarOnDrawMethodMatch().match(seekbarMethod.immutableClassDef).method.addInstructionsWithLabels( + seekbarMethod.immutableClassDef.seekbarOnDrawMethodMatch.method.addInstructionsWithLabels( 0, """ const/4 v0, 0x0 @@ -54,7 +54,7 @@ val hideSeekbarPatch = bytecodePatch( if (is_20_28_or_greater) { fullscreenLargeSeekbarFeatureFlagMethodMatch.let { it.method.insertLiteralOverride( - it.indices.first(), + it[0], "$EXTENSION_CLASS_DESCRIPTOR->useFullscreenLargeSeekbar(Z)Z", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/Fingerprints.kt index 1a2cd2379..d65723084 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/Fingerprints.kt @@ -1,8 +1,8 @@ package app.revanced.patches.youtube.interaction.swipecontrols import app.revanced.patcher.accessFlags +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.definingClass -import app.revanced.patcher.firstMethodComposite import app.revanced.patcher.gettingFirstMethodDeclaratively import app.revanced.patcher.instructions import app.revanced.patcher.invoke @@ -16,7 +16,7 @@ internal val BytecodePatchContext.swipeControlsHostActivityMethod by gettingFirs parameterTypes() } -internal val swipeChangeVideoMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.swipeChangeVideoMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) instructions( 45631116L(), // Swipe to change fullscreen video feature flag. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt index cd86a260d..6c49c6161 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/SwipeControlsPatch.kt @@ -138,7 +138,7 @@ val swipeControlsPatch = bytecodePatch( if (is_19_43_or_greater && !is_20_34_or_greater) { swipeChangeVideoMethodMatch.let { it.method.insertLiteralOverride( - it.indices.last(), + it[-1], "$EXTENSION_CLASS_DESCRIPTOR->allowSwipeChangeVideo(Z)Z", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/Fingerprints.kt index 03c2a9cdc..35d51ba01 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.youtube.layout.buttons.navigation import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val addCreateButtonViewMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.addCreateButtonViewMethodMatch by composingFirstMethod { instructions( "Android Wear"(), Opcode.IF_EQZ(), @@ -12,7 +13,7 @@ internal val addCreateButtonViewMethodMatch = firstMethodComposite { ) } -internal val createPivotBarMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.createPivotBarMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameterTypes( "Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;", @@ -25,7 +26,7 @@ internal val createPivotBarMethodMatch = firstMethodComposite { ) } -internal val animatedNavigationTabsFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.animatedNavigationTabsFeatureFlagMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") instructions( @@ -33,7 +34,7 @@ internal val animatedNavigationTabsFeatureFlagMethodMatch = firstMethodComposite ) } -internal val translucentNavigationStatusBarFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.translucentNavigationStatusBarFeatureFlagMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") instructions( @@ -44,7 +45,7 @@ internal val translucentNavigationStatusBarFeatureFlagMethodMatch = firstMethodC /** * YouTube nav buttons. */ -internal val translucentNavigationButtonsFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.translucentNavigationButtonsFeatureFlagMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") instructions( @@ -55,7 +56,7 @@ internal val translucentNavigationButtonsFeatureFlagMethodMatch = firstMethodCom /** * Device on screen back/home/recent buttons. */ -internal val translucentNavigationButtonsSystemFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.translucentNavigationButtonsSystemFeatureFlagMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") instructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt index 133acf38b..230db65c6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/navigation/NavigationButtonsPatch.kt @@ -84,7 +84,7 @@ val navigationButtonsPatch = bytecodePatch( // Switch create with notifications button. addCreateButtonViewMethodMatch.method.apply { - val conditionalCheckIndex = addCreateButtonViewMethodMatch.indices[1] + val conditionalCheckIndex = addCreateButtonViewMethodMatch[1] val conditionRegister = getInstruction(conditionalCheckIndex).registerA @@ -100,7 +100,7 @@ val navigationButtonsPatch = bytecodePatch( // Hide navigation button labels. createPivotBarMethodMatch.let { it.method.apply { - val setTextIndex = it.indices.first() + val setTextIndex = it[0] val targetRegister = getInstruction(setTextIndex).registerC addInstruction( @@ -118,21 +118,21 @@ val navigationButtonsPatch = bytecodePatch( if (is_19_25_or_greater) { translucentNavigationStatusBarFeatureFlagMethodMatch.let { it.method.insertLiteralOverride( - it.indices.first(), + it[0], "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationStatusBar(Z)Z", ) } translucentNavigationButtonsFeatureFlagMethodMatch.let { it.method.insertLiteralOverride( - it.indices.first(), + it[0], "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z", ) } translucentNavigationButtonsSystemFeatureFlagMethodMatch.let { it.method.insertLiteralOverride( - it.indices.first(), + it[0], "$EXTENSION_CLASS_DESCRIPTOR->useTranslucentNavigationButtons(Z)Z", ) } @@ -141,7 +141,7 @@ val navigationButtonsPatch = bytecodePatch( if (is_20_15_or_greater) { animatedNavigationTabsFeatureFlagMethodMatch.let { it.method.insertLiteralOverride( - it.indices.first(), + it[0], "$EXTENSION_CLASS_DESCRIPTOR->useAnimatedNavigationButtons(Z)Z", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt index 2002497b8..82e07852e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/Fingerprints.kt @@ -11,17 +11,17 @@ internal val BytecodePatchContext.mediaRouteButtonMethod by gettingFirstMutableM parameterTypes("I") } -internal val castButtonPlayerFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.castButtonPlayerFeatureFlagMethodMatch by composingFirstMethod { returnType("Z") instructions(45690091L()) } -internal val castButtonActionFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.castButtonActionFeatureFlagMethodMatch by composingFirstMethod { returnType("Z") instructions(45690090L()) } -internal val inflateControlsGroupLayoutStubMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.inflateControlsGroupLayoutStubMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameterTypes() returnType("V") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt index 596909c96..4039e8a7c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/overlay/HidePlayerOverlayButtonsPatch.kt @@ -32,7 +32,7 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( sharedExtensionPatch, settingsPatch, addResourcesPatch, - resourceMappingPatch, // Used by fingerprints. + resourceMappingPatch, // Used for finding methods. versionCheckPatch, ) @@ -59,7 +59,7 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( // region Hide player next/previous button. getLayoutConstructorMethodMatch().let { - val insertIndex = it.indices.last() + val insertIndex = it[-1] val viewRegister = it.method.getInstruction(insertIndex).registerC it.method.addInstruction( @@ -87,7 +87,7 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( castButtonActionFeatureFlagMethodMatch, ).forEach { match -> match.method.insertLiteralOverride( - match.indices.first(), + match[0], "$EXTENSION_CLASS_DESCRIPTOR->getCastButtonOverrideV2(Z)Z", ) } @@ -139,7 +139,7 @@ val hidePlayerOverlayButtonsPatch = bytecodePatch( inflateControlsGroupLayoutStubMethodMatch.let { it.method.apply { - val insertIndex = it.indices.last() + 1 + val insertIndex = it[-1] + 1 val freeRegister = findFreeRegister(insertIndex) addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatch.kt index f0209b0ed..e4a5d1d1a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/formfactor/ChangeFormFactorPatch.kt @@ -61,7 +61,7 @@ val changeFormFactorPatch = bytecodePatch( createPlayerRequestBodyWithModelMatch.let { it.method.apply { - val index = it.indices.last() + val index = it[-1] val register = getInstruction(index).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/Fingerprints.kt index 7b716ff75..2088a2cf7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/Fingerprints.kt @@ -10,7 +10,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.reference.FieldReference -internal val layoutCircleMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.layoutCircleMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameterTypes() returnType("Landroid/view/View;") @@ -24,7 +24,7 @@ internal val layoutCircleMethodMatch = firstMethodComposite { literal { layoutCircle } } -internal val layoutIconMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.layoutIconMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameterTypes() returnType("Landroid/view/View;") @@ -37,7 +37,7 @@ internal val layoutIconMethodMatch = firstMethodComposite { literal { layoutIcon } } -internal val layoutVideoMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.layoutVideoMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC) parameterTypes() returnType("Landroid/view/View;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndScreenCardsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndScreenCardsPatch.kt index 7cc8a67ec..ca2fca5c3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndScreenCardsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreencards/HideEndScreenCardsPatch.kt @@ -76,7 +76,7 @@ val hideEndScreenCardsPatch = bytecodePatch( layoutVideoMethodMatch, ).forEach { match -> match.method.apply { - val insertIndex = match.indices.last() + 1 + val insertIndex = match[-1] + 1 val viewRegister = getInstruction(insertIndex - 1).registerA addInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/Fingerprints.kt index 4fdf367e7..99233409b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/Fingerprints.kt @@ -20,7 +20,7 @@ internal fun ClassDef.getAutoNavStatusMethod() = firstMutableMethodDeclaratively parameterTypes() } -internal val removeOnLayoutChangeListenerMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.removeOnLayoutChangeListenerMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatch.kt index 631deb20d..979621b5e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/endscreensuggestion/HideEndScreenSuggestedVideoPatch.kt @@ -46,7 +46,7 @@ val hideEndScreenSuggestedVideoPatch = bytecodePatch( ) removeOnLayoutChangeListenerMethodMatch.let { - val endScreenMethod = navigate(it.immutableMethod).to(it.indices.last()).stop() // TODO + val endScreenMethod = navigate(it.immutableMethod).to(it[-1]).stop() endScreenMethod.apply { val autoNavStatusMethodName = autoNavConstructorMethod.immutableClassDef.getAutoNavStatusMethod().name diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/Fingerprints.kt index 837eacbea..d687e7155 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/Fingerprints.kt @@ -12,7 +12,7 @@ import com.android.tools.smali.dexlib2.iface.ClassDef /** * 20.26+ */ -internal val hideShowMoreButtonMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.hideShowMoreButtonMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL, AccessFlags.SYNTHETIC) returnType("V") parameterTypes("L", "Ljava/lang/Object;") @@ -23,7 +23,7 @@ internal val hideShowMoreButtonMethodMatch = firstMethodComposite { ) } -internal val hideShowMoreLegacyButtonMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.hideShowMoreLegacyButtonMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) instructions( ResourceType.LAYOUT("expand_button_down"), @@ -32,7 +32,7 @@ internal val hideShowMoreLegacyButtonMethodMatch = firstMethodComposite { ) } -internal val parseElementFromBufferMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.parseElementFromBufferMethodMatch by composingFirstMethod { parameterTypes("L", "L", "[B", "L", "L") instructions( Opcode.IGET_OBJECT(), @@ -68,7 +68,7 @@ internal val BytecodePatchContext.yoodlesImageViewMethod by gettingFirstMutableM instructions(ResourceType.ID("youtube_logo")) } -internal val crowdfundingBoxMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.crowdfundingBoxMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.INVOKE_VIRTUAL, @@ -78,7 +78,7 @@ internal val crowdfundingBoxMethodMatch = firstMethodComposite { literal { crowdfundingBoxId } } -internal val albumCardsMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.albumCardsMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.MOVE_RESULT_OBJECT, @@ -91,7 +91,7 @@ internal val albumCardsMethodMatch = firstMethodComposite { literal { albumCardId } } -internal val filterBarHeightMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.filterBarHeightMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.CONST, @@ -102,7 +102,7 @@ internal val filterBarHeightMethodMatch = firstMethodComposite { literal { filterBarHeightId } } -internal val relatedChipCloudMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.relatedChipCloudMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.CONST, @@ -112,7 +112,7 @@ internal val relatedChipCloudMethodMatch = firstMethodComposite { literal { relatedChipCloudMarginId } } -internal val searchResultsChipBarMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.searchResultsChipBarMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.CONST, @@ -124,7 +124,7 @@ internal val searchResultsChipBarMethodMatch = firstMethodComposite { literal { barContainerHeightId } } -internal val showFloatingMicrophoneButtonMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.showFloatingMicrophoneButtonMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() @@ -135,7 +135,7 @@ internal val showFloatingMicrophoneButtonMethodMatch = firstMethodComposite { ) } -internal val hideViewCountMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.hideViewCountMethodMatch by composingFirstMethod( "Has attachmentRuns but drawableRequester is missing.", ) { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt index 592625c63..c0183d365 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt @@ -1,6 +1,6 @@ package app.revanced.patches.youtube.layout.hide.general -import app.revanced.patcher.MatchBuilder +import app.revanced.patcher.Match import app.revanced.patcher.extensions.* import app.revanced.patcher.immutableClassDef import app.revanced.patcher.patch.bytecodePatch @@ -230,7 +230,7 @@ val hideLayoutComponentsPatch = bytecodePatch( parseElementFromBufferMethodMatch.let { it.method.apply { - val startIndex = it.indices.first() + val startIndex = it[0] val insertIndex = startIndex + 1 val byteArrayParameter = "p3" @@ -280,7 +280,7 @@ val hideLayoutComponentsPatch = bytecodePatch( (if (is_20_26_or_greater) hideShowMoreButtonMethodMatch else hideShowMoreLegacyButtonMethodMatch).let { it.method.apply { - val moveRegisterIndex = it.indices.last() + val moveRegisterIndex = it[-1] val viewRegister = getInstruction(moveRegisterIndex).registerA val insertIndex = moveRegisterIndex + 1 @@ -297,7 +297,7 @@ val hideLayoutComponentsPatch = bytecodePatch( // region crowdfunding box crowdfundingBoxMethodMatch.let { it.method.apply { - val insertIndex = it.indices.last() + val insertIndex = it[-1] val objectRegister = getInstruction(insertIndex).registerA addInstruction( @@ -314,7 +314,7 @@ val hideLayoutComponentsPatch = bytecodePatch( albumCardsMethodMatch.let { it.method.apply { - val checkCastAnchorIndex = it.indices.last() + val checkCastAnchorIndex = it[-1] val insertIndex = checkCastAnchorIndex + 1 val register = getInstruction(checkCastAnchorIndex).registerA @@ -332,7 +332,7 @@ val hideLayoutComponentsPatch = bytecodePatch( showFloatingMicrophoneButtonMethodMatch.let { it.method.apply { - val index = it.indices.last() + val index = it[-1] val register = getInstruction(index).registerA addInstructions( @@ -369,7 +369,7 @@ val hideLayoutComponentsPatch = bytecodePatch( // region hide view count hideViewCountMethodMatch.method.apply { - val startIndex = hideViewCountMethodMatch.indices.first() + val startIndex = hideViewCountMethodMatch[0] var returnStringRegister = getInstruction(startIndex).registerA // Find the instruction where the text dimension is retrieved. @@ -404,16 +404,16 @@ val hideLayoutComponentsPatch = bytecodePatch( * Patch a [Method] with a given [instructions]. * * @param RegisterInstruction The type of instruction to get the register from. - * @param insertIndexOffset The offset to add to the end index of the [MatchBuilder.indices]. + * @param insertIndexOffset The offset to add to the end index of the [Match.indices]. * @param hookRegisterOffset The offset to add to the register of the hook. * @param instructions The instructions to add with the register as a parameter. */ - fun MatchBuilder.patch( + fun Match.patch( insertIndexOffset: Int = 0, hookRegisterOffset: Int = 0, instructions: (Int) -> String, ) = method.apply { - val endIndex = indices.last() + val endIndex = get(-1) val insertIndex = endIndex + insertIndexOffset val register = getInstruction(endIndex + hookRegisterOffset).registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt index 0fe436f65..a5c135e39 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/Fingerprints.kt @@ -23,8 +23,8 @@ internal val BytecodePatchContext.infocardsIncognitoParentMethod by gettingFirst ) } -internal val infocardsMethodCallMethodMatch = - firstMethodComposite("Missing ControlsOverlayPresenter for InfoCards to work.") { +internal val BytecodePatchContext.infocardsMethodCallMethodMatch by + composingFirstMethod("Missing ControlsOverlayPresenter for InfoCards to work.") { opcodes( Opcode.INVOKE_VIRTUAL, Opcode.IGET_OBJECT, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt index da6b00d15..cb9b30f8b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/infocards/HideInfoCardsPatch.kt @@ -77,7 +77,7 @@ val hideInfoCardsPatch = bytecodePatch( // Edit: This old non litho code may be obsolete and no longer used by any supported versions. infocardsMethodCallMethodMatch.let { - val invokeInterfaceIndex = it.indices.last() + val invokeInterfaceIndex = it[-1] it.method.apply { val register = implementation!!.registerCount - 1 diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt index 13812c922..0372dfb2e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/rollingnumber/DisableRollingNumberAnimationPatch.kt @@ -47,8 +47,8 @@ val disableRollingNumberAnimationsPatch = bytecodePatch( // Animations are disabled by preventing an Image from being applied to the text span, // which prevents the animations from appearing. rollingNumberTextViewAnimationUpdateMethodMatch.let { - val blockStartIndex = it.indices.first() - val blockEndIndex = it.indices.last() + 1 + val blockStartIndex = it[0] + val blockEndIndex = it[-1] + 1 it.method.apply { val freeRegister = getInstruction(blockStartIndex).registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt index 9ef8624f1..3076ced8d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/Fingerprints.kt @@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.ClassDef -internal val shortsBottomBarContainerMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.shortsBottomBarContainerMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/view/View;", "Landroid/os/Bundle;") @@ -91,7 +91,7 @@ internal val BytecodePatchContext.renderBottomNavigationBarParentMethod by getti ) } -internal val setPivotBarVisibilityMethodMatch = firstMethodComposite { +internal val ClassDef.setPivotBarVisibilityMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL) returnType("V") parameterTypes("Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt index 5352e91a4..111d2dfd4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/shorts/HideShortsComponentsPatch.kt @@ -211,9 +211,9 @@ val hideShortsComponentsPatch = bytecodePatch( // region Hide the navigation bar. // Hook to get the pivotBar view. - setPivotBarVisibilityMethodMatch.match(setPivotBarVisibilityParentMethod.immutableClassDef).let { match -> + setPivotBarVisibilityParentMethod.immutableClassDef.setPivotBarVisibilityMethodMatch.let { match -> match.method.apply { - val insertIndex = match.indices.last() + val insertIndex = match[-1] val viewRegister = getInstruction(insertIndex - 1).registerA addInstruction( insertIndex, @@ -240,7 +240,7 @@ val hideShortsComponentsPatch = bytecodePatch( // Hide the bottom bar container of the Shorts player. shortsBottomBarContainerMethodMatch.let { it.method.apply { - val targetIndex = it.indices.last() + val targetIndex = it[-1] val heightRegister = getInstruction(targetIndex).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/Fingerprints.kt index d5c103bb0..203b87f06 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/Fingerprints.kt @@ -3,6 +3,7 @@ package app.revanced.patches.youtube.layout.miniplayer import app.revanced.patcher.* +import app.revanced.patcher.ClassDefComposing import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patches.shared.misc.mapping.ResourceType import com.android.tools.smali.dexlib2.AccessFlags @@ -59,7 +60,7 @@ internal fun ClassDef.getMiniplayerModernAddViewListenerMethod() = firstMutableM /** * Matches using the class found in [miniplayerModernViewParentMethod]. */ -internal val miniplayerModernCloseButtonMethodMatch = firstMethodComposite { +internal val ClassDef.miniplayerModernCloseButtonMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes() @@ -72,7 +73,7 @@ internal val miniplayerModernCloseButtonMethodMatch = firstMethodComposite { /** * Matches using the class found in [miniplayerModernViewParentMethod]. */ -internal val miniplayerModernExpandButtonMethodMatch = firstMethodComposite { +internal val ClassDef.miniplayerModernExpandButtonMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes() @@ -98,7 +99,7 @@ internal fun ClassDef.getMiniplayerModernExpandCloseDrawablesMethod() = firstMut /** * Matches using the class found in [miniplayerModernViewParentMethod]. */ -internal val miniplayerModernForwardButtonMethodMatch = firstMethodComposite { +internal val ClassDef.miniplayerModernForwardButtonMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes() @@ -108,7 +109,7 @@ internal val miniplayerModernForwardButtonMethodMatch = firstMethodComposite { ) } -internal val miniplayerModernOverlayViewMethodMatch = firstMethodComposite { +internal val ClassDef.miniplayerModernOverlayViewMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameterTypes() instructions( @@ -120,7 +121,7 @@ internal val miniplayerModernOverlayViewMethodMatch = firstMethodComposite { /** * Matches using the class found in [miniplayerModernViewParentMethod]. */ -internal val miniplayerModernRewindButtonMethodMatch = firstMethodComposite { +internal val ClassDef.miniplayerModernRewindButtonMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes() @@ -133,7 +134,7 @@ internal val miniplayerModernRewindButtonMethodMatch = firstMethodComposite { /** * Matches using the class found in [miniplayerModernViewParentMethod]. */ -internal val miniplayerModernActionButtonMethodMatch = firstMethodComposite { +internal val ClassDef.miniplayerModernActionButtonMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes() @@ -143,7 +144,7 @@ internal val miniplayerModernActionButtonMethodMatch = firstMethodComposite { ) } -internal val miniplayerMinimumSizeMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.miniplayerMinimumSizeMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) instructions( ResourceType.DIMEN("miniplayer_max_size"), @@ -152,7 +153,7 @@ internal val miniplayerMinimumSizeMethodMatch = firstMethodComposite { ) } -internal val miniplayerOverrideMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.miniplayerOverrideMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") instructions( @@ -176,7 +177,7 @@ internal fun ClassDef.getMiniplayerOverrideNoContextMethod() = firstMutableMetho /** * 20.36 and lower. Codes appears to be removed in 20.37+ */ -internal val miniplayerResponseModelSizeCheckMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.miniplayerResponseModelSizeCheckMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes("Ljava/lang/Object;", "Ljava/lang/Object;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt index d1fa8a77a..e17b39353 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/miniplayer/MiniplayerPatch.kt @@ -25,6 +25,7 @@ import app.revanced.util.* import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation +import com.android.tools.smali.dexlib2.iface.ClassDef import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @@ -235,7 +236,7 @@ val Miniplayer = bytecodePatch( // region Legacy tablet miniplayer hooks. miniplayerOverrideMethodMatch.let { - val appNameStringIndex = it.indices.last() + val appNameStringIndex = it[-1] navigate(it.immutableMethod).to(appNameStringIndex).stop().apply { findReturnIndicesReversed().forEach { index -> insertLegacyTabletMiniplayerOverride( @@ -246,7 +247,7 @@ val Miniplayer = bytecodePatch( } miniplayerResponseModelSizeCheckMethodMatch.let { - it.method.insertLegacyTabletMiniplayerOverride(it.indices.last()) + it.method.insertLegacyTabletMiniplayerOverride(it[-1]) } } @@ -312,7 +313,7 @@ val Miniplayer = bytecodePatch( // Override a minimum size constant. miniplayerMinimumSizeMethodMatch.let { it.method.apply { - val index = it.indices[1] + val index = it[1] val register = getInstruction(index).registerA // Smaller sizes can be used, but the miniplayer will always start in size 170 if set any smaller. @@ -395,15 +396,17 @@ val Miniplayer = bytecodePatch( // region Add hooks to hide modern miniplayer buttons. listOf( - miniplayerModernExpandButtonMethodMatch to "hideMiniplayerExpandClose", - miniplayerModernCloseButtonMethodMatch to "hideMiniplayerExpandClose", - miniplayerModernActionButtonMethodMatch to "hideMiniplayerActionButton", - miniplayerModernRewindButtonMethodMatch to "hideMiniplayerRewindForward", - miniplayerModernForwardButtonMethodMatch to "hideMiniplayerRewindForward", - miniplayerModernOverlayViewMethodMatch to "adjustMiniplayerOpacity", - ).forEach { (match, methodName) -> - match.match(miniplayerModernViewParentMethod.immutableClassDef).method.apply { - val index = match.indices.last() + ClassDef::miniplayerModernExpandButtonMethodMatch to "hideMiniplayerExpandClose", + ClassDef::miniplayerModernCloseButtonMethodMatch to "hideMiniplayerExpandClose", + ClassDef::miniplayerModernActionButtonMethodMatch to "hideMiniplayerActionButton", + ClassDef::miniplayerModernRewindButtonMethodMatch to "hideMiniplayerRewindForward", + ClassDef::miniplayerModernForwardButtonMethodMatch to "hideMiniplayerRewindForward", + ClassDef::miniplayerModernOverlayViewMethodMatch to "adjustMiniplayerOpacity", + ).forEach { (matching, methodName) -> + val match = matching.get(miniplayerModernViewParentMethod.immutableClassDef) + + match.method.apply { + val index = match[-1] val register = getInstruction(index).registerA addInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt index 7322a252f..5947817dc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/Fingerprints.kt @@ -8,7 +8,7 @@ import com.android.tools.smali.dexlib2.Opcode /** * 19.46+ */ -internal val openVideosFullscreenPortraitMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.openVideosFullscreenPortraitMethodMatch by composingFirstMethod { returnType("V") parameterTypes("L", "Lj\$/util/Optional;") instructions( @@ -22,7 +22,7 @@ internal val openVideosFullscreenPortraitMethodMatch = firstMethodComposite { /** * Pre 19.46. */ -internal val openVideosFullscreenPortraitLegacyMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.openVideosFullscreenPortraitLegacyMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("L", "Lj\$/util/Optional;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenHookPatch.kt index bcb81d383..3db908d03 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/fullscreen/OpenVideosFullscreenHookPatch.kt @@ -1,6 +1,6 @@ package app.revanced.patches.youtube.layout.player.fullscreen -import app.revanced.patcher.MatchBuilder +import app.revanced.patcher.Match import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.getInstruction import app.revanced.patcher.patch.bytecodePatch @@ -25,12 +25,12 @@ internal val openVideosFullscreenHookPatch = bytecodePatch { ) apply { - var match: MatchBuilder + var match: Match var insertIndex: Int if (is_19_46_or_greater) { match = openVideosFullscreenPortraitMethodMatch - insertIndex = match.indices.first() + insertIndex = match[0] openVideosFullscreenPortraitMethodMatch.let { // Remove A/B feature call that forces what this patch already does. @@ -38,13 +38,13 @@ internal val openVideosFullscreenHookPatch = bytecodePatch { // Shorts fullscreen regular player does not use fullscreen // if the player is minimized and it must be forced using other conditional check. it.method.insertLiteralOverride( - it.indices.last(), + it[-1], false, ) } } else { match = openVideosFullscreenPortraitLegacyMethodMatch - insertIndex = match.indices.last() + insertIndex = match[-1] } match.method.apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt index 4160feaf3..4bb4c275d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/CustomPlayerOverlayOpacityPatch.kt @@ -44,7 +44,7 @@ val customPlayerOverlayOpacityPatch = bytecodePatch( createPlayerOverviewMethodMatch.let { it.method.apply { - val viewRegisterIndex = it.indices.last() + val viewRegisterIndex = it[-1] val viewRegister = getInstruction(viewRegisterIndex).registerA addInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/Fingerprints.kt index 62c49c774..7756cda08 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/player/overlay/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.youtube.layout.player.overlay import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patches.shared.misc.mapping.ResourceType import com.android.tools.smali.dexlib2.Opcode -internal val createPlayerOverviewMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.createPlayerOverviewMethodMatch by composingFirstMethod { returnType("V") instructions( ResourceType.ID("scrim_overlay"), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/Fingerprints.kt index 551f5977a..a52c897c0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/Fingerprints.kt @@ -22,7 +22,7 @@ internal val BytecodePatchContext.removeLikeMethod by gettingFirstMutableMethodD instructions("like/removelike"()) } -internal val rollingNumberMeasureAnimatedTextMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.rollingNumberMeasureAnimatedTextMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returnType("Lj\$/util/Optional;") parameterTypes("L", "Ljava/lang/String;", "L") @@ -43,7 +43,7 @@ internal val rollingNumberMeasureAnimatedTextMethodMatch = firstMethodComposite /** * Matches to class found in [rollingNumberMeasureStaticLabelParentMethod]. */ -internal val rollingNumberMeasureStaticLabelMethod = firstMethodComposite { +internal val ClassDef.rollingNumberMeasureStaticLabelMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("F") parameterTypes("Ljava/lang/String;") @@ -64,17 +64,14 @@ internal val BytecodePatchContext.rollingNumberMeasureStaticLabelParentMethod by ) } -internal val rollingNumberSetterMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.rollingNumberSetterMethodMatch by composingFirstMethod { opcodes( Opcode.INVOKE_DIRECT, Opcode.IGET_OBJECT, ) - custom { - instructions.matchIndexed( - "string", - "RollingNumberType required properties missing! Need"(String::contains), - ) - } + + val match = indexedMatcher("RollingNumberType required properties missing! Need"(String::contains)) + custom { match(instructions) } } internal val BytecodePatchContext.rollingNumberTextViewMethod by gettingFirstMutableMethodDeclaratively { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index 0a37bf68e..13d1f613b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -226,7 +226,7 @@ val returnYouTubeDislikePatch = bytecodePatch( rollingNumberSetterMethodMatch.method.apply { val insertIndex = 1 - val dislikesIndex = rollingNumberSetterMethodMatch.indices.last() + val dislikesIndex = rollingNumberSetterMethodMatch[-1] val charSequenceInstanceRegister = getInstruction(0).registerA val charSequenceFieldReference = getInstruction(dislikesIndex).reference @@ -249,8 +249,8 @@ val returnYouTubeDislikePatch = bytecodePatch( // Modify the measure text calculation to include the left drawable separator if needed. rollingNumberMeasureAnimatedTextMethodMatch.let { // Additional check to verify the opcodes are at the start of the method - if (it.indices.first() != 0) throw PatchException("Unexpected opcode location") - val endIndex = it.indices.last() + if (it[0] != 0) throw PatchException("Unexpected opcode location") + val endIndex = it[-1] it.method.apply { val measuredTextWidthRegister = getInstruction(endIndex).registerA @@ -267,10 +267,8 @@ val returnYouTubeDislikePatch = bytecodePatch( // Additional text measurement method. Used if YouTube decides not to animate the likes count // and sometimes used for initial video load. - rollingNumberMeasureStaticLabelMethod.match( - rollingNumberMeasureStaticLabelParentMethod.immutableClassDef, - ).let { - val measureTextIndex = it.indices.first() + 1 + rollingNumberMeasureStaticLabelParentMethod.immutableClassDef.rollingNumberMeasureStaticLabelMethodMatch.let { + val measureTextIndex = it[0] + 1 it.method.apply { val freeRegister = getInstruction(0).registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt index 46c910abb..42f9c0a4e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/Fingerprints.kt @@ -16,7 +16,7 @@ internal val BytecodePatchContext.fullscreenSeekbarThumbnailsMethod by gettingFi ) } -internal val playerSeekbarColorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playerSeekbarColorMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) instructions( ResourceType.COLOR("inline_time_bar_played_not_highlighted_color"), @@ -25,7 +25,7 @@ internal val playerSeekbarColorMethodMatch = firstMethodComposite { } // class is ControlsOverlayStyle in 20.32 and lower, and obfuscated in 20.33+ -internal val setSeekbarClickedColorMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.setSeekbarClickedColorMethodMatch by composingFirstMethod( "YOUTUBE", "PREROLL", "POSTROLL", @@ -35,14 +35,14 @@ internal val setSeekbarClickedColorMethodMatch = firstMethodComposite( opcodes(Opcode.CONST_HIGH16) } -internal val shortsSeekbarColorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.shortsSeekbarColorMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) instructions( ResourceType.COLOR("reel_time_bar_played_color"), ) } -internal val playerSeekbarHandle1ColorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playerSeekbarHandle1ColorMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) instructions( ResourceType.COLOR("inline_time_bar_live_seekable_range"), @@ -50,7 +50,7 @@ internal val playerSeekbarHandle1ColorMethodMatch = firstMethodComposite { ) } -internal val playerSeekbarHandle2ColorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playerSeekbarHandle2ColorMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) parameterTypes("Landroid/content/Context;") instructions( @@ -59,7 +59,7 @@ internal val playerSeekbarHandle2ColorMethodMatch = firstMethodComposite { ) } -internal val watchHistoryMenuUseProgressDrawableMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.watchHistoryMenuUseProgressDrawableMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("L") @@ -79,7 +79,7 @@ internal val BytecodePatchContext.lithoLinearGradientMethod by gettingFirstMutab /** * 19.49+ */ -internal val playerLinearGradientMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playerLinearGradientMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) parameterTypes("I", "I", "I", "I", "Landroid/content/Context;", "I") returnType("Landroid/graphics/LinearGradient;") @@ -94,7 +94,7 @@ internal val playerLinearGradientMethodMatch = firstMethodComposite { /** * 19.25 - 19.47 */ -internal val playerLinearGradientLegacyMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playerLinearGradientLegacyMethodMatch by composingFirstMethod { returnType("V") instructions( ResourceType.COLOR("yt_youtube_magenta"), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt index 5136d43e8..9a9a0ffd2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/seekbar/SeekbarColorPatch.kt @@ -50,17 +50,17 @@ val seekbarColorPatch = bytecodePatch( playerSeekbarColorMethodMatch.let { it.method.apply { - addColorChangeInstructions(it.indices.last()) - addColorChangeInstructions(it.indices.first()) + addColorChangeInstructions(it[-1]) + addColorChangeInstructions(it[0]) } } shortsSeekbarColorMethodMatch.let { - it.method.addColorChangeInstructions(it.indices.first()) + it.method.addColorChangeInstructions(it[0]) } setSeekbarClickedColorMethodMatch.immutableMethod.let { - val setColorMethodIndex = setSeekbarClickedColorMethodMatch.indices.first() + 1 + val setColorMethodIndex = setSeekbarClickedColorMethodMatch[0] + 1 navigate(it).to(setColorMethodIndex).stop().apply { val colorRegister = getInstruction(0).registerA @@ -78,12 +78,12 @@ val seekbarColorPatch = bytecodePatch( // 19.25+ changes - var handleBarColorFingerprints = mutableListOf(playerSeekbarHandle1ColorMethodMatch) + var handleBarColorMethodMatches = mutableListOf(playerSeekbarHandle1ColorMethodMatch) if (!is_20_34_or_greater) { - handleBarColorFingerprints += playerSeekbarHandle2ColorMethodMatch + handleBarColorMethodMatches += playerSeekbarHandle2ColorMethodMatch } - handleBarColorFingerprints.forEach { - it.method.addColorChangeInstructions(it.indices.last()) + handleBarColorMethodMatches.forEach { + it.method.addColorChangeInstructions(it[-1]) } // If hiding feed seekbar thumbnails, then turn off the cairo gradient @@ -92,7 +92,7 @@ val seekbarColorPatch = bytecodePatch( if (is_19_34_or_greater) { watchHistoryMenuUseProgressDrawableMethodMatch.let { it.method.apply { - val index = it.indices[1] + val index = it[1] val register = getInstruction(index).registerA addInstructions( @@ -114,7 +114,7 @@ val seekbarColorPatch = bytecodePatch( """, ) - val playerMatch: MatchBuilder + val playerMatch: Match val checkGradientCoordinates: Boolean if (is_19_49_or_greater) { playerMatch = playerLinearGradientMethodMatch @@ -126,7 +126,7 @@ val seekbarColorPatch = bytecodePatch( playerMatch.let { it.method.apply { - val index = it.indices.last() + val index = it[-1] val register = getInstruction(index).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/Fingerprints.kt index 9c6551e70..14aecd4f9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/Fingerprints.kt @@ -6,7 +6,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.ClassDef -internal val reelEnumConstructorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.reelEnumConstructorMethodMatch by composingFirstMethod { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) instructions( "REEL_LOOP_BEHAVIOR_UNKNOWN"(), @@ -35,7 +35,7 @@ internal fun ClassDef.getReelPlaybackRepeatMethod() = firstMutableMethodDeclarat instructions(method { toString() == "Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z" }) } -internal val reelPlaybackMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.reelPlaybackMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameterTypes("J") returnType("V") @@ -47,7 +47,7 @@ internal val reelPlaybackMethodMatch = firstMethodComposite { 15, method { name == "" && - parameterTypes.zip(methodParametersPrefix).all { (a, b) -> a.startsWith(b) } + parameterTypes.zip(methodParametersPrefix).all { (a, b) -> a.startsWith(b) } }, ), afterAtMost( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt index 310b2064a..988529db9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsautoplay/ShortsAutoplayPatch.kt @@ -80,7 +80,7 @@ val shortsAutoplayPatch = bytecodePatch( reelEnumClass = immutableClassDef.type method.addInstructions( - indices.last(), + reelEnumConstructorMethodMatch[-1], """ # Pass the first enum value to extension. # Any enum value of this type will work. @@ -117,9 +117,9 @@ val shortsAutoplayPatch = bytecodePatch( if (is_20_09_or_greater) { // Variable names are only a rough guess of what these methods do. val userActionMethodReference = - reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch.indices[1]).methodReference!! + reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch[1]).methodReference!! val reelSequenceControllerMethodReference = - reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch.indices[2]).methodReference!! + reelPlaybackMethodMatch.method.getInstruction(reelPlaybackMethodMatch[2]).methodReference!! reelPlaybackRepeatMethod.apply { // Find the first call modified by extension code above. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt index 335bf1319..5afa4e8de 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/Fingerprints.kt @@ -11,7 +11,7 @@ import com.android.tools.smali.dexlib2.Opcode * the obfuscated name of the videoId() method in PlaybackStartDescriptor. * 20.38 and lower. */ -internal val playbackStartFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playbackStartFeatureFlagMethodMatch by composingFirstMethod { returnType("Z") parameterTypes("Lcom/google/android/libraries/youtube/player/model/PlaybackStartDescriptor;") instructions( @@ -28,7 +28,7 @@ internal val playbackStartFeatureFlagMethodMatch = firstMethodComposite { * the obfuscated name of the videoId() method in PlaybackStartDescriptor. * 20.39+ */ -internal val watchPanelVideoIdMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.watchPanelVideoIdMethodMatch by composingFirstMethod { returnType("Ljava/lang/String;") parameterTypes() instructions( @@ -53,7 +53,7 @@ internal val watchPanelVideoIdMethodMatch = firstMethodComposite { } // Pre 19.25 -internal val shortsPlaybackIntentLegacyMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.shortsPlaybackIntentLegacyMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt index a440bc1d5..9b115730b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/shortsplayer/OpenShortsInRegularPlayerPatch.kt @@ -70,11 +70,11 @@ val openShortsInRegularPlayerPatch = bytecodePatch( // Find the obfuscated method name for PlaybackStartDescriptor.videoId() val (videoIdStartMethod, videoIdIndex) = if (is_20_39_or_greater) { watchPanelVideoIdMethodMatch.let { - it.immutableMethod to it.indices.last() + it.immutableMethod to it[-1] } } else { playbackStartFeatureFlagMethodMatch.let { - it.immutableMethod to it.indices.first() + it.immutableMethod to it[0] } } val playbackStartVideoIdMethodName = navigate(videoIdStartMethod).to(videoIdIndex).stop().name @@ -103,7 +103,7 @@ val openShortsInRegularPlayerPatch = bytecodePatch( } else { shortsPlaybackIntentLegacyMethodMatch.let { it.method.apply { - val index = it.indices.first() + val index = it[0] val playbackStartRegister = getInstruction(index + 1).registerA val insertIndex = index + 2 val freeRegister = findFreeRegister(insertIndex, playbackStartRegister) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/Fingerprints.kt index c8730824e..de6ee8f0e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/Fingerprints.kt @@ -1,12 +1,14 @@ package app.revanced.patches.youtube.layout.sponsorblock import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patches.shared.misc.mapping.ResourceType import app.revanced.patches.youtube.shared.seekbarMethod import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef -internal val appendTimeMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.appendTimeMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Ljava/lang/CharSequence;", "Ljava/lang/CharSequence;", "Ljava/lang/CharSequence;") @@ -17,7 +19,7 @@ internal val appendTimeMethodMatch = firstMethodComposite { ) } -internal val controlsOverlayMethodMatch = firstMethodComposite { +internal val ClassDef.controlsOverlayMethodMatch by ClassDefComposing.composingFirstMethod { returnType("V") parameterTypes() instructions( @@ -29,13 +31,13 @@ internal val controlsOverlayMethodMatch = firstMethodComposite { /** * Resolves to the class found in [seekbarMethod]. */ -internal val rectangleFieldInvalidatorMethodMatch = firstMethodComposite { +internal val ClassDef.rectangleFieldInvalidatorMethodMatch by ClassDefComposing.composingFirstMethod { returnType("V") parameterTypes() instructions(method("invalidate")) } -internal val adProgressTextViewVisibilityMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.adProgressTextViewVisibilityMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatch.kt index ecfd45b1c..0c8559180 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/SponsorBlockPatch.kt @@ -21,8 +21,8 @@ import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.shared.getLayoutConstructorMethodMatch -import app.revanced.patches.youtube.shared.getSeekbarOnDrawMethodMatch import app.revanced.patches.youtube.shared.seekbarMethod +import app.revanced.patches.youtube.shared.seekbarOnDrawMethodMatch import app.revanced.patches.youtube.video.information.onCreateHook import app.revanced.patches.youtube.video.information.videoInformationPatch import app.revanced.patches.youtube.video.information.videoTimeHook @@ -149,10 +149,10 @@ val SponsorBlock = bytecodePatch( // Set seekbar draw rectangle. val rectangleFieldName: FieldReference - rectangleFieldInvalidatorMethodMatch.match(seekbarMethod.immutableClassDef).let { + seekbarMethod.immutableClassDef.rectangleFieldInvalidatorMethodMatch.let { it.method.apply { val rectangleIndex = indexOfFirstInstructionReversedOrThrow( - it.indices.first(), + it[0], ) { getReference()?.type == "Landroid/graphics/Rect;" } @@ -164,10 +164,10 @@ val SponsorBlock = bytecodePatch( // Cannot match using original immutable class because // class may have been modified by other patches - getSeekbarOnDrawMethodMatch().match(seekbarMethod.immutableClassDef).let { + seekbarMethod.immutableClassDef.seekbarOnDrawMethodMatch.let { it.method.apply { // Set seekbar thickness. - val thicknessIndex = it.indices.last() + val thicknessIndex = it[-1] val thicknessRegister = getInstruction(thicknessIndex).registerA addInstruction( thicknessIndex + 1, @@ -212,7 +212,7 @@ val SponsorBlock = bytecodePatch( // Append the new time to the player layout. appendTimeMethodMatch.let { it.method.apply { - val index = it.indices.last() + val index = it[-1] val register = getInstruction(index).registerA addInstructions( @@ -229,8 +229,8 @@ val SponsorBlock = bytecodePatch( onCreateHook(EXTENSION_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR, "initialize") // Initialize the SponsorBlock view. - controlsOverlayMethodMatch.match(getLayoutConstructorMethodMatch().immutableClassDef).let { - val checkCastIndex = it.indices.last() + getLayoutConstructorMethodMatch().immutableClassDef.controlsOverlayMethodMatch.let { + val checkCastIndex = it[-1] it.method.apply { val frameLayoutRegister = getInstruction(checkCastIndex).registerA @@ -242,7 +242,7 @@ val SponsorBlock = bytecodePatch( } adProgressTextViewVisibilityMethodMatch.let { - val setVisibilityIndex = it.indices.first() + val setVisibilityIndex = it[0] val register = it.method.getInstruction(setVisibilityIndex).registerD it.method.addInstructionsAtControlFlowLabel( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/Fingerprints.kt index 06dcbbe79..1ef791ef7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/Fingerprints.kt @@ -6,7 +6,7 @@ import app.revanced.patches.shared.misc.mapping.ResourceType import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val toolBarButtonMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.toolBarButtonMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") instructions( @@ -21,7 +21,7 @@ internal val toolBarButtonMethodMatch = firstMethodComposite { custom { parameterTypes.count() in 1..2 && parameterTypes.first() == "Landroid/view/MenuItem;" } } -internal val spoofAppVersionMethodMatch = firstMethodComposite( +internal val BytecodePatchContext.spoofAppVersionMethodMatch by composingFirstMethod( // Instead of applying a bytecode patch, it might be possible to only rely on code from the extension and // manually set the desired version string as this keyed value in the SharedPreferences. // But, this bytecode patch is simple and it works. diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt index 58f2590d9..cb9259325 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/SpoofAppVersionPatch.kt @@ -83,9 +83,9 @@ val spoofAppVersionPatch = bytecodePatch( * toolbar when the enum name is UNKNOWN. */ toolBarButtonMethodMatch.let { - val imageResourceIndex = it.indices[2] + val imageResourceIndex = it[2] val register = it.method.getInstruction(imageResourceIndex).registerA - val jumpIndex = it.indices.last() + 1 + val jumpIndex = it[-1] + 1 it.method.addInstructionsWithLabels( imageResourceIndex + 1, @@ -95,7 +95,7 @@ val spoofAppVersionPatch = bytecodePatch( } spoofAppVersionMethodMatch.let { - val index = it.indices.first() + val index = it[0] val register = it.method.getInstruction(index).registerA it.method.addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/ChangeStartPagePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/ChangeStartPagePatch.kt index dad7d40d9..ec86e1d56 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/ChangeStartPagePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/ChangeStartPagePatch.kt @@ -58,7 +58,7 @@ val changeStartPagePatch = bytecodePatch( // Hook browseId. browseIdMethodMatch.let { it.method.apply { - val browseIdIndex = it.indices.first() + val browseIdIndex = it[0] val browseIdRegister = getInstruction(browseIdIndex).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/Fingerprints.kt index 02bec111c..2bdcdf398 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startpage/Fingerprints.kt @@ -10,7 +10,7 @@ internal val BytecodePatchContext.intentActionMethod by gettingFirstMutableMetho parameterTypes("Landroid/content/Intent;") } -internal val browseIdMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.browseIdMethodMatch by composingFirstMethod { returnType("Lcom/google/android/apps/youtube/app/common/ui/navigation/PaneDescriptor;") // parameterTypes() // 20.30 and earlier is no parameters. 20.31+ parameter is L. instructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt index 44051b0b3..3b8023f26 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt @@ -53,7 +53,7 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( if (is_20_03_or_greater) { userWasInShortsAlternativeMethodMatch.let { it.method.apply { - val insertIndex = it.indices[2] + 1 + val insertIndex = it[2] + 1 val register = getInstruction(insertIndex).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt index 1a8848ce9..ed0908224 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt @@ -8,7 +8,7 @@ import com.android.tools.smali.dexlib2.Opcode /** * 20.02+ */ -internal val userWasInShortsAlternativeMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.userWasInShortsAlternativeMethodMatch by composingFirstMethod { returnType("V") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) parameterTypes("Ljava/lang/Object;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/Fingerprints.kt index abc9268e7..c89783668 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/Fingerprints.kt @@ -1,13 +1,14 @@ package app.revanced.patches.youtube.layout.theme import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE -internal val useGradientLoadingScreenMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.useGradientLoadingScreenMethodMatch by composingFirstMethod { instructions(45412406L()) } -internal val splashScreenStyleMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.splashScreenStyleMethodMatch by composingFirstMethod { definingClass(YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE) name("onCreate") returnType("V") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt index 946f8eb8d..dad35b727 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/theme/ThemePatch.kt @@ -200,14 +200,14 @@ val themePatch = baseThemePatch( } useGradientLoadingScreenMethodMatch.method.insertLiteralOverride( - useGradientLoadingScreenMethodMatch.indices.first(), + useGradientLoadingScreenMethodMatch[0], "$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z", ) if (is_19_47_or_greater) { // Lottie splash screen exists in earlier versions, but it may not be always on. splashScreenStyleMethodMatch.method.insertLiteralOverride( - splashScreenStyleMethodMatch.indices.first(), + splashScreenStyleMethodMatch[0], "$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt index 8da25477b..6b39c04b5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt @@ -101,7 +101,7 @@ val removeBackgroundPlaybackRestrictionsPatch = bytecodePatch( if (is_19_34_or_greater) { pipInputConsumerFeatureFlagMethodMatch.let { it.method.insertLiteralOverride( - it.indices.first(), + it[0], false, ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt index 1b9f07fdd..da1b03b0e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt @@ -87,7 +87,7 @@ internal val BytecodePatchContext.shortsBackgroundPlaybackFeatureFlagMethod by g } // Fix 'E/InputDispatcher: Window handle pip_input_consumer has no registered input channel' -internal val pipInputConsumerFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.pipInputConsumerFeatureFlagMethodMatch by composingFirstMethod { instructions( // PiP input consumer feature flag. 45638483L(), diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt index 5e798a09f..f3f466007 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/Fingerprints.kt @@ -1,10 +1,11 @@ package app.revanced.patches.youtube.misc.fix.backtoexitgesture import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val scrollPositionMethodMatch = firstMethodComposite("scroll_position") { +internal val BytecodePatchContext.scrollPositionMethodMatch by composingFirstMethod("scroll_position") { accessFlags(AccessFlags.PROTECTED, AccessFlags.FINAL) returnType("V") parameterTypes("L") @@ -15,7 +16,7 @@ internal val scrollPositionMethodMatch = firstMethodComposite("scroll_position") ) } -internal val recyclerViewTopScrollingMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.recyclerViewTopScrollingMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt index 1e91dc580..a8615c1d5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/FixBackToExitGesturePatch.kt @@ -18,13 +18,13 @@ internal val fixBackToExitGesturePatch = bytecodePatch( apply { with(recyclerViewTopScrollingMethodMatch) { method.addInstructionsAtControlFlowLabel( - indices.last() + 1, + recyclerViewTopScrollingMethodMatch[-1] + 1, "invoke-static { }, $EXTENSION_CLASS_DESCRIPTOR->onTopView()V", ) } with(scrollPositionMethodMatch) { - navigate(immutableMethod).to(indices.first() + 1).stop().apply { + navigate(immutableMethod).to(scrollPositionMethodMatch[0] + 1).stop().apply { val index = indexOfFirstInstructionOrThrow { opcode == Opcode.INVOKE_VIRTUAL && getReference()?.definingClass == "Landroid/support/v7/widget/RecyclerView;" diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/contentprovider/FIxContentProviderPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/contentprovider/FIxContentProviderPatch.kt index 4ae2e5eec..e97c6725d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/contentprovider/FIxContentProviderPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/contentprovider/FIxContentProviderPatch.kt @@ -20,7 +20,7 @@ internal val fixContentProviderPatch = bytecodePatch { apply { unstableContentProviderMethodMatch.let { - val insertIndex = it.indices.first() + val insertIndex = it[0] it.method.apply { val register = getInstruction(insertIndex).registerD diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/contentprovider/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/contentprovider/Fingerprints.kt index abac7f64a..ac8772d05 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/contentprovider/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/fix/contentprovider/Fingerprints.kt @@ -1,9 +1,10 @@ package app.revanced.patches.youtube.misc.fix.contentprovider import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags -internal val unstableContentProviderMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.unstableContentProviderMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/content/ContentResolver;", "[Ljava/lang/String;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/AccountCredentialsInvalidTextPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/AccountCredentialsInvalidTextPatch.kt index 452b01ea6..6b07ea5be 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/AccountCredentialsInvalidTextPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/AccountCredentialsInvalidTextPatch.kt @@ -33,7 +33,7 @@ internal val accountCredentialsInvalidTextPatch = bytecodePatch { specificNetworkErrorViewControllerMethodMatch, loadingFrameLayoutControllerMethodMatch, ).forEach { match -> - val index = match.indices.last() + val index = match[-1] val register = match.method.getInstruction(index).registerA match.method.addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Fingerprints.kt index 23f6c1149..78ab4b951 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/gms/Fingerprints.kt @@ -1,11 +1,12 @@ package app.revanced.patches.youtube.misc.gms import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patches.shared.misc.mapping.ResourceType import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val specificNetworkErrorViewControllerMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.specificNetworkErrorViewControllerMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() @@ -18,8 +19,8 @@ internal val specificNetworkErrorViewControllerMethodMatch = firstMethodComposit } // It's not clear if this second class is ever used and it may be dead code, -// but it the layout image/text is identical to the network error fingerprint above. -internal val loadingFrameLayoutControllerMethodMatch = firstMethodComposite { +// but it the layout image/text is identical to the network error match above. +internal val BytecodePatchContext.loadingFrameLayoutControllerMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/imageurlhook/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/imageurlhook/Fingerprints.kt index e45548d55..0a60c7093 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/imageurlhook/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/imageurlhook/Fingerprints.kt @@ -17,7 +17,7 @@ internal fun ClassDef.getOnFailureMethod() = firstMutableMethodDeclaratively { ) } -// Acts as a parent fingerprint. +// Acts as a parent method. internal val BytecodePatchContext.onResponseStartedMethod by gettingFirstMutableMethodDeclaratively( "Content-Length", "Content-Type", diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt index f1b0ee994..99f4a9f2c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/BypassURLRedirectsPatch.kt @@ -49,7 +49,7 @@ val bypassURLRedirectsPatch = bytecodePatch( }, httpUriParserMethodMatch to 0, ).forEach { (match, index) -> - val insertIndex = match.indices[index] + val insertIndex = match[index] val uriStringRegister = match.method.getInstruction(insertIndex).registerC match.method.replaceInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/Fingerprints.kt index 36e96baa9..bea03da44 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/links/Fingerprints.kt @@ -1,12 +1,13 @@ package app.revanced.patches.youtube.misc.links import app.revanced.patcher.* +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags /** * 20.36 and lower. */ -internal val abUriParserLegacyMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.abUriParserLegacyMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Ljava/lang/Object;") parameterTypes("Ljava/lang/Object;") @@ -20,13 +21,13 @@ internal val abUriParserLegacyMethodMatch = firstMethodComposite { /** * 20.37+ */ -internal val abUriParserMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.abUriParserMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Ljava/lang/Object;") parameterTypes("Ljava/lang/Object;") instructions( // Method is a switch statement of unrelated code, - // and there's no strings or anything unique to fingerprint. + // and there's no strings or anything unique to match to. method { toString() == "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;" }, method { toString() == "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;" }, method { toString() == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" }, @@ -34,7 +35,7 @@ internal val abUriParserMethodMatch = firstMethodComposite { ) } -internal val httpUriParserMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.httpUriParserMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returnType("Landroid/net/Uri;") parameterTypes("Ljava/lang/String;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt index ef5b08094..756d6eb6d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/Fingerprints.kt @@ -17,7 +17,7 @@ internal val BytecodePatchContext.lithoFilterMethod by gettingFirstMutableMethod accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) } -internal val protobufBufferReferenceMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.protobufBufferReferenceMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("[B") @@ -72,7 +72,7 @@ internal val BytecodePatchContext.lithoComponentNameUpbFeatureFlagMethod by gett instructions(45631264L()) } -internal val lithoConverterBufferUpbFeatureFlagMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.lithoConverterBufferUpbFeatureFlagMethodMatch by composingFirstMethod { returnType("L") instructions(45419603L()) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt index 834b9a65a..b7afbc0e8 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/LithoFilterPatch.kt @@ -94,7 +94,7 @@ val lithoFilterPatch = bytecodePatch( protobufBufferReferenceMethodMatch.let { // Hook the buffer after the call to jniDecode(). it.method.addInstruction( - it.indices.last() + 1, + it[-1] + 1, "invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->setProtoBuffer([B)V", ) } @@ -201,7 +201,7 @@ val lithoFilterPatch = bytecodePatch( // 20.22 the flag is still enabled in one location, but what it does is not known. // Disable it anyway. it.method.insertLiteralOverride( - it.indices.first(), + it[0], false, ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt index 2ddb4b0a7..cbd10c78b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/Fingerprints.kt @@ -8,11 +8,12 @@ import app.revanced.patcher.parameterTypes import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.returnType import app.revanced.patches.shared.misc.mapping.ResourceType +import app.revanced.patches.youtube.layout.buttons.navigation.navigationButtonsPatch import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.ClassDef -internal val actionBarSearchResultsMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.actionBarSearchResultsMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Landroid/view/View;") instructions( @@ -21,14 +22,14 @@ internal val actionBarSearchResultsMethodMatch = firstMethodComposite { ) } -internal val toolbarLayoutMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.toolbarLayoutMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PROTECTED, AccessFlags.CONSTRUCTOR) instructions( ResourceType.ID("toolbar_container"), allOf( Opcode.CHECK_CAST(), - type("Lcom/google/android/apps/youtube/app/ui/actionbar/MainCollapsingToolbarLayout;") - ) + type("Lcom/google/android/apps/youtube/app/ui/actionbar/MainCollapsingToolbarLayout;"), + ), ) } @@ -49,9 +50,7 @@ context(_: BytecodePatchContext) internal fun ClassDef.getInitializeButtonsMethod() = firstMutableMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") - instructions( - ResourceType.LAYOUT("image_only_tab"), - ) + instructions(ResourceType.LAYOUT("image_only_tab")) } /** @@ -112,7 +111,7 @@ internal val BytecodePatchContext.pivotBarButtonsCreateResourceIntViewMethod by } } -internal val pivotBarButtonsViewSetSelectedMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.pivotBarButtonsViewSetSelectedMethodMatch by composingFirstMethod { definingClass("Lcom/google/android/libraries/youtube/rendering/ui/pivotbar/PivotBar;") accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") @@ -122,12 +121,10 @@ internal val pivotBarButtonsViewSetSelectedMethodMatch = firstMethodComposite { internal val BytecodePatchContext.pivotBarConstructorMethod by gettingFirstMethodDeclaratively { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) - instructions( - "com.google.android.apps.youtube.app.endpoint.flags"(), - ) + instructions("com.google.android.apps.youtube.app.endpoint.flags"()) } -internal val imageEnumConstructorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.imageEnumConstructorMethodMatch by composingFirstMethod { accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) instructions( "TAB_ACTIVITY_CAIRO"(), @@ -136,13 +133,13 @@ internal val imageEnumConstructorMethodMatch = firstMethodComposite { ) } -internal val setEnumMapMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.setEnumMapMethodMatch by composingFirstMethod { instructions( ResourceType.DRAWABLE("yt_fill_bell_black_24"), afterAtMost(10, method { toString() == "Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;" }), afterAtMost( 10, - method { toString() == "Ljava/util/EnumMap;->put(Ljava/lang/Enum;Ljava/lang/Object;)Ljava/lang/Object;" } - ) + method { toString() == "Ljava/util/EnumMap;->put(Ljava/lang/Enum;Ljava/lang/Object;)Ljava/lang/Object;" }, + ), ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt index 48dd9f9c3..8e7651635 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/navigation/NavigationBarHookPatch.kt @@ -28,6 +28,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.Instruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.util.MethodUtil @@ -36,9 +37,9 @@ import java.util.logging.Logger internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/youtube/shared/NavigationBar;" internal const val EXTENSION_NAVIGATION_BUTTON_DESCRIPTOR = - "Lapp/revanced/extension/youtube/shared/NavigationBar\$NavigationButton;" + $$"Lapp/revanced/extension/youtube/shared/NavigationBar$NavigationButton;" private const val EXTENSION_TOOLBAR_INTERFACE = - "Lapp/revanced/extension/youtube/shared/NavigationBar${'$'}AppCompatToolbarPatchInterface;" + $$"Lapp/revanced/extension/youtube/shared/NavigationBar$AppCompatToolbarPatchInterface;" lateinit var hookNavigationButtonCreated: (String) -> Unit @@ -47,7 +48,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig sharedExtensionPatch, versionCheckPatch, playerTypeHookPatch, // Required to detect the search bar in all situations. - resourceMappingPatch, // Used by fingerprints + resourceMappingPatch, // Used to find methods resourcePatch { // Copy missing notification icon. apply { @@ -113,7 +114,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig } pivotBarButtonsViewSetSelectedMethodMatch.method.apply { - val index = pivotBarButtonsViewSetSelectedMethodMatch.indices.first() + val index = pivotBarButtonsViewSetSelectedMethodMatch[0] val instruction = getInstruction(index) val viewRegister = instruction.registerC val isSelectedRegister = instruction.registerD @@ -139,7 +140,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig // so this works regardless which layout is used. actionBarSearchResultsMethodMatch.let { it.method.apply { - val instructionIndex = it.indices.last() + val instructionIndex = it[-1] val viewRegister = getInstruction(instructionIndex).registerC addInstruction( @@ -154,7 +155,7 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig toolbarLayoutMethodMatch.let { it.method.apply { - val index = it.indices.last() + val index = it[-1] val register = getInstruction(index).registerA addInstruction( @@ -212,10 +213,10 @@ val navigationBarHookPatch = bytecodePatch(description = "Hooks the active navig // Fix YT bug of notification tab missing the filled icon. if (is_19_35_or_greater && !is_20_39_or_greater) { // FIXME: 20.39+ needs this fix. val cairoNotificationEnumReference = - imageEnumConstructorMethodMatch.method.getInstruction(imageEnumConstructorMethodMatch.indices.last()).reference + imageEnumConstructorMethodMatch.method.getInstruction(imageEnumConstructorMethodMatch[-1]).reference setEnumMapMethodMatch.apply { - val setEnumIntegerIndex = setEnumMapMethodMatch.indices.last() + val setEnumIntegerIndex = setEnumMapMethodMatch[-1] method.apply { val enumMapRegister = getInstruction(setEnumIntegerIndex).registerC val insertIndex = setEnumIntegerIndex + 1 diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt index 1a511610b..469e6b8aa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/Fingerprints.kt @@ -7,7 +7,7 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.ClassDef -internal val playerControlsVisibilityEntityModelMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playerControlsVisibilityEntityModelMethodMatch by composingFirstMethod { name("getPlayerControlsVisibility") accessFlags(AccessFlags.PUBLIC) returnType("L") @@ -28,7 +28,7 @@ internal val BytecodePatchContext.youtubeControlsOverlayMethod by gettingFirstMe ) } -internal val motionEventMethodMatch = firstMethodComposite { +internal val ClassDef.motionEventMethodMatch by ClassDefComposing.composingFirstMethod { returnType("V") parameterTypes("Landroid/view/MotionEvent;") instructions(method("setTranslationY")) @@ -50,7 +50,7 @@ internal val BytecodePatchContext.playerControlsExtensionHookMethod by gettingFi parameterTypes("Z") } -internal val playerTopControlsInflateMethod = firstMethodComposite { +internal val BytecodePatchContext.playerTopControlsInflateMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() @@ -61,7 +61,7 @@ internal val playerTopControlsInflateMethod = firstMethodComposite { ) } -internal val playerBottomControlsInflateMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.playerBottomControlsInflateMethodMatch by composingFirstMethod { returnType("Ljava/lang/Object;") parameterTypes() instructions( @@ -71,7 +71,7 @@ internal val playerBottomControlsInflateMethodMatch = firstMethodComposite { ) } -internal val overlayViewInflateMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.overlayViewInflateMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/view/View;") @@ -83,7 +83,7 @@ internal val overlayViewInflateMethodMatch = firstMethodComposite { } /** - * Resolves to the class found in [playerTopControlsInflateMethod]. + * Resolves to the class found in [playerTopControlsInflateMethodMatch]. */ context(_: BytecodePatchContext) internal fun ClassDef.getControlsOverlayVisibilityMethod() = firstMutableMethodDeclaratively { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsOverlayVisibilityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsOverlayVisibilityPatch.kt index d4eaabb6b..aff5b9a4d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsOverlayVisibilityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsOverlayVisibilityPatch.kt @@ -18,7 +18,7 @@ val playerControlsOverlayVisibilityPatch = bytecodePatch { apply { playerControlsVisibilityEntityModelMethodMatch.let { it.method.apply { - val startIndex = it.indices.first() + val startIndex = it[0] val iGetReference = getInstruction(startIndex).reference val staticReference = getInstruction(startIndex + 1).reference diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt index b3233d512..973fa94ff 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/PlayerControlsPatch.kt @@ -227,7 +227,7 @@ val playerControlsPatch = bytecodePatch( dependsOn( playerControlsResourcePatch, sharedExtensionPatch, - resourceMappingPatch, // Used by fingerprints. + resourceMappingPatch, // Used to find methods. playerControlsOverlayVisibilityPatch, versionCheckPatch, ) @@ -236,26 +236,26 @@ val playerControlsPatch = bytecodePatch( playerBottomControlsInflateMethodMatch.method.apply { inflateBottomControlMethod = this - val inflateReturnObjectIndex = playerBottomControlsInflateMethodMatch.indices.last() + val inflateReturnObjectIndex = playerBottomControlsInflateMethodMatch[-1] inflateBottomControlRegister = getInstruction(inflateReturnObjectIndex).registerA inflateBottomControlInsertIndex = inflateReturnObjectIndex + 1 } - playerTopControlsInflateMethod.method.apply { + playerTopControlsInflateMethodMatch.method.apply { inflateTopControlMethod = this - val inflateReturnObjectIndex = playerTopControlsInflateMethod.indices.last() + val inflateReturnObjectIndex = playerTopControlsInflateMethodMatch[-1] inflateTopControlRegister = getInstruction(inflateReturnObjectIndex).registerA inflateTopControlInsertIndex = inflateReturnObjectIndex + 1 } visibilityMethod = - playerTopControlsInflateMethod.immutableClassDef.getControlsOverlayVisibilityMethod() + playerTopControlsInflateMethodMatch.immutableClassDef.getControlsOverlayVisibilityMethod() // Hook the fullscreen close button. Used to fix visibility // when seeking and other situations. overlayViewInflateMethodMatch.method.apply { - val index = overlayViewInflateMethodMatch.indices.last() + val index = overlayViewInflateMethodMatch[-1] val register = getInstruction(index).registerA addInstruction( @@ -268,9 +268,9 @@ val playerControlsPatch = bytecodePatch( visibilityImmediateCallbacksExistMethod = playerControlsExtensionHookListenersExistMethod visibilityImmediateMethod = playerControlsExtensionHookMethod - motionEventMethodMatch.match(youtubeControlsOverlayMethod.immutableClassDef).let { + youtubeControlsOverlayMethod.immutableClassDef.motionEventMethodMatch.let { visibilityNegatedImmediateMethod = it.method - visibilityNegatedImmediateInsertIndex = it.indices.first() + 1 + visibilityNegatedImmediateInsertIndex = it[0] + 1 } // A/B test for a slightly different bottom overlay controls, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt index 5b4ba07c1..fe49276ab 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/Fingerprints.kt @@ -22,7 +22,7 @@ internal val BytecodePatchContext.playerTypeEnumMethod by gettingFirstMethodDecl accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR) } -internal val reelWatchPagerMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.reelWatchPagerMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Landroid/view/View;") instructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt index e99afc754..a37d2d9cc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/PlayerTypeHookPatch.kt @@ -31,7 +31,7 @@ val playerTypeHookPatch = bytecodePatch( ) reelWatchPagerMethodMatch.method.apply { - val index = reelWatchPagerMethodMatch.indices.last() + val index = reelWatchPagerMethodMatch[-1] val register = getInstruction(index).registerA addInstruction( @@ -57,7 +57,7 @@ val playerTypeHookPatch = bytecodePatch( ) }.let { it.method.apply { - val videoStateFieldName = getInstruction(it.indices.first()).reference + val videoStateFieldName = getInstruction(it[0]).reference addInstructions( 0, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/Fingerprints.kt index bbd73d846..efece581f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/Fingerprints.kt @@ -1,12 +1,13 @@ package app.revanced.patches.youtube.misc.recyclerviewtree.hook import app.revanced.patcher.accessFlags -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.opcodes +import app.revanced.patcher.patch.BytecodePatchContext import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal val recyclerViewTreeObserverMethodMatch = firstMethodComposite("LithoRVSLCBinder") { +internal val BytecodePatchContext.recyclerViewTreeObserverMethodMatch by composingFirstMethod("LithoRVSLCBinder") { accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR) opcodes( Opcode.CHECK_CAST, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt index ed861cb1c..70182237f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/RecyclerViewTreeHookPatch.kt @@ -12,7 +12,7 @@ val recyclerViewTreeHookPatch = bytecodePatch { apply { recyclerViewTreeObserverMethodMatch.let { - val insertIndex = it.indices.first() + 1 + val insertIndex = it[0] + 1 val recyclerViewParameter = 2 addRecyclerViewTreeHook = { classDescriptor -> diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt index 7dfbacb7f..4e9d967bb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/Fingerprints.kt @@ -8,7 +8,7 @@ import com.android.tools.smali.dexlib2.Opcode internal val BytecodePatchContext.licenseActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively { name("onCreate") - definingClass("/LicenseActivity;") + definingClass { endsWith("/LicenseActivity;") } accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/os/Bundle;") @@ -21,7 +21,7 @@ internal val BytecodePatchContext.setThemeMethod by gettingFirstMutableMethodDec instructions(ResourceType.STRING("app_theme_appearance_dark")) } -internal val cairoFragmentConfigMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.cairoFragmentConfigMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") instructions( @@ -32,7 +32,7 @@ internal val cairoFragmentConfigMethodMatch = firstMethodComposite { // Flag is present in 20.23, but bold icons are missing and forcing them crashes the app. // 20.31 is the first target with all the bold icons present. -internal val boldIconsFeatureFlagMethod = firstMethodComposite { +internal val BytecodePatchContext.boldIconsFeatureFlagMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") parameterTypes() diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt index 920025857..38b200d4b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/settings/SettingsPatch.kt @@ -241,16 +241,16 @@ val settingsPatch = bytecodePatch( // Add setting to force Cairo settings fragment on/off. cairoFragmentConfigMethodMatch.method.insertLiteralOverride( - cairoFragmentConfigMethodMatch.indices.first(), + cairoFragmentConfigMethodMatch[0], "$YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z", ) // Bold icon resources are found starting in 20.23, but many YT icons are not bold. // 20.31 is the first version that seems to have all the bold icons. if (is_20_31_or_greater) { - boldIconsFeatureFlagMethod.let { + boldIconsFeatureFlagMethodMatch.let { it.method.insertLiteralOverride( - it.indices.first(), + it[0], "$YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useBoldIcons(Z)Z", ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt index 9bb669c9d..6bb0e6075 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/shared/Fingerprints.kt @@ -1,17 +1,17 @@ package app.revanced.patches.youtube.shared +import app.revanced.patcher.ClassDefComposing import app.revanced.patcher.accessFlags import app.revanced.patcher.after import app.revanced.patcher.allOf +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.custom import app.revanced.patcher.definingClass import app.revanced.patcher.field import app.revanced.patcher.firstMethodComposite -import app.revanced.patcher.firstMethodDeclaratively import app.revanced.patcher.gettingFirstMethodDeclaratively import app.revanced.patcher.gettingFirstMutableMethodDeclaratively import app.revanced.patcher.immutableClassDef -import app.revanced.patcher.instruction import app.revanced.patcher.instructions import app.revanced.patcher.invoke import app.revanced.patcher.method @@ -24,6 +24,7 @@ import app.revanced.patcher.type import app.revanced.patches.shared.misc.mapping.ResourceType import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.ClassDef internal const val YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE = "Lcom/google/android/apps/youtube/app/watchwhile/MainActivity;" @@ -39,7 +40,7 @@ internal val BytecodePatchContext.conversionContextToStringMethod by gettingFirs instructions("ConversionContext{"(String::startsWith)) // Partial string match. } -internal fun getLayoutConstructorMethodMatch() = firstMethodComposite { +internal fun BytecodePatchContext.getLayoutConstructorMethodMatch() = firstMethodComposite { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes() @@ -78,7 +79,7 @@ internal val BytecodePatchContext.mainActivityOnCreateMethod by gettingFirstMuta parameterTypes("Landroid/os/Bundle;") } -internal val rollingNumberTextViewAnimationUpdateMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.rollingNumberTextViewAnimationUpdateMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") parameterTypes("Landroid/graphics/Bitmap;") @@ -112,7 +113,7 @@ internal val BytecodePatchContext.seekbarMethod by gettingFirstMethodDeclarative /** * Matches to _mutable_ class found in [seekbarMethod]. */ -internal fun getSeekbarOnDrawMethodMatch() = firstMethodComposite { +internal val ClassDef.seekbarOnDrawMethodMatch by ClassDefComposing.composingFirstMethod { name("onDraw") instructions( method { toString() == "Ljava/lang/Math;->round(F)I" }, @@ -130,7 +131,7 @@ internal val BytecodePatchContext.subtitleButtonControllerMethod by gettingFirst ) } -internal val videoQualityChangedMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.videoQualityChangedMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt index 964218069..783bfc0f5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/Fingerprints.kt @@ -7,6 +7,7 @@ import app.revanced.patches.youtube.shared.videoQualityChangedMethodMatch import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.ClassDef +import org.stringtemplate.v4.compiler.Bytecode internal val BytecodePatchContext.createVideoPlayerSeekbarMethod by gettingFirstMethodDeclaratively { returnType("V") @@ -21,15 +22,16 @@ internal val BytecodePatchContext.onPlaybackSpeedItemClickMethod by gettingFirst instructions( allOf( Opcode.IGET_OBJECT(), - field { type == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" }) + field { type == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" }, + ), ) } -internal val playerControllerSetTimeReferenceMethodMatch = - firstMethodComposite("Media progress reported outside media playback: ") { +internal val BytecodePatchContext.playerControllerSetTimeReferenceMethodMatch by + composingFirstMethod("Media progress reported outside media playback: ") { opcodes( Opcode.INVOKE_DIRECT_RANGE, - Opcode.IGET_OBJECT + Opcode.IGET_OBJECT, ) } @@ -44,7 +46,7 @@ internal fun ClassDef.getSeekMethod() = firstMethodDeclaratively { instructions("Attempting to seek during an ad"()) } -internal val videoLengthMethodMatch = firstMethodComposite { +internal val ClassDef.videoLengthMethodMatch by ClassDefComposing.composingFirstMethod { opcodes( Opcode.MOVE_RESULT_WIDE, Opcode.CMP_LONG, @@ -114,7 +116,7 @@ internal fun ClassDef.getSeekRelativeMethod() = firstMutableMethodDeclaratively ) } -internal val videoEndMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.videoEndMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("Z") parameterTypes("J", "L") @@ -128,7 +130,7 @@ internal val videoEndMethodMatch = firstMethodComposite { /** * Matches with the class found in [videoQualityChangedMethodMatch]. */ -internal val playbackSpeedMenuSpeedChangedMethodMatch = firstMethodComposite { +internal val ClassDef.playbackSpeedMenuSpeedChangedMethodMatch by ClassDefComposing.composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes("L") @@ -136,7 +138,7 @@ internal val playbackSpeedMenuSpeedChangedMethodMatch = firstMethodComposite { } internal val BytecodePatchContext.playbackSpeedClassMethod by gettingFirstMutableMethodDeclaratively( - "PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT" + "PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT", ) { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returnType("L") @@ -144,7 +146,6 @@ internal val BytecodePatchContext.playbackSpeedClassMethod by gettingFirstMutabl opcodes(Opcode.RETURN_OBJECT) } - internal const val YOUTUBE_VIDEO_QUALITY_CLASS_TYPE = "Lcom/google/android/libraries/youtube/innertube/model/media/VideoQuality;" @@ -158,7 +159,7 @@ internal val BytecodePatchContext.videoQualityLegacyMethod by gettingFirstMutabl "I", // Resolution. "Ljava/lang/String;", // Human readable resolution: "480p", "1080p Premium", etc "Z", - "L" + "L", ) } @@ -170,12 +171,12 @@ internal val BytecodePatchContext.videoQualityMethod by gettingFirstMutableMetho "L", "Ljava/lang/String;", // Human readable resolution: "480p", "1080p Premium", etc "Z", - "L" + "L", ) } internal val BytecodePatchContext.videoQualitySetterMethod by gettingFirstMutableMethodDeclaratively( - "menu_item_video_quality" + "menu_item_video_quality", ) { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("V") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index d7a8f2d4c..f573e45de 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -130,15 +130,15 @@ val videoInformationPatch = bytecodePatch( } with(createVideoPlayerSeekbarMethod) { - val videoLengthMethodMatch = videoLengthMethodMatch.match(immutableClassDef) + val videoLengthMethodMatch = immutableClassDef.videoLengthMethodMatch videoLengthMethodMatch.method.apply { - val videoLengthRegisterIndex = videoLengthMethodMatch.indices.last() + val videoLengthRegisterIndex = videoLengthMethodMatch[-1] val videoLengthRegister = getInstruction(videoLengthRegisterIndex).registerA val dummyRegisterForLong = videoLengthRegister + 1 // required for long values since they are wide addInstruction( - videoLengthMethodMatch.indices.last(), + videoLengthMethodMatch[-1], "invoke-static {v$videoLengthRegister, v$dummyRegisterForLong}, " + "$EXTENSION_CLASS_DESCRIPTOR->setVideoLength(J)V", ) @@ -146,7 +146,7 @@ val videoInformationPatch = bytecodePatch( } videoEndMethod = navigate(videoEndMethodMatch.immutableMethod) - .to(videoEndMethodMatch.indices.first()).stop() + .to(videoEndMethodMatch[0]).stop() /* * Inject call for video ids @@ -170,7 +170,7 @@ val videoInformationPatch = bytecodePatch( * Set the video time method */ timeMethod = navigate(playerControllerSetTimeReferenceMethodMatch.immutableMethod) - .to(playerControllerSetTimeReferenceMethodMatch.indices.first()).stop() + .to(playerControllerSetTimeReferenceMethodMatch[0]).stop() /* * Hook the methods which set the time @@ -270,9 +270,9 @@ val videoInformationPatch = bytecodePatch( } // Handle new playback speed menu. - playbackSpeedMenuSpeedChangedMethodMatch.match(videoQualityChangedMethodMatch.immutableClassDef).let { + videoQualityChangedMethodMatch.immutableClassDef.playbackSpeedMenuSpeedChangedMethodMatch.let { it.method.apply { - val index = it.indices.first() + val index = it[0] speedSelectionInsertMethod = this speedSelectionInsertIndex = index + 1 diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt index 8ed829f26..5f10870c0 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/AdvancedVideoQualityMenuPatch.kt @@ -57,7 +57,7 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch { // and for the Shorts quality flyout on newer app versions. videoQualityMenuViewInflateMethodMatch.let { it.method.apply { - val checkCastIndex = it.indices.last() + val checkCastIndex = it[-1] val listViewRegister = getInstruction(checkCastIndex).registerA addInstruction( @@ -70,8 +70,8 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch { // Force YT to add the 'advanced' quality menu for Shorts. videoQualityMenuOptionsMethodMatch.let { - val startIndex = it.indices.first() - val insertIndex = it.indices.last() + val startIndex = it[0] + val insertIndex = it[-1] if (startIndex != 0) throw PatchException("Unexpected opcode start index: $startIndex") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt index ad37bdb17..093a759b2 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/Fingerprints.kt @@ -1,7 +1,7 @@ package app.revanced.patches.youtube.video.quality import app.revanced.patcher.accessFlags -import app.revanced.patcher.firstMethodComposite +import app.revanced.patcher.composingFirstMethod import app.revanced.patcher.firstMutableMethodDeclaratively import app.revanced.patcher.gettingFirstMethodDeclaratively import app.revanced.patcher.name @@ -32,7 +32,7 @@ internal fun ClassDef.getVideoQualityItemOnClickMethod() = firstMutableMethodDec ) } -internal val videoQualityMenuOptionsMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.videoQualityMenuOptionsMethodMatch by composingFirstMethod { accessFlags(AccessFlags.STATIC) returnType("[L") parameterTypes("Landroid/content/Context", "L", "L") @@ -46,7 +46,7 @@ internal val videoQualityMenuOptionsMethodMatch = firstMethodComposite { literal { videoQualityQuickMenuAdvancedMenuDescription } } -internal val videoQualityMenuViewInflateMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.videoQualityMenuViewInflateMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("L") parameterTypes("L", "L", "L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt index f7893c686..9b38ead45 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt @@ -72,7 +72,7 @@ val rememberVideoQualityPatch = bytecodePatch { // Inject a call to remember the user selected quality for regular videos. videoQualityChangedMethodMatch.let { match -> - val index = match.indices[3] + val index = match[3] val register = match.method.getInstruction(index).registerA match.method.addInstruction( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt index 88b557bdf..c55a3d95c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/CustomPlaybackSpeedPatch.kt @@ -97,15 +97,15 @@ internal val customPlaybackSpeedPatch = bytecodePatch( val playbackSpeedsArrayType = "$EXTENSION_CLASS_DESCRIPTOR->customPlaybackSpeeds:[F" // Apply changes from last index to first to preserve indexes. - val originalArrayFetchIndex = it.indices[5] - val originalArrayFetchDestination = getInstruction(it.indices[5]).registerA + val originalArrayFetchIndex = it[5] + val originalArrayFetchDestination = getInstruction(it[5]).registerA replaceInstruction( originalArrayFetchIndex, "sget-object v$originalArrayFetchDestination, $playbackSpeedsArrayType", ) - val arrayLengthConstDestination = getInstruction(it.indices[3]).registerA - val newArrayIndex = it.indices[4] + val arrayLengthConstDestination = getInstruction(it[3]).registerA + val newArrayIndex = it[4] addInstructions( newArrayIndex, """ @@ -114,7 +114,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch( """, ) - val sizeCallIndex = it.indices[0] + 1 + val sizeCallIndex = it[0] + 1 val sizeCallResultRegister = getInstruction(sizeCallIndex).registerA replaceInstruction(sizeCallIndex, "const/4 v$sizeCallResultRegister, 0x0") } @@ -172,7 +172,7 @@ internal val customPlaybackSpeedPatch = bytecodePatch( if (is_19_47_or_greater) { customTapAndHoldMethodMatch.let { it.method.apply { - val index = it.indices.first() + val index = it[0] val register = getInstruction(index).registerA addInstructions( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt index 43ce7443d..f7c0cdbce 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/Fingerprints.kt @@ -32,7 +32,7 @@ internal val BytecodePatchContext.serverSideMaxSpeedFeatureFlagMethod by getting ) } -internal val speedArrayGeneratorMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.speedArrayGeneratorMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC) returnType("[L") parameterTypes("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/Fingerprints.kt index b3ed07bbf..535f38abc 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/Fingerprints.kt @@ -23,7 +23,7 @@ internal fun ClassDef.getVideoIdMethodMatch() = firstMethodComposite { ) } -internal val videoIdBackgroundPlayMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.videoIdBackgroundPlayMethodMatch by composingFirstMethod { accessFlags(AccessFlags.DECLARED_SYNCHRONIZED, AccessFlags.FINAL, AccessFlags.PUBLIC) returnType("V") parameterTypes("L") @@ -45,7 +45,7 @@ internal val videoIdBackgroundPlayMethodMatch = firstMethodComposite { } } -internal val videoIdParentMethodMatch = firstMethodComposite { +internal val BytecodePatchContext.videoIdParentMethodMatch by composingFirstMethod { accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) returnType("[L") parameterTypes("L") diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt index 6fc87aa3b..76465dd9e 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/videoid/VideoIdPatch.kt @@ -95,7 +95,7 @@ val videoIdPatch = bytecodePatch( videoIdParentMethodMatch.immutableClassDef.getVideoIdMethodMatch().let { videoIdMethod = it.method - val index = it.indices.first() + val index = it[0] videoIdRegister = it.method.getInstruction(index + 1).registerA videoIdInsertIndex = index + 2 } @@ -103,7 +103,7 @@ val videoIdPatch = bytecodePatch( videoIdBackgroundPlayMethodMatch.let { backgroundPlaybackMethod = it.method - val index = it.indices.first() + val index = it[0] backgroundPlaybackVideoIdRegister = it.method.getInstruction(index + 1).registerA backgroundPlaybackInsertIndex = index + 2 } diff --git a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 9e18d21c2..78a784e89 100644 --- a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -1238,7 +1238,7 @@ internal fun BytecodePatchContext.addStaticFieldToExtension( } /** - * Set the custom condition for this fingerprint to check for a literal value. + * Set the custom condition for this predicate to check for a literal value. * * @param literalSupplier The supplier for the literal value to check for. */